From: notaz Date: Mon, 9 Feb 2015 00:03:24 +0000 (+0200) Subject: port to 3.2 X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c4e04f49cb773305757376d3109dcff2d6283b67;p=pandora-wifi.git port to 3.2 --- diff --git a/sta_dk/pform/linux/build/Makefile b/sta_dk/pform/linux/build/Makefile index ee32f2f..ce1a5c2 100644 --- a/sta_dk/pform/linux/build/Makefile +++ b/sta_dk/pform/linux/build/Makefile @@ -10,6 +10,7 @@ NO_ARCH_STRCMP ?= y NO_USERMODE_WORKAROUND ?= n MEM_ALLOC_TRACE ?= n TIWLAN_INIT_FILE_SUPPORT ?= y +USE_SDIO_DRIVER ?= y @@ -62,7 +63,9 @@ OS_SRCS += \ $(DK_ROOT)/pform/linux/src/ioctl_utils.c \ $(DK_ROOT)/pform/linux/src/osRgstry_parser.c \ $(DK_ROOT)/pform/linux/src/ipc_k.c \ - $(DK_ROOT)/pform/linux/src/proc_stat.c + $(DK_ROOT)/pform/linux/src/proc_stat.c \ + $(DK_ROOT)/pform/linux/src/tnetw_sdio.c \ + $(DK_ROOT)/pform/linux/src/mmc_tnetw1150_api.c ifeq ($(DRIVER_PROFILING),y) OS_SRCS += $(DK_ROOT)/pform/linux/src/tiwlan_profile.c @@ -141,6 +144,10 @@ ifeq ($(MEM_ALLOC_TRACE),y) EXTRA_CFLAGS += -D TI_MEM_ALLOC_TRACE endif +ifeq ($(USE_SDIO_DRIVER),y) + EXTRA_CFLAGS += -D USE_SDIO_DRIVER +endif + diff --git a/sta_dk/pform/linux/inc/esta_drv.h b/sta_dk/pform/linux/inc/esta_drv.h index 635e870..3b23559 100644 --- a/sta_dk/pform/linux/inc/esta_drv.h +++ b/sta_dk/pform/linux/inc/esta_drv.h @@ -40,6 +40,7 @@ #include #include #include +#include //#include diff --git a/sta_dk/pform/linux/src/esta_drv.c b/sta_dk/pform/linux/src/esta_drv.c index 2066302..a77a3cb 100644 --- a/sta_dk/pform/linux/src/esta_drv.c +++ b/sta_dk/pform/linux/src/esta_drv.c @@ -99,6 +99,18 @@ #include "Ethernet.h" #include "tiwlan_profile.h" +#ifdef USE_SDIO_DRIVER +#include +#include +#include +#include +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) +#include +#endif + +#if 0 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28) #define io_p2v(pa) ((pa) + IO_OFFSET)/* Works for the entire IO Map */ typedef struct { volatile u32 offset[4096]; } __regbase32; @@ -188,6 +200,7 @@ typedef struct { volatile u32 offset[4096]; } __regbase32; #define GPIO3_LEVELDETECT0 GPIO3_REG32(0x040) #define GPIO3_DEBOUNCENABLE GPIO3_REG32(0x050) #define GPIO3_DEBOUNCINGTIME GPIO3_REG32(0x054) +#endif /* Drivers list */ static LIST_HEAD(tiwlan_drv_list); @@ -695,6 +708,17 @@ struct net_device_stats * tiwlan_drv_net_get_stats(struct net_device * dev) return &drv->stats; } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)) +extern int ti1610_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); + +static struct net_device_ops netdev_ops = { + .ndo_open = tiwlan_drv_net_open, + .ndo_stop = tiwlan_drv_net_stop, + .ndo_start_xmit = tiwlan_drv_dummy_net_xmit, + .ndo_get_stats = tiwlan_drv_net_get_stats, + .ndo_do_ioctl = ti1610_do_ioctl, +}; +#endif static int setup_netif(tiwlan_net_dev_t *drv) { @@ -715,10 +739,14 @@ static int setup_netif(tiwlan_net_dev_t *drv) #ifndef mike tiwlan_iwhandler_init(dev); #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)) + dev->netdev_ops = &netdev_ops; +#else dev->open = tiwlan_drv_net_open; dev->stop = tiwlan_drv_net_stop; dev->hard_start_xmit = tiwlan_drv_dummy_net_xmit; dev->get_stats = tiwlan_drv_net_get_stats; +#endif dev->tx_queue_len = 100; res = tiwlan_ioctl_init(dev); @@ -1140,6 +1168,11 @@ int tiwlan_init_drv (tiwlan_net_dev_t *drv, tiwlan_dev_init_t *init_info) pWLAN_Images, init_table, (macAddress_t *) &drv->adapter.CurrentAddr); + if (drv->adapter.CoreHalCtx == NULL) + { + printk("configMgr_create failed\n"); + return -1; + } drv->interrupt_pending = 0; drv->dma_done = 0; @@ -1167,8 +1200,10 @@ int tiwlan_init_drv (tiwlan_net_dev_t *drv, tiwlan_dev_init_t *init_info) } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) set_irq_type (drv->irq, IRQT_FALLING); +#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) + set_irq_type (drv->irq, IRQ_TYPE_EDGE_FALLING); #else - set_irq_type (drv->irq, IRQ_TYPE_EDGE_FALLING); + irq_set_irq_type(drv->irq, IRQ_TYPE_EDGE_FALLING); #endif disable_irq (drv->irq); spin_unlock_irqrestore (&drv->lock, flags); @@ -1229,7 +1264,11 @@ int tiwlan_init_drv (tiwlan_net_dev_t *drv, tiwlan_dev_init_t *init_info) } /* Finalize network interface setup */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)) + netdev_ops.ndo_start_xmit = tiwlan_drv_net_xmit; +#else drv->netdev->hard_start_xmit = tiwlan_drv_net_xmit; +#endif memcpy (drv->netdev->dev_addr, drv->adapter.CurrentAddr, MAC_ADDR_LEN); drv->netdev->addr_len = MAC_ADDR_LEN; @@ -1504,15 +1543,120 @@ static struct pci_driver tnetw1130_pci_driver = { #ifdef TIWLAN_OMAP1610 int omap1610_drv_create(void) { + int irq = TIWLAN_OMAP1610_IRQ; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) + const struct wl12xx_platform_data *wl12xx_board_data; + irq = -1; + wl12xx_board_data = wl12xx_get_platform_data(); + if (!IS_ERR(wl12xx_board_data)) + irq = wl12xx_board_data->irq; + if (irq < 0) + return -1; +#endif + omap_memif_init(); return tiwlan_create_drv(TIWLAN_OMAP1610_REGBASE, TIWLAN_OMAP1610_REGSIZE, TIWLAN_OMAP1610_MEMBASE, TIWLAN_OMAP1610_MEMSIZE, - 0, TIWLAN_OMAP1610_IRQ, NULL, NULL); + 0, irq, NULL, NULL); } #endif /* #ifdef TIWLAN_OMAP1610 */ +#ifdef USE_SDIO_DRIVER +extern void SDIO_SetFunc( struct sdio_func * ); + +int tiwlan_sdio_init(struct sdio_func *func) +{ + int rc; + + rc = sdio_enable_func(func); + if (rc) + return rc; + + rc = sdio_set_block_size(func, 512); + if( rc ) { + sdio_disable_func(func); + } + return rc; +} + +static int tiwlan_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) +{ + int rc; + + SDIO_SetFunc( NULL ); + if (func->vendor != VENDOR_ID_TI || func->device != DEVICE_ID_TI_WLAN) + return -ENODEV; + + printk(KERN_INFO + "TIWLAN: Found SDIO controller (vendor 0x%x, device 0x%x)\n", + func->vendor, func->device); + + sdio_claim_host(func); + + rc = tiwlan_sdio_init(func); + if (rc) + goto err2; + + SDIO_SetFunc( func ); + + rc = omap1610_drv_create(); + + printk(KERN_INFO "TIWLAN: Driver initialized (rc %d)\n", rc); + //complete(&sdio_wait); + return rc; + +err2: + sdio_release_host(func); + //complete(&sdio_wait); + printk(KERN_ERR "TIWLAN: SDIO failure (err %d)\n", rc); + return rc; +} + +static void tiwlan_sdio_remove(struct sdio_func *func) +{ + printk(KERN_DEBUG "TIWLAN: Releasing SDIO resources\n"); + sdio_disable_func(func); + sdio_release_host(func); + printk(KERN_DEBUG "TIWLAN: SDIO resources released\n"); +} + +static const struct sdio_device_id tiwlan_sdio_ids[] = { + { SDIO_DEVICE(VENDOR_ID_TI, DEVICE_ID_TI_WLAN) }, + { }, +}; + +MODULE_DEVICE_TABLE(sdio, tiwlan_sdio_ids); + +static int tiwlan_suspend(struct device *dev) +{ + /* + * Tell MMC/SDIO core it's OK to power down the card + * (if it isn't already), but not to remove it completely. + */ + return 0; +} + +static int tiwlan_resume(struct device *dev) +{ + return 0; +} + +static const struct dev_pm_ops tiwlan_sdio_pm_ops = { + .suspend = tiwlan_suspend, + .resume = tiwlan_resume, +}; + +static struct sdio_driver tiwlan_sdio_drv = { + .probe = tiwlan_sdio_probe, + .remove = tiwlan_sdio_remove, + .name = "sdio_tiwlan", + .id_table = tiwlan_sdio_ids, + .drv.pm = &tiwlan_sdio_pm_ops, +}; +#endif + #define PANDORA_WIFI_GPIO 23 extern void omap_mmc_fake_detect_mmc3(int is_in); @@ -1524,10 +1668,12 @@ static int __init tiwlan_module_init(void) if (packed_struct_tst()) ;/*IT: return -EINVAL; */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) gpio_set_value(PANDORA_WIFI_GPIO, 1); msleep(100); omap_mmc_fake_detect_mmc3(1); msleep(100); +#endif tiwlan_deb_entry=create_proc_entry("mem", 0644, NULL); if (tiwlan_deb_entry == NULL) @@ -1535,7 +1681,16 @@ static int __init tiwlan_module_init(void) tiwlan_deb_entry->read_proc=tiwlan_deb_read_proc; tiwlan_deb_entry->write_proc=tiwlan_deb_write_proc; -#ifdef TIWLAN_CARDBUS +#ifdef USE_SDIO_DRIVER + { + int rc = 0; + rc = sdio_register_driver(&tiwlan_sdio_drv); + if (rc < 0) + printk(KERN_ERR "sdio register failed (%d)\n", rc); + /* omap1610_drv_create() called by probe */ + return rc; + } +#elif defined(TIWLAN_CARDBUS) { int rc = 0; if ((rc=pci_register_driver(&tnetw1130_pci_driver)) < 0) @@ -1564,6 +1719,9 @@ static void __exit tiwlan_module_cleanup(void) #ifdef TIWLAN_CARDBUS pci_unregister_driver(&tnetw1130_pci_driver); +#endif +#ifdef USE_SDIO_DRIVER + sdio_unregister_driver(&tiwlan_sdio_drv); #endif list_for_each_safe(l, tmp, &tiwlan_drv_list) { @@ -1572,9 +1730,12 @@ static void __exit tiwlan_module_cleanup(void) } remove_proc_entry("mem", NULL); printk(KERN_INFO "TI WLAN: driver unloaded\n"); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) gpio_set_value(PANDORA_WIFI_GPIO, 0); msleep(100); omap_mmc_fake_detect_mmc3(0); +#endif } module_init(tiwlan_module_init); diff --git a/sta_dk/pform/linux/src/ioctl_list.c b/sta_dk/pform/linux/src/ioctl_list.c index 971b779..89ee550 100644 --- a/sta_dk/pform/linux/src/ioctl_list.c +++ b/sta_dk/pform/linux/src/ioctl_list.c @@ -251,7 +251,9 @@ if( !extra ) int tiwlan_ioctl_init( struct net_device *dev ) { +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)) dev->do_ioctl = ti1610_do_ioctl; +#endif return 0; } diff --git a/sta_dk/pform/linux/src/mmc_tnetw1150_api.c b/sta_dk/pform/linux/src/mmc_tnetw1150_api.c new file mode 100644 index 0000000..5915f6a --- /dev/null +++ b/sta_dk/pform/linux/src/mmc_tnetw1150_api.c @@ -0,0 +1,550 @@ +/* mmc_tnetw1150_api.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Copyright © Texas Instruments Incorporated (Oct 2005) + * THIS CODE/PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDED BUT NOT LIMITED TO , THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * This program has been modified from its original operation by Texas + * Instruments Incorporated. These changes are covered under version 2 + * of the GNU General Public License, dated June 1991. + * + * Copyright © Google Inc (Feb 2008) + */ +/*-------------------------------------------------------------------*/ +#ifdef USE_SDIO_DRIVER + +#include +#include +#include +#include "mmc_tnetw1150_api.h" +#include + +#include +#include + +#define SDIO_INVALID_PERIPHERAL_ADDRESS 0x1FFFF + +/* CCCR 0x000000 - 0x0000ff */ +/* Function Basic Register (Function 1) 0x000100 - 0x0001ff */ + /* 0x101 - Function 1 Extended standard I/O device type code */ + /* 0x102 - RFU[4-0] EnableHighPower Supports High-Power[1-0] SHP[0] */ + /* 0x103 - 0x108 - RFU */ + /* 0x109 - 0x10b - Pointer to Function 1 Card Information Structure */ + /* 0x10c - 0x10e - Pointer to Function 1 Code Storage Area */ + /* 0x10f - Data access window to Function 1 Code Storage Area */ + /* 0x110 - 0x111 - I/O block size for Function 1 */ + /* 0x112 - 0x1ff - RFU */ +/* Function Basic Register (Function 2) 0x000200 - 0x0002ff */ +/* Function Basic Register (Function 3) 0x000300 - 0x0003ff */ +/* Function Basic Register (Function 4) 0x000400 - 0x0004ff */ +/* Function Basic Register (Function 5) 0x000500 - 0x0005ff */ +/* Function Basic Register (Function 6) 0x000600 - 0x0006ff */ +/* Function Basic Register (Function 7) 0x000700 - 0x0007ff */ +/* RFU 0x000800 - 0x000fff */ +/* CIS common and per-function area 0x001000 - 0x017fff */ +/* RFU 0x018000 - 0x01ffff */ +#define SDIO_FUNC1_OFFSET 0x1FFC0 + +typedef struct +{ + Peripheral_Address mem_start_addr; + Peripheral_Address mem_part_size; + Peripheral_Address mem_end_addr; + Peripheral_Address reg_start_addr; + Peripheral_Address reg_part_size; + Peripheral_Address reg_end_addr; +} SDIO_TNETW_partitions; +static SDIO_TNETW_partitions TNETW_table; + +static SDIO_TNETWConfigParams TNETW_params; + +#ifdef CONFIG_MMC_TNET_INFO +typedef struct { + u8 scr_space[SDIO_FUNC1_OFFSET]; /* 0x000000 - 0x01ffbf; + 131072B(128kB)-64B=131008B(0x01ffc0) */ + u32 amap_size1; /* 0x01ffc0 */ + u32 amap_offset1; /* 0x01ffc4 */ + u32 amap_size2; /* 0x01ffc8 */ + u32 amap_offset2; /* 0x01ffcc */ + u32 amap_size3; /* 0x01ffd0 */ + u32 amap_offset3; /* 0x01ffd4 */ + u32 amap_offset4; /* 0x01ffd8 */ + u32 cis_offset; /* 0x01ffdc - Card Information Structure */ + u32 csa_offset; /* 0x01ffe0 - Code Storage Area */ + u8 filler[16]; /* 0x01ffe4 - 0x01fff3 */ + u32 wr_err_len; /* 0x01fff4 */ + u32 wr_err_addr; /* 0x01fff8 */ + u32 status; /* 0x01fffc */ +} SDIO_FUNC1AddressMap; +SDIO_FUNC1AddressMap mapping; + +int sdio_tnetw1150_dump(int count) +{ + unsigned long from; + unsigned long br_offset; + unsigned long offset=0; + unsigned long p1_offset=0; + unsigned long p2_offset=0; + struct mmc_request request; + int lines; + int i=0; + int second_part=0; + + printk("%s:\n", __FUNCTION__); +#define TNETW1150_OFFSET 1024 + from=TNETW1150_OFFSET*count; + if((from+TNETW1150_OFFSET)>(SDIO_FUNC1_OFFSET+64)) + return -1; + br_offset=TNETW1150_OFFSET*count; + if(br_offset>=TNETW_params.map_reg[0].reg_size) { + second_part=1; + p2_offset = SDIO_DRIVER_REG_PARTITION_START; + offset = TNETW_params.map_reg[1].scr_offset - TNETW_params.map_reg[0].reg_size; + } + else { + p1_offset += SDIO_DOWNLOAD_PARTITION_START; + offset = TNETW_params.map_reg[0].scr_offset; + } + + request.cmd=SD_IO_RW_DIRECT; + request.buffer_len=1; + request.nob=0; + request.block_len=0; + request.buffer=&mapping.scr_space[from]; + printk(" TNETW1150 try br_offset:0x%08lx offset:0x%08lx):\n", br_offset, offset); + do { + request.arg = SDIO_CMD52_READ(0,FUNCTION_SELECT_1,0,br_offset); + if(__submit_control_request(omap_mmc_dev_get_handle(), &request)!=SDIO_SUCCESS) + return SDIO_FAILURE; + udelay(1); + *request.buffer = (char)omap_readw(OMAP_MMC_RSP6); + i++; + request.buffer++; + br_offset++; + } while(i>7), ((buf3[0]&0x40)>>6), (buf3[1]&0x0f), buf3[1], (buf3[2]&0x07), buf_fbr[2], buf_fbr[1], buf_fbr[0], buf_fbr[5], buf_fbr[4], buf_fbr[3], buf_fbr[6], buf_fbr[8], buf_fbr[7]):0; + + *eof = 1; + return len; +} +#endif /*CONFIG_MMC_TNET_STATISTICS*/ + + +/* + Initialization of TNETW memory configuration. +*/ +extern int debug_level; +SDIO_Status SDIO_TNETWInit(SDIO_TNETWConfigParams *params) +{ + /* debug_level=3; */ + /* printk("%s\n", __FUNCTION__); */ + + memset(&TNETW_params, 0, sizeof(SDIO_TNETWConfigParams)); + + if(!params) { + /* printk("%s set to default\n", __FUNCTION__); */ + /* set to default value in case params is not presented */ + TNETW_params.num_of_parts = 2; + /* First time initialization */ + TNETW_params.map_reg[0].reg_size = SDIO_DOWNLOAD_PARTITION_SIZE; + TNETW_params.map_reg[0].scr_offset = SDIO_DOWNLOAD_PARTITION_START; + /* After firmware has been downloaded, data memory region + has to be re-initialized as following: + TNETW_params.map_reg[0].reg_size = SDIO_MEM_PARTITION_START; + TNETW_params.map_reg[0].scr_offset = SDIO_MEM_PARTITION_SIZE; + */ + TNETW_params.map_reg[1].reg_size = SDIO_REG_PARTITION_SIZE; + TNETW_params.map_reg[1].scr_offset = SDIO_REG_PARTITION_START; + } + else { + /* printk("%s: params->num_of_parts=%d\n", __FUNCTION__, params->num_of_parts); */ + /* validate input parameters */ + switch(params->num_of_parts) { + case 1: + if(params->map_reg[0].reg_size > AMAP_ONE_REGION) + return SDIO_FAILURE; + break; + case 2: + if((params->map_reg[0].reg_size + params->map_reg[1].reg_size) > AMAP_ONE_REGION) + return SDIO_FAILURE; + break; + case 3: + if((params->map_reg[0].reg_size + params->map_reg[1].reg_size + params->map_reg[2].reg_size) > AMAP_ONE_REGION) + return SDIO_FAILURE; + break; + case 4: + if((params->map_reg[0].reg_size + params->map_reg[1].reg_size + params->map_reg[2].reg_size + params->map_reg[3].reg_size) > AMAP_ONE_REGION) + return SDIO_FAILURE; + break; + default: + return SDIO_FAILURE; + } + memcpy(&TNETW_params, params, sizeof(SDIO_TNETWConfigParams)); + } + +#ifdef CONFIG_PROC_FS +#ifdef CONFIG_MMC_TNET_INFO + create_proc_read_entry("sdio_tnetw1150", 0, NULL, sdio_tnetw1150_read_proc, NULL); +#endif +#endif + + /* printk("%s completed\n", __FUNCTION__); */ + + return SDIO_SUCCESS; +} + +SDIO_Status SDIO_TNETWReset(SDIO_TNETWConfigParams *params) +{ + /* printk("%s\n", __FUNCTION__); */ + + memset(&TNETW_params, 0, sizeof(SDIO_TNETWConfigParams)); + + if(!params) { + /* printk("%s set to default\n", __FUNCTION__); */ + /* set to default value in case params is not presented */ + TNETW_params.num_of_parts = 2; + + /* After firmware has been downloaded, data memory region + has to be re-initialized as following */ + TNETW_params.map_reg[0].reg_size = SDIO_MEM_PARTITION_START; + TNETW_params.map_reg[0].scr_offset = SDIO_MEM_PARTITION_SIZE; + TNETW_params.map_reg[1].reg_size = SDIO_REG_PARTITION_SIZE; + TNETW_params.map_reg[1].scr_offset = SDIO_REG_PARTITION_START; + } + else { + /* printk("%s: params->num_of_parts=%d\n", __FUNCTION__, params->num_of_parts); */ + /* validate input parameters */ + switch(params->num_of_parts) { + case 1: + if(params->map_reg[0].reg_size > AMAP_ONE_REGION) + return SDIO_FAILURE; + break; + case 2: + if((params->map_reg[0].reg_size + params->map_reg[1].reg_size) > AMAP_ONE_REGION) + return SDIO_FAILURE; + break; + case 3: + if((params->map_reg[0].reg_size + params->map_reg[1].reg_size + params->map_reg[2].reg_size) > AMAP_ONE_REGION) + return SDIO_FAILURE; + break; + case 4: + if((params->map_reg[0].reg_size + params->map_reg[1].reg_size + params->map_reg[2].reg_size + params->map_reg[3].reg_size) > AMAP_ONE_REGION) + return SDIO_FAILURE; + break; + default: + return SDIO_FAILURE; + } + memcpy(&TNETW_params, params, sizeof(SDIO_TNETWConfigParams)); + } + + /* printk("%s completed\n", __FUNCTION__); */ + + return SDIO_SUCCESS; +} + + +static SDIO_Status config_partition(SDIO_Handle sdioHandle, int partition_no, Peripheral_Address start_addr, SDIO_BufferLength part_size) +{ + struct sdio_func *func = (struct sdio_func *) sdioHandle; + u8 data; + int br_offset = SDIO_FUNC1_OFFSET + (partition_no-1)*8; + int i, rc; + + /* printk("%s: partition_no=%d\n", __FUNCTION__, partition_no); */ + + /* Set size - write out 4 bytes by 4 requests */ + if (partition_no < AMAP_MAX_REGIONS) + { + for(i=0;i<4;i++,br_offset++) { + data = (part_size>>(8*i))&0xFF; + + /* put R/W Flag (1 for write); Function Number(1), RAW Flag(0), + Register Address - the address of the byte of data inside + of the selected function that will be written + (br_offset for func1), + Write Data - for a direct write command, this is the byte=data, + that will be written to the selected address=br_offset). + */ + sdio_writeb(func, data, br_offset, &rc); + if (rc < 0) { + printk(KERN_ERR "%s: Error writing size\n", __FUNCTION__); + return SDIO_FAILURE; + } + /* printk("%s: offset byte=%d data=0x%08x at=0x%08x\n", __FUNCTION__, i, data, br_offset); */ + } + + /* Set offset - write out 4 bytes by 4 requests */ + for(i=0;i<4;i++,br_offset++) { + data = (start_addr>>(8*i))&0xFF; + sdio_writeb(func, data, br_offset, &rc); + if (rc < 0) { + printk(KERN_ERR "%s: Error writing offset\n", __FUNCTION__); + return SDIO_FAILURE; + } + /* printk("%s: offset byte=%d data=0x%08x at=0x%08x\n", __FUNCTION__, i, data, br_offset); */ + } + } +#if 0 + if( partition_no == 2 ) { + unsigned long id1; + for(i=0,br_offset=0x1ce34;i<4;i++,br_offset++) { + data = sdio_readb(func, br_offset, &rc); + if (rc < 0) { + printk(KERN_ERR "%s: Error reading offset\n", __FUNCTION__); + return SDIO_FAILURE; + } + printk("%s: offset byte=%d data=0x%08x at=0x%08x\n", __FUNCTION__, i, data, br_offset); + } + rc = sdio_memcpy_fromio(func, &id1, 0x1ce34, 4); /* Dm: Important - DO NOT REMOVE !!! */ + if (rc < 0) { + printk(KERN_ERR "%s: Error reading offset\n", __FUNCTION__); + return SDIO_FAILURE; + } + printk("%s: data=0x%08x at=0x%08x\n", __FUNCTION__, id1, br_offset); + } +#endif + return SDIO_SUCCESS; +} + +/* + This function configures the slave SDIO device for the required + operation mode. +*/ +SDIO_Status SDIO_TNETWConfig(SDIO_Handle sdioHandle, Peripheral_ConfigParams **peripheral_info) +{ + SDIO_Status rc; + + /* printk("%s\n", __FUNCTION__); */ + + TNETW_table.mem_start_addr = TNETW_params.map_reg[0].scr_offset; + TNETW_table.mem_part_size = TNETW_params.map_reg[0].reg_size; + TNETW_table.mem_end_addr = TNETW_table.mem_start_addr + TNETW_table.mem_part_size - 1; + + TNETW_table.reg_start_addr = TNETW_params.map_reg[1].scr_offset; + TNETW_table.reg_part_size = TNETW_params.map_reg[1].reg_size; + TNETW_table.reg_end_addr = TNETW_table.reg_start_addr + TNETW_table.reg_part_size - 1; +#if 0 + printk("%s: memory area: start_addr=0x%08lx end_addr=0x%08lx part_size=0x%08lx\n", __FUNCTION__, TNETW_table.mem_start_addr, TNETW_table.mem_end_addr, TNETW_table.mem_part_size); + printk("%s: register area: start_addr=0x%08lx end_addr=0x%08lx part_size=0x%08lx\n", __FUNCTION__, TNETW_table.reg_start_addr, TNETW_table.reg_end_addr, TNETW_table.reg_part_size); +#endif + /* Configure 17-bits address range in peripheral */ + rc=config_partition(sdioHandle, 1, TNETW_table.mem_start_addr, TNETW_table.mem_part_size); + rc = (rc==SDIO_SUCCESS)?config_partition(sdioHandle, 2, TNETW_table.reg_start_addr, TNETW_table.reg_part_size):rc; + + if(*peripheral_info) + *peripheral_info = (void *)&TNETW_table; + + /* printk("%s: TNETW1150 partitions:\n", __FUNCTION__); + printk("Memory : start:0x%08lx end:0x%08lx size:0x%08lx bytes\n", TNETW_table.mem_start_addr, TNETW_table.mem_end_addr, TNETW_table.mem_part_size); + printk("Registers: start:0x%08lx end:0x%08lx size:0x%08lx bytes\n", TNETW_table.reg_start_addr, TNETW_table.reg_end_addr, TNETW_table.reg_part_size); + */ + + return rc; +} + +/* + This function performs convertion of peripheral adddress into 17 bits + SDIO address. If found that the memory partition configuration must be + changed, the memory is re-mapped in accordance to requested address. +*/ +SDIO_Address SDIO_ConvertTNETWToSDIOMaster(Peripheral_Address in_tnetw_address, SDIO_BufferLength packet_size) +{ + SDIO_Address out_sdio_address; + +#ifdef CONFIG_SDIO_ADDRESS_MAPPING_BY_APPLICATION + out_sdio_address = in_tnetw_address; +#else + Peripheral_Address tnetw_last_address = in_tnetw_address + packet_size - 1; + + /* printk("%s:\n", __FUNCTION__); */ + + if ((in_tnetw_address >= TNETW_table.mem_start_addr) && (tnetw_last_address <= TNETW_table.mem_end_addr)) { + /* printk("%s part1 from=0x%08lx to 0x%08lx\n", __FUNCTION__, in_tnetw_address, tnetw_last_address); */ + /* address in the 1-st partition range (data memory space) */ + out_sdio_address = in_tnetw_address - TNETW_table.mem_start_addr; + } + else if ((in_tnetw_address >= TNETW_table.reg_start_addr) && (tnetw_last_address <= TNETW_table.reg_end_addr)) { + /* printk("%s part2 from=0x%08lx to 0x%08lx\n", __FUNCTION__, in_tnetw_address, tnetw_last_address); */ + /* address in the 2-nd partition range (register memory space) */ + out_sdio_address = in_tnetw_address - TNETW_table.reg_start_addr + TNETW_table.mem_part_size; + } + else { + /* printk("%s peripheral addresses from=0x%08lx to 0x%08lx is out of range\n", __FUNCTION__, in_tnetw_address, tnetw_last_address); */ + /* invalid address */ + return SDIO_INVALID_PERIPHERAL_ADDRESS; + } + /* printk("%s: in_tnetw_addr=0x%08lx out_sdio_addr=0x%08lx\n", __FUNCTION__, in_tnetw_address, out_sdio_address); */ + +#endif /* CONFIG_SDIO_ADDRESS_MAPPING_BY_APPLICATION */ + + return out_sdio_address; +} + +SDIO_Status SDIO_TNETW_Set_ELP_Reg(SDIO_Handle sdioHandle, Peripheral_Address start_addr, unsigned int data) +{ + struct sdio_func *func = (struct sdio_func *) sdioHandle; + u8 data1 = 0; + int br_offset = start_addr; + int i, rc; + + /* Set size - write out 4 bytes by 4 requests */ + for(i=0;i<1;i++,br_offset++) { + data1 = (data>>(8*i))&0xFF; + + /* put R/W Flag (1 for write); Function Number(1), RAW Flag(0), + Register Address - the address of the byte of data inside + of the selected function that will be written + (br_offset for func1), + Write Data - for a direct write command, this is the byte=data, + that will be written to the selected address=br_offset). + */ + sdio_writeb(func, data1, br_offset, &rc); + if (rc < 0) { + printk(KERN_ERR "%s: Error writing size\n", __FUNCTION__); + return SDIO_FAILURE; + } + } + return SDIO_SUCCESS; +} + +SDIO_Status SDIO_TNETW_Get_ELP_Reg(SDIO_Handle sdioHandle, Peripheral_Address start_addr, unsigned int *data) +{ + struct sdio_func *func = (struct sdio_func *) sdioHandle; + int br_offset = start_addr; + int rc; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) + // 0x01 - ELPCTRL_WAKE_UP + *(u8*)data = sdio_writeb_readb(func, 0x01, br_offset, &rc); +#else + *(u8*)data = sdio_readb_ext(func, br_offset, &rc, 0x01); +#endif + if (rc) { + printk(KERN_ERR "%s: Error reading sdio register (%d)\n", __FUNCTION__, rc); + return SDIO_FAILURE; + } + return SDIO_SUCCESS; +} + +#endif /* TIWLAN_MSM7000 */ diff --git a/sta_dk/pform/linux/src/tnetw_sdio.c b/sta_dk/pform/linux/src/tnetw_sdio.c new file mode 100644 index 0000000..4d0219b --- /dev/null +++ b/sta_dk/pform/linux/src/tnetw_sdio.c @@ -0,0 +1,237 @@ +/* tnetw_sdio.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Copyright © Texas Instruments Incorporated (Oct 2005) + * THIS CODE/PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDED BUT NOT LIMITED TO , THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * This program has been modified from its original operation by Texas + * Instruments Incorporated. These changes are covered under version 2 + * of the GNU General Public License, dated June 1991. + * + * Copyright © Google Inc (Feb 2008) + */ +/*-------------------------------------------------------------------*/ +#ifdef USE_SDIO_DRIVER +#include +#include +#include +#include +#include +#include +#include "esta_drv.h" +#include "mmc_omap_api.h" +#include "osApi.h" +#define DM_DMA_WORKAROUND +/*-------------------------------------------------------------------*/ +extern int tiwlan_sdio_init(struct sdio_func *func); +extern int sdio_reset_comm(struct mmc_card *card); +/*-------------------------------------------------------------------*/ +static struct sdio_func *tiwlan_func = NULL; +static int sdio_reset_flag = 0; +#ifdef DM_DMA_WORKAROUND +static void *sdio_dma_ptr = NULL; +#endif +/*-------------------------------------------------------------------*/ +void SDIO_SetFunc( struct sdio_func *func ) +{ + tiwlan_func = func; +} + +struct sdio_func *SDIO_GetFunc( void ) +{ + return( tiwlan_func ); +} + +SDIO_Status SDIO_Init(SDIO_ConfigParams *ConfigParams, SDIO_Handle *Handle) +{ + if( Handle == NULL ) { + printk(KERN_ERR "Error: SDIO_Init() called with NULL!\n"); + return SDIO_FAILURE; + } + *Handle = (SDIO_Handle)SDIO_GetFunc(); + if( (*Handle) == NULL ) { + printk(KERN_ERR "Error: SDIO_Init() called before SDIO probe completed!\n"); + return SDIO_FAILURE; + } +#ifdef DM_DMA_WORKAROUND + if( !sdio_dma_ptr ) { + sdio_dma_ptr = kmalloc( PAGE_SIZE, GFP_KERNEL ); + if( !sdio_dma_ptr ) + return SDIO_FAILURE; + } +#endif + return SDIO_SUCCESS; +} + +SDIO_Status SDIO_Shutdown(SDIO_Handle Handle) +{ + /* printk("%s:\n", __FUNCTION__); */ +#ifdef DM_DMA_WORKAROUND + if( sdio_dma_ptr ) { + kfree( sdio_dma_ptr ); + sdio_dma_ptr = NULL; + } +#endif + return SDIO_SUCCESS; +} + +SDIO_Status SDIO_Start(SDIO_Handle Handle) +{ + struct sdio_func *func = (struct sdio_func *)Handle; + + /* printk("%s:\n", __FUNCTION__); */ + if( func ) { + if( sdio_reset_flag ) { + sdio_reset_flag = 0; + if( tiwlan_sdio_init(func) ) { + printk("TI: tiwlan_sdio_init Error !\n"); + return SDIO_FAILURE; + } + } + } + return SDIO_SUCCESS; +} + +SDIO_Status SDIO_Reset(SDIO_Handle Handle) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) + struct sdio_func *func = (struct sdio_func *)Handle; + + /* printk("%s:\n", __FUNCTION__); */ + if( func && func->card ) { + sdio_reset_comm(func->card); + } +#endif + printk("%s:\n", __FUNCTION__); + return SDIO_SUCCESS; +} + +SDIO_Status SDIO_Stop(SDIO_Handle Handle, unsigned long Wait_Window) +{ + /* printk("%s:\n", __FUNCTION__); */ + sdio_reset_flag = 1; + return SDIO_Reset( Handle ); +} + +static int read_direct(struct sdio_func *func, unsigned char *buf, + unsigned long addr, unsigned len) +{ + unsigned i; + int rc0, rc = 0; + + for(i=0;( i < len );i++,addr++) { + *buf++ = (unsigned char)sdio_readb(func, addr, &rc0); + if( rc0 != 0 ) + rc = rc0; + } + return rc; +} + +static int write_direct(struct sdio_func *func, unsigned long addr, + unsigned char *buf, unsigned len) +{ + unsigned i; + int rc0, rc = 0; + + for(i=0;( i < len );i++,addr++) { + sdio_writeb(func, *buf++, addr, &rc0); + if( rc0 != 0 ) + rc = rc0; + } + return rc; +} + +SDIO_Status SDIO_SyncRead(SDIO_Handle Handle, SDIO_Request_t *Req) +{ + struct sdio_func *func = (struct sdio_func *)Handle; + int rc, retries = 5; + +#if 0 + printk("%s: p_addr = 0x%.8lx, sz = %d\n", + __FUNCTION__, + Req->peripheral_addr, + Req->buffer_len); +#endif + + while(retries) { + if( retries > 2 ) +#ifdef DM_DMA_WORKAROUND + if( virt_addr_valid(Req->buffer) ) { + rc = sdio_memcpy_fromio(func, Req->buffer, Req->peripheral_addr, Req->buffer_len); + } + else { + rc = sdio_memcpy_fromio(func, sdio_dma_ptr, Req->peripheral_addr, Req->buffer_len); + memcpy( Req->buffer, sdio_dma_ptr, Req->buffer_len ); + } +#else + rc = sdio_memcpy_fromio(func, Req->buffer, Req->peripheral_addr, Req->buffer_len); +#endif + else + rc = read_direct(func, Req->buffer, Req->peripheral_addr, Req->buffer_len); + + if (rc) { + printk(KERN_ERR "%s: Read operation failed (%d) (retries = %d)\n", + __FUNCTION__, rc, retries); + retries--; + continue; + } + if (retries != 5) + printk(KERN_ERR "%s: Retry succeeded\n", __FUNCTION__); + return SDIO_SUCCESS; + } + printk(KERN_ERR "%s: Giving up\n", __FUNCTION__); + return SDIO_FAILURE; +} + +SDIO_Status SDIO_SyncWrite(SDIO_Handle Handle, SDIO_Request_t *Req) +{ + struct sdio_func *func = (struct sdio_func *)Handle; + int rc, retries = 5; +#ifdef DM_DMA_WORKAROUND + void *dma_ptr; +#endif + +#if 0 + printk("%s: p_addr = 0x%.8lx, sz = %d\n", + __FUNCTION__, + Req->peripheral_addr, + Req->buffer_len); +#endif + + while(retries) { + if( retries > 2 ) { +#ifdef DM_DMA_WORKAROUND + if( virt_addr_valid(Req->buffer) ) { + dma_ptr = Req->buffer; + } + else { + dma_ptr = sdio_dma_ptr; + memcpy( dma_ptr, Req->buffer, Req->buffer_len ); + } + rc = sdio_memcpy_toio(func, Req->peripheral_addr, dma_ptr, Req->buffer_len); +#else + rc = sdio_memcpy_toio(func, Req->peripheral_addr, Req->buffer, Req->buffer_len); +#endif + } + else + rc = write_direct(func, Req->peripheral_addr, Req->buffer, Req->buffer_len); + + if (rc) { + printk(KERN_ERR "%s: Write operation failed (%d) (retries = %d)\n", + __FUNCTION__, rc, retries); + retries--; + continue; + } + + if (retries != 5) + printk(KERN_ERR "%s: Retry succeeded\n", __FUNCTION__); + return SDIO_SUCCESS; + } + printk(KERN_ERR "%s: Giving up\n", __FUNCTION__); + return SDIO_FAILURE; +} +#endif