diff options
author | Kevin | 2014-11-15 10:00:36 +0800 |
---|---|---|
committer | Kevin | 2014-11-15 10:00:36 +0800 |
commit | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (patch) | |
tree | de942df665fac4bac0d9cb7ae86910fe937b0c1a /ANDROID_3.4.5/drivers/net/wireless/eagle/esp_io.c | |
parent | 392e8802486cb573b916e746010e141a75f507e6 (diff) | |
download | FOSSEE-netbook-kernel-source-9d40ac5867b9aefe0722bc1f110b965ff294d30d.tar.gz FOSSEE-netbook-kernel-source-9d40ac5867b9aefe0722bc1f110b965ff294d30d.tar.bz2 FOSSEE-netbook-kernel-source-9d40ac5867b9aefe0722bc1f110b965ff294d30d.zip |
add via modify part source code for wm8880 4.4 kitkat
Diffstat (limited to 'ANDROID_3.4.5/drivers/net/wireless/eagle/esp_io.c')
-rwxr-xr-x | ANDROID_3.4.5/drivers/net/wireless/eagle/esp_io.c | 596 |
1 files changed, 596 insertions, 0 deletions
diff --git a/ANDROID_3.4.5/drivers/net/wireless/eagle/esp_io.c b/ANDROID_3.4.5/drivers/net/wireless/eagle/esp_io.c new file mode 100755 index 00000000..9623d3c2 --- /dev/null +++ b/ANDROID_3.4.5/drivers/net/wireless/eagle/esp_io.c @@ -0,0 +1,596 @@ +#include <linux/mmc/sdio_func.h> +#include "esp_sif.h" +#include "slc_host_register.h" +#include "esp_debug.h" + +#ifdef SIF_DEBUG_DSR_DUMP_REG +static void dump_slc_regs(struct slc_host_regs *regs); +#endif /* SIF_DEBUG_DSR_DUMP_REG */ + +int esp_common_read(struct esp_pub *epub, u8 *buf, u32 len, int sync, bool noround) +{ + if (sync) { +#ifdef ESP_USE_SDIO + return sif_lldesc_read_sync(epub, buf, len); +#endif +#ifdef ESP_USE_SPI + //return sif_spi_read_sync(epub, buf, len, NOT_CHECK_IDLE); + return sif_spi_read_sync(epub, buf, len, CHECK_IDLE); +#endif + } else { +#ifdef ESP_USE_SDIO + return sif_lldesc_read_raw(epub, buf, len, noround); +#endif +#ifdef ESP_USE_SPI + //return sif_spi_read_nosync(epub, buf, len, NOT_CHECK_IDLE, noround); + return sif_spi_read_nosync(epub, buf, len, CHECK_IDLE, noround); +#endif + } +} + + +int esp_common_write(struct esp_pub *epub, u8 *buf, u32 len, int sync) +{ + if (sync) { +#ifdef ESP_USE_SDIO + return sif_lldesc_write_sync(epub, buf, len); +#endif +#ifdef ESP_USE_SPI + //return sif_spi_write_sync(epub, buf, len, NOT_CHECK_IDLE); + return sif_spi_write_sync(epub, buf, len, CHECK_IDLE); +#endif + } else { +#ifdef ESP_USE_SDIO + return sif_lldesc_write_raw(epub, buf, len); +#endif +#ifdef ESP_USE_SPI + //return sif_spi_write_nosync(epub, buf, len, NOT_CHECK_IDLE); + return sif_spi_write_nosync(epub, buf, len, CHECK_IDLE); +#endif + } +} + + +int esp_common_read_with_addr(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, int sync) +{ + if (sync) { +#ifdef ESP_USE_SDIO + return sif_io_sync(epub, addr, buf, len, SIF_FROM_DEVICE | SIF_SYNC | SIF_BYTE_BASIS | SIF_INC_ADDR); +#endif +#ifdef ESP_USE_SPI + return sif_spi_epub_read_mix_sync(epub, addr, buf, len, CHECK_IDLE); +#endif + } else { +#ifdef ESP_USE_SDIO + return sif_io_raw(epub, addr, buf, len, SIF_FROM_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR); +#endif +#ifdef ESP_USE_SPI + return sif_spi_epub_read_mix_nosync(epub, addr, buf, len, CHECK_IDLE); +#endif + } + +} + + +int esp_common_write_with_addr(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, int sync) +{ + if (sync) { +#ifdef ESP_USE_SDIO + return sif_io_sync(epub, addr, buf, len, SIF_TO_DEVICE | SIF_SYNC | SIF_BYTE_BASIS | SIF_INC_ADDR); +#endif +#ifdef ESP_USE_SPI + return sif_spi_epub_write_mix_sync(epub, addr, buf, len, CHECK_IDLE); +#endif + } else { +#ifdef ESP_USE_SDIO + return sif_io_raw(epub, addr, buf, len, SIF_TO_DEVICE | SIF_BYTE_BASIS | SIF_INC_ADDR); +#endif +#ifdef ESP_USE_SPI + return sif_spi_epub_write_mix_nosync(epub, addr, buf, len, CHECK_IDLE); +#endif + } +} + +int esp_common_readbyte_with_addr(struct esp_pub *epub, u32 addr, u8 *buf, int sync) +{ + if(sync){ +#ifdef ESP_USE_SDIO + int res; + sif_lock_bus(epub); + *buf = sdio_io_readb(epub, addr, &res); + sif_unlock_bus(epub); + return res; +#endif +#ifdef ESP_USE_SPI + return sif_spi_epub_read_mix_sync(epub, addr, buf, 1, CHECK_IDLE); +#endif + } else { +#ifdef ESP_USE_SDIO + int res; + *buf = sdio_io_readb(epub, addr, &res); + return res; +#endif +#ifdef ESP_USE_SPI + return sif_spi_epub_read_mix_nosync(epub, addr, buf, 1, CHECK_IDLE); +#endif + } + +} + + + +int esp_common_writebyte_with_addr(struct esp_pub *epub, u32 addr, u8 buf, int sync) +{ + if(sync){ +#ifdef ESP_USE_SDIO + int res; + sif_lock_bus(epub); + sdio_io_writeb(epub, buf, addr, &res); + sif_unlock_bus(epub); + return res; +#endif +#ifdef ESP_USE_SPI + return sif_spi_epub_write_mix_sync(epub, addr, &buf, 1, CHECK_IDLE); +#endif + } else { +#ifdef ESP_USE_SDIO + int res; + sdio_io_writeb(epub, buf, addr, &res); + return res; +#endif +#ifdef ESP_USE_SPI + return sif_spi_epub_write_mix_nosync(epub, addr, &buf, 1, CHECK_IDLE); +#endif + } +} + +typedef enum _SDIO_INTR_MODE { + SDIO_INTR_IB = 0, + SDIO_INTR_OOB_TOGGLE, + SDIO_INTR_OOB_HIGH_LEVEL, + SDIO_INTR_OOB_LOW_LEVEL, +} SDIO_INTR_MODE; + +#define GEN_GPIO_SEL(_gpio_num, _sel_func, _intr_mode, _offset) (((_offset)<< 9 ) |((_intr_mode) << 7)|((_sel_func) << 4)|(_gpio_num)) +//bit[3:0] = gpio num, 2 +//bit[6:4] = gpio sel func, 0 +//bit[8:7] = gpio intr mode, SDIO_INTR_OOB_TOGGLE +//bit[15:9] = register offset, 0x38 + +u16 gpio_sel_sets[17] = { + GEN_GPIO_SEL(0, 0, SDIO_INTR_OOB_TOGGLE, 0x34),//GPIO0 + GEN_GPIO_SEL(1, 3, SDIO_INTR_OOB_TOGGLE, 0x18),//U0TXD + GEN_GPIO_SEL(2, 0, SDIO_INTR_OOB_TOGGLE, 0x38),//GPIO2 + GEN_GPIO_SEL(3, 3, SDIO_INTR_OOB_TOGGLE, 0x14),//U0RXD + GEN_GPIO_SEL(4, 0, SDIO_INTR_OOB_TOGGLE, 0x3C),//GPIO4 + GEN_GPIO_SEL(5, 0, SDIO_INTR_OOB_TOGGLE, 0x40),//GPIO5 + GEN_GPIO_SEL(6, 3, SDIO_INTR_OOB_TOGGLE, 0x1C),//SD_CLK + GEN_GPIO_SEL(7, 3, SDIO_INTR_OOB_TOGGLE, 0x20),//SD_DATA0 + GEN_GPIO_SEL(8, 3, SDIO_INTR_OOB_TOGGLE, 0x24),//SD_DATA1 + GEN_GPIO_SEL(9, 3, SDIO_INTR_OOB_TOGGLE, 0x28),//SD_DATA2 + GEN_GPIO_SEL(10, 3, SDIO_INTR_OOB_TOGGLE, 0x2C),//SD_DATA3 + GEN_GPIO_SEL(11, 3, SDIO_INTR_OOB_TOGGLE, 0x30),//SD_CMD + GEN_GPIO_SEL(12, 3, SDIO_INTR_OOB_TOGGLE, 0x04),//MTDI + GEN_GPIO_SEL(13, 3, SDIO_INTR_OOB_TOGGLE, 0x08),//MTCK + GEN_GPIO_SEL(14, 3, SDIO_INTR_OOB_TOGGLE, 0x0C),//MTMS + GEN_GPIO_SEL(15, 3, SDIO_INTR_OOB_TOGGLE, 0x10),//MTDO + //pls do not change sel before, if you want to change intr mode,change the one blow + //GEN_GPIO_SEL(2, 0, SDIO_INTR_OOB_TOGGLE, 0x38) + GEN_GPIO_SEL(2, 0, SDIO_INTR_OOB_LOW_LEVEL, 0x38) +}; +#if defined(USE_EXT_GPIO) +u16 gpio_forbidden = 0; +#endif + +int sif_interrupt_target(struct esp_pub *epub, u8 index) +{ + u8 low_byte = BIT(index); + return esp_common_writebyte_with_addr(epub, SLC_HOST_CONF_W4 + 2, low_byte, ESP_SIF_NOSYNC); + +} + +#ifdef USE_EXT_GPIO +int sif_config_gpio_mode(struct esp_pub *epub, u8 gpio_num, u8 gpio_mode) +{ + u32 *p_tbuf = NULL; + int err; + + if((BIT(gpio_num) & gpio_forbidden) || gpio_num > 15) + return -EINVAL; + + p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL); + ASSERT(p_tbuf != NULL); + *p_tbuf = (gpio_mode << 16) | gpio_sel_sets[gpio_num]; + err = esp_common_write_with_addr(epub, SLC_HOST_CONF_W1, (u8*)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC); + if (err) + return err; + + kfree(p_tbuf); + + return sif_interrupt_target(epub, 4); +} + +int sif_set_gpio_output(struct esp_pub *epub, u16 mask, u16 value) +{ + u32 *p_tbuf = NULL; + int err; + + mask &= ~gpio_forbidden; + p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL); + ASSERT(p_tbuf != NULL); + *p_tbuf = (mask << 16) | value; + err = esp_common_write_with_addr(epub, SLC_HOST_CONF_W2, (u8*)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC); + if (err) + return err; + + kfree(p_tbuf); + + return sif_interrupt_target(epub, 5); +} + +int sif_get_gpio_intr(struct esp_pub *epub, u16 intr_mask, u16 *value) +{ + u32 *p_tbuf = NULL; + int err; + + p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL); + ASSERT(p_tbuf != NULL); + *p_tbuf = 0; + err = esp_common_read_with_addr(epub, SLC_HOST_CONF_W3, (u8*)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC); + if (err) + return err; + + *value = *p_tbuf & intr_mask; + kfree(p_tbuf); + if(*value == 0) + return 0; + return sif_interrupt_target(epub, 6); +} + +int sif_get_gpio_input(struct esp_pub *epub, u16 *mask, u16 *value) +{ + u32 *p_tbuf = NULL; + int err; + + err = sif_interrupt_target(epub, 3); + if (err) + return err; + + udelay(20); + p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL); + ASSERT(p_tbuf != NULL); + *p_tbuf = 0; + err = esp_common_read_with_addr(epub, SLC_HOST_CONF_W3, (u8*)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC); + if (err) + return err; + + *mask = *p_tbuf >> 16; + *value = *p_tbuf & *mask; + kfree(p_tbuf); + + return 0; +} +#endif + +void sif_raw_dummy_read(struct esp_pub *epub) +{ + int retry = 0; + u32 *p_tbuf = NULL; + static u32 read_err_cnt = 0; + static u32 write_err_cnt = 0; + static u32 unknow_err_cnt = 0; + static u32 check_cnt = 0; + int ext_cnt = 0; + + if (atomic_read(&epub->ps.state) == ESP_PM_ON) { + atomic_set(&epub->ps.state, ESP_PM_OFF); + } else { + return ; + } + + + p_tbuf = kzalloc(sizeof(u32), GFP_KERNEL); + ASSERT(p_tbuf != NULL); + *p_tbuf = 0; + + *p_tbuf = 0x010001ff; + + esp_common_write_with_addr(epub, SLC_HOST_CONF_W4, (u8 *)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC); + + do { + *p_tbuf = 0xffffffff; + udelay(20); + esp_common_read_with_addr(epub, SLC_HOST_CONF_W4, (u8 *)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC); + + if(*p_tbuf == 0x020001ff){ +#ifdef ESP_USE_SPI + if(--ext_cnt >= 0){ + mdelay(10); + esp_common_write_with_addr(epub, SLC_HOST_CONF_W4, (u8 *)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC); + retry = -1; + continue; + } +#endif + break; + } + + if(*p_tbuf == 0x010001ff){ + if(retry < 5) + continue; + }else if(*p_tbuf == 0x000001ff){ + write_err_cnt++; + ext_cnt = 5; + }else if(*p_tbuf == 0xffffffff){ + read_err_cnt++; + write_err_cnt++; + ext_cnt = 5; + }else { + unknow_err_cnt++; + ext_cnt = 5; + } + + *p_tbuf = 0x010001ff; + udelay(20); + esp_common_write_with_addr(epub, SLC_HOST_CONF_W4, (u8 *)p_tbuf, sizeof(u32), ESP_SIF_NOSYNC); + + } while (retry++ < 1000); + + kfree(p_tbuf); + + if(read_err_cnt || write_err_cnt || unknow_err_cnt){ + if((check_cnt & 0xf) == 0) + //esp_dbg(ESP_DBG_ERROR, "==============sdio err===============\n,read:%u, write:%u, unknow:%u\n", read_err_cnt,write_err_cnt,unknow_err_cnt); + esp_dbg(ESP_DBG_ERROR, "r%u,w%u,u%u\n", read_err_cnt,write_err_cnt,unknow_err_cnt); + check_cnt++; + } + + if (retry > 1) { + esp_dbg(ESP_DBG_ERROR, "=========%s tried %d times===========\n", __func__, retry - 1); + //if (retry>=100) + // ASSERT(0); + } +} + +void check_target_id(struct esp_pub *epub) +{ + u32 date; + int err = 0; + int i; + + EPUB_CTRL_CHECK(epub); + + sif_lock_bus(epub); + + for(i = 0; i < 4; i++) { + err = esp_common_readbyte_with_addr(epub, SLC_HOST_DATE + i, (u8 *)&date + i, ESP_SIF_NOSYNC); + err = esp_common_readbyte_with_addr(epub, SLC_HOST_ID + i, (u8 *)&EPUB_TO_CTRL(epub)->target_id + i, ESP_SIF_NOSYNC); + } + + sif_unlock_bus(epub); + + esp_dbg(ESP_DBG_LOG, "\n\n \t\t SLC data 0x%08x, ID 0x%08x\n\n", date, EPUB_TO_CTRL(epub)->target_id); + + switch(EPUB_TO_CTRL(epub)->target_id) { + case 0x100: + EPUB_TO_CTRL(epub)->slc_window_end_addr = 0x20000; + break; + case 0x600: + EPUB_TO_CTRL(epub)->slc_window_end_addr = 0x20000 - 0x800; + + do{ + u16 gpio_sel; + u8 low_byte = 0; + u8 high_byte = 0; + u8 byte2 = 0; + u8 byte3 = 0; +#ifdef USE_OOB_INTR + gpio_sel = gpio_sel_sets[16]; + low_byte = gpio_sel; + high_byte = gpio_sel >> 8; +#ifdef USE_EXT_GPIO + gpio_forbidden |= BIT(gpio_sel & 0xf); +#endif /* USE_EXT_GPIO */ +#endif /* USE_OOB_INTR */ + + if(sif_get_bt_config() == 1 && sif_get_rst_config() != 1){ + u8 gpio_num = sif_get_wakeup_gpio_config(); + gpio_sel = gpio_sel_sets[gpio_num]; + byte2 = gpio_sel; + byte3 = gpio_sel >> 8; +#ifdef USE_EXT_GPIO + gpio_forbidden |= BIT(gpio_num); +#endif + } + sif_lock_bus(epub); + err = esp_common_writebyte_with_addr(epub, SLC_HOST_CONF_W1, low_byte, ESP_SIF_NOSYNC); + err = esp_common_writebyte_with_addr(epub, SLC_HOST_CONF_W1 + 1, high_byte, ESP_SIF_NOSYNC); + err = esp_common_writebyte_with_addr(epub, SLC_HOST_CONF_W1 + 2, byte2, ESP_SIF_NOSYNC); + err = esp_common_writebyte_with_addr(epub, SLC_HOST_CONF_W1 + 3, byte3, ESP_SIF_NOSYNC); + sif_unlock_bus(epub); + }while(0); + break; + default: + EPUB_TO_CTRL(epub)->slc_window_end_addr = 0x20000; + break; + } + + return; +} + +u32 sif_get_blksz(struct esp_pub *epub) +{ + EPUB_CTRL_CHECK(epub); + + return EPUB_TO_CTRL(epub)->slc_blk_sz; +} + +u32 sif_get_target_id(struct esp_pub *epub) +{ + EPUB_CTRL_CHECK(epub); + + return EPUB_TO_CTRL(epub)->target_id; +} + + +#ifdef SIF_CHECK_FIRST_INTR +static bool first_intr_checked = false; +#endif //SIF_CHECK_FIRST_INTR + +#ifdef ESP_USE_SDIO +void sif_dsr(struct sdio_func *func) +{ + struct esp_sdio_ctrl *sctrl = sdio_get_drvdata(func); +#else +void sif_dsr(struct spi_device *spi) +{ + struct esp_spi_ctrl *sctrl = spi_get_drvdata(spi); +#endif +#ifdef SIF_DSR_WAR + static int dsr_cnt = 0, real_intr_cnt = 0, bogus_intr_cnt = 0; + struct slc_host_regs *regs = &(sctrl->slc_regs); + esp_dbg(ESP_DBG_TRACE, " %s enter %d \n", __func__, dsr_cnt++); +#endif /* SIF_DSR_WAR */ + + atomic_set(&sctrl->irq_handling, 1); + +#ifdef ESP_USE_SDIO + sdio_release_host(sctrl->func); +#endif + +#ifdef SIF_DSR_WAR + do { +#ifdef SIF_CHECK_FIRST_INTR + if (likely(first_intr_checked)) { + esp_dsr(sctrl->epub); + break; + } +#endif //SIF_CHECK_FIRST_INTR + + memset(regs, 0x0, sizeof(struct slc_host_regs)); + esp_common_read_with_addr(sctrl->epub, REG_SLC_HOST_BASE + 8, (u8 *)regs, sizeof(struct slc_host_regs), ESP_SIF_SYNC); + + if (regs->intr_status & SLC_HOST_RX_ST) { +#ifdef SIF_CHECK_FIRST_INTR + first_intr_checked = true; +#endif //SIF_CHECK_FIRST_INTR + esp_dbg(ESP_DBG_TRACE, "%s eal intr cnt: %d", __func__, ++real_intr_cnt); + + esp_dsr(sctrl->epub); + + } else { +#ifdef ESP_ACK_INTERRUPT + sif_lock_bus(sctrl->epub); + sif_platform_ack_interrupt(sctrl->epub); + sif_unlock_bus(sctrl->epub); +#endif //ESP_ACK_INTERRUPT + + esp_dbg(ESP_DBG_TRACE, "%s bogus_intr_cnt %d\n", __func__, ++bogus_intr_cnt); + } + +#ifdef SIF_DEBUG_DSR_DUMP_REG + dump_slc_regs(regs); +#endif /* SIF_DEBUG_DUMP_DSR */ + + } while (0); + +#else + esp_dsr(sctrl->epub); +#endif /* SIF_DSR_WAR */ + +#ifdef ESP_USE_SDIO + sdio_claim_host(func); +#endif + + atomic_set(&sctrl->irq_handling, 0); +} + + +struct slc_host_regs * sif_get_regs(struct esp_pub *epub) +{ + EPUB_CTRL_CHECK(epub); + + return &EPUB_TO_CTRL(epub)->slc_regs; +} + +void sif_disable_target_interrupt(struct esp_pub *epub) +{ + EPUB_FUNC_CHECK(epub); + sif_lock_bus(epub); +#ifdef HOST_RESET_BUG + mdelay(10); +#endif + sif_raw_dummy_read(epub); + memset(EPUB_TO_CTRL(epub)->dma_buffer, 0x00, sizeof(u32)); + esp_common_write_with_addr(epub, SLC_HOST_INT_ENA, EPUB_TO_CTRL(epub)->dma_buffer, sizeof(u32), ESP_SIF_NOSYNC); +#ifdef HOST_RESET_BUG + mdelay(10); +#endif + + sif_unlock_bus(epub); +} + +#ifdef SIF_DEBUG_DSR_DUMP_REG +static void dump_slc_regs(struct slc_host_regs *regs) +{ + esp_dbg(ESP_DBG_TRACE, "\n\n ------- %s --------------\n", __func__); + + esp_dbg(ESP_DBG_TRACE, " \ + intr_raw 0x%08X \t \n \ + state_w0 0x%08X \t state_w1 0x%08X \n \ + config_w0 0x%08X \t config_w1 0x%08X \n \ + intr_status 0x%08X \t config_w2 0x%08X \n \ + config_w3 0x%08X \t config_w4 0x%08X \n \ + token_wdata 0x%08X \t intr_clear 0x%08X \n \ + intr_enable 0x%08X \n\n", regs->intr_raw, \ + regs->state_w0, regs->state_w1, regs->config_w0, regs->config_w1, \ + regs->intr_status, \ + regs->config_w2, regs->config_w3, regs->config_w4, regs->token_wdata, \ + regs->intr_clear, regs->intr_enable); +} +#endif /* SIF_DEBUG_DSR_DUMP_REG */ + +static int bt_config = 0; +void sif_record_bt_config(int value) +{ + bt_config = value; +} + +int sif_get_bt_config(void) +{ + return bt_config; +} + +static int rst_config = 0; +void sif_record_rst_config(int value) +{ + rst_config = value; +} + +int sif_get_rst_config(void) +{ + return rst_config; +} + +static int retry_reset = 0; +void sif_record_retry_config(void) +{ + retry_reset = 1; +} + +int sif_get_retry_config(void) +{ + return retry_reset; +} + +static int wakeup_gpio = 12; +void sif_record_wakeup_gpio_config(int value) +{ + wakeup_gpio = value; +} + +int sif_get_wakeup_gpio_config(void) +{ + return wakeup_gpio; +} + + |