X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=kernel%2Fdrivers%2Fstaging%2Fwilc1000%2Flinux_wlan_sdio.c;fp=kernel%2Fdrivers%2Fstaging%2Fwilc1000%2Flinux_wlan_sdio.c;h=4aff953a88f167880959ee12973bc11deecec734;hb=e09b41010ba33a20a87472ee821fa407a5b8da36;hp=0000000000000000000000000000000000000000;hpb=f93b97fd65072de626c074dbe099a1fff05ce060;p=kvmfornfv.git diff --git a/kernel/drivers/staging/wilc1000/linux_wlan_sdio.c b/kernel/drivers/staging/wilc1000/linux_wlan_sdio.c new file mode 100644 index 000000000..4aff953a8 --- /dev/null +++ b/kernel/drivers/staging/wilc1000/linux_wlan_sdio.c @@ -0,0 +1,251 @@ +#include "wilc_wfi_netdevice.h" + +#include +#include +#include +#include +#include + + + +#define SDIO_MODALIAS "wilc1000_sdio" + +#if defined(CUSTOMER_PLATFORM) +/* TODO : User have to stable bus clock as user's environment. */ + #ifdef MAX_BUS_SPEED + #define MAX_SPEED MAX_BUS_SPEED + #else + #define MAX_SPEED 50000000 + #endif +#else + #define MAX_SPEED (6 * 1000000) /* Max 50M */ +#endif + +struct wilc_sdio { + struct sdio_func *func; + struct wilc *wilc; +}; + +struct sdio_func *local_sdio_func; + +static unsigned int sdio_default_speed; + +#define SDIO_VENDOR_ID_WILC 0x0296 +#define SDIO_DEVICE_ID_WILC 0x5347 + +static const struct sdio_device_id wilc_sdio_ids[] = { + { SDIO_DEVICE(SDIO_VENDOR_ID_WILC, SDIO_DEVICE_ID_WILC) }, + { }, +}; + + +static void wilc_sdio_interrupt(struct sdio_func *func) +{ + struct wilc_sdio *wl_sdio; + + wl_sdio = sdio_get_drvdata(func); + +#ifndef WILC_SDIO_IRQ_GPIO + sdio_release_host(func); + wilc_handle_isr(wl_sdio->wilc); + sdio_claim_host(func); +#endif +} + + +int linux_sdio_cmd52(sdio_cmd52_t *cmd) +{ + struct sdio_func *func = g_linux_wlan->wilc_sdio_func; + int ret; + u8 data; + + sdio_claim_host(func); + + func->num = cmd->function; + if (cmd->read_write) { /* write */ + if (cmd->raw) { + sdio_writeb(func, cmd->data, cmd->address, &ret); + data = sdio_readb(func, cmd->address, &ret); + cmd->data = data; + } else { + sdio_writeb(func, cmd->data, cmd->address, &ret); + } + } else { /* read */ + data = sdio_readb(func, cmd->address, &ret); + cmd->data = data; + } + + sdio_release_host(func); + + if (ret < 0) { + PRINT_ER("wilc_sdio_cmd52..failed, err(%d)\n", ret); + return 0; + } + return 1; +} + + +int linux_sdio_cmd53(sdio_cmd53_t *cmd) +{ + struct sdio_func *func = g_linux_wlan->wilc_sdio_func; + int size, ret; + + sdio_claim_host(func); + + func->num = cmd->function; + func->cur_blksize = cmd->block_size; + if (cmd->block_mode) + size = cmd->count * cmd->block_size; + else + size = cmd->count; + + if (cmd->read_write) { /* write */ + ret = sdio_memcpy_toio(func, cmd->address, (void *)cmd->buffer, size); + } else { /* read */ + ret = sdio_memcpy_fromio(func, (void *)cmd->buffer, cmd->address, size); + } + + sdio_release_host(func); + + + if (ret < 0) { + PRINT_ER("wilc_sdio_cmd53..failed, err(%d)\n", ret); + return 0; + } + + return 1; +} + +static int linux_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) +{ + struct wilc_sdio *wl_sdio; + struct wilc *wilc; + + PRINT_D(INIT_DBG, "probe function\n"); + wl_sdio = kzalloc(sizeof(struct wilc_sdio), GFP_KERNEL); + if (!wl_sdio) + return -ENOMEM; + + PRINT_D(INIT_DBG, "Initializing netdev\n"); + local_sdio_func = func; + if (wilc_netdev_init(&wilc)) { + PRINT_ER("Couldn't initialize netdev\n"); + kfree(wl_sdio); + return -1; + } + wl_sdio->func = func; + wl_sdio->wilc = wilc; + sdio_set_drvdata(func, wl_sdio); + + printk("Driver Initializing success\n"); + return 0; +} + +static void linux_sdio_remove(struct sdio_func *func) +{ + struct wilc_sdio *wl_sdio; + + wl_sdio = sdio_get_drvdata(func); + wl_wlan_cleanup(); + kfree(wl_sdio); +} + +struct sdio_driver wilc_bus = { + .name = SDIO_MODALIAS, + .id_table = wilc_sdio_ids, + .probe = linux_sdio_probe, + .remove = linux_sdio_remove, +}; + +int enable_sdio_interrupt(void) +{ + int ret = 0; +#ifndef WILC_SDIO_IRQ_GPIO + + sdio_claim_host(local_sdio_func); + ret = sdio_claim_irq(local_sdio_func, wilc_sdio_interrupt); + sdio_release_host(local_sdio_func); + + if (ret < 0) { + PRINT_ER("can't claim sdio_irq, err(%d)\n", ret); + ret = -EIO; + } +#endif + return ret; +} + +void disable_sdio_interrupt(void) +{ + +#ifndef WILC_SDIO_IRQ_GPIO + int ret; + + PRINT_D(INIT_DBG, "disable_sdio_interrupt IN\n"); + + sdio_claim_host(local_sdio_func); + ret = sdio_release_irq(local_sdio_func); + if (ret < 0) { + PRINT_ER("can't release sdio_irq, err(%d)\n", ret); + } + sdio_release_host(local_sdio_func); + + PRINT_D(INIT_DBG, "disable_sdio_interrupt OUT\n"); +#endif +} + +static int linux_sdio_set_speed(int speed) +{ + struct mmc_ios ios; + + sdio_claim_host(local_sdio_func); + + memcpy((void *)&ios, (void *)&local_sdio_func->card->host->ios, sizeof(struct mmc_ios)); + local_sdio_func->card->host->ios.clock = speed; + ios.clock = speed; + local_sdio_func->card->host->ops->set_ios(local_sdio_func->card->host, &ios); + sdio_release_host(local_sdio_func); + PRINT_INFO(INIT_DBG, "@@@@@@@@@@@@ change SDIO speed to %d @@@@@@@@@\n", speed); + + return 1; +} + +static int linux_sdio_get_speed(void) +{ + return local_sdio_func->card->host->ios.clock; +} + +int linux_sdio_init(void *pv) +{ + + /** + * TODO : + **/ + + + sdio_default_speed = linux_sdio_get_speed(); + return 1; +} + +void linux_sdio_deinit(void *pv) +{ + + /** + * TODO : + **/ + + + sdio_unregister_driver(&wilc_bus); +} + +int linux_sdio_set_max_speed(void) +{ + return linux_sdio_set_speed(MAX_SPEED); +} + +int linux_sdio_set_default_speed(void) +{ + return linux_sdio_set_speed(sdio_default_speed); +} + + +