1 /* linux/arch/arm/mach-msm/board-stingray-wifi.c
3 #include <linux/kernel.h>
4 #include <linux/init.h>
5 #include <linux/platform_device.h>
6 #include <linux/delay.h>
8 #include <asm/mach-types.h>
11 #include <asm/setup.h>
13 #include <linux/skbuff.h>
14 #include <linux/wlan_plat.h>
15 #include <mach/sdhci.h>
17 #include <linux/random.h>
18 #include <linux/jiffies.h>
20 #include "board-stingray.h"
21 #include "gpio-names.h"
23 #define STINGRAY_WLAN_IRQ TEGRA_GPIO_PU5
24 #define STINGRAY_WLAN_PWR TEGRA_GPIO_PU4
25 #define STINGRAY_WLAN_RST TEGRA_GPIO_PU2
27 #define ATAG_STINGRAY_MAC 0x57464d41
28 #define ATAG_STINGRAY_MAC_DEBUG
30 #define PREALLOC_WLAN_NUMBER_OF_SECTIONS 4
31 #define PREALLOC_WLAN_NUMBER_OF_BUFFERS 160
32 #define PREALLOC_WLAN_SECTION_HEADER 24
34 #define WLAN_SECTION_SIZE_0 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 128)
35 #define WLAN_SECTION_SIZE_1 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 128)
36 #define WLAN_SECTION_SIZE_2 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 512)
37 #define WLAN_SECTION_SIZE_3 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 1024)
39 #define WLAN_SKB_BUF_NUM 16
41 static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];
43 typedef struct wifi_mem_prealloc_struct {
46 } wifi_mem_prealloc_t;
48 static wifi_mem_prealloc_t wifi_mem_array[PREALLOC_WLAN_NUMBER_OF_SECTIONS] = {
49 { NULL, (WLAN_SECTION_SIZE_0 + PREALLOC_WLAN_SECTION_HEADER) },
50 { NULL, (WLAN_SECTION_SIZE_1 + PREALLOC_WLAN_SECTION_HEADER) },
51 { NULL, (WLAN_SECTION_SIZE_2 + PREALLOC_WLAN_SECTION_HEADER) },
52 { NULL, (WLAN_SECTION_SIZE_3 + PREALLOC_WLAN_SECTION_HEADER) }
55 static void *stingray_wifi_mem_prealloc(int section, unsigned long size)
57 if (section == PREALLOC_WLAN_NUMBER_OF_SECTIONS)
58 return wlan_static_skb;
59 if ((section < 0) || (section > PREALLOC_WLAN_NUMBER_OF_SECTIONS))
61 if (wifi_mem_array[section].size < size)
63 return wifi_mem_array[section].mem_ptr;
66 int __init stingray_init_wifi_mem(void)
70 for(i=0;( i < WLAN_SKB_BUF_NUM );i++) {
71 if (i < (WLAN_SKB_BUF_NUM/2))
72 wlan_static_skb[i] = dev_alloc_skb(4096);
74 wlan_static_skb[i] = dev_alloc_skb(8192);
76 for(i=0;( i < PREALLOC_WLAN_NUMBER_OF_SECTIONS );i++) {
77 wifi_mem_array[i].mem_ptr = kmalloc(wifi_mem_array[i].size,
79 if (wifi_mem_array[i].mem_ptr == NULL)
85 static struct resource stingray_wifi_resources[] = {
87 .name = "bcm4329_wlan_irq",
88 .start = TEGRA_GPIO_TO_IRQ(STINGRAY_WLAN_IRQ),
89 .end = TEGRA_GPIO_TO_IRQ(STINGRAY_WLAN_IRQ),
90 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE,
94 /* BCM4329 returns wrong sdio_vsn(1) when we read cccr,
95 * we use predefined value (sdio_vsn=2) here to initial sdio driver well
97 static struct embedded_sdio_data stingray_wifi_emb_data = {
108 static int stingray_wifi_cd = 0; /* WIFI virtual 'card detect' status */
109 static void (*wifi_status_cb)(int card_present, void *dev_id);
110 static void *wifi_status_cb_devid;
112 static int stingray_wifi_status_register(
113 void (*callback)(int card_present, void *dev_id),
118 wifi_status_cb = callback;
119 wifi_status_cb_devid = dev_id;
123 static unsigned int stingray_wifi_status(struct device *dev)
125 return stingray_wifi_cd;
128 struct tegra_sdhci_platform_data stingray_wifi_data = {
132 .ocr_mask = MMC_VDD_165_195,
134 .status = stingray_wifi_status,
135 .register_status_notify = stingray_wifi_status_register,
136 .embedded_sdio = &stingray_wifi_emb_data,
143 static int stingray_wifi_set_carddetect(int val)
145 pr_debug("%s: %d\n", __func__, val);
146 stingray_wifi_cd = val;
147 if (wifi_status_cb) {
148 wifi_status_cb(val, wifi_status_cb_devid);
150 pr_warning("%s: Nobody to notify\n", __func__);
154 static int stingray_wifi_power_state;
156 static int stingray_wifi_power(int on)
158 pr_debug("%s: %d\n", __func__, on);
161 gpio_set_value(STINGRAY_WLAN_PWR, on);
163 gpio_set_value(STINGRAY_WLAN_RST, on);
166 stingray_wifi_power_state = on;
170 static int stingray_wifi_reset_state;
172 static int stingray_wifi_reset(int on)
174 pr_debug("%s: do nothing\n", __func__);
175 stingray_wifi_reset_state = on;
179 static unsigned char stingray_mac_addr[IFHWADDRLEN] = { 0,0x90,0x4c,0,0,0 };
181 static int __init parse_tag_wlan_mac(const struct tag *tag)
183 unsigned char *dptr = (unsigned char *)(&tag->u);
185 #ifdef ATAG_STINGRAY_MAC_DEBUG
189 size = min((tag->hdr.size - 2) * sizeof(__u32), (unsigned)IFHWADDRLEN);
190 #ifdef ATAG_STINGRAY_MAC_DEBUG
191 printk("WiFi MAC Addr [%d] = 0x%x\n", tag->hdr.size, tag->hdr.tag);
192 for(i=0;(i < size);i++) {
193 printk(" %02x", dptr[i]);
197 memcpy(stingray_mac_addr, dptr, size);
201 __tagtable(ATAG_STINGRAY_MAC, parse_tag_wlan_mac);
203 static int stingray_wifi_get_mac_addr(unsigned char *buf)
210 if ((stingray_mac_addr[4] == 0) && (stingray_mac_addr[5] == 0)) {
211 srandom32((uint)jiffies);
212 rand_mac = random32();
213 stingray_mac_addr[3] = (unsigned char)rand_mac;
214 stingray_mac_addr[4] = (unsigned char)(rand_mac >> 8);
215 stingray_mac_addr[5] = (unsigned char)(rand_mac >> 16);
217 memcpy(buf, stingray_mac_addr, IFHWADDRLEN);
221 static struct wifi_platform_data stingray_wifi_control = {
222 .set_power = stingray_wifi_power,
223 .set_reset = stingray_wifi_reset,
224 .set_carddetect = stingray_wifi_set_carddetect,
225 .mem_prealloc = stingray_wifi_mem_prealloc,
226 .get_mac_addr = stingray_wifi_get_mac_addr,
229 static struct platform_device stingray_wifi_device = {
230 .name = "bcm4329_wlan",
232 .num_resources = ARRAY_SIZE(stingray_wifi_resources),
233 .resource = stingray_wifi_resources,
235 .platform_data = &stingray_wifi_control,
239 static void __init stingray_wlan_gpio(void)
241 tegra_gpio_enable(STINGRAY_WLAN_PWR);
242 gpio_request(STINGRAY_WLAN_PWR, "wlan_pwr");
243 gpio_direction_output(STINGRAY_WLAN_PWR, 0);
245 tegra_gpio_enable(STINGRAY_WLAN_RST);
246 gpio_request(STINGRAY_WLAN_RST, "wlan_rst");
247 gpio_direction_output(STINGRAY_WLAN_RST, 0);
249 tegra_gpio_enable(STINGRAY_WLAN_IRQ);
250 gpio_request(STINGRAY_WLAN_IRQ, "wlan_irq");
251 gpio_direction_input(STINGRAY_WLAN_IRQ);
254 int __init stingray_wlan_init(void)
256 pr_debug("%s: start\n", __func__);
257 stingray_wlan_gpio();
258 stingray_init_wifi_mem();
259 return platform_device_register(&stingray_wifi_device);