ar71xx: add kernel support for the buffalo wzr-hp-ag300h
[oweals/openwrt.git] / target / linux / ar71xx / files / arch / mips / ar71xx / mach-wzr-hp-ag300h.c
1 /*
2  *  Buffalo WZR-HP-AG300H board support
3  *
4  *  Copyright (C) 2011 Felix Fietkau <nbd@openwrt.org>
5  *
6  *  This program is free software; you can redistribute it and/or modify it
7  *  under the terms of the GNU General Public License version 2 as published
8  *  by the Free Software Foundation.
9  */
10
11 #include <linux/platform_device.h>
12 #include <linux/mtd/mtd.h>
13 #include <linux/mtd/partitions.h>
14 #include <linux/mtd/concat.h>
15
16 #include <asm/mips_machine.h>
17 #include <asm/mach-ar71xx/ar71xx.h>
18
19 #include "machtype.h"
20 #include "devices.h"
21 #include "dev-ap94-pci.h"
22 #include "dev-gpio-buttons.h"
23 #include "dev-leds-gpio.h"
24 #include "dev-m25p80.h"
25 #include "dev-usb.h"
26
27 #define WZRHPAG300H_MAC_OFFSET          0x20c
28 #define WZRHPAG300H_KEYS_POLL_INTERVAL     20      /* msecs */
29 #define WZRHPAG300H_KEYS_DEBOUNCE_INTERVAL (3 * WZRHPAG300H_KEYS_POLL_INTERVAL)
30
31 #ifdef CONFIG_MTD_CONCAT
32
33 #ifdef CONFIG_MTD_PARTITIONS
34 static struct mtd_partition wzrhpag300h_flash_partitions[] = {
35         {
36                 .name           = "u-boot",
37                 .offset         = 0,
38                 .size           = 0x0040000,
39                 .mask_flags     = MTD_WRITEABLE,
40         }, {
41                 .name           = "u-boot-env",
42                 .offset         = 0x0040000,
43                 .size           = 0x0010000,
44                 .mask_flags     = MTD_WRITEABLE,
45         }, {
46                 .name           = "art",
47                 .offset         = 0x0050000,
48                 .size           = 0x0010000,
49                 .mask_flags     = MTD_WRITEABLE,
50         }, {
51                 .name           = "kernel",
52                 .offset         = 0x0060000,
53                 .size           = 0x0100000,
54         }, {
55                 .name           = "rootfs",
56                 .offset         = 0x0160000,
57                 .size           = 0x1e90000,
58         }, {
59                 .name           = "user_property",
60                 .offset         = 0x1ff0000,
61                 .size           = 0x0010000,
62                 .mask_flags     = MTD_WRITEABLE,
63         }, {
64                 .name           = "firmware",
65                 .offset         = 0x0060000,
66                 .size           = 0x1f90000,
67         }
68 };
69
70 #endif /* CONFIG_MTD_PARTITIONS */
71
72 static struct mtd_info *concat_devs[2] = { NULL, NULL };
73 static struct work_struct mtd_concat_work;
74
75 static void mtd_concat_add_work(struct work_struct *work)
76 {
77         struct mtd_info *mtd;
78
79         mtd = mtd_concat_create(concat_devs, ARRAY_SIZE(concat_devs), "flash");
80
81 #ifdef CONFIG_MTD_PARTITIONS
82         add_mtd_partitions(mtd, wzrhpag300h_flash_partitions,
83                            ARRAY_SIZE(wzrhpag300h_flash_partitions));
84 #else
85         add_mtd_device(mtd);
86 #endif
87 }
88
89 static void mtd_concat_add(struct mtd_info *mtd)
90 {
91         static bool registered = false;
92
93         if (registered)
94                 return;
95
96         if (!strcmp(mtd->name, "spi0.0"))
97                 concat_devs[0] = mtd;
98         else if (!strcmp(mtd->name, "spi0.1"))
99                 concat_devs[1] = mtd;
100         else
101                 return;
102
103         if (!concat_devs[0] || !concat_devs[1])
104                 return;
105
106         registered = true;
107         INIT_WORK(&mtd_concat_work, mtd_concat_add_work);
108         schedule_work(&mtd_concat_work);
109 }
110
111 static void mtd_concat_remove(struct mtd_info *mtd)
112 {
113 }
114
115 static void add_mtd_concat_notifier(void)
116 {
117         static struct mtd_notifier not = {
118                 .add = mtd_concat_add,
119                 .remove = mtd_concat_remove,
120         };
121
122         register_mtd_user(&not);
123 }
124
125 #endif
126
127 static struct gpio_led wzrhpag300h_leds_gpio[] __initdata = {
128         {
129                 .name           = "wzr-hp-ag300h:red:diag",
130                 .gpio           = 1,
131                 .active_low     = 1,
132         },
133 };
134
135
136 static struct gpio_keys_button wzrhpag300h_gpio_keys[] __initdata = {
137         {
138                 .desc           = "reset",
139                 .type           = EV_KEY,
140                 .code           = KEY_RESTART,
141                 .debounce_interval = WZRHPAG300H_KEYS_DEBOUNCE_INTERVAL,
142                 .gpio           = 11,
143                 .active_low     = 1,
144         }, {
145                 .desc           = "usb",
146                 .type           = EV_KEY,
147                 .code           = BTN_2,
148                 .debounce_interval = WZRHPAG300H_KEYS_DEBOUNCE_INTERVAL,
149                 .gpio           = 3,
150                 .active_low     = 1,
151         }, {
152                 .desc           = "aoss",
153                 .type           = EV_KEY,
154                 .code           = KEY_WPS_BUTTON,
155                 .debounce_interval = WZRHPAG300H_KEYS_DEBOUNCE_INTERVAL,
156                 .gpio           = 5,
157                 .active_low     = 1,
158         }, {
159                 .desc           = "router_auto",
160                 .type           = EV_KEY,
161                 .code           = BTN_6,
162                 .debounce_interval = WZRHPAG300H_KEYS_DEBOUNCE_INTERVAL,
163                 .gpio           = 6,
164                 .active_low     = 1,
165         }, {
166                 .desc           = "router_off",
167                 .type           = EV_KEY,
168                 .code           = BTN_5,
169                 .debounce_interval = WZRHPAG300H_KEYS_DEBOUNCE_INTERVAL,
170                 .gpio           = 7,
171                 .active_low     = 1,
172         }
173 };
174
175 static struct spi_board_info ar71xx_spi_info[] = {
176         {
177                 .bus_num        = 0,
178                 .chip_select    = 0,
179                 .max_speed_hz   = 25000000,
180                 .modalias   = "m25p80",
181         },
182         {
183                 .bus_num        = 0,
184                 .chip_select    = 1,
185                 .max_speed_hz   = 25000000,
186                 .modalias   = "m25p80",
187         }
188 };
189
190 static void __init wzrhpag300h_setup(void)
191 {
192         u8 *eeprom = (u8 *) KSEG1ADDR(0x1f051000);
193         u8 *mac = eeprom + WZRHPAG300H_MAC_OFFSET;
194
195         ar71xx_init_mac(ar71xx_eth0_data.mac_addr, mac, 0);
196         ar71xx_init_mac(ar71xx_eth1_data.mac_addr, mac, 1);
197
198         ar71xx_add_device_mdio(~(BIT(0) | BIT(4)));
199
200         ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
201         ar71xx_eth0_data.speed = SPEED_1000;
202         ar71xx_eth0_data.duplex = DUPLEX_FULL;
203         ar71xx_eth0_data.phy_mask = BIT(0);
204
205         ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
206         ar71xx_eth1_data.phy_mask = BIT(4);
207
208         ar71xx_add_device_eth(0);
209         ar71xx_add_device_eth(1);
210
211         ar71xx_add_device_usb();
212
213         ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(wzrhpag300h_leds_gpio),
214                                         wzrhpag300h_leds_gpio);
215
216         ar71xx_register_gpio_keys_polled(-1, WZRHPAG300H_KEYS_POLL_INTERVAL,
217                                          ARRAY_SIZE(wzrhpag300h_gpio_keys),
218                                          wzrhpag300h_gpio_keys);
219
220         ar71xx_add_device_spi(NULL, ar71xx_spi_info,
221                               ARRAY_SIZE(ar71xx_spi_info));
222
223 #ifdef CONFIG_MTD_CONCAT
224         add_mtd_concat_notifier();
225 #endif
226
227         ap94_pci_init(eeprom, mac, NULL, NULL);
228 }
229
230 MIPS_MACHINE(AR71XX_MACH_WZR_HP_AG300H, "WZR-HP-AG300H",
231              "Buffalo WZR-HP-AG300H", wzrhpag300h_setup);
232