1 /* linux/arch/arm/mach-msm/board-olympus-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 <linux/skbuff.h>
12 #include <linux/wlan_plat.h>
13 #include <mach/sdhci.h>
15 #include "board-olympus.h"
16 #include "gpio-names.h"
18 #define OLYMPUS_WLAN_IRQ TEGRA_GPIO_PU5
19 #define OLYMPUS_WLAN_PWR TEGRA_GPIO_PU3
20 #define OLYMPUS_WLAN_RST TEGRA_GPIO_PU2
22 #define PREALLOC_WLAN_NUMBER_OF_SECTIONS 4
23 #define PREALLOC_WLAN_NUMBER_OF_BUFFERS 160
24 #define PREALLOC_WLAN_SECTION_HEADER 24
26 #define WLAN_SECTION_SIZE_0 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 128)
27 #define WLAN_SECTION_SIZE_1 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 128)
28 #define WLAN_SECTION_SIZE_2 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 512)
29 #define WLAN_SECTION_SIZE_3 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 1024)
31 #define WLAN_SKB_BUF_NUM 16
33 static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];
35 typedef struct wifi_mem_prealloc_struct {
38 } wifi_mem_prealloc_t;
40 static wifi_mem_prealloc_t wifi_mem_array[PREALLOC_WLAN_NUMBER_OF_SECTIONS] = {
41 { NULL, (WLAN_SECTION_SIZE_0 + PREALLOC_WLAN_SECTION_HEADER) },
42 { NULL, (WLAN_SECTION_SIZE_1 + PREALLOC_WLAN_SECTION_HEADER) },
43 { NULL, (WLAN_SECTION_SIZE_2 + PREALLOC_WLAN_SECTION_HEADER) },
44 { NULL, (WLAN_SECTION_SIZE_3 + PREALLOC_WLAN_SECTION_HEADER) }
47 static void *olympus_wifi_mem_prealloc(int section, unsigned long size)
49 if (section == PREALLOC_WLAN_NUMBER_OF_SECTIONS)
50 return wlan_static_skb;
51 if ((section < 0) || (section > PREALLOC_WLAN_NUMBER_OF_SECTIONS))
53 if (wifi_mem_array[section].size < size)
55 return wifi_mem_array[section].mem_ptr;
58 int __init olympus_init_wifi_mem(void)
62 for(i=0;( i < WLAN_SKB_BUF_NUM );i++) {
63 if (i < (WLAN_SKB_BUF_NUM/2))
64 wlan_static_skb[i] = dev_alloc_skb(4096);
66 wlan_static_skb[i] = dev_alloc_skb(8192);
68 for(i=0;( i < PREALLOC_WLAN_NUMBER_OF_SECTIONS );i++) {
69 wifi_mem_array[i].mem_ptr = kmalloc(wifi_mem_array[i].size,
71 if (wifi_mem_array[i].mem_ptr == NULL)
77 static struct resource olympus_wifi_resources[] = {
79 .name = "bcm4329_wlan_irq",
80 .start = TEGRA_GPIO_TO_IRQ(OLYMPUS_WLAN_IRQ),
81 .end = TEGRA_GPIO_TO_IRQ(OLYMPUS_WLAN_IRQ),
82 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
86 /* BCM4329 returns wrong sdio_vsn(1) when we read cccr,
87 * we use predefined value (sdio_vsn=2) here to initial sdio driver well
89 static struct embedded_sdio_data olympus_wifi_emb_data = {
100 static int olympus_wifi_cd = 0; /* WIFI virtual 'card detect' status */
101 static void (*wifi_status_cb)(int card_present, void *dev_id);
102 static void *wifi_status_cb_devid;
104 static int olympus_wifi_status_register(
105 void (*callback)(int card_present, void *dev_id),
110 wifi_status_cb = callback;
111 wifi_status_cb_devid = dev_id;
115 static unsigned int olympus_wifi_status(struct device *dev)
117 return olympus_wifi_cd;
120 struct tegra_sdhci_platform_data olympus_wifi_data = {
124 .ocr_mask = MMC_VDD_165_195,
125 .status = olympus_wifi_status,
126 .register_status_notify = olympus_wifi_status_register,
127 .embedded_sdio = &olympus_wifi_emb_data,
131 int olympus_wifi_set_carddetect(int val)
133 pr_debug("%s: %d\n", __func__, val);
134 olympus_wifi_cd = val;
135 if (wifi_status_cb) {
136 wifi_status_cb(val, wifi_status_cb_devid);
138 pr_warning("%s: Nobody to notify\n", __func__);
142 static int olympus_wifi_power_state;
144 int olympus_wifi_power(int on)
146 pr_debug("%s: %d\n", __func__, on);
149 gpio_set_value(OLYMPUS_WLAN_PWR, on);
151 gpio_set_value(OLYMPUS_WLAN_RST, on);
154 olympus_wifi_power_state = on;
158 static int olympus_wifi_reset_state;
160 int olympus_wifi_reset(int on)
162 pr_debug("%s: do nothing\n", __func__);
163 olympus_wifi_reset_state = on;
167 static struct wifi_platform_data olympus_wifi_control = {
168 .set_power = olympus_wifi_power,
169 .set_reset = olympus_wifi_reset,
170 .set_carddetect = olympus_wifi_set_carddetect,
171 .mem_prealloc = olympus_wifi_mem_prealloc,
174 static struct platform_device olympus_wifi_device = {
175 .name = "bcm4329_wlan",
177 .num_resources = ARRAY_SIZE(olympus_wifi_resources),
178 .resource = olympus_wifi_resources,
180 .platform_data = &olympus_wifi_control,
184 static void __init olympus_wlan_gpio(void)
186 tegra_gpio_enable(OLYMPUS_WLAN_PWR);
187 gpio_request(OLYMPUS_WLAN_PWR, "wlan_pwr");
188 gpio_direction_output(OLYMPUS_WLAN_PWR, 0);
190 tegra_gpio_enable(OLYMPUS_WLAN_RST);
191 gpio_request(OLYMPUS_WLAN_RST, "wlan_rst");
192 gpio_direction_output(OLYMPUS_WLAN_RST, 0);
194 tegra_gpio_enable(OLYMPUS_WLAN_IRQ);
195 gpio_request(OLYMPUS_WLAN_IRQ, "wlan_irq");
196 gpio_direction_input(OLYMPUS_WLAN_IRQ);
199 int __init olympus_wlan_init(void)
201 pr_debug("%s: start\n", __func__);
203 olympus_init_wifi_mem();
204 return platform_device_register(&olympus_wifi_device);