Bryan Huntsman | 3f2bc4d | 2011-08-16 17:27:22 -0700 | [diff] [blame] | 1 | /* linux/arch/arm/mach-msm/board-mahimahi-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 | |
| 14 | #include "board-mahimahi.h" |
| 15 | |
| 16 | int mahimahi_wifi_power(int on); |
| 17 | int mahimahi_wifi_reset(int on); |
| 18 | int mahimahi_wifi_set_carddetect(int on); |
| 19 | |
| 20 | #define PREALLOC_WLAN_NUMBER_OF_SECTIONS 4 |
| 21 | #define PREALLOC_WLAN_NUMBER_OF_BUFFERS 160 |
| 22 | #define PREALLOC_WLAN_SECTION_HEADER 24 |
| 23 | |
| 24 | #define WLAN_SECTION_SIZE_0 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 128) |
| 25 | #define WLAN_SECTION_SIZE_1 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 128) |
| 26 | #define WLAN_SECTION_SIZE_2 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 512) |
| 27 | #define WLAN_SECTION_SIZE_3 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 1024) |
| 28 | |
| 29 | #define WLAN_SKB_BUF_NUM 16 |
| 30 | |
| 31 | static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM]; |
| 32 | |
| 33 | typedef struct wifi_mem_prealloc_struct { |
| 34 | void *mem_ptr; |
| 35 | unsigned long size; |
| 36 | } wifi_mem_prealloc_t; |
| 37 | |
| 38 | static wifi_mem_prealloc_t wifi_mem_array[PREALLOC_WLAN_NUMBER_OF_SECTIONS] = { |
| 39 | { NULL, (WLAN_SECTION_SIZE_0 + PREALLOC_WLAN_SECTION_HEADER) }, |
| 40 | { NULL, (WLAN_SECTION_SIZE_1 + PREALLOC_WLAN_SECTION_HEADER) }, |
| 41 | { NULL, (WLAN_SECTION_SIZE_2 + PREALLOC_WLAN_SECTION_HEADER) }, |
| 42 | { NULL, (WLAN_SECTION_SIZE_3 + PREALLOC_WLAN_SECTION_HEADER) } |
| 43 | }; |
| 44 | |
| 45 | static void *mahimahi_wifi_mem_prealloc(int section, unsigned long size) |
| 46 | { |
| 47 | if (section == PREALLOC_WLAN_NUMBER_OF_SECTIONS) |
| 48 | return wlan_static_skb; |
| 49 | if ((section < 0) || (section > PREALLOC_WLAN_NUMBER_OF_SECTIONS)) |
| 50 | return NULL; |
| 51 | if (wifi_mem_array[section].size < size) |
| 52 | return NULL; |
| 53 | return wifi_mem_array[section].mem_ptr; |
| 54 | } |
| 55 | |
| 56 | int __init mahimahi_init_wifi_mem(void) |
| 57 | { |
| 58 | int i; |
| 59 | |
| 60 | for(i=0;( i < WLAN_SKB_BUF_NUM );i++) { |
| 61 | if (i < (WLAN_SKB_BUF_NUM/2)) |
| 62 | wlan_static_skb[i] = dev_alloc_skb(4096); |
| 63 | else |
| 64 | wlan_static_skb[i] = dev_alloc_skb(8192); |
| 65 | } |
| 66 | for(i=0;( i < PREALLOC_WLAN_NUMBER_OF_SECTIONS );i++) { |
| 67 | wifi_mem_array[i].mem_ptr = kmalloc(wifi_mem_array[i].size, |
| 68 | GFP_KERNEL); |
| 69 | if (wifi_mem_array[i].mem_ptr == NULL) |
| 70 | return -ENOMEM; |
| 71 | } |
| 72 | return 0; |
| 73 | } |
| 74 | |
| 75 | static struct resource mahimahi_wifi_resources[] = { |
| 76 | [0] = { |
| 77 | .name = "bcm4329_wlan_irq", |
| 78 | .start = MSM_GPIO_TO_INT(MAHIMAHI_GPIO_WIFI_IRQ), |
| 79 | .end = MSM_GPIO_TO_INT(MAHIMAHI_GPIO_WIFI_IRQ), |
| 80 | .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE, |
| 81 | }, |
| 82 | }; |
| 83 | |
| 84 | static struct wifi_platform_data mahimahi_wifi_control = { |
| 85 | .set_power = mahimahi_wifi_power, |
| 86 | .set_reset = mahimahi_wifi_reset, |
| 87 | .set_carddetect = mahimahi_wifi_set_carddetect, |
| 88 | .mem_prealloc = mahimahi_wifi_mem_prealloc, |
| 89 | }; |
| 90 | |
| 91 | static struct platform_device mahimahi_wifi_device = { |
| 92 | .name = "bcm4329_wlan", |
| 93 | .id = 1, |
| 94 | .num_resources = ARRAY_SIZE(mahimahi_wifi_resources), |
| 95 | .resource = mahimahi_wifi_resources, |
| 96 | .dev = { |
| 97 | .platform_data = &mahimahi_wifi_control, |
| 98 | }, |
| 99 | }; |
| 100 | |
| 101 | extern unsigned char *get_wifi_nvs_ram(void); |
| 102 | extern int wifi_calibration_size_set(void); |
| 103 | |
| 104 | static unsigned mahimahi_wifi_update_nvs(char *str, int add_flag) |
| 105 | { |
| 106 | #define NVS_LEN_OFFSET 0x0C |
| 107 | #define NVS_DATA_OFFSET 0x40 |
| 108 | unsigned char *ptr; |
| 109 | unsigned len; |
| 110 | |
| 111 | if (!str) |
| 112 | return -EINVAL; |
| 113 | ptr = get_wifi_nvs_ram(); |
| 114 | /* Size in format LE assumed */ |
| 115 | memcpy(&len, ptr + NVS_LEN_OFFSET, sizeof(len)); |
| 116 | /* if the last byte in NVRAM is 0, trim it */ |
| 117 | if (ptr[NVS_DATA_OFFSET + len - 1] == 0) |
| 118 | len -= 1; |
| 119 | if (add_flag) { |
| 120 | strcpy(ptr + NVS_DATA_OFFSET + len, str); |
| 121 | len += strlen(str); |
| 122 | } else { |
| 123 | if (strnstr(ptr + NVS_DATA_OFFSET, str, len)) |
| 124 | len -= strlen(str); |
| 125 | } |
| 126 | memcpy(ptr + NVS_LEN_OFFSET, &len, sizeof(len)); |
| 127 | wifi_calibration_size_set(); |
| 128 | return 0; |
| 129 | } |
| 130 | |
| 131 | static int __init mahimahi_wifi_init(void) |
| 132 | { |
| 133 | int ret; |
| 134 | |
| 135 | if (!machine_is_mahimahi()) |
| 136 | return 0; |
| 137 | |
| 138 | printk("%s: start\n", __func__); |
| 139 | mahimahi_wifi_update_nvs("sd_oobonly=1\r\n", 0); |
| 140 | mahimahi_wifi_update_nvs("btc_params70=0x32\r\n", 1); |
| 141 | mahimahi_init_wifi_mem(); |
| 142 | ret = platform_device_register(&mahimahi_wifi_device); |
| 143 | return ret; |
| 144 | } |
| 145 | |
| 146 | late_initcall(mahimahi_wifi_init); |