15625f965SAjay Singh // SPDX-License-Identifier: GPL-2.0 25625f965SAjay Singh /* 35625f965SAjay Singh * Copyright (c) 2012 - 2018 Microchip Technology Inc., and its subsidiaries. 45625f965SAjay Singh * All rights reserved. 55625f965SAjay Singh */ 65625f965SAjay Singh 75625f965SAjay Singh #include <linux/clk.h> 85625f965SAjay Singh #include <linux/mmc/sdio_func.h> 9c83e2a6eSAjay Singh #include <linux/mmc/sdio_ids.h> 105625f965SAjay Singh #include <linux/mmc/host.h> 115625f965SAjay Singh #include <linux/mmc/sdio.h> 125625f965SAjay Singh #include <linux/of_irq.h> 135625f965SAjay Singh 145625f965SAjay Singh #include "netdev.h" 155625f965SAjay Singh #include "cfg80211.h" 165625f965SAjay Singh 175625f965SAjay Singh #define SDIO_MODALIAS "wilc1000_sdio" 185625f965SAjay Singh 195625f965SAjay Singh static const struct sdio_device_id wilc_sdio_ids[] = { 20c83e2a6eSAjay Singh { SDIO_DEVICE(SDIO_VENDOR_ID_MICROCHIP_WILC, SDIO_DEVICE_ID_MICROCHIP_WILC1000) }, 215625f965SAjay Singh { }, 225625f965SAjay Singh }; 23*57d545b5SMichael Walle MODULE_DEVICE_TABLE(sdio, wilc_sdio_ids); 245625f965SAjay Singh 255625f965SAjay Singh #define WILC_SDIO_BLOCK_SIZE 512 265625f965SAjay Singh 275625f965SAjay Singh struct wilc_sdio { 285625f965SAjay Singh bool irq_gpio; 295625f965SAjay Singh u32 block_size; 3039d0f1b0SAjay Singh bool isinit; 315625f965SAjay Singh int has_thrpt_enh3; 3240b717bfSAjay.Kathat@microchip.com u8 *cmd53_buf; 335625f965SAjay Singh }; 345625f965SAjay Singh 355625f965SAjay Singh struct sdio_cmd52 { 365625f965SAjay Singh u32 read_write: 1; 375625f965SAjay Singh u32 function: 3; 385625f965SAjay Singh u32 raw: 1; 395625f965SAjay Singh u32 address: 17; 405625f965SAjay Singh u32 data: 8; 415625f965SAjay Singh }; 425625f965SAjay Singh 435625f965SAjay Singh struct sdio_cmd53 { 445625f965SAjay Singh u32 read_write: 1; 455625f965SAjay Singh u32 function: 3; 465625f965SAjay Singh u32 block_mode: 1; 475625f965SAjay Singh u32 increment: 1; 485625f965SAjay Singh u32 address: 17; 495625f965SAjay Singh u32 count: 9; 505625f965SAjay Singh u8 *buffer; 515625f965SAjay Singh u32 block_size; 5240b717bfSAjay.Kathat@microchip.com bool use_global_buf; 535625f965SAjay Singh }; 545625f965SAjay Singh 555625f965SAjay Singh static const struct wilc_hif_func wilc_hif_sdio; 565625f965SAjay Singh 575625f965SAjay Singh static void wilc_sdio_interrupt(struct sdio_func *func) 585625f965SAjay Singh { 595625f965SAjay Singh sdio_release_host(func); 605625f965SAjay Singh wilc_handle_isr(sdio_get_drvdata(func)); 615625f965SAjay Singh sdio_claim_host(func); 625625f965SAjay Singh } 635625f965SAjay Singh 645625f965SAjay Singh static int wilc_sdio_cmd52(struct wilc *wilc, struct sdio_cmd52 *cmd) 655625f965SAjay Singh { 665625f965SAjay Singh struct sdio_func *func = container_of(wilc->dev, struct sdio_func, dev); 675625f965SAjay Singh int ret; 685625f965SAjay Singh u8 data; 695625f965SAjay Singh 705625f965SAjay Singh sdio_claim_host(func); 715625f965SAjay Singh 725625f965SAjay Singh func->num = cmd->function; 735625f965SAjay Singh if (cmd->read_write) { /* write */ 745625f965SAjay Singh if (cmd->raw) { 755625f965SAjay Singh sdio_writeb(func, cmd->data, cmd->address, &ret); 765625f965SAjay Singh data = sdio_readb(func, cmd->address, &ret); 775625f965SAjay Singh cmd->data = data; 785625f965SAjay Singh } else { 795625f965SAjay Singh sdio_writeb(func, cmd->data, cmd->address, &ret); 805625f965SAjay Singh } 815625f965SAjay Singh } else { /* read */ 825625f965SAjay Singh data = sdio_readb(func, cmd->address, &ret); 835625f965SAjay Singh cmd->data = data; 845625f965SAjay Singh } 855625f965SAjay Singh 865625f965SAjay Singh sdio_release_host(func); 875625f965SAjay Singh 885625f965SAjay Singh if (ret) 895625f965SAjay Singh dev_err(&func->dev, "%s..failed, err(%d)\n", __func__, ret); 905625f965SAjay Singh return ret; 915625f965SAjay Singh } 925625f965SAjay Singh 935625f965SAjay Singh static int wilc_sdio_cmd53(struct wilc *wilc, struct sdio_cmd53 *cmd) 945625f965SAjay Singh { 955625f965SAjay Singh struct sdio_func *func = container_of(wilc->dev, struct sdio_func, dev); 965625f965SAjay Singh int size, ret; 9740b717bfSAjay.Kathat@microchip.com struct wilc_sdio *sdio_priv = wilc->bus_data; 9840b717bfSAjay.Kathat@microchip.com u8 *buf = cmd->buffer; 995625f965SAjay Singh 1005625f965SAjay Singh sdio_claim_host(func); 1015625f965SAjay Singh 1025625f965SAjay Singh func->num = cmd->function; 1035625f965SAjay Singh func->cur_blksize = cmd->block_size; 1045625f965SAjay Singh if (cmd->block_mode) 1055625f965SAjay Singh size = cmd->count * cmd->block_size; 1065625f965SAjay Singh else 1075625f965SAjay Singh size = cmd->count; 1085625f965SAjay Singh 10940b717bfSAjay.Kathat@microchip.com if (cmd->use_global_buf) { 11040b717bfSAjay.Kathat@microchip.com if (size > sizeof(u32)) 11140b717bfSAjay.Kathat@microchip.com return -EINVAL; 11240b717bfSAjay.Kathat@microchip.com 11340b717bfSAjay.Kathat@microchip.com buf = sdio_priv->cmd53_buf; 11440b717bfSAjay.Kathat@microchip.com } 11540b717bfSAjay.Kathat@microchip.com 1165625f965SAjay Singh if (cmd->read_write) { /* write */ 11740b717bfSAjay.Kathat@microchip.com if (cmd->use_global_buf) 11840b717bfSAjay.Kathat@microchip.com memcpy(buf, cmd->buffer, size); 11940b717bfSAjay.Kathat@microchip.com 12040b717bfSAjay.Kathat@microchip.com ret = sdio_memcpy_toio(func, cmd->address, buf, size); 1215625f965SAjay Singh } else { /* read */ 12240b717bfSAjay.Kathat@microchip.com ret = sdio_memcpy_fromio(func, buf, cmd->address, size); 12340b717bfSAjay.Kathat@microchip.com 12440b717bfSAjay.Kathat@microchip.com if (cmd->use_global_buf) 12540b717bfSAjay.Kathat@microchip.com memcpy(cmd->buffer, buf, size); 1265625f965SAjay Singh } 1275625f965SAjay Singh 1285625f965SAjay Singh sdio_release_host(func); 1295625f965SAjay Singh 1305625f965SAjay Singh if (ret) 1315625f965SAjay Singh dev_err(&func->dev, "%s..failed, err(%d)\n", __func__, ret); 1325625f965SAjay Singh 1335625f965SAjay Singh return ret; 1345625f965SAjay Singh } 1355625f965SAjay Singh 1365625f965SAjay Singh static int wilc_sdio_probe(struct sdio_func *func, 1375625f965SAjay Singh const struct sdio_device_id *id) 1385625f965SAjay Singh { 1395625f965SAjay Singh struct wilc *wilc; 1405625f965SAjay Singh int ret; 1415625f965SAjay Singh struct wilc_sdio *sdio_priv; 1425625f965SAjay Singh 1435625f965SAjay Singh sdio_priv = kzalloc(sizeof(*sdio_priv), GFP_KERNEL); 1445625f965SAjay Singh if (!sdio_priv) 1455625f965SAjay Singh return -ENOMEM; 1465625f965SAjay Singh 14740b717bfSAjay.Kathat@microchip.com sdio_priv->cmd53_buf = kzalloc(sizeof(u32), GFP_KERNEL); 14840b717bfSAjay.Kathat@microchip.com if (!sdio_priv->cmd53_buf) { 14940b717bfSAjay.Kathat@microchip.com ret = -ENOMEM; 15040b717bfSAjay.Kathat@microchip.com goto free; 15140b717bfSAjay.Kathat@microchip.com } 15240b717bfSAjay.Kathat@microchip.com 1535625f965SAjay Singh ret = wilc_cfg80211_init(&wilc, &func->dev, WILC_HIF_SDIO, 1545625f965SAjay Singh &wilc_hif_sdio); 155dc8b338fSClaudiu Beznea if (ret) 156dc8b338fSClaudiu Beznea goto free; 1575625f965SAjay Singh 1585625f965SAjay Singh if (IS_ENABLED(CONFIG_WILC1000_HW_OOB_INTR)) { 1595625f965SAjay Singh struct device_node *np = func->card->dev.of_node; 1605625f965SAjay Singh int irq_num = of_irq_get(np, 0); 1615625f965SAjay Singh 1625625f965SAjay Singh if (irq_num > 0) { 1635625f965SAjay Singh wilc->dev_irq_num = irq_num; 1645625f965SAjay Singh sdio_priv->irq_gpio = true; 1655625f965SAjay Singh } 1665625f965SAjay Singh } 1675625f965SAjay Singh 1685625f965SAjay Singh sdio_set_drvdata(func, wilc); 1695625f965SAjay Singh wilc->bus_data = sdio_priv; 1705625f965SAjay Singh wilc->dev = &func->dev; 1715625f965SAjay Singh 1721d89fd1aSClaudiu Beznea wilc->rtc_clk = devm_clk_get_optional(&func->card->dev, "rtc"); 1731d89fd1aSClaudiu Beznea if (IS_ERR(wilc->rtc_clk)) { 1741d89fd1aSClaudiu Beznea ret = PTR_ERR(wilc->rtc_clk); 175f36a0ee5SClaudiu Beznea goto dispose_irq; 1761d89fd1aSClaudiu Beznea } 1775625f965SAjay Singh clk_prepare_enable(wilc->rtc_clk); 1785625f965SAjay Singh 1795625f965SAjay Singh dev_info(&func->dev, "Driver Initializing success\n"); 1805625f965SAjay Singh return 0; 181dc8b338fSClaudiu Beznea 182f36a0ee5SClaudiu Beznea dispose_irq: 183f36a0ee5SClaudiu Beznea irq_dispose_mapping(wilc->dev_irq_num); 184dc8b338fSClaudiu Beznea wilc_netdev_cleanup(wilc); 185dc8b338fSClaudiu Beznea free: 18640b717bfSAjay.Kathat@microchip.com kfree(sdio_priv->cmd53_buf); 187dc8b338fSClaudiu Beznea kfree(sdio_priv); 188dc8b338fSClaudiu Beznea return ret; 1895625f965SAjay Singh } 1905625f965SAjay Singh 1915625f965SAjay Singh static void wilc_sdio_remove(struct sdio_func *func) 1925625f965SAjay Singh { 1935625f965SAjay Singh struct wilc *wilc = sdio_get_drvdata(func); 1944894edacSDan Carpenter struct wilc_sdio *sdio_priv = wilc->bus_data; 1955625f965SAjay Singh 1965625f965SAjay Singh clk_disable_unprepare(wilc->rtc_clk); 1975625f965SAjay Singh wilc_netdev_cleanup(wilc); 19840b717bfSAjay.Kathat@microchip.com kfree(sdio_priv->cmd53_buf); 1994894edacSDan Carpenter kfree(sdio_priv); 2005625f965SAjay Singh } 2015625f965SAjay Singh 2025625f965SAjay Singh static int wilc_sdio_reset(struct wilc *wilc) 2035625f965SAjay Singh { 2045625f965SAjay Singh struct sdio_cmd52 cmd; 2055625f965SAjay Singh int ret; 2065625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev); 2075625f965SAjay Singh 2085625f965SAjay Singh cmd.read_write = 1; 2095625f965SAjay Singh cmd.function = 0; 2105625f965SAjay Singh cmd.raw = 0; 2115625f965SAjay Singh cmd.address = SDIO_CCCR_ABORT; 2125625f965SAjay Singh cmd.data = WILC_SDIO_CCCR_ABORT_RESET; 2135625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd); 2145625f965SAjay Singh if (ret) { 2155625f965SAjay Singh dev_err(&func->dev, "Fail cmd 52, reset cmd ...\n"); 2165625f965SAjay Singh return ret; 2175625f965SAjay Singh } 2185625f965SAjay Singh return 0; 2195625f965SAjay Singh } 2205625f965SAjay Singh 22139d0f1b0SAjay Singh static bool wilc_sdio_is_init(struct wilc *wilc) 22239d0f1b0SAjay Singh { 22339d0f1b0SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data; 22439d0f1b0SAjay Singh 22539d0f1b0SAjay Singh return sdio_priv->isinit; 22639d0f1b0SAjay Singh } 22739d0f1b0SAjay Singh 2285625f965SAjay Singh static int wilc_sdio_suspend(struct device *dev) 2295625f965SAjay Singh { 2305625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(dev); 2315625f965SAjay Singh struct wilc *wilc = sdio_get_drvdata(func); 2325625f965SAjay Singh int ret; 2335625f965SAjay Singh 2345625f965SAjay Singh dev_info(dev, "sdio suspend\n"); 2355625f965SAjay Singh chip_wakeup(wilc); 2365625f965SAjay Singh 2375625f965SAjay Singh if (!IS_ERR(wilc->rtc_clk)) 2385625f965SAjay Singh clk_disable_unprepare(wilc->rtc_clk); 2395625f965SAjay Singh 2405625f965SAjay Singh if (wilc->suspend_event) { 2415625f965SAjay Singh host_sleep_notify(wilc); 2425625f965SAjay Singh chip_allow_sleep(wilc); 2435625f965SAjay Singh } 2445625f965SAjay Singh 2455625f965SAjay Singh ret = wilc_sdio_reset(wilc); 2465625f965SAjay Singh if (ret) { 2475625f965SAjay Singh dev_err(&func->dev, "Fail reset sdio\n"); 2485625f965SAjay Singh return ret; 2495625f965SAjay Singh } 2505625f965SAjay Singh sdio_claim_host(func); 2515625f965SAjay Singh 2525625f965SAjay Singh return 0; 2535625f965SAjay Singh } 2545625f965SAjay Singh 2555625f965SAjay Singh static int wilc_sdio_enable_interrupt(struct wilc *dev) 2565625f965SAjay Singh { 2575625f965SAjay Singh struct sdio_func *func = container_of(dev->dev, struct sdio_func, dev); 2585625f965SAjay Singh int ret = 0; 2595625f965SAjay Singh 2605625f965SAjay Singh sdio_claim_host(func); 2615625f965SAjay Singh ret = sdio_claim_irq(func, wilc_sdio_interrupt); 2625625f965SAjay Singh sdio_release_host(func); 2635625f965SAjay Singh 2645625f965SAjay Singh if (ret < 0) { 2655625f965SAjay Singh dev_err(&func->dev, "can't claim sdio_irq, err(%d)\n", ret); 2665625f965SAjay Singh ret = -EIO; 2675625f965SAjay Singh } 2685625f965SAjay Singh return ret; 2695625f965SAjay Singh } 2705625f965SAjay Singh 2715625f965SAjay Singh static void wilc_sdio_disable_interrupt(struct wilc *dev) 2725625f965SAjay Singh { 2735625f965SAjay Singh struct sdio_func *func = container_of(dev->dev, struct sdio_func, dev); 2745625f965SAjay Singh int ret; 2755625f965SAjay Singh 2765625f965SAjay Singh sdio_claim_host(func); 2775625f965SAjay Singh ret = sdio_release_irq(func); 2785625f965SAjay Singh if (ret < 0) 2795625f965SAjay Singh dev_err(&func->dev, "can't release sdio_irq, err(%d)\n", ret); 2805625f965SAjay Singh sdio_release_host(func); 2815625f965SAjay Singh } 2825625f965SAjay Singh 2835625f965SAjay Singh /******************************************** 2845625f965SAjay Singh * 2855625f965SAjay Singh * Function 0 2865625f965SAjay Singh * 2875625f965SAjay Singh ********************************************/ 2885625f965SAjay Singh 2895625f965SAjay Singh static int wilc_sdio_set_func0_csa_address(struct wilc *wilc, u32 adr) 2905625f965SAjay Singh { 2915625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev); 2925625f965SAjay Singh struct sdio_cmd52 cmd; 2935625f965SAjay Singh int ret; 2945625f965SAjay Singh 2955625f965SAjay Singh /** 2965625f965SAjay Singh * Review: BIG ENDIAN 2975625f965SAjay Singh **/ 2985625f965SAjay Singh cmd.read_write = 1; 2995625f965SAjay Singh cmd.function = 0; 3005625f965SAjay Singh cmd.raw = 0; 3015625f965SAjay Singh cmd.address = WILC_SDIO_FBR_CSA_REG; 3025625f965SAjay Singh cmd.data = (u8)adr; 3035625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd); 3045625f965SAjay Singh if (ret) { 3055625f965SAjay Singh dev_err(&func->dev, "Failed cmd52, set %04x data...\n", 3065625f965SAjay Singh cmd.address); 3075625f965SAjay Singh return ret; 3085625f965SAjay Singh } 3095625f965SAjay Singh 3105625f965SAjay Singh cmd.address = WILC_SDIO_FBR_CSA_REG + 1; 3115625f965SAjay Singh cmd.data = (u8)(adr >> 8); 3125625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd); 3135625f965SAjay Singh if (ret) { 3145625f965SAjay Singh dev_err(&func->dev, "Failed cmd52, set %04x data...\n", 3155625f965SAjay Singh cmd.address); 3165625f965SAjay Singh return ret; 3175625f965SAjay Singh } 3185625f965SAjay Singh 3195625f965SAjay Singh cmd.address = WILC_SDIO_FBR_CSA_REG + 2; 3205625f965SAjay Singh cmd.data = (u8)(adr >> 16); 3215625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd); 3225625f965SAjay Singh if (ret) { 3235625f965SAjay Singh dev_err(&func->dev, "Failed cmd52, set %04x data...\n", 3245625f965SAjay Singh cmd.address); 3255625f965SAjay Singh return ret; 3265625f965SAjay Singh } 3275625f965SAjay Singh 3285625f965SAjay Singh return 0; 3295625f965SAjay Singh } 3305625f965SAjay Singh 3315625f965SAjay Singh static int wilc_sdio_set_block_size(struct wilc *wilc, u8 func_num, 3325625f965SAjay Singh u32 block_size) 3335625f965SAjay Singh { 3345625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev); 3355625f965SAjay Singh struct sdio_cmd52 cmd; 3365625f965SAjay Singh int ret; 3375625f965SAjay Singh 3385625f965SAjay Singh cmd.read_write = 1; 3395625f965SAjay Singh cmd.function = 0; 3405625f965SAjay Singh cmd.raw = 0; 3415625f965SAjay Singh cmd.address = SDIO_FBR_BASE(func_num) + SDIO_CCCR_BLKSIZE; 3425625f965SAjay Singh cmd.data = (u8)block_size; 3435625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd); 3445625f965SAjay Singh if (ret) { 3455625f965SAjay Singh dev_err(&func->dev, "Failed cmd52, set %04x data...\n", 3465625f965SAjay Singh cmd.address); 3475625f965SAjay Singh return ret; 3485625f965SAjay Singh } 3495625f965SAjay Singh 3505625f965SAjay Singh cmd.address = SDIO_FBR_BASE(func_num) + SDIO_CCCR_BLKSIZE + 1; 3515625f965SAjay Singh cmd.data = (u8)(block_size >> 8); 3525625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd); 3535625f965SAjay Singh if (ret) { 3545625f965SAjay Singh dev_err(&func->dev, "Failed cmd52, set %04x data...\n", 3555625f965SAjay Singh cmd.address); 3565625f965SAjay Singh return ret; 3575625f965SAjay Singh } 3585625f965SAjay Singh 3595625f965SAjay Singh return 0; 3605625f965SAjay Singh } 3615625f965SAjay Singh 3625625f965SAjay Singh /******************************************** 3635625f965SAjay Singh * 3645625f965SAjay Singh * Sdio interfaces 3655625f965SAjay Singh * 3665625f965SAjay Singh ********************************************/ 3675625f965SAjay Singh static int wilc_sdio_write_reg(struct wilc *wilc, u32 addr, u32 data) 3685625f965SAjay Singh { 3695625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev); 3705625f965SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data; 3715625f965SAjay Singh int ret; 3725625f965SAjay Singh 3735625f965SAjay Singh cpu_to_le32s(&data); 3745625f965SAjay Singh 3755625f965SAjay Singh if (addr >= 0xf0 && addr <= 0xff) { /* only vendor specific registers */ 3765625f965SAjay Singh struct sdio_cmd52 cmd; 3775625f965SAjay Singh 3785625f965SAjay Singh cmd.read_write = 1; 3795625f965SAjay Singh cmd.function = 0; 3805625f965SAjay Singh cmd.raw = 0; 3815625f965SAjay Singh cmd.address = addr; 3825625f965SAjay Singh cmd.data = data; 3835625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd); 3845625f965SAjay Singh if (ret) 3855625f965SAjay Singh dev_err(&func->dev, 3865625f965SAjay Singh "Failed cmd 52, read reg (%08x) ...\n", addr); 3875625f965SAjay Singh } else { 3885625f965SAjay Singh struct sdio_cmd53 cmd; 3895625f965SAjay Singh 3905625f965SAjay Singh /** 3915625f965SAjay Singh * set the AHB address 3925625f965SAjay Singh **/ 3935625f965SAjay Singh ret = wilc_sdio_set_func0_csa_address(wilc, addr); 3945625f965SAjay Singh if (ret) 3955625f965SAjay Singh return ret; 3965625f965SAjay Singh 3975625f965SAjay Singh cmd.read_write = 1; 3985625f965SAjay Singh cmd.function = 0; 3995625f965SAjay Singh cmd.address = WILC_SDIO_FBR_DATA_REG; 4005625f965SAjay Singh cmd.block_mode = 0; 4015625f965SAjay Singh cmd.increment = 1; 40240b717bfSAjay.Kathat@microchip.com cmd.count = sizeof(u32); 4035625f965SAjay Singh cmd.buffer = (u8 *)&data; 40440b717bfSAjay.Kathat@microchip.com cmd.use_global_buf = true; 4055625f965SAjay Singh cmd.block_size = sdio_priv->block_size; 4065625f965SAjay Singh ret = wilc_sdio_cmd53(wilc, &cmd); 4075625f965SAjay Singh if (ret) 4085625f965SAjay Singh dev_err(&func->dev, 4095625f965SAjay Singh "Failed cmd53, write reg (%08x)...\n", addr); 4105625f965SAjay Singh } 4115625f965SAjay Singh 4125625f965SAjay Singh return ret; 4135625f965SAjay Singh } 4145625f965SAjay Singh 4155625f965SAjay Singh static int wilc_sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size) 4165625f965SAjay Singh { 4175625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev); 4185625f965SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data; 4195625f965SAjay Singh u32 block_size = sdio_priv->block_size; 4205625f965SAjay Singh struct sdio_cmd53 cmd; 4215625f965SAjay Singh int nblk, nleft, ret; 4225625f965SAjay Singh 4235625f965SAjay Singh cmd.read_write = 1; 4245625f965SAjay Singh if (addr > 0) { 4255625f965SAjay Singh /** 4265625f965SAjay Singh * func 0 access 4275625f965SAjay Singh **/ 4285625f965SAjay Singh cmd.function = 0; 4295625f965SAjay Singh cmd.address = WILC_SDIO_FBR_DATA_REG; 4305625f965SAjay Singh } else { 4315625f965SAjay Singh /** 4325625f965SAjay Singh * func 1 access 4335625f965SAjay Singh **/ 4345625f965SAjay Singh cmd.function = 1; 4355625f965SAjay Singh cmd.address = WILC_SDIO_F1_DATA_REG; 4365625f965SAjay Singh } 4375625f965SAjay Singh 4385625f965SAjay Singh size = ALIGN(size, 4); 4395625f965SAjay Singh nblk = size / block_size; 4405625f965SAjay Singh nleft = size % block_size; 4415625f965SAjay Singh 44240b717bfSAjay.Kathat@microchip.com cmd.use_global_buf = false; 4435625f965SAjay Singh if (nblk > 0) { 4445625f965SAjay Singh cmd.block_mode = 1; 4455625f965SAjay Singh cmd.increment = 1; 4465625f965SAjay Singh cmd.count = nblk; 4475625f965SAjay Singh cmd.buffer = buf; 4485625f965SAjay Singh cmd.block_size = block_size; 4495625f965SAjay Singh if (addr > 0) { 4505625f965SAjay Singh ret = wilc_sdio_set_func0_csa_address(wilc, addr); 4515625f965SAjay Singh if (ret) 4525625f965SAjay Singh return ret; 4535625f965SAjay Singh } 4545625f965SAjay Singh ret = wilc_sdio_cmd53(wilc, &cmd); 4555625f965SAjay Singh if (ret) { 4565625f965SAjay Singh dev_err(&func->dev, 4575625f965SAjay Singh "Failed cmd53 [%x], block send...\n", addr); 4585625f965SAjay Singh return ret; 4595625f965SAjay Singh } 4605625f965SAjay Singh if (addr > 0) 4615625f965SAjay Singh addr += nblk * block_size; 4625625f965SAjay Singh buf += nblk * block_size; 4635625f965SAjay Singh } 4645625f965SAjay Singh 4655625f965SAjay Singh if (nleft > 0) { 4665625f965SAjay Singh cmd.block_mode = 0; 4675625f965SAjay Singh cmd.increment = 1; 4685625f965SAjay Singh cmd.count = nleft; 4695625f965SAjay Singh cmd.buffer = buf; 4705625f965SAjay Singh 4715625f965SAjay Singh cmd.block_size = block_size; 4725625f965SAjay Singh 4735625f965SAjay Singh if (addr > 0) { 4745625f965SAjay Singh ret = wilc_sdio_set_func0_csa_address(wilc, addr); 4755625f965SAjay Singh if (ret) 4765625f965SAjay Singh return ret; 4775625f965SAjay Singh } 4785625f965SAjay Singh ret = wilc_sdio_cmd53(wilc, &cmd); 4795625f965SAjay Singh if (ret) { 4805625f965SAjay Singh dev_err(&func->dev, 4815625f965SAjay Singh "Failed cmd53 [%x], bytes send...\n", addr); 4825625f965SAjay Singh return ret; 4835625f965SAjay Singh } 4845625f965SAjay Singh } 4855625f965SAjay Singh 4865625f965SAjay Singh return 0; 4875625f965SAjay Singh } 4885625f965SAjay Singh 4895625f965SAjay Singh static int wilc_sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data) 4905625f965SAjay Singh { 4915625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev); 4925625f965SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data; 4935625f965SAjay Singh int ret; 4945625f965SAjay Singh 4955625f965SAjay Singh if (addr >= 0xf0 && addr <= 0xff) { /* only vendor specific registers */ 4965625f965SAjay Singh struct sdio_cmd52 cmd; 4975625f965SAjay Singh 4985625f965SAjay Singh cmd.read_write = 0; 4995625f965SAjay Singh cmd.function = 0; 5005625f965SAjay Singh cmd.raw = 0; 5015625f965SAjay Singh cmd.address = addr; 5025625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd); 5035625f965SAjay Singh if (ret) { 5045625f965SAjay Singh dev_err(&func->dev, 5055625f965SAjay Singh "Failed cmd 52, read reg (%08x) ...\n", addr); 5065625f965SAjay Singh return ret; 5075625f965SAjay Singh } 5085625f965SAjay Singh *data = cmd.data; 5095625f965SAjay Singh } else { 5105625f965SAjay Singh struct sdio_cmd53 cmd; 5115625f965SAjay Singh 5125625f965SAjay Singh ret = wilc_sdio_set_func0_csa_address(wilc, addr); 5135625f965SAjay Singh if (ret) 5145625f965SAjay Singh return ret; 5155625f965SAjay Singh 5165625f965SAjay Singh cmd.read_write = 0; 5175625f965SAjay Singh cmd.function = 0; 5185625f965SAjay Singh cmd.address = WILC_SDIO_FBR_DATA_REG; 5195625f965SAjay Singh cmd.block_mode = 0; 5205625f965SAjay Singh cmd.increment = 1; 52140b717bfSAjay.Kathat@microchip.com cmd.count = sizeof(u32); 5225625f965SAjay Singh cmd.buffer = (u8 *)data; 52340b717bfSAjay.Kathat@microchip.com cmd.use_global_buf = true; 5245625f965SAjay Singh 5255625f965SAjay Singh cmd.block_size = sdio_priv->block_size; 5265625f965SAjay Singh ret = wilc_sdio_cmd53(wilc, &cmd); 5275625f965SAjay Singh if (ret) { 5285625f965SAjay Singh dev_err(&func->dev, 5295625f965SAjay Singh "Failed cmd53, read reg (%08x)...\n", addr); 5305625f965SAjay Singh return ret; 5315625f965SAjay Singh } 5325625f965SAjay Singh } 5335625f965SAjay Singh 5345625f965SAjay Singh le32_to_cpus(data); 5355625f965SAjay Singh return 0; 5365625f965SAjay Singh } 5375625f965SAjay Singh 5385625f965SAjay Singh static int wilc_sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size) 5395625f965SAjay Singh { 5405625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev); 5415625f965SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data; 5425625f965SAjay Singh u32 block_size = sdio_priv->block_size; 5435625f965SAjay Singh struct sdio_cmd53 cmd; 5445625f965SAjay Singh int nblk, nleft, ret; 5455625f965SAjay Singh 5465625f965SAjay Singh cmd.read_write = 0; 5475625f965SAjay Singh if (addr > 0) { 5485625f965SAjay Singh /** 5495625f965SAjay Singh * func 0 access 5505625f965SAjay Singh **/ 5515625f965SAjay Singh cmd.function = 0; 5525625f965SAjay Singh cmd.address = WILC_SDIO_FBR_DATA_REG; 5535625f965SAjay Singh } else { 5545625f965SAjay Singh /** 5555625f965SAjay Singh * func 1 access 5565625f965SAjay Singh **/ 5575625f965SAjay Singh cmd.function = 1; 5585625f965SAjay Singh cmd.address = WILC_SDIO_F1_DATA_REG; 5595625f965SAjay Singh } 5605625f965SAjay Singh 5615625f965SAjay Singh size = ALIGN(size, 4); 5625625f965SAjay Singh nblk = size / block_size; 5635625f965SAjay Singh nleft = size % block_size; 5645625f965SAjay Singh 56540b717bfSAjay.Kathat@microchip.com cmd.use_global_buf = false; 5665625f965SAjay Singh if (nblk > 0) { 5675625f965SAjay Singh cmd.block_mode = 1; 5685625f965SAjay Singh cmd.increment = 1; 5695625f965SAjay Singh cmd.count = nblk; 5705625f965SAjay Singh cmd.buffer = buf; 5715625f965SAjay Singh cmd.block_size = block_size; 5725625f965SAjay Singh if (addr > 0) { 5735625f965SAjay Singh ret = wilc_sdio_set_func0_csa_address(wilc, addr); 5745625f965SAjay Singh if (ret) 5755625f965SAjay Singh return ret; 5765625f965SAjay Singh } 5775625f965SAjay Singh ret = wilc_sdio_cmd53(wilc, &cmd); 5785625f965SAjay Singh if (ret) { 5795625f965SAjay Singh dev_err(&func->dev, 5805625f965SAjay Singh "Failed cmd53 [%x], block read...\n", addr); 5815625f965SAjay Singh return ret; 5825625f965SAjay Singh } 5835625f965SAjay Singh if (addr > 0) 5845625f965SAjay Singh addr += nblk * block_size; 5855625f965SAjay Singh buf += nblk * block_size; 5865625f965SAjay Singh } /* if (nblk > 0) */ 5875625f965SAjay Singh 5885625f965SAjay Singh if (nleft > 0) { 5895625f965SAjay Singh cmd.block_mode = 0; 5905625f965SAjay Singh cmd.increment = 1; 5915625f965SAjay Singh cmd.count = nleft; 5925625f965SAjay Singh cmd.buffer = buf; 5935625f965SAjay Singh 5945625f965SAjay Singh cmd.block_size = block_size; 5955625f965SAjay Singh 5965625f965SAjay Singh if (addr > 0) { 5975625f965SAjay Singh ret = wilc_sdio_set_func0_csa_address(wilc, addr); 5985625f965SAjay Singh if (ret) 5995625f965SAjay Singh return ret; 6005625f965SAjay Singh } 6015625f965SAjay Singh ret = wilc_sdio_cmd53(wilc, &cmd); 6025625f965SAjay Singh if (ret) { 6035625f965SAjay Singh dev_err(&func->dev, 6045625f965SAjay Singh "Failed cmd53 [%x], bytes read...\n", addr); 6055625f965SAjay Singh return ret; 6065625f965SAjay Singh } 6075625f965SAjay Singh } 6085625f965SAjay Singh 6095625f965SAjay Singh return 0; 6105625f965SAjay Singh } 6115625f965SAjay Singh 6125625f965SAjay Singh /******************************************** 6135625f965SAjay Singh * 6145625f965SAjay Singh * Bus interfaces 6155625f965SAjay Singh * 6165625f965SAjay Singh ********************************************/ 6175625f965SAjay Singh 6185625f965SAjay Singh static int wilc_sdio_deinit(struct wilc *wilc) 6195625f965SAjay Singh { 62039d0f1b0SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data; 62139d0f1b0SAjay Singh 62239d0f1b0SAjay Singh sdio_priv->isinit = false; 6235625f965SAjay Singh return 0; 6245625f965SAjay Singh } 6255625f965SAjay Singh 6265625f965SAjay Singh static int wilc_sdio_init(struct wilc *wilc, bool resume) 6275625f965SAjay Singh { 6285625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev); 6295625f965SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data; 6305625f965SAjay Singh struct sdio_cmd52 cmd; 6315625f965SAjay Singh int loop, ret; 6325625f965SAjay Singh u32 chipid; 6335625f965SAjay Singh 6345625f965SAjay Singh /** 6355625f965SAjay Singh * function 0 csa enable 6365625f965SAjay Singh **/ 6375625f965SAjay Singh cmd.read_write = 1; 6385625f965SAjay Singh cmd.function = 0; 6395625f965SAjay Singh cmd.raw = 1; 64072ebd675SAjay Singh cmd.address = SDIO_FBR_BASE(1); 6415625f965SAjay Singh cmd.data = SDIO_FBR_ENABLE_CSA; 6425625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd); 6435625f965SAjay Singh if (ret) { 6445625f965SAjay Singh dev_err(&func->dev, "Fail cmd 52, enable csa...\n"); 6455625f965SAjay Singh return ret; 6465625f965SAjay Singh } 6475625f965SAjay Singh 6485625f965SAjay Singh /** 6495625f965SAjay Singh * function 0 block size 6505625f965SAjay Singh **/ 6515625f965SAjay Singh ret = wilc_sdio_set_block_size(wilc, 0, WILC_SDIO_BLOCK_SIZE); 6525625f965SAjay Singh if (ret) { 6535625f965SAjay Singh dev_err(&func->dev, "Fail cmd 52, set func 0 block size...\n"); 6545625f965SAjay Singh return ret; 6555625f965SAjay Singh } 6565625f965SAjay Singh sdio_priv->block_size = WILC_SDIO_BLOCK_SIZE; 6575625f965SAjay Singh 6585625f965SAjay Singh /** 6595625f965SAjay Singh * enable func1 IO 6605625f965SAjay Singh **/ 6615625f965SAjay Singh cmd.read_write = 1; 6625625f965SAjay Singh cmd.function = 0; 6635625f965SAjay Singh cmd.raw = 1; 6645625f965SAjay Singh cmd.address = SDIO_CCCR_IOEx; 6655625f965SAjay Singh cmd.data = WILC_SDIO_CCCR_IO_EN_FUNC1; 6665625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd); 6675625f965SAjay Singh if (ret) { 6685625f965SAjay Singh dev_err(&func->dev, 6695625f965SAjay Singh "Fail cmd 52, set IOE register...\n"); 6705625f965SAjay Singh return ret; 6715625f965SAjay Singh } 6725625f965SAjay Singh 6735625f965SAjay Singh /** 6745625f965SAjay Singh * make sure func 1 is up 6755625f965SAjay Singh **/ 6765625f965SAjay Singh cmd.read_write = 0; 6775625f965SAjay Singh cmd.function = 0; 6785625f965SAjay Singh cmd.raw = 0; 6795625f965SAjay Singh cmd.address = SDIO_CCCR_IORx; 6805625f965SAjay Singh loop = 3; 6815625f965SAjay Singh do { 6825625f965SAjay Singh cmd.data = 0; 6835625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd); 6845625f965SAjay Singh if (ret) { 6855625f965SAjay Singh dev_err(&func->dev, 6865625f965SAjay Singh "Fail cmd 52, get IOR register...\n"); 6875625f965SAjay Singh return ret; 6885625f965SAjay Singh } 6895625f965SAjay Singh if (cmd.data == WILC_SDIO_CCCR_IO_EN_FUNC1) 6905625f965SAjay Singh break; 6915625f965SAjay Singh } while (loop--); 6925625f965SAjay Singh 6935625f965SAjay Singh if (loop <= 0) { 6945625f965SAjay Singh dev_err(&func->dev, "Fail func 1 is not ready...\n"); 6955625f965SAjay Singh return -EINVAL; 6965625f965SAjay Singh } 6975625f965SAjay Singh 6985625f965SAjay Singh /** 6995625f965SAjay Singh * func 1 is ready, set func 1 block size 7005625f965SAjay Singh **/ 7015625f965SAjay Singh ret = wilc_sdio_set_block_size(wilc, 1, WILC_SDIO_BLOCK_SIZE); 7025625f965SAjay Singh if (ret) { 7035625f965SAjay Singh dev_err(&func->dev, "Fail set func 1 block size...\n"); 7045625f965SAjay Singh return ret; 7055625f965SAjay Singh } 7065625f965SAjay Singh 7075625f965SAjay Singh /** 7085625f965SAjay Singh * func 1 interrupt enable 7095625f965SAjay Singh **/ 7105625f965SAjay Singh cmd.read_write = 1; 7115625f965SAjay Singh cmd.function = 0; 7125625f965SAjay Singh cmd.raw = 1; 7135625f965SAjay Singh cmd.address = SDIO_CCCR_IENx; 7145625f965SAjay Singh cmd.data = WILC_SDIO_CCCR_IEN_MASTER | WILC_SDIO_CCCR_IEN_FUNC1; 7155625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd); 7165625f965SAjay Singh if (ret) { 7175625f965SAjay Singh dev_err(&func->dev, "Fail cmd 52, set IEN register...\n"); 7185625f965SAjay Singh return ret; 7195625f965SAjay Singh } 7205625f965SAjay Singh 7215625f965SAjay Singh /** 7225625f965SAjay Singh * make sure can read back chip id correctly 7235625f965SAjay Singh **/ 7245625f965SAjay Singh if (!resume) { 7255625f965SAjay Singh int rev; 7265625f965SAjay Singh 7275625f965SAjay Singh ret = wilc_sdio_read_reg(wilc, WILC_CHIPID, &chipid); 7285625f965SAjay Singh if (ret) { 7295625f965SAjay Singh dev_err(&func->dev, "Fail cmd read chip id...\n"); 7305625f965SAjay Singh return ret; 7315625f965SAjay Singh } 7325625f965SAjay Singh dev_err(&func->dev, "chipid (%08x)\n", chipid); 7335625f965SAjay Singh rev = FIELD_GET(WILC_CHIP_REV_FIELD, chipid); 7345625f965SAjay Singh if (rev > FIELD_GET(WILC_CHIP_REV_FIELD, WILC_1000_BASE_ID_2A)) 7355625f965SAjay Singh sdio_priv->has_thrpt_enh3 = 1; 7365625f965SAjay Singh else 7375625f965SAjay Singh sdio_priv->has_thrpt_enh3 = 0; 7385625f965SAjay Singh dev_info(&func->dev, "has_thrpt_enh3 = %d...\n", 7395625f965SAjay Singh sdio_priv->has_thrpt_enh3); 7405625f965SAjay Singh } 7415625f965SAjay Singh 74239d0f1b0SAjay Singh sdio_priv->isinit = true; 7435625f965SAjay Singh return 0; 7445625f965SAjay Singh } 7455625f965SAjay Singh 7465625f965SAjay Singh static int wilc_sdio_read_size(struct wilc *wilc, u32 *size) 7475625f965SAjay Singh { 7485625f965SAjay Singh u32 tmp; 7495625f965SAjay Singh struct sdio_cmd52 cmd; 7505625f965SAjay Singh 7515625f965SAjay Singh /** 7525625f965SAjay Singh * Read DMA count in words 7535625f965SAjay Singh **/ 7545625f965SAjay Singh cmd.read_write = 0; 7555625f965SAjay Singh cmd.function = 0; 7565625f965SAjay Singh cmd.raw = 0; 7575625f965SAjay Singh cmd.address = WILC_SDIO_INTERRUPT_DATA_SZ_REG; 7585625f965SAjay Singh cmd.data = 0; 7595625f965SAjay Singh wilc_sdio_cmd52(wilc, &cmd); 7605625f965SAjay Singh tmp = cmd.data; 7615625f965SAjay Singh 7625625f965SAjay Singh cmd.address = WILC_SDIO_INTERRUPT_DATA_SZ_REG + 1; 7635625f965SAjay Singh cmd.data = 0; 7645625f965SAjay Singh wilc_sdio_cmd52(wilc, &cmd); 7655625f965SAjay Singh tmp |= (cmd.data << 8); 7665625f965SAjay Singh 7675625f965SAjay Singh *size = tmp; 7685625f965SAjay Singh return 0; 7695625f965SAjay Singh } 7705625f965SAjay Singh 7715625f965SAjay Singh static int wilc_sdio_read_int(struct wilc *wilc, u32 *int_status) 7725625f965SAjay Singh { 7735625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev); 7745625f965SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data; 7755625f965SAjay Singh u32 tmp; 7765625f965SAjay Singh u8 irq_flags; 7775625f965SAjay Singh struct sdio_cmd52 cmd; 7785625f965SAjay Singh 7795625f965SAjay Singh wilc_sdio_read_size(wilc, &tmp); 7805625f965SAjay Singh 7815625f965SAjay Singh /** 7825625f965SAjay Singh * Read IRQ flags 7835625f965SAjay Singh **/ 7845625f965SAjay Singh if (!sdio_priv->irq_gpio) { 7855625f965SAjay Singh cmd.function = 1; 7865625f965SAjay Singh cmd.address = WILC_SDIO_EXT_IRQ_FLAG_REG; 7875625f965SAjay Singh } else { 7885625f965SAjay Singh cmd.function = 0; 7895625f965SAjay Singh cmd.address = WILC_SDIO_IRQ_FLAG_REG; 7905625f965SAjay Singh } 7915625f965SAjay Singh cmd.raw = 0; 7925625f965SAjay Singh cmd.read_write = 0; 7935625f965SAjay Singh cmd.data = 0; 7945625f965SAjay Singh wilc_sdio_cmd52(wilc, &cmd); 7955625f965SAjay Singh irq_flags = cmd.data; 7965625f965SAjay Singh tmp |= FIELD_PREP(IRG_FLAGS_MASK, cmd.data); 7975625f965SAjay Singh 7985625f965SAjay Singh if (FIELD_GET(UNHANDLED_IRQ_MASK, irq_flags)) 7995625f965SAjay Singh dev_err(&func->dev, "Unexpected interrupt (1) int=%lx\n", 8005625f965SAjay Singh FIELD_GET(UNHANDLED_IRQ_MASK, irq_flags)); 8015625f965SAjay Singh 8025625f965SAjay Singh *int_status = tmp; 8035625f965SAjay Singh 8045625f965SAjay Singh return 0; 8055625f965SAjay Singh } 8065625f965SAjay Singh 8075625f965SAjay Singh static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val) 8085625f965SAjay Singh { 8095625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev); 8105625f965SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data; 8115625f965SAjay Singh int ret; 8125625f965SAjay Singh int vmm_ctl; 8135625f965SAjay Singh 8145625f965SAjay Singh if (sdio_priv->has_thrpt_enh3) { 8155625f965SAjay Singh u32 reg = 0; 8165625f965SAjay Singh 8175625f965SAjay Singh if (sdio_priv->irq_gpio) 8185625f965SAjay Singh reg = val & (BIT(MAX_NUM_INT) - 1); 8195625f965SAjay Singh 8205625f965SAjay Singh /* select VMM table 0 */ 8215625f965SAjay Singh if (val & SEL_VMM_TBL0) 8225625f965SAjay Singh reg |= BIT(5); 8235625f965SAjay Singh /* select VMM table 1 */ 8245625f965SAjay Singh if (val & SEL_VMM_TBL1) 8255625f965SAjay Singh reg |= BIT(6); 8265625f965SAjay Singh /* enable VMM */ 8275625f965SAjay Singh if (val & EN_VMM) 8285625f965SAjay Singh reg |= BIT(7); 8295625f965SAjay Singh if (reg) { 8305625f965SAjay Singh struct sdio_cmd52 cmd; 8315625f965SAjay Singh 8325625f965SAjay Singh cmd.read_write = 1; 8335625f965SAjay Singh cmd.function = 0; 8345625f965SAjay Singh cmd.raw = 0; 8355625f965SAjay Singh cmd.address = WILC_SDIO_IRQ_CLEAR_FLAG_REG; 8365625f965SAjay Singh cmd.data = reg; 8375625f965SAjay Singh 8385625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd); 8395625f965SAjay Singh if (ret) { 8405625f965SAjay Singh dev_err(&func->dev, 8415625f965SAjay Singh "Failed cmd52, set (%02x) data (%d) ...\n", 8425625f965SAjay Singh cmd.address, __LINE__); 8435625f965SAjay Singh return ret; 8445625f965SAjay Singh } 8455625f965SAjay Singh } 8465625f965SAjay Singh return 0; 8475625f965SAjay Singh } 8485625f965SAjay Singh if (sdio_priv->irq_gpio) { 8495625f965SAjay Singh /* has_thrpt_enh2 uses register 0xf8 to clear interrupts. */ 8505625f965SAjay Singh /* 8515625f965SAjay Singh * Cannot clear multiple interrupts. 8525625f965SAjay Singh * Must clear each interrupt individually. 8535625f965SAjay Singh */ 8545625f965SAjay Singh u32 flags; 8555625f965SAjay Singh int i; 8565625f965SAjay Singh 8575625f965SAjay Singh flags = val & (BIT(MAX_NUM_INT) - 1); 8585625f965SAjay Singh for (i = 0; i < NUM_INT_EXT && flags; i++) { 8595625f965SAjay Singh if (flags & BIT(i)) { 8605625f965SAjay Singh struct sdio_cmd52 cmd; 8615625f965SAjay Singh 8625625f965SAjay Singh cmd.read_write = 1; 8635625f965SAjay Singh cmd.function = 0; 8645625f965SAjay Singh cmd.raw = 0; 8655625f965SAjay Singh cmd.address = WILC_SDIO_IRQ_CLEAR_FLAG_REG; 8665625f965SAjay Singh cmd.data = BIT(i); 8675625f965SAjay Singh 8685625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd); 8695625f965SAjay Singh if (ret) { 8705625f965SAjay Singh dev_err(&func->dev, 8715625f965SAjay Singh "Failed cmd52, set (%02x) data (%d) ...\n", 8725625f965SAjay Singh cmd.address, __LINE__); 8735625f965SAjay Singh return ret; 8745625f965SAjay Singh } 8755625f965SAjay Singh flags &= ~BIT(i); 8765625f965SAjay Singh } 8775625f965SAjay Singh } 8785625f965SAjay Singh 8795625f965SAjay Singh for (i = NUM_INT_EXT; i < MAX_NUM_INT && flags; i++) { 8805625f965SAjay Singh if (flags & BIT(i)) { 8815625f965SAjay Singh dev_err(&func->dev, 8825625f965SAjay Singh "Unexpected interrupt cleared %d...\n", 8835625f965SAjay Singh i); 8845625f965SAjay Singh flags &= ~BIT(i); 8855625f965SAjay Singh } 8865625f965SAjay Singh } 8875625f965SAjay Singh } 8885625f965SAjay Singh 8895625f965SAjay Singh vmm_ctl = 0; 8905625f965SAjay Singh /* select VMM table 0 */ 8915625f965SAjay Singh if (val & SEL_VMM_TBL0) 8925625f965SAjay Singh vmm_ctl |= BIT(0); 8935625f965SAjay Singh /* select VMM table 1 */ 8945625f965SAjay Singh if (val & SEL_VMM_TBL1) 8955625f965SAjay Singh vmm_ctl |= BIT(1); 8965625f965SAjay Singh /* enable VMM */ 8975625f965SAjay Singh if (val & EN_VMM) 8985625f965SAjay Singh vmm_ctl |= BIT(2); 8995625f965SAjay Singh 9005625f965SAjay Singh if (vmm_ctl) { 9015625f965SAjay Singh struct sdio_cmd52 cmd; 9025625f965SAjay Singh 9035625f965SAjay Singh cmd.read_write = 1; 9045625f965SAjay Singh cmd.function = 0; 9055625f965SAjay Singh cmd.raw = 0; 9065625f965SAjay Singh cmd.address = WILC_SDIO_VMM_TBL_CTRL_REG; 9075625f965SAjay Singh cmd.data = vmm_ctl; 9085625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd); 9095625f965SAjay Singh if (ret) { 9105625f965SAjay Singh dev_err(&func->dev, 9115625f965SAjay Singh "Failed cmd52, set (%02x) data (%d) ...\n", 9125625f965SAjay Singh cmd.address, __LINE__); 9135625f965SAjay Singh return ret; 9145625f965SAjay Singh } 9155625f965SAjay Singh } 9165625f965SAjay Singh return 0; 9175625f965SAjay Singh } 9185625f965SAjay Singh 9195625f965SAjay Singh static int wilc_sdio_sync_ext(struct wilc *wilc, int nint) 9205625f965SAjay Singh { 9215625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev); 9225625f965SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data; 9235625f965SAjay Singh u32 reg; 9245625f965SAjay Singh 9255625f965SAjay Singh if (nint > MAX_NUM_INT) { 9265625f965SAjay Singh dev_err(&func->dev, "Too many interrupts (%d)...\n", nint); 9275625f965SAjay Singh return -EINVAL; 9285625f965SAjay Singh } 9295625f965SAjay Singh 9305625f965SAjay Singh /** 9315625f965SAjay Singh * Disable power sequencer 9325625f965SAjay Singh **/ 9335625f965SAjay Singh if (wilc_sdio_read_reg(wilc, WILC_MISC, ®)) { 9345625f965SAjay Singh dev_err(&func->dev, "Failed read misc reg...\n"); 9355625f965SAjay Singh return -EINVAL; 9365625f965SAjay Singh } 9375625f965SAjay Singh 9385625f965SAjay Singh reg &= ~BIT(8); 9395625f965SAjay Singh if (wilc_sdio_write_reg(wilc, WILC_MISC, reg)) { 9405625f965SAjay Singh dev_err(&func->dev, "Failed write misc reg...\n"); 9415625f965SAjay Singh return -EINVAL; 9425625f965SAjay Singh } 9435625f965SAjay Singh 9445625f965SAjay Singh if (sdio_priv->irq_gpio) { 9455625f965SAjay Singh u32 reg; 9465625f965SAjay Singh int ret, i; 9475625f965SAjay Singh 9485625f965SAjay Singh /** 9495625f965SAjay Singh * interrupt pin mux select 9505625f965SAjay Singh **/ 9515625f965SAjay Singh ret = wilc_sdio_read_reg(wilc, WILC_PIN_MUX_0, ®); 9525625f965SAjay Singh if (ret) { 9535625f965SAjay Singh dev_err(&func->dev, "Failed read reg (%08x)...\n", 9545625f965SAjay Singh WILC_PIN_MUX_0); 9555625f965SAjay Singh return ret; 9565625f965SAjay Singh } 9575625f965SAjay Singh reg |= BIT(8); 9585625f965SAjay Singh ret = wilc_sdio_write_reg(wilc, WILC_PIN_MUX_0, reg); 9595625f965SAjay Singh if (ret) { 9605625f965SAjay Singh dev_err(&func->dev, "Failed write reg (%08x)...\n", 9615625f965SAjay Singh WILC_PIN_MUX_0); 9625625f965SAjay Singh return ret; 9635625f965SAjay Singh } 9645625f965SAjay Singh 9655625f965SAjay Singh /** 9665625f965SAjay Singh * interrupt enable 9675625f965SAjay Singh **/ 9685625f965SAjay Singh ret = wilc_sdio_read_reg(wilc, WILC_INTR_ENABLE, ®); 9695625f965SAjay Singh if (ret) { 9705625f965SAjay Singh dev_err(&func->dev, "Failed read reg (%08x)...\n", 9715625f965SAjay Singh WILC_INTR_ENABLE); 9725625f965SAjay Singh return ret; 9735625f965SAjay Singh } 9745625f965SAjay Singh 9755625f965SAjay Singh for (i = 0; (i < 5) && (nint > 0); i++, nint--) 9765625f965SAjay Singh reg |= BIT((27 + i)); 9775625f965SAjay Singh ret = wilc_sdio_write_reg(wilc, WILC_INTR_ENABLE, reg); 9785625f965SAjay Singh if (ret) { 9795625f965SAjay Singh dev_err(&func->dev, "Failed write reg (%08x)...\n", 9805625f965SAjay Singh WILC_INTR_ENABLE); 9815625f965SAjay Singh return ret; 9825625f965SAjay Singh } 9835625f965SAjay Singh if (nint) { 9845625f965SAjay Singh ret = wilc_sdio_read_reg(wilc, WILC_INTR2_ENABLE, ®); 9855625f965SAjay Singh if (ret) { 9865625f965SAjay Singh dev_err(&func->dev, 9875625f965SAjay Singh "Failed read reg (%08x)...\n", 9885625f965SAjay Singh WILC_INTR2_ENABLE); 9895625f965SAjay Singh return ret; 9905625f965SAjay Singh } 9915625f965SAjay Singh 9925625f965SAjay Singh for (i = 0; (i < 3) && (nint > 0); i++, nint--) 9935625f965SAjay Singh reg |= BIT(i); 9945625f965SAjay Singh 995e21b6e5aSMarcus Folkesson ret = wilc_sdio_write_reg(wilc, WILC_INTR2_ENABLE, reg); 9965625f965SAjay Singh if (ret) { 9975625f965SAjay Singh dev_err(&func->dev, 9985625f965SAjay Singh "Failed write reg (%08x)...\n", 9995625f965SAjay Singh WILC_INTR2_ENABLE); 10005625f965SAjay Singh return ret; 10015625f965SAjay Singh } 10025625f965SAjay Singh } 10035625f965SAjay Singh } 10045625f965SAjay Singh return 0; 10055625f965SAjay Singh } 10065625f965SAjay Singh 10075625f965SAjay Singh /* Global sdio HIF function table */ 10085625f965SAjay Singh static const struct wilc_hif_func wilc_hif_sdio = { 10095625f965SAjay Singh .hif_init = wilc_sdio_init, 10105625f965SAjay Singh .hif_deinit = wilc_sdio_deinit, 10115625f965SAjay Singh .hif_read_reg = wilc_sdio_read_reg, 10125625f965SAjay Singh .hif_write_reg = wilc_sdio_write_reg, 10135625f965SAjay Singh .hif_block_rx = wilc_sdio_read, 10145625f965SAjay Singh .hif_block_tx = wilc_sdio_write, 10155625f965SAjay Singh .hif_read_int = wilc_sdio_read_int, 10165625f965SAjay Singh .hif_clear_int_ext = wilc_sdio_clear_int_ext, 10175625f965SAjay Singh .hif_read_size = wilc_sdio_read_size, 10185625f965SAjay Singh .hif_block_tx_ext = wilc_sdio_write, 10195625f965SAjay Singh .hif_block_rx_ext = wilc_sdio_read, 10205625f965SAjay Singh .hif_sync_ext = wilc_sdio_sync_ext, 10215625f965SAjay Singh .enable_interrupt = wilc_sdio_enable_interrupt, 10225625f965SAjay Singh .disable_interrupt = wilc_sdio_disable_interrupt, 1023c2dcb476SAjay Singh .hif_reset = wilc_sdio_reset, 102439d0f1b0SAjay Singh .hif_is_init = wilc_sdio_is_init, 10255625f965SAjay Singh }; 10265625f965SAjay Singh 10275625f965SAjay Singh static int wilc_sdio_resume(struct device *dev) 10285625f965SAjay Singh { 10295625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(dev); 10305625f965SAjay Singh struct wilc *wilc = sdio_get_drvdata(func); 10315625f965SAjay Singh 10325625f965SAjay Singh dev_info(dev, "sdio resume\n"); 10335625f965SAjay Singh sdio_release_host(func); 10345625f965SAjay Singh chip_wakeup(wilc); 10355625f965SAjay Singh wilc_sdio_init(wilc, true); 10365625f965SAjay Singh 10375625f965SAjay Singh if (wilc->suspend_event) 10385625f965SAjay Singh host_wakeup_notify(wilc); 10395625f965SAjay Singh 10405625f965SAjay Singh chip_allow_sleep(wilc); 10415625f965SAjay Singh 10425625f965SAjay Singh return 0; 10435625f965SAjay Singh } 10445625f965SAjay Singh 10455625f965SAjay Singh static const struct of_device_id wilc_of_match[] = { 10465625f965SAjay Singh { .compatible = "microchip,wilc1000", }, 10475625f965SAjay Singh { /* sentinel */ } 10485625f965SAjay Singh }; 10495625f965SAjay Singh MODULE_DEVICE_TABLE(of, wilc_of_match); 10505625f965SAjay Singh 10515625f965SAjay Singh static const struct dev_pm_ops wilc_sdio_pm_ops = { 10525625f965SAjay Singh .suspend = wilc_sdio_suspend, 10535625f965SAjay Singh .resume = wilc_sdio_resume, 10545625f965SAjay Singh }; 10555625f965SAjay Singh 10565625f965SAjay Singh static struct sdio_driver wilc_sdio_driver = { 10575625f965SAjay Singh .name = SDIO_MODALIAS, 10585625f965SAjay Singh .id_table = wilc_sdio_ids, 10595625f965SAjay Singh .probe = wilc_sdio_probe, 10605625f965SAjay Singh .remove = wilc_sdio_remove, 10615625f965SAjay Singh .drv = { 10625625f965SAjay Singh .pm = &wilc_sdio_pm_ops, 10635625f965SAjay Singh .of_match_table = wilc_of_match, 10645625f965SAjay Singh } 10655625f965SAjay Singh }; 10665625f965SAjay Singh module_driver(wilc_sdio_driver, 10675625f965SAjay Singh sdio_register_driver, 10685625f965SAjay Singh sdio_unregister_driver); 10695625f965SAjay Singh MODULE_LICENSE("GPL"); 1070