/* linux/arch/arm/mach-msm/board-mahimahi-wifi.c */ #include #include #include #include #include #include #include #include #include #include #include "board-mahimahi.h" int mahimahi_wifi_power(int on); int mahimahi_wifi_reset(int on); int mahimahi_wifi_set_carddetect(int on); #define PREALLOC_WLAN_NUMBER_OF_SECTIONS 4 #define PREALLOC_WLAN_NUMBER_OF_BUFFERS 160 #define PREALLOC_WLAN_SECTION_HEADER 24 #define WLAN_SECTION_SIZE_0 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 128) #define WLAN_SECTION_SIZE_1 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 128) #define WLAN_SECTION_SIZE_2 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 512) #define WLAN_SECTION_SIZE_3 (PREALLOC_WLAN_NUMBER_OF_BUFFERS * 1024) #define WLAN_SKB_BUF_NUM 16 static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM]; typedef struct wifi_mem_prealloc_struct { void *mem_ptr; unsigned long size; } wifi_mem_prealloc_t; static wifi_mem_prealloc_t wifi_mem_array[PREALLOC_WLAN_NUMBER_OF_SECTIONS] = { { NULL, (WLAN_SECTION_SIZE_0 + PREALLOC_WLAN_SECTION_HEADER) }, { NULL, (WLAN_SECTION_SIZE_1 + PREALLOC_WLAN_SECTION_HEADER) }, { NULL, (WLAN_SECTION_SIZE_2 + PREALLOC_WLAN_SECTION_HEADER) }, { NULL, (WLAN_SECTION_SIZE_3 + PREALLOC_WLAN_SECTION_HEADER) } }; static void *mahimahi_wifi_mem_prealloc(int section, unsigned long size) { if (section == PREALLOC_WLAN_NUMBER_OF_SECTIONS) return wlan_static_skb; if ((section < 0) || (section > PREALLOC_WLAN_NUMBER_OF_SECTIONS)) return NULL; if (wifi_mem_array[section].size < size) return NULL; return wifi_mem_array[section].mem_ptr; } int __init mahimahi_init_wifi_mem(void) { int i; for(i=0;( i < WLAN_SKB_BUF_NUM );i++) { if (i < (WLAN_SKB_BUF_NUM/2)) wlan_static_skb[i] = dev_alloc_skb(4096); else wlan_static_skb[i] = dev_alloc_skb(8192); } for(i=0;( i < PREALLOC_WLAN_NUMBER_OF_SECTIONS );i++) { wifi_mem_array[i].mem_ptr = kmalloc(wifi_mem_array[i].size, GFP_KERNEL); if (wifi_mem_array[i].mem_ptr == NULL) return -ENOMEM; } return 0; } static struct resource mahimahi_wifi_resources[] = { [0] = { .name = "bcm4329_wlan_irq", .start = MSM_GPIO_TO_INT(MAHIMAHI_GPIO_WIFI_IRQ), .end = MSM_GPIO_TO_INT(MAHIMAHI_GPIO_WIFI_IRQ), .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE, }, }; static struct wifi_platform_data mahimahi_wifi_control = { .set_power = mahimahi_wifi_power, .set_reset = mahimahi_wifi_reset, .set_carddetect = mahimahi_wifi_set_carddetect, .mem_prealloc = mahimahi_wifi_mem_prealloc, }; static struct platform_device mahimahi_wifi_device = { .name = "bcm4329_wlan", .id = 1, .num_resources = ARRAY_SIZE(mahimahi_wifi_resources), .resource = mahimahi_wifi_resources, .dev = { .platform_data = &mahimahi_wifi_control, }, }; extern unsigned char *get_wifi_nvs_ram(void); extern int wifi_calibration_size_set(void); static unsigned mahimahi_wifi_update_nvs(char *str, int add_flag) { #define NVS_LEN_OFFSET 0x0C #define NVS_DATA_OFFSET 0x40 unsigned char *ptr; unsigned len; if (!str) return -EINVAL; ptr = get_wifi_nvs_ram(); /* Size in format LE assumed */ memcpy(&len, ptr + NVS_LEN_OFFSET, sizeof(len)); /* if the last byte in NVRAM is 0, trim it */ if (ptr[NVS_DATA_OFFSET + len - 1] == 0) len -= 1; if (add_flag) { strcpy(ptr + NVS_DATA_OFFSET + len, str); len += strlen(str); } else { if (strnstr(ptr + NVS_DATA_OFFSET, str, len)) len -= strlen(str); } memcpy(ptr + NVS_LEN_OFFSET, &len, sizeof(len)); wifi_calibration_size_set(); return 0; } static int __init mahimahi_wifi_init(void) { int ret; if (!machine_is_mahimahi()) return 0; printk("%s: start\n", __func__); mahimahi_wifi_update_nvs("sd_oobonly=1\r\n", 0); mahimahi_wifi_update_nvs("btc_params70=0x32\r\n", 1); mahimahi_init_wifi_mem(); ret = platform_device_register(&mahimahi_wifi_device); return ret; } late_initcall(mahimahi_wifi_init);