temp revert rk change
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-tegra / board-olympus-wifi.c
1 /* linux/arch/arm/mach-msm/board-olympus-wifi.c
2 */
3 #include <linux/kernel.h>
4 #include <linux/init.h>
5 #include <linux/platform_device.h>
6 #include <linux/delay.h>
7 #include <linux/err.h>
8 #include <asm/mach-types.h>
9 #include <asm/gpio.h>
10 #include <asm/io.h>
11 #include <linux/skbuff.h>
12 #include <linux/wlan_plat.h>
13 #include <mach/sdhci.h>
14
15 #include "board-olympus.h"
16 #include "gpio-names.h"
17
18 #define OLYMPUS_WLAN_IRQ        TEGRA_GPIO_PU5
19 #define OLYMPUS_WLAN_PWR        TEGRA_GPIO_PU3
20 #define OLYMPUS_WLAN_RST        TEGRA_GPIO_PU2
21
22 #define PREALLOC_WLAN_NUMBER_OF_SECTIONS        4
23 #define PREALLOC_WLAN_NUMBER_OF_BUFFERS         160
24 #define PREALLOC_WLAN_SECTION_HEADER            24
25
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)
30
31 #define WLAN_SKB_BUF_NUM        16
32
33 static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];
34
35 typedef struct wifi_mem_prealloc_struct {
36         void *mem_ptr;
37         unsigned long size;
38 } wifi_mem_prealloc_t;
39
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) }
45 };
46
47 static void *olympus_wifi_mem_prealloc(int section, unsigned long size)
48 {
49         if (section == PREALLOC_WLAN_NUMBER_OF_SECTIONS)
50                 return wlan_static_skb;
51         if ((section < 0) || (section > PREALLOC_WLAN_NUMBER_OF_SECTIONS))
52                 return NULL;
53         if (wifi_mem_array[section].size < size)
54                 return NULL;
55         return wifi_mem_array[section].mem_ptr;
56 }
57
58 int __init olympus_init_wifi_mem(void)
59 {
60         int i;
61
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);
65                 else
66                         wlan_static_skb[i] = dev_alloc_skb(8192);
67         }
68         for(i=0;( i < PREALLOC_WLAN_NUMBER_OF_SECTIONS );i++) {
69                 wifi_mem_array[i].mem_ptr = kmalloc(wifi_mem_array[i].size,
70                                                         GFP_KERNEL);
71                 if (wifi_mem_array[i].mem_ptr == NULL)
72                         return -ENOMEM;
73         }
74         return 0;
75 }
76
77 static struct resource olympus_wifi_resources[] = {
78         [0] = {
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,
83         },
84 };
85
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
88   */
89 static struct embedded_sdio_data olympus_wifi_emb_data = {
90         .cccr   = {
91                 .sdio_vsn       = 2,
92                 .multi_block    = 1,
93                 .low_speed      = 0,
94                 .wide_bus       = 0,
95                 .high_power     = 1,
96                 .high_speed     = 1,
97         },
98 };
99
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;
103
104 static int olympus_wifi_status_register(
105                 void (*callback)(int card_present, void *dev_id),
106                 void *dev_id)
107 {
108         if (wifi_status_cb)
109                 return -EAGAIN;
110         wifi_status_cb = callback;
111         wifi_status_cb_devid = dev_id;
112         return 0;
113 }
114
115 static unsigned int olympus_wifi_status(struct device *dev)
116 {
117         return olympus_wifi_cd;
118 }
119
120 struct tegra_sdhci_platform_data olympus_wifi_data = {
121         .clk_id = NULL,
122         .force_hs = 0,
123         .mmc_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,
128         }
129 };
130
131 int olympus_wifi_set_carddetect(int val)
132 {
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);
137         } else
138                 pr_warning("%s: Nobody to notify\n", __func__);
139         return 0;
140 }
141
142 static int olympus_wifi_power_state;
143
144 int olympus_wifi_power(int on)
145 {
146         pr_debug("%s: %d\n", __func__, on);
147
148         mdelay(100);
149         gpio_set_value(OLYMPUS_WLAN_PWR, on);
150         mdelay(100);
151         gpio_set_value(OLYMPUS_WLAN_RST, on);
152         mdelay(200);
153
154         olympus_wifi_power_state = on;
155         return 0;
156 }
157
158 static int olympus_wifi_reset_state;
159
160 int olympus_wifi_reset(int on)
161 {
162         pr_debug("%s: do nothing\n", __func__);
163         olympus_wifi_reset_state = on;
164         return 0;
165 }
166
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,
172 };
173
174 static struct platform_device olympus_wifi_device = {
175         .name           = "bcm4329_wlan",
176         .id             = 1,
177         .num_resources  = ARRAY_SIZE(olympus_wifi_resources),
178         .resource       = olympus_wifi_resources,
179         .dev            = {
180                 .platform_data = &olympus_wifi_control,
181         },
182 };
183
184 static void __init olympus_wlan_gpio(void)
185 {
186         tegra_gpio_enable(OLYMPUS_WLAN_PWR);
187         gpio_request(OLYMPUS_WLAN_PWR, "wlan_pwr");
188         gpio_direction_output(OLYMPUS_WLAN_PWR, 0);
189
190         tegra_gpio_enable(OLYMPUS_WLAN_RST);
191         gpio_request(OLYMPUS_WLAN_RST, "wlan_rst");
192         gpio_direction_output(OLYMPUS_WLAN_RST, 0);
193
194         tegra_gpio_enable(OLYMPUS_WLAN_IRQ);
195         gpio_request(OLYMPUS_WLAN_IRQ, "wlan_irq");
196         gpio_direction_input(OLYMPUS_WLAN_IRQ);
197 }
198
199 int __init olympus_wlan_init(void)
200 {
201         pr_debug("%s: start\n", __func__);
202         olympus_wlan_gpio();
203         olympus_init_wifi_mem();
204         return platform_device_register(&olympus_wifi_device);
205 }