ar71xx/mac80211: add a workaround for the bad signal strength on the WNDR3700
[openwrt.git] / target / linux / ar71xx / files / arch / mips / ar71xx / mach-wndr3700.c
1 /*
2  *  Netgear WNDR3700 board support
3  *
4  *  Copyright (C) 2009 Marco Porsch
5  *  Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org>
6  *
7  *  This program is free software; you can redistribute it and/or modify it
8  *  under the terms of the GNU General Public License version 2 as published
9  *  by the Free Software Foundation.
10  */
11
12 #include <linux/platform_device.h>
13 #include <linux/mtd/mtd.h>
14 #include <linux/mtd/partitions.h>
15 #include <linux/delay.h>
16 #include <linux/rtl8366s.h>
17
18 #include <asm/mach-ar71xx/ar71xx.h>
19
20 #include "machtype.h"
21 #include "devices.h"
22 #include "dev-m25p80.h"
23 #include "dev-ap94-pci.h"
24 #include "dev-gpio-buttons.h"
25 #include "dev-leds-gpio.h"
26 #include "dev-usb.h"
27
28 #define WNDR3700_GPIO_LED_WPS_ORANGE    0
29 #define WNDR3700_GPIO_LED_POWER_ORANGE  1
30 #define WNDR3700_GPIO_LED_POWER_GREEN   2
31 #define WNDR3700_GPIO_LED_WPS_GREEN     4
32
33 #define WNDR3700_GPIO_BTN_WPS           3
34 #define WNDR3700_GPIO_BTN_RESET         8
35 #define WNDR3700_GPIO_BTN_WIFI          11
36
37 #define WNDR3700_GPIO_RTL8366_SDA       5
38 #define WNDR3700_GPIO_RTL8366_SCK       7
39
40 #define WNDR3700_BUTTONS_POLL_INTERVAL    20
41
42 #define WNDR3700_WMAC0_MAC_OFFSET       0
43 #define WNDR3700_WMAC1_MAC_OFFSET       0xc
44 #define WNDR3700_CALDATA0_OFFSET        0x1000
45 #define WNDR3700_CALDATA1_OFFSET        0x5000
46
47 #ifdef CONFIG_MTD_PARTITIONS
48 static struct mtd_partition wndr3700_partitions[] = {
49         {
50                 .name           = "uboot",
51                 .offset         = 0,
52                 .size           = 0x050000,
53                 .mask_flags     = MTD_WRITEABLE,
54         } , {
55                 .name           = "env",
56                 .offset         = 0x050000,
57                 .size           = 0x020000,
58                 .mask_flags     = MTD_WRITEABLE,
59         } , {
60                 .name           = "rootfs",
61                 .offset         = 0x070000,
62                 .size           = 0x720000,
63         } , {
64                 .name           = "config",
65                 .offset         = 0x790000,
66                 .size           = 0x010000,
67                 .mask_flags     = MTD_WRITEABLE,
68         } , {
69                 .name           = "config_bak",
70                 .offset         = 0x7a0000,
71                 .size           = 0x010000,
72                 .mask_flags     = MTD_WRITEABLE,
73         } , {
74                 .name           = "pot",
75                 .offset         = 0x7b0000,
76                 .size           = 0x010000,
77                 .mask_flags     = MTD_WRITEABLE,
78         } , {
79                 .name           = "traffic_meter",
80                 .offset         = 0x7c0000,
81                 .size           = 0x010000,
82                 .mask_flags     = MTD_WRITEABLE,
83         } , {
84                 .name           = "language",
85                 .offset         = 0x7d0000,
86                 .size           = 0x020000,
87                 .mask_flags     = MTD_WRITEABLE,
88         } , {
89                 .name           = "caldata",
90                 .offset         = 0x7f0000,
91                 .size           = 0x010000,
92                 .mask_flags     = MTD_WRITEABLE,
93         }
94 };
95 #endif /* CONFIG_MTD_PARTITIONS */
96
97 static struct flash_platform_data wndr3700_flash_data = {
98 #ifdef CONFIG_MTD_PARTITIONS
99         .parts          = wndr3700_partitions,
100         .nr_parts       = ARRAY_SIZE(wndr3700_partitions),
101 #endif
102 };
103
104 static struct gpio_led wndr3700_leds_gpio[] __initdata = {
105         {
106                 .name           = "wndr3700:green:power",
107                 .gpio           = WNDR3700_GPIO_LED_POWER_GREEN,
108                 .active_low     = 1,
109         }, {
110                 .name           = "wndr3700:orange:power",
111                 .gpio           = WNDR3700_GPIO_LED_POWER_ORANGE,
112                 .active_low     = 1,
113         }, {
114                 .name           = "wndr3700:green:wps",
115                 .gpio           = WNDR3700_GPIO_LED_WPS_GREEN,
116                 .active_low     = 1,
117         }, {
118                 .name           = "wndr3700:orange:wps",
119                 .gpio           = WNDR3700_GPIO_LED_WPS_ORANGE,
120                 .active_low     = 1,
121         }
122 };
123
124 static struct gpio_button wndr3700_gpio_buttons[] __initdata = {
125         {
126                 .desc           = "reset",
127                 .type           = EV_KEY,
128                 .code           = BTN_0,
129                 .threshold      = 3,
130                 .gpio           = WNDR3700_GPIO_BTN_RESET,
131         }, {
132                 .desc           = "wps",
133                 .type           = EV_KEY,
134                 .code           = BTN_1,
135                 .threshold      = 3,
136                 .gpio           = WNDR3700_GPIO_BTN_WPS,
137         } , {
138                 .desc           = "wifi",
139                 .type           = EV_KEY,
140                 .code           = BTN_2,
141                 .threshold      = 3,
142                 .gpio           = WNDR3700_GPIO_BTN_WIFI,
143         }
144 };
145
146 static struct rtl8366s_platform_data wndr3700_rtl8366s_data = {
147         .gpio_sda        = WNDR3700_GPIO_RTL8366_SDA,
148         .gpio_sck        = WNDR3700_GPIO_RTL8366_SCK,
149 };
150
151 static struct platform_device wndr3700_rtl8366s_device = {
152         .name           = RTL8366S_DRIVER_NAME,
153         .id             = -1,
154         .dev = {
155                 .platform_data  = &wndr3700_rtl8366s_data,
156         }
157 };
158
159 static void __init wndr3700_setup(void)
160 {
161         u8 *art = (u8 *) KSEG1ADDR(0x1fff0000);
162
163         ar71xx_set_mac_base(art);
164
165         ar71xx_eth0_pll_data.pll_1000 = 0x11110000;
166         ar71xx_eth0_data.mii_bus_dev = &wndr3700_rtl8366s_device.dev;
167         ar71xx_eth0_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
168         ar71xx_eth0_data.phy_mask = 0xf;
169         ar71xx_eth0_data.speed = SPEED_1000;
170         ar71xx_eth0_data.duplex = DUPLEX_FULL;
171
172         ar71xx_eth1_pll_data.pll_1000 = 0x11110000;
173         ar71xx_eth1_data.mii_bus_dev = &wndr3700_rtl8366s_device.dev;
174         ar71xx_eth1_data.phy_if_mode = PHY_INTERFACE_MODE_RGMII;
175         ar71xx_eth1_data.phy_mask = 0x10;
176
177         ar71xx_add_device_eth(0);
178         ar71xx_add_device_eth(1);
179
180         ar71xx_add_device_usb();
181
182         ar71xx_add_device_m25p80(&wndr3700_flash_data);
183
184         ar71xx_add_device_leds_gpio(-1, ARRAY_SIZE(wndr3700_leds_gpio),
185                                     wndr3700_leds_gpio);
186
187         ar71xx_add_device_gpio_buttons(-1, WNDR3700_BUTTONS_POLL_INTERVAL,
188                                       ARRAY_SIZE(wndr3700_gpio_buttons),
189                                       wndr3700_gpio_buttons);
190
191         platform_device_register(&wndr3700_rtl8366s_device);
192         platform_device_register_simple("wndr3700-led-usb", -1, NULL, 0);
193
194         ap94_pci_enable_quirk_wndr3700();
195         ap94_pci_init(art + WNDR3700_CALDATA0_OFFSET,
196                       art + WNDR3700_WMAC0_MAC_OFFSET,
197                       art + WNDR3700_CALDATA1_OFFSET,
198                       art + WNDR3700_WMAC1_MAC_OFFSET);
199 }
200
201 MIPS_MACHINE(AR71XX_MACH_WNDR3700, "WNDR3700", "NETGEAR WNDR3700",
202              wndr3700_setup);