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 };
2357d545b5SMichael Walle MODULE_DEVICE_TABLE(sdio, wilc_sdio_ids);
245625f965SAjay Singh
255625f965SAjay Singh #define WILC_SDIO_BLOCK_SIZE 512
265625f965SAjay Singh
2783d9b54eSAjay Singh static int wilc_sdio_init(struct wilc *wilc, bool resume);
2883d9b54eSAjay Singh static int wilc_sdio_deinit(struct wilc *wilc);
2983d9b54eSAjay Singh
305625f965SAjay Singh struct wilc_sdio {
315625f965SAjay Singh bool irq_gpio;
325625f965SAjay Singh u32 block_size;
3339d0f1b0SAjay Singh bool isinit;
3440b717bfSAjay.Kathat@microchip.com u8 *cmd53_buf;
355625f965SAjay Singh };
365625f965SAjay Singh
375625f965SAjay Singh struct sdio_cmd52 {
385625f965SAjay Singh u32 read_write: 1;
395625f965SAjay Singh u32 function: 3;
405625f965SAjay Singh u32 raw: 1;
415625f965SAjay Singh u32 address: 17;
425625f965SAjay Singh u32 data: 8;
435625f965SAjay Singh };
445625f965SAjay Singh
455625f965SAjay Singh struct sdio_cmd53 {
465625f965SAjay Singh u32 read_write: 1;
475625f965SAjay Singh u32 function: 3;
485625f965SAjay Singh u32 block_mode: 1;
495625f965SAjay Singh u32 increment: 1;
505625f965SAjay Singh u32 address: 17;
515625f965SAjay Singh u32 count: 9;
525625f965SAjay Singh u8 *buffer;
535625f965SAjay Singh u32 block_size;
5440b717bfSAjay.Kathat@microchip.com bool use_global_buf;
555625f965SAjay Singh };
565625f965SAjay Singh
575625f965SAjay Singh static const struct wilc_hif_func wilc_hif_sdio;
585625f965SAjay Singh
wilc_sdio_interrupt(struct sdio_func * func)595625f965SAjay Singh static void wilc_sdio_interrupt(struct sdio_func *func)
605625f965SAjay Singh {
615625f965SAjay Singh sdio_release_host(func);
625625f965SAjay Singh wilc_handle_isr(sdio_get_drvdata(func));
635625f965SAjay Singh sdio_claim_host(func);
645625f965SAjay Singh }
655625f965SAjay Singh
wilc_sdio_cmd52(struct wilc * wilc,struct sdio_cmd52 * cmd)665625f965SAjay Singh static int wilc_sdio_cmd52(struct wilc *wilc, struct sdio_cmd52 *cmd)
675625f965SAjay Singh {
685625f965SAjay Singh struct sdio_func *func = container_of(wilc->dev, struct sdio_func, dev);
695625f965SAjay Singh int ret;
705625f965SAjay Singh u8 data;
715625f965SAjay Singh
725625f965SAjay Singh sdio_claim_host(func);
735625f965SAjay Singh
745625f965SAjay Singh func->num = cmd->function;
755625f965SAjay Singh if (cmd->read_write) { /* write */
765625f965SAjay Singh if (cmd->raw) {
775625f965SAjay Singh sdio_writeb(func, cmd->data, cmd->address, &ret);
785625f965SAjay Singh data = sdio_readb(func, cmd->address, &ret);
795625f965SAjay Singh cmd->data = data;
805625f965SAjay Singh } else {
815625f965SAjay Singh sdio_writeb(func, cmd->data, cmd->address, &ret);
825625f965SAjay Singh }
835625f965SAjay Singh } else { /* read */
845625f965SAjay Singh data = sdio_readb(func, cmd->address, &ret);
855625f965SAjay Singh cmd->data = data;
865625f965SAjay Singh }
875625f965SAjay Singh
885625f965SAjay Singh sdio_release_host(func);
895625f965SAjay Singh
905625f965SAjay Singh if (ret)
915625f965SAjay Singh dev_err(&func->dev, "%s..failed, err(%d)\n", __func__, ret);
925625f965SAjay Singh return ret;
935625f965SAjay Singh }
945625f965SAjay Singh
wilc_sdio_cmd53(struct wilc * wilc,struct sdio_cmd53 * cmd)955625f965SAjay Singh static int wilc_sdio_cmd53(struct wilc *wilc, struct sdio_cmd53 *cmd)
965625f965SAjay Singh {
975625f965SAjay Singh struct sdio_func *func = container_of(wilc->dev, struct sdio_func, dev);
985625f965SAjay Singh int size, ret;
9940b717bfSAjay.Kathat@microchip.com struct wilc_sdio *sdio_priv = wilc->bus_data;
10040b717bfSAjay.Kathat@microchip.com u8 *buf = cmd->buffer;
1015625f965SAjay Singh
1025625f965SAjay Singh sdio_claim_host(func);
1035625f965SAjay Singh
1045625f965SAjay Singh func->num = cmd->function;
1055625f965SAjay Singh func->cur_blksize = cmd->block_size;
1065625f965SAjay Singh if (cmd->block_mode)
1075625f965SAjay Singh size = cmd->count * cmd->block_size;
1085625f965SAjay Singh else
1095625f965SAjay Singh size = cmd->count;
1105625f965SAjay Singh
11140b717bfSAjay.Kathat@microchip.com if (cmd->use_global_buf) {
112ebab2723SDmitry Antipov if (size > sizeof(u32)) {
113ebab2723SDmitry Antipov ret = -EINVAL;
114ebab2723SDmitry Antipov goto out;
115ebab2723SDmitry Antipov }
11640b717bfSAjay.Kathat@microchip.com buf = sdio_priv->cmd53_buf;
11740b717bfSAjay.Kathat@microchip.com }
11840b717bfSAjay.Kathat@microchip.com
1195625f965SAjay Singh if (cmd->read_write) { /* write */
12040b717bfSAjay.Kathat@microchip.com if (cmd->use_global_buf)
12140b717bfSAjay.Kathat@microchip.com memcpy(buf, cmd->buffer, size);
12240b717bfSAjay.Kathat@microchip.com
12340b717bfSAjay.Kathat@microchip.com ret = sdio_memcpy_toio(func, cmd->address, buf, size);
1245625f965SAjay Singh } else { /* read */
12540b717bfSAjay.Kathat@microchip.com ret = sdio_memcpy_fromio(func, buf, cmd->address, size);
12640b717bfSAjay.Kathat@microchip.com
12740b717bfSAjay.Kathat@microchip.com if (cmd->use_global_buf)
12840b717bfSAjay.Kathat@microchip.com memcpy(cmd->buffer, buf, size);
1295625f965SAjay Singh }
130ebab2723SDmitry Antipov out:
1315625f965SAjay Singh sdio_release_host(func);
1325625f965SAjay Singh
1335625f965SAjay Singh if (ret)
1345625f965SAjay Singh dev_err(&func->dev, "%s..failed, err(%d)\n", __func__, ret);
1355625f965SAjay Singh
1365625f965SAjay Singh return ret;
1375625f965SAjay Singh }
1385625f965SAjay Singh
wilc_sdio_probe(struct sdio_func * func,const struct sdio_device_id * id)1395625f965SAjay Singh static int wilc_sdio_probe(struct sdio_func *func,
1405625f965SAjay Singh const struct sdio_device_id *id)
1415625f965SAjay Singh {
142ec999089SAlexis Lothoré struct wilc_sdio *sdio_priv;
143ec999089SAlexis Lothoré struct wilc_vif *vif;
1445625f965SAjay Singh struct wilc *wilc;
1455625f965SAjay Singh int ret;
146ec999089SAlexis Lothoré
1475625f965SAjay Singh
1485625f965SAjay Singh sdio_priv = kzalloc(sizeof(*sdio_priv), GFP_KERNEL);
1495625f965SAjay Singh if (!sdio_priv)
1505625f965SAjay Singh return -ENOMEM;
1515625f965SAjay Singh
15240b717bfSAjay.Kathat@microchip.com sdio_priv->cmd53_buf = kzalloc(sizeof(u32), GFP_KERNEL);
15340b717bfSAjay.Kathat@microchip.com if (!sdio_priv->cmd53_buf) {
15440b717bfSAjay.Kathat@microchip.com ret = -ENOMEM;
15540b717bfSAjay.Kathat@microchip.com goto free;
15640b717bfSAjay.Kathat@microchip.com }
15740b717bfSAjay.Kathat@microchip.com
1585625f965SAjay Singh ret = wilc_cfg80211_init(&wilc, &func->dev, WILC_HIF_SDIO,
1595625f965SAjay Singh &wilc_hif_sdio);
160dc8b338fSClaudiu Beznea if (ret)
161dc8b338fSClaudiu Beznea goto free;
1625625f965SAjay Singh
1635625f965SAjay Singh if (IS_ENABLED(CONFIG_WILC1000_HW_OOB_INTR)) {
1645625f965SAjay Singh struct device_node *np = func->card->dev.of_node;
1655625f965SAjay Singh int irq_num = of_irq_get(np, 0);
1665625f965SAjay Singh
1675625f965SAjay Singh if (irq_num > 0) {
1685625f965SAjay Singh wilc->dev_irq_num = irq_num;
1695625f965SAjay Singh sdio_priv->irq_gpio = true;
1705625f965SAjay Singh }
1715625f965SAjay Singh }
1725625f965SAjay Singh
1735625f965SAjay Singh sdio_set_drvdata(func, wilc);
1745625f965SAjay Singh wilc->bus_data = sdio_priv;
1755625f965SAjay Singh wilc->dev = &func->dev;
1765625f965SAjay Singh
177*55447524SLi Zetao wilc->rtc_clk = devm_clk_get_optional_enabled(&func->card->dev, "rtc");
1781d89fd1aSClaudiu Beznea if (IS_ERR(wilc->rtc_clk)) {
1791d89fd1aSClaudiu Beznea ret = PTR_ERR(wilc->rtc_clk);
180f36a0ee5SClaudiu Beznea goto dispose_irq;
1811d89fd1aSClaudiu Beznea }
1825625f965SAjay Singh
18383d9b54eSAjay Singh wilc_sdio_init(wilc, false);
18483d9b54eSAjay Singh
18583d9b54eSAjay Singh ret = wilc_load_mac_from_nv(wilc);
18683d9b54eSAjay Singh if (ret) {
18783d9b54eSAjay Singh pr_err("Can not retrieve MAC address from chip\n");
188*55447524SLi Zetao goto dispose_irq;
18983d9b54eSAjay Singh }
19083d9b54eSAjay Singh
19183d9b54eSAjay Singh wilc_sdio_deinit(wilc);
19283d9b54eSAjay Singh
193ec999089SAlexis Lothoré vif = wilc_netdev_ifc_init(wilc, "wlan%d", WILC_STATION_MODE,
194ec999089SAlexis Lothoré NL80211_IFTYPE_STATION, false);
195ec999089SAlexis Lothoré if (IS_ERR(vif)) {
196ec999089SAlexis Lothoré ret = PTR_ERR(vif);
197*55447524SLi Zetao goto dispose_irq;
198ec999089SAlexis Lothoré }
199ec999089SAlexis Lothoré
2005625f965SAjay Singh dev_info(&func->dev, "Driver Initializing success\n");
2015625f965SAjay Singh return 0;
20283d9b54eSAjay Singh
203f36a0ee5SClaudiu Beznea dispose_irq:
204f36a0ee5SClaudiu Beznea irq_dispose_mapping(wilc->dev_irq_num);
205dc8b338fSClaudiu Beznea wilc_netdev_cleanup(wilc);
206dc8b338fSClaudiu Beznea free:
20740b717bfSAjay.Kathat@microchip.com kfree(sdio_priv->cmd53_buf);
208dc8b338fSClaudiu Beznea kfree(sdio_priv);
209dc8b338fSClaudiu Beznea return ret;
2105625f965SAjay Singh }
2115625f965SAjay Singh
wilc_sdio_remove(struct sdio_func * func)2125625f965SAjay Singh static void wilc_sdio_remove(struct sdio_func *func)
2135625f965SAjay Singh {
2145625f965SAjay Singh struct wilc *wilc = sdio_get_drvdata(func);
2154894edacSDan Carpenter struct wilc_sdio *sdio_priv = wilc->bus_data;
2165625f965SAjay Singh
2175625f965SAjay Singh wilc_netdev_cleanup(wilc);
21840b717bfSAjay.Kathat@microchip.com kfree(sdio_priv->cmd53_buf);
2194894edacSDan Carpenter kfree(sdio_priv);
2205625f965SAjay Singh }
2215625f965SAjay Singh
wilc_sdio_reset(struct wilc * wilc)2225625f965SAjay Singh static int wilc_sdio_reset(struct wilc *wilc)
2235625f965SAjay Singh {
2245625f965SAjay Singh struct sdio_cmd52 cmd;
2255625f965SAjay Singh int ret;
2265625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev);
2275625f965SAjay Singh
2285625f965SAjay Singh cmd.read_write = 1;
2295625f965SAjay Singh cmd.function = 0;
2305625f965SAjay Singh cmd.raw = 0;
2315625f965SAjay Singh cmd.address = SDIO_CCCR_ABORT;
2325625f965SAjay Singh cmd.data = WILC_SDIO_CCCR_ABORT_RESET;
2335625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd);
2345625f965SAjay Singh if (ret) {
2355625f965SAjay Singh dev_err(&func->dev, "Fail cmd 52, reset cmd ...\n");
2365625f965SAjay Singh return ret;
2375625f965SAjay Singh }
2385625f965SAjay Singh return 0;
2395625f965SAjay Singh }
2405625f965SAjay Singh
wilc_sdio_is_init(struct wilc * wilc)24139d0f1b0SAjay Singh static bool wilc_sdio_is_init(struct wilc *wilc)
24239d0f1b0SAjay Singh {
24339d0f1b0SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data;
24439d0f1b0SAjay Singh
24539d0f1b0SAjay Singh return sdio_priv->isinit;
24639d0f1b0SAjay Singh }
24739d0f1b0SAjay Singh
wilc_sdio_enable_interrupt(struct wilc * dev)2485625f965SAjay Singh static int wilc_sdio_enable_interrupt(struct wilc *dev)
2495625f965SAjay Singh {
2505625f965SAjay Singh struct sdio_func *func = container_of(dev->dev, struct sdio_func, dev);
2515625f965SAjay Singh int ret = 0;
2525625f965SAjay Singh
2535625f965SAjay Singh sdio_claim_host(func);
2545625f965SAjay Singh ret = sdio_claim_irq(func, wilc_sdio_interrupt);
2555625f965SAjay Singh sdio_release_host(func);
2565625f965SAjay Singh
2575625f965SAjay Singh if (ret < 0) {
2585625f965SAjay Singh dev_err(&func->dev, "can't claim sdio_irq, err(%d)\n", ret);
2595625f965SAjay Singh ret = -EIO;
2605625f965SAjay Singh }
2615625f965SAjay Singh return ret;
2625625f965SAjay Singh }
2635625f965SAjay Singh
wilc_sdio_disable_interrupt(struct wilc * dev)2645625f965SAjay Singh static void wilc_sdio_disable_interrupt(struct wilc *dev)
2655625f965SAjay Singh {
2665625f965SAjay Singh struct sdio_func *func = container_of(dev->dev, struct sdio_func, dev);
2675625f965SAjay Singh int ret;
2685625f965SAjay Singh
2695625f965SAjay Singh sdio_claim_host(func);
2705625f965SAjay Singh ret = sdio_release_irq(func);
2715625f965SAjay Singh if (ret < 0)
2725625f965SAjay Singh dev_err(&func->dev, "can't release sdio_irq, err(%d)\n", ret);
2735625f965SAjay Singh sdio_release_host(func);
2745625f965SAjay Singh }
2755625f965SAjay Singh
2765625f965SAjay Singh /********************************************
2775625f965SAjay Singh *
2785625f965SAjay Singh * Function 0
2795625f965SAjay Singh *
2805625f965SAjay Singh ********************************************/
2815625f965SAjay Singh
wilc_sdio_set_func0_csa_address(struct wilc * wilc,u32 adr)2825625f965SAjay Singh static int wilc_sdio_set_func0_csa_address(struct wilc *wilc, u32 adr)
2835625f965SAjay Singh {
2845625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev);
2855625f965SAjay Singh struct sdio_cmd52 cmd;
2865625f965SAjay Singh int ret;
2875625f965SAjay Singh
2885625f965SAjay Singh /**
2895625f965SAjay Singh * Review: BIG ENDIAN
2905625f965SAjay Singh **/
2915625f965SAjay Singh cmd.read_write = 1;
2925625f965SAjay Singh cmd.function = 0;
2935625f965SAjay Singh cmd.raw = 0;
2945625f965SAjay Singh cmd.address = WILC_SDIO_FBR_CSA_REG;
2955625f965SAjay Singh cmd.data = (u8)adr;
2965625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd);
2975625f965SAjay Singh if (ret) {
2985625f965SAjay Singh dev_err(&func->dev, "Failed cmd52, set %04x data...\n",
2995625f965SAjay Singh cmd.address);
3005625f965SAjay Singh return ret;
3015625f965SAjay Singh }
3025625f965SAjay Singh
3035625f965SAjay Singh cmd.address = WILC_SDIO_FBR_CSA_REG + 1;
3045625f965SAjay Singh cmd.data = (u8)(adr >> 8);
3055625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd);
3065625f965SAjay Singh if (ret) {
3075625f965SAjay Singh dev_err(&func->dev, "Failed cmd52, set %04x data...\n",
3085625f965SAjay Singh cmd.address);
3095625f965SAjay Singh return ret;
3105625f965SAjay Singh }
3115625f965SAjay Singh
3125625f965SAjay Singh cmd.address = WILC_SDIO_FBR_CSA_REG + 2;
3135625f965SAjay Singh cmd.data = (u8)(adr >> 16);
3145625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd);
3155625f965SAjay Singh if (ret) {
3165625f965SAjay Singh dev_err(&func->dev, "Failed cmd52, set %04x data...\n",
3175625f965SAjay Singh cmd.address);
3185625f965SAjay Singh return ret;
3195625f965SAjay Singh }
3205625f965SAjay Singh
3215625f965SAjay Singh return 0;
3225625f965SAjay Singh }
3235625f965SAjay Singh
wilc_sdio_set_block_size(struct wilc * wilc,u8 func_num,u32 block_size)3245625f965SAjay Singh static int wilc_sdio_set_block_size(struct wilc *wilc, u8 func_num,
3255625f965SAjay Singh u32 block_size)
3265625f965SAjay Singh {
3275625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev);
3285625f965SAjay Singh struct sdio_cmd52 cmd;
3295625f965SAjay Singh int ret;
3305625f965SAjay Singh
3315625f965SAjay Singh cmd.read_write = 1;
3325625f965SAjay Singh cmd.function = 0;
3335625f965SAjay Singh cmd.raw = 0;
3345625f965SAjay Singh cmd.address = SDIO_FBR_BASE(func_num) + SDIO_CCCR_BLKSIZE;
3355625f965SAjay Singh cmd.data = (u8)block_size;
3365625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd);
3375625f965SAjay Singh if (ret) {
3385625f965SAjay Singh dev_err(&func->dev, "Failed cmd52, set %04x data...\n",
3395625f965SAjay Singh cmd.address);
3405625f965SAjay Singh return ret;
3415625f965SAjay Singh }
3425625f965SAjay Singh
3435625f965SAjay Singh cmd.address = SDIO_FBR_BASE(func_num) + SDIO_CCCR_BLKSIZE + 1;
3445625f965SAjay Singh cmd.data = (u8)(block_size >> 8);
3455625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd);
3465625f965SAjay Singh if (ret) {
3475625f965SAjay Singh dev_err(&func->dev, "Failed cmd52, set %04x data...\n",
3485625f965SAjay Singh cmd.address);
3495625f965SAjay Singh return ret;
3505625f965SAjay Singh }
3515625f965SAjay Singh
3525625f965SAjay Singh return 0;
3535625f965SAjay Singh }
3545625f965SAjay Singh
3555625f965SAjay Singh /********************************************
3565625f965SAjay Singh *
3575625f965SAjay Singh * Sdio interfaces
3585625f965SAjay Singh *
3595625f965SAjay Singh ********************************************/
wilc_sdio_write_reg(struct wilc * wilc,u32 addr,u32 data)3605625f965SAjay Singh static int wilc_sdio_write_reg(struct wilc *wilc, u32 addr, u32 data)
3615625f965SAjay Singh {
3625625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev);
3635625f965SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data;
3645625f965SAjay Singh int ret;
3655625f965SAjay Singh
3665625f965SAjay Singh cpu_to_le32s(&data);
3675625f965SAjay Singh
3685625f965SAjay Singh if (addr >= 0xf0 && addr <= 0xff) { /* only vendor specific registers */
3695625f965SAjay Singh struct sdio_cmd52 cmd;
3705625f965SAjay Singh
3715625f965SAjay Singh cmd.read_write = 1;
3725625f965SAjay Singh cmd.function = 0;
3735625f965SAjay Singh cmd.raw = 0;
3745625f965SAjay Singh cmd.address = addr;
3755625f965SAjay Singh cmd.data = data;
3765625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd);
3775625f965SAjay Singh if (ret)
3785625f965SAjay Singh dev_err(&func->dev,
3795625f965SAjay Singh "Failed cmd 52, read reg (%08x) ...\n", addr);
3805625f965SAjay Singh } else {
3815625f965SAjay Singh struct sdio_cmd53 cmd;
3825625f965SAjay Singh
3835625f965SAjay Singh /**
3845625f965SAjay Singh * set the AHB address
3855625f965SAjay Singh **/
3865625f965SAjay Singh ret = wilc_sdio_set_func0_csa_address(wilc, addr);
3875625f965SAjay Singh if (ret)
3885625f965SAjay Singh return ret;
3895625f965SAjay Singh
3905625f965SAjay Singh cmd.read_write = 1;
3915625f965SAjay Singh cmd.function = 0;
3925625f965SAjay Singh cmd.address = WILC_SDIO_FBR_DATA_REG;
3935625f965SAjay Singh cmd.block_mode = 0;
3945625f965SAjay Singh cmd.increment = 1;
39540b717bfSAjay.Kathat@microchip.com cmd.count = sizeof(u32);
3965625f965SAjay Singh cmd.buffer = (u8 *)&data;
39740b717bfSAjay.Kathat@microchip.com cmd.use_global_buf = true;
3985625f965SAjay Singh cmd.block_size = sdio_priv->block_size;
3995625f965SAjay Singh ret = wilc_sdio_cmd53(wilc, &cmd);
4005625f965SAjay Singh if (ret)
4015625f965SAjay Singh dev_err(&func->dev,
4025625f965SAjay Singh "Failed cmd53, write reg (%08x)...\n", addr);
4035625f965SAjay Singh }
4045625f965SAjay Singh
4055625f965SAjay Singh return ret;
4065625f965SAjay Singh }
4075625f965SAjay Singh
wilc_sdio_write(struct wilc * wilc,u32 addr,u8 * buf,u32 size)4085625f965SAjay Singh static int wilc_sdio_write(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
4095625f965SAjay Singh {
4105625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev);
4115625f965SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data;
4125625f965SAjay Singh u32 block_size = sdio_priv->block_size;
4135625f965SAjay Singh struct sdio_cmd53 cmd;
4145625f965SAjay Singh int nblk, nleft, ret;
4155625f965SAjay Singh
4165625f965SAjay Singh cmd.read_write = 1;
4175625f965SAjay Singh if (addr > 0) {
4185625f965SAjay Singh /**
4195625f965SAjay Singh * func 0 access
4205625f965SAjay Singh **/
4215625f965SAjay Singh cmd.function = 0;
4225625f965SAjay Singh cmd.address = WILC_SDIO_FBR_DATA_REG;
4235625f965SAjay Singh } else {
4245625f965SAjay Singh /**
4255625f965SAjay Singh * func 1 access
4265625f965SAjay Singh **/
4275625f965SAjay Singh cmd.function = 1;
4285625f965SAjay Singh cmd.address = WILC_SDIO_F1_DATA_REG;
4295625f965SAjay Singh }
4305625f965SAjay Singh
4315625f965SAjay Singh size = ALIGN(size, 4);
4325625f965SAjay Singh nblk = size / block_size;
4335625f965SAjay Singh nleft = size % block_size;
4345625f965SAjay Singh
43540b717bfSAjay.Kathat@microchip.com cmd.use_global_buf = false;
4365625f965SAjay Singh if (nblk > 0) {
4375625f965SAjay Singh cmd.block_mode = 1;
4385625f965SAjay Singh cmd.increment = 1;
4395625f965SAjay Singh cmd.count = nblk;
4405625f965SAjay Singh cmd.buffer = buf;
4415625f965SAjay Singh cmd.block_size = block_size;
4425625f965SAjay Singh if (addr > 0) {
4435625f965SAjay Singh ret = wilc_sdio_set_func0_csa_address(wilc, addr);
4445625f965SAjay Singh if (ret)
4455625f965SAjay Singh return ret;
4465625f965SAjay Singh }
4475625f965SAjay Singh ret = wilc_sdio_cmd53(wilc, &cmd);
4485625f965SAjay Singh if (ret) {
4495625f965SAjay Singh dev_err(&func->dev,
4505625f965SAjay Singh "Failed cmd53 [%x], block send...\n", addr);
4515625f965SAjay Singh return ret;
4525625f965SAjay Singh }
4535625f965SAjay Singh if (addr > 0)
4545625f965SAjay Singh addr += nblk * block_size;
4555625f965SAjay Singh buf += nblk * block_size;
4565625f965SAjay Singh }
4575625f965SAjay Singh
4585625f965SAjay Singh if (nleft > 0) {
4595625f965SAjay Singh cmd.block_mode = 0;
4605625f965SAjay Singh cmd.increment = 1;
4615625f965SAjay Singh cmd.count = nleft;
4625625f965SAjay Singh cmd.buffer = buf;
4635625f965SAjay Singh
4645625f965SAjay Singh cmd.block_size = block_size;
4655625f965SAjay Singh
4665625f965SAjay Singh if (addr > 0) {
4675625f965SAjay Singh ret = wilc_sdio_set_func0_csa_address(wilc, addr);
4685625f965SAjay Singh if (ret)
4695625f965SAjay Singh return ret;
4705625f965SAjay Singh }
4715625f965SAjay Singh ret = wilc_sdio_cmd53(wilc, &cmd);
4725625f965SAjay Singh if (ret) {
4735625f965SAjay Singh dev_err(&func->dev,
4745625f965SAjay Singh "Failed cmd53 [%x], bytes send...\n", addr);
4755625f965SAjay Singh return ret;
4765625f965SAjay Singh }
4775625f965SAjay Singh }
4785625f965SAjay Singh
4795625f965SAjay Singh return 0;
4805625f965SAjay Singh }
4815625f965SAjay Singh
wilc_sdio_read_reg(struct wilc * wilc,u32 addr,u32 * data)4825625f965SAjay Singh static int wilc_sdio_read_reg(struct wilc *wilc, u32 addr, u32 *data)
4835625f965SAjay Singh {
4845625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev);
4855625f965SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data;
4865625f965SAjay Singh int ret;
4875625f965SAjay Singh
4885625f965SAjay Singh if (addr >= 0xf0 && addr <= 0xff) { /* only vendor specific registers */
4895625f965SAjay Singh struct sdio_cmd52 cmd;
4905625f965SAjay Singh
4915625f965SAjay Singh cmd.read_write = 0;
4925625f965SAjay Singh cmd.function = 0;
4935625f965SAjay Singh cmd.raw = 0;
4945625f965SAjay Singh cmd.address = addr;
4955625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd);
4965625f965SAjay Singh if (ret) {
4975625f965SAjay Singh dev_err(&func->dev,
4985625f965SAjay Singh "Failed cmd 52, read reg (%08x) ...\n", addr);
4995625f965SAjay Singh return ret;
5005625f965SAjay Singh }
5015625f965SAjay Singh *data = cmd.data;
5025625f965SAjay Singh } else {
5035625f965SAjay Singh struct sdio_cmd53 cmd;
5045625f965SAjay Singh
5055625f965SAjay Singh ret = wilc_sdio_set_func0_csa_address(wilc, addr);
5065625f965SAjay Singh if (ret)
5075625f965SAjay Singh return ret;
5085625f965SAjay Singh
5095625f965SAjay Singh cmd.read_write = 0;
5105625f965SAjay Singh cmd.function = 0;
5115625f965SAjay Singh cmd.address = WILC_SDIO_FBR_DATA_REG;
5125625f965SAjay Singh cmd.block_mode = 0;
5135625f965SAjay Singh cmd.increment = 1;
51440b717bfSAjay.Kathat@microchip.com cmd.count = sizeof(u32);
5155625f965SAjay Singh cmd.buffer = (u8 *)data;
51640b717bfSAjay.Kathat@microchip.com cmd.use_global_buf = true;
5175625f965SAjay Singh
5185625f965SAjay Singh cmd.block_size = sdio_priv->block_size;
5195625f965SAjay Singh ret = wilc_sdio_cmd53(wilc, &cmd);
5205625f965SAjay Singh if (ret) {
5215625f965SAjay Singh dev_err(&func->dev,
5225625f965SAjay Singh "Failed cmd53, read reg (%08x)...\n", addr);
5235625f965SAjay Singh return ret;
5245625f965SAjay Singh }
5255625f965SAjay Singh }
5265625f965SAjay Singh
5275625f965SAjay Singh le32_to_cpus(data);
5285625f965SAjay Singh return 0;
5295625f965SAjay Singh }
5305625f965SAjay Singh
wilc_sdio_read(struct wilc * wilc,u32 addr,u8 * buf,u32 size)5315625f965SAjay Singh static int wilc_sdio_read(struct wilc *wilc, u32 addr, u8 *buf, u32 size)
5325625f965SAjay Singh {
5335625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev);
5345625f965SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data;
5355625f965SAjay Singh u32 block_size = sdio_priv->block_size;
5365625f965SAjay Singh struct sdio_cmd53 cmd;
5375625f965SAjay Singh int nblk, nleft, ret;
5385625f965SAjay Singh
5395625f965SAjay Singh cmd.read_write = 0;
5405625f965SAjay Singh if (addr > 0) {
5415625f965SAjay Singh /**
5425625f965SAjay Singh * func 0 access
5435625f965SAjay Singh **/
5445625f965SAjay Singh cmd.function = 0;
5455625f965SAjay Singh cmd.address = WILC_SDIO_FBR_DATA_REG;
5465625f965SAjay Singh } else {
5475625f965SAjay Singh /**
5485625f965SAjay Singh * func 1 access
5495625f965SAjay Singh **/
5505625f965SAjay Singh cmd.function = 1;
5515625f965SAjay Singh cmd.address = WILC_SDIO_F1_DATA_REG;
5525625f965SAjay Singh }
5535625f965SAjay Singh
5545625f965SAjay Singh size = ALIGN(size, 4);
5555625f965SAjay Singh nblk = size / block_size;
5565625f965SAjay Singh nleft = size % block_size;
5575625f965SAjay Singh
55840b717bfSAjay.Kathat@microchip.com cmd.use_global_buf = false;
5595625f965SAjay Singh if (nblk > 0) {
5605625f965SAjay Singh cmd.block_mode = 1;
5615625f965SAjay Singh cmd.increment = 1;
5625625f965SAjay Singh cmd.count = nblk;
5635625f965SAjay Singh cmd.buffer = buf;
5645625f965SAjay Singh cmd.block_size = block_size;
5655625f965SAjay Singh if (addr > 0) {
5665625f965SAjay Singh ret = wilc_sdio_set_func0_csa_address(wilc, addr);
5675625f965SAjay Singh if (ret)
5685625f965SAjay Singh return ret;
5695625f965SAjay Singh }
5705625f965SAjay Singh ret = wilc_sdio_cmd53(wilc, &cmd);
5715625f965SAjay Singh if (ret) {
5725625f965SAjay Singh dev_err(&func->dev,
5735625f965SAjay Singh "Failed cmd53 [%x], block read...\n", addr);
5745625f965SAjay Singh return ret;
5755625f965SAjay Singh }
5765625f965SAjay Singh if (addr > 0)
5775625f965SAjay Singh addr += nblk * block_size;
5785625f965SAjay Singh buf += nblk * block_size;
5795625f965SAjay Singh } /* if (nblk > 0) */
5805625f965SAjay Singh
5815625f965SAjay Singh if (nleft > 0) {
5825625f965SAjay Singh cmd.block_mode = 0;
5835625f965SAjay Singh cmd.increment = 1;
5845625f965SAjay Singh cmd.count = nleft;
5855625f965SAjay Singh cmd.buffer = buf;
5865625f965SAjay Singh
5875625f965SAjay Singh cmd.block_size = block_size;
5885625f965SAjay Singh
5895625f965SAjay Singh if (addr > 0) {
5905625f965SAjay Singh ret = wilc_sdio_set_func0_csa_address(wilc, addr);
5915625f965SAjay Singh if (ret)
5925625f965SAjay Singh return ret;
5935625f965SAjay Singh }
5945625f965SAjay Singh ret = wilc_sdio_cmd53(wilc, &cmd);
5955625f965SAjay Singh if (ret) {
5965625f965SAjay Singh dev_err(&func->dev,
5975625f965SAjay Singh "Failed cmd53 [%x], bytes read...\n", addr);
5985625f965SAjay Singh return ret;
5995625f965SAjay Singh }
6005625f965SAjay Singh }
6015625f965SAjay Singh
6025625f965SAjay Singh return 0;
6035625f965SAjay Singh }
6045625f965SAjay Singh
6055625f965SAjay Singh /********************************************
6065625f965SAjay Singh *
6075625f965SAjay Singh * Bus interfaces
6085625f965SAjay Singh *
6095625f965SAjay Singh ********************************************/
6105625f965SAjay Singh
wilc_sdio_deinit(struct wilc * wilc)6115625f965SAjay Singh static int wilc_sdio_deinit(struct wilc *wilc)
6125625f965SAjay Singh {
613a5d6b1d4SAlexis Lothoré struct sdio_func *func = dev_to_sdio_func(wilc->dev);
61439d0f1b0SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data;
615a5d6b1d4SAlexis Lothoré struct sdio_cmd52 cmd;
616a5d6b1d4SAlexis Lothoré int ret;
617a5d6b1d4SAlexis Lothoré
618a5d6b1d4SAlexis Lothoré cmd.read_write = 1;
619a5d6b1d4SAlexis Lothoré cmd.function = 0;
620a5d6b1d4SAlexis Lothoré cmd.raw = 1;
621a5d6b1d4SAlexis Lothoré
622a5d6b1d4SAlexis Lothoré /* Disable all functions interrupts */
623a5d6b1d4SAlexis Lothoré cmd.address = SDIO_CCCR_IENx;
624a5d6b1d4SAlexis Lothoré cmd.data = 0;
625a5d6b1d4SAlexis Lothoré ret = wilc_sdio_cmd52(wilc, &cmd);
626a5d6b1d4SAlexis Lothoré if (ret) {
627a5d6b1d4SAlexis Lothoré dev_err(&func->dev, "Failed to disable functions interrupts\n");
628a5d6b1d4SAlexis Lothoré return ret;
629a5d6b1d4SAlexis Lothoré }
630a5d6b1d4SAlexis Lothoré
631a5d6b1d4SAlexis Lothoré /* Disable all functions */
632a5d6b1d4SAlexis Lothoré cmd.address = SDIO_CCCR_IOEx;
633a5d6b1d4SAlexis Lothoré cmd.data = 0;
634a5d6b1d4SAlexis Lothoré ret = wilc_sdio_cmd52(wilc, &cmd);
635a5d6b1d4SAlexis Lothoré if (ret) {
636a5d6b1d4SAlexis Lothoré dev_err(&func->dev,
637a5d6b1d4SAlexis Lothoré "Failed to reset all functions\n");
638a5d6b1d4SAlexis Lothoré return ret;
639a5d6b1d4SAlexis Lothoré }
640a5d6b1d4SAlexis Lothoré
641a5d6b1d4SAlexis Lothoré /* Disable CSA */
642a5d6b1d4SAlexis Lothoré cmd.read_write = 0;
643a5d6b1d4SAlexis Lothoré cmd.address = SDIO_FBR_BASE(1);
644a5d6b1d4SAlexis Lothoré ret = wilc_sdio_cmd52(wilc, &cmd);
645a5d6b1d4SAlexis Lothoré if (ret) {
646a5d6b1d4SAlexis Lothoré dev_err(&func->dev,
647a5d6b1d4SAlexis Lothoré "Failed to read CSA for function 1\n");
648a5d6b1d4SAlexis Lothoré return ret;
649a5d6b1d4SAlexis Lothoré }
650a5d6b1d4SAlexis Lothoré cmd.read_write = 1;
651a5d6b1d4SAlexis Lothoré cmd.address = SDIO_FBR_BASE(1);
652a5d6b1d4SAlexis Lothoré cmd.data &= ~SDIO_FBR_ENABLE_CSA;
653a5d6b1d4SAlexis Lothoré ret = wilc_sdio_cmd52(wilc, &cmd);
654a5d6b1d4SAlexis Lothoré if (ret) {
655a5d6b1d4SAlexis Lothoré dev_err(&func->dev,
656a5d6b1d4SAlexis Lothoré "Failed to disable CSA for function 1\n");
657a5d6b1d4SAlexis Lothoré return ret;
658a5d6b1d4SAlexis Lothoré }
65939d0f1b0SAjay Singh
66039d0f1b0SAjay Singh sdio_priv->isinit = false;
6615625f965SAjay Singh return 0;
6625625f965SAjay Singh }
6635625f965SAjay Singh
wilc_sdio_init(struct wilc * wilc,bool resume)6645625f965SAjay Singh static int wilc_sdio_init(struct wilc *wilc, bool resume)
6655625f965SAjay Singh {
6665625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev);
6675625f965SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data;
6685625f965SAjay Singh struct sdio_cmd52 cmd;
6695625f965SAjay Singh int loop, ret;
6705625f965SAjay Singh u32 chipid;
6715625f965SAjay Singh
6725625f965SAjay Singh /**
6735625f965SAjay Singh * function 0 csa enable
6745625f965SAjay Singh **/
6755625f965SAjay Singh cmd.read_write = 1;
6765625f965SAjay Singh cmd.function = 0;
6775625f965SAjay Singh cmd.raw = 1;
67872ebd675SAjay Singh cmd.address = SDIO_FBR_BASE(1);
6795625f965SAjay Singh cmd.data = SDIO_FBR_ENABLE_CSA;
6805625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd);
6815625f965SAjay Singh if (ret) {
6825625f965SAjay Singh dev_err(&func->dev, "Fail cmd 52, enable csa...\n");
6835625f965SAjay Singh return ret;
6845625f965SAjay Singh }
6855625f965SAjay Singh
6865625f965SAjay Singh /**
6875625f965SAjay Singh * function 0 block size
6885625f965SAjay Singh **/
6895625f965SAjay Singh ret = wilc_sdio_set_block_size(wilc, 0, WILC_SDIO_BLOCK_SIZE);
6905625f965SAjay Singh if (ret) {
6915625f965SAjay Singh dev_err(&func->dev, "Fail cmd 52, set func 0 block size...\n");
6925625f965SAjay Singh return ret;
6935625f965SAjay Singh }
6945625f965SAjay Singh sdio_priv->block_size = WILC_SDIO_BLOCK_SIZE;
6955625f965SAjay Singh
6965625f965SAjay Singh /**
6975625f965SAjay Singh * enable func1 IO
6985625f965SAjay Singh **/
6995625f965SAjay Singh cmd.read_write = 1;
7005625f965SAjay Singh cmd.function = 0;
7015625f965SAjay Singh cmd.raw = 1;
7025625f965SAjay Singh cmd.address = SDIO_CCCR_IOEx;
7035625f965SAjay Singh cmd.data = WILC_SDIO_CCCR_IO_EN_FUNC1;
7045625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd);
7055625f965SAjay Singh if (ret) {
7065625f965SAjay Singh dev_err(&func->dev,
7075625f965SAjay Singh "Fail cmd 52, set IOE register...\n");
7085625f965SAjay Singh return ret;
7095625f965SAjay Singh }
7105625f965SAjay Singh
7115625f965SAjay Singh /**
7125625f965SAjay Singh * make sure func 1 is up
7135625f965SAjay Singh **/
7145625f965SAjay Singh cmd.read_write = 0;
7155625f965SAjay Singh cmd.function = 0;
7165625f965SAjay Singh cmd.raw = 0;
7175625f965SAjay Singh cmd.address = SDIO_CCCR_IORx;
7185625f965SAjay Singh loop = 3;
7195625f965SAjay Singh do {
7205625f965SAjay Singh cmd.data = 0;
7215625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd);
7225625f965SAjay Singh if (ret) {
7235625f965SAjay Singh dev_err(&func->dev,
7245625f965SAjay Singh "Fail cmd 52, get IOR register...\n");
7255625f965SAjay Singh return ret;
7265625f965SAjay Singh }
7275625f965SAjay Singh if (cmd.data == WILC_SDIO_CCCR_IO_EN_FUNC1)
7285625f965SAjay Singh break;
7295625f965SAjay Singh } while (loop--);
7305625f965SAjay Singh
7315625f965SAjay Singh if (loop <= 0) {
7325625f965SAjay Singh dev_err(&func->dev, "Fail func 1 is not ready...\n");
7335625f965SAjay Singh return -EINVAL;
7345625f965SAjay Singh }
7355625f965SAjay Singh
7365625f965SAjay Singh /**
7375625f965SAjay Singh * func 1 is ready, set func 1 block size
7385625f965SAjay Singh **/
7395625f965SAjay Singh ret = wilc_sdio_set_block_size(wilc, 1, WILC_SDIO_BLOCK_SIZE);
7405625f965SAjay Singh if (ret) {
7415625f965SAjay Singh dev_err(&func->dev, "Fail set func 1 block size...\n");
7425625f965SAjay Singh return ret;
7435625f965SAjay Singh }
7445625f965SAjay Singh
7455625f965SAjay Singh /**
7465625f965SAjay Singh * func 1 interrupt enable
7475625f965SAjay Singh **/
7485625f965SAjay Singh cmd.read_write = 1;
7495625f965SAjay Singh cmd.function = 0;
7505625f965SAjay Singh cmd.raw = 1;
7515625f965SAjay Singh cmd.address = SDIO_CCCR_IENx;
7525625f965SAjay Singh cmd.data = WILC_SDIO_CCCR_IEN_MASTER | WILC_SDIO_CCCR_IEN_FUNC1;
7535625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd);
7545625f965SAjay Singh if (ret) {
7555625f965SAjay Singh dev_err(&func->dev, "Fail cmd 52, set IEN register...\n");
7565625f965SAjay Singh return ret;
7575625f965SAjay Singh }
7585625f965SAjay Singh
7595625f965SAjay Singh /**
7605625f965SAjay Singh * make sure can read back chip id correctly
7615625f965SAjay Singh **/
7625625f965SAjay Singh if (!resume) {
7635625f965SAjay Singh ret = wilc_sdio_read_reg(wilc, WILC_CHIPID, &chipid);
7645625f965SAjay Singh if (ret) {
7655625f965SAjay Singh dev_err(&func->dev, "Fail cmd read chip id...\n");
7665625f965SAjay Singh return ret;
7675625f965SAjay Singh }
7685625f965SAjay Singh dev_err(&func->dev, "chipid (%08x)\n", chipid);
7695625f965SAjay Singh }
7705625f965SAjay Singh
77139d0f1b0SAjay Singh sdio_priv->isinit = true;
7725625f965SAjay Singh return 0;
7735625f965SAjay Singh }
7745625f965SAjay Singh
wilc_sdio_read_size(struct wilc * wilc,u32 * size)7755625f965SAjay Singh static int wilc_sdio_read_size(struct wilc *wilc, u32 *size)
7765625f965SAjay Singh {
7775625f965SAjay Singh u32 tmp;
7785625f965SAjay Singh struct sdio_cmd52 cmd;
7795625f965SAjay Singh
7805625f965SAjay Singh /**
7815625f965SAjay Singh * Read DMA count in words
7825625f965SAjay Singh **/
7835625f965SAjay Singh cmd.read_write = 0;
7845625f965SAjay Singh cmd.function = 0;
7855625f965SAjay Singh cmd.raw = 0;
7865625f965SAjay Singh cmd.address = WILC_SDIO_INTERRUPT_DATA_SZ_REG;
7875625f965SAjay Singh cmd.data = 0;
7885625f965SAjay Singh wilc_sdio_cmd52(wilc, &cmd);
7895625f965SAjay Singh tmp = cmd.data;
7905625f965SAjay Singh
7915625f965SAjay Singh cmd.address = WILC_SDIO_INTERRUPT_DATA_SZ_REG + 1;
7925625f965SAjay Singh cmd.data = 0;
7935625f965SAjay Singh wilc_sdio_cmd52(wilc, &cmd);
7945625f965SAjay Singh tmp |= (cmd.data << 8);
7955625f965SAjay Singh
7965625f965SAjay Singh *size = tmp;
7975625f965SAjay Singh return 0;
7985625f965SAjay Singh }
7995625f965SAjay Singh
wilc_sdio_read_int(struct wilc * wilc,u32 * int_status)8005625f965SAjay Singh static int wilc_sdio_read_int(struct wilc *wilc, u32 *int_status)
8015625f965SAjay Singh {
8025625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev);
8035625f965SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data;
8045625f965SAjay Singh u32 tmp;
8055625f965SAjay Singh u8 irq_flags;
8065625f965SAjay Singh struct sdio_cmd52 cmd;
8075625f965SAjay Singh
8085625f965SAjay Singh wilc_sdio_read_size(wilc, &tmp);
8095625f965SAjay Singh
8105625f965SAjay Singh /**
8115625f965SAjay Singh * Read IRQ flags
8125625f965SAjay Singh **/
8135625f965SAjay Singh if (!sdio_priv->irq_gpio) {
8145625f965SAjay Singh cmd.function = 1;
8155625f965SAjay Singh cmd.address = WILC_SDIO_EXT_IRQ_FLAG_REG;
8165625f965SAjay Singh } else {
8175625f965SAjay Singh cmd.function = 0;
8185625f965SAjay Singh cmd.address = WILC_SDIO_IRQ_FLAG_REG;
8195625f965SAjay Singh }
8205625f965SAjay Singh cmd.raw = 0;
8215625f965SAjay Singh cmd.read_write = 0;
8225625f965SAjay Singh cmd.data = 0;
8235625f965SAjay Singh wilc_sdio_cmd52(wilc, &cmd);
8245625f965SAjay Singh irq_flags = cmd.data;
8255625f965SAjay Singh tmp |= FIELD_PREP(IRG_FLAGS_MASK, cmd.data);
8265625f965SAjay Singh
8275625f965SAjay Singh if (FIELD_GET(UNHANDLED_IRQ_MASK, irq_flags))
8285625f965SAjay Singh dev_err(&func->dev, "Unexpected interrupt (1) int=%lx\n",
8295625f965SAjay Singh FIELD_GET(UNHANDLED_IRQ_MASK, irq_flags));
8305625f965SAjay Singh
8315625f965SAjay Singh *int_status = tmp;
8325625f965SAjay Singh
8335625f965SAjay Singh return 0;
8345625f965SAjay Singh }
8355625f965SAjay Singh
wilc_sdio_clear_int_ext(struct wilc * wilc,u32 val)8365625f965SAjay Singh static int wilc_sdio_clear_int_ext(struct wilc *wilc, u32 val)
8375625f965SAjay Singh {
8385625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev);
8395625f965SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data;
8405625f965SAjay Singh int ret;
8415625f965SAjay Singh u32 reg = 0;
8425625f965SAjay Singh
8435625f965SAjay Singh if (sdio_priv->irq_gpio)
8445625f965SAjay Singh reg = val & (BIT(MAX_NUM_INT) - 1);
8455625f965SAjay Singh
8465625f965SAjay Singh /* select VMM table 0 */
8475625f965SAjay Singh if (val & SEL_VMM_TBL0)
8485625f965SAjay Singh reg |= BIT(5);
8495625f965SAjay Singh /* select VMM table 1 */
8505625f965SAjay Singh if (val & SEL_VMM_TBL1)
8515625f965SAjay Singh reg |= BIT(6);
8525625f965SAjay Singh /* enable VMM */
8535625f965SAjay Singh if (val & EN_VMM)
8545625f965SAjay Singh reg |= BIT(7);
8555625f965SAjay Singh if (reg) {
8565625f965SAjay Singh struct sdio_cmd52 cmd;
8575625f965SAjay Singh
8585625f965SAjay Singh cmd.read_write = 1;
8595625f965SAjay Singh cmd.function = 0;
8605625f965SAjay Singh cmd.raw = 0;
8615625f965SAjay Singh cmd.address = WILC_SDIO_IRQ_CLEAR_FLAG_REG;
8625625f965SAjay Singh cmd.data = reg;
8635625f965SAjay Singh
8645625f965SAjay Singh ret = wilc_sdio_cmd52(wilc, &cmd);
8655625f965SAjay Singh if (ret) {
8665625f965SAjay Singh dev_err(&func->dev,
8675625f965SAjay Singh "Failed cmd52, set (%02x) data (%d) ...\n",
8685625f965SAjay Singh cmd.address, __LINE__);
8695625f965SAjay Singh return ret;
8705625f965SAjay Singh }
8715625f965SAjay Singh }
8725625f965SAjay Singh return 0;
8735625f965SAjay Singh }
8745625f965SAjay Singh
wilc_sdio_sync_ext(struct wilc * wilc,int nint)8755625f965SAjay Singh static int wilc_sdio_sync_ext(struct wilc *wilc, int nint)
8765625f965SAjay Singh {
8775625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(wilc->dev);
8785625f965SAjay Singh struct wilc_sdio *sdio_priv = wilc->bus_data;
8795625f965SAjay Singh
8805625f965SAjay Singh if (nint > MAX_NUM_INT) {
8815625f965SAjay Singh dev_err(&func->dev, "Too many interrupts (%d)...\n", nint);
8825625f965SAjay Singh return -EINVAL;
8835625f965SAjay Singh }
8845625f965SAjay Singh
8855625f965SAjay Singh if (sdio_priv->irq_gpio) {
8865625f965SAjay Singh u32 reg;
8875625f965SAjay Singh int ret, i;
8885625f965SAjay Singh
8895625f965SAjay Singh /**
8905625f965SAjay Singh * interrupt pin mux select
8915625f965SAjay Singh **/
8925625f965SAjay Singh ret = wilc_sdio_read_reg(wilc, WILC_PIN_MUX_0, ®);
8935625f965SAjay Singh if (ret) {
8945625f965SAjay Singh dev_err(&func->dev, "Failed read reg (%08x)...\n",
8955625f965SAjay Singh WILC_PIN_MUX_0);
8965625f965SAjay Singh return ret;
8975625f965SAjay Singh }
8985625f965SAjay Singh reg |= BIT(8);
8995625f965SAjay Singh ret = wilc_sdio_write_reg(wilc, WILC_PIN_MUX_0, reg);
9005625f965SAjay Singh if (ret) {
9015625f965SAjay Singh dev_err(&func->dev, "Failed write reg (%08x)...\n",
9025625f965SAjay Singh WILC_PIN_MUX_0);
9035625f965SAjay Singh return ret;
9045625f965SAjay Singh }
9055625f965SAjay Singh
9065625f965SAjay Singh /**
9075625f965SAjay Singh * interrupt enable
9085625f965SAjay Singh **/
9095625f965SAjay Singh ret = wilc_sdio_read_reg(wilc, WILC_INTR_ENABLE, ®);
9105625f965SAjay Singh if (ret) {
9115625f965SAjay Singh dev_err(&func->dev, "Failed read reg (%08x)...\n",
9125625f965SAjay Singh WILC_INTR_ENABLE);
9135625f965SAjay Singh return ret;
9145625f965SAjay Singh }
9155625f965SAjay Singh
9165625f965SAjay Singh for (i = 0; (i < 5) && (nint > 0); i++, nint--)
9175625f965SAjay Singh reg |= BIT((27 + i));
9185625f965SAjay Singh ret = wilc_sdio_write_reg(wilc, WILC_INTR_ENABLE, reg);
9195625f965SAjay Singh if (ret) {
9205625f965SAjay Singh dev_err(&func->dev, "Failed write reg (%08x)...\n",
9215625f965SAjay Singh WILC_INTR_ENABLE);
9225625f965SAjay Singh return ret;
9235625f965SAjay Singh }
9245625f965SAjay Singh if (nint) {
9255625f965SAjay Singh ret = wilc_sdio_read_reg(wilc, WILC_INTR2_ENABLE, ®);
9265625f965SAjay Singh if (ret) {
9275625f965SAjay Singh dev_err(&func->dev,
9285625f965SAjay Singh "Failed read reg (%08x)...\n",
9295625f965SAjay Singh WILC_INTR2_ENABLE);
9305625f965SAjay Singh return ret;
9315625f965SAjay Singh }
9325625f965SAjay Singh
9335625f965SAjay Singh for (i = 0; (i < 3) && (nint > 0); i++, nint--)
9345625f965SAjay Singh reg |= BIT(i);
9355625f965SAjay Singh
936e21b6e5aSMarcus Folkesson ret = wilc_sdio_write_reg(wilc, WILC_INTR2_ENABLE, reg);
9375625f965SAjay Singh if (ret) {
9385625f965SAjay Singh dev_err(&func->dev,
9395625f965SAjay Singh "Failed write reg (%08x)...\n",
9405625f965SAjay Singh WILC_INTR2_ENABLE);
9415625f965SAjay Singh return ret;
9425625f965SAjay Singh }
9435625f965SAjay Singh }
9445625f965SAjay Singh }
9455625f965SAjay Singh return 0;
9465625f965SAjay Singh }
9475625f965SAjay Singh
9485625f965SAjay Singh /* Global sdio HIF function table */
9495625f965SAjay Singh static const struct wilc_hif_func wilc_hif_sdio = {
9505625f965SAjay Singh .hif_init = wilc_sdio_init,
9515625f965SAjay Singh .hif_deinit = wilc_sdio_deinit,
9525625f965SAjay Singh .hif_read_reg = wilc_sdio_read_reg,
9535625f965SAjay Singh .hif_write_reg = wilc_sdio_write_reg,
9545625f965SAjay Singh .hif_block_rx = wilc_sdio_read,
9555625f965SAjay Singh .hif_block_tx = wilc_sdio_write,
9565625f965SAjay Singh .hif_read_int = wilc_sdio_read_int,
9575625f965SAjay Singh .hif_clear_int_ext = wilc_sdio_clear_int_ext,
9585625f965SAjay Singh .hif_read_size = wilc_sdio_read_size,
9595625f965SAjay Singh .hif_block_tx_ext = wilc_sdio_write,
9605625f965SAjay Singh .hif_block_rx_ext = wilc_sdio_read,
9615625f965SAjay Singh .hif_sync_ext = wilc_sdio_sync_ext,
9625625f965SAjay Singh .enable_interrupt = wilc_sdio_enable_interrupt,
9635625f965SAjay Singh .disable_interrupt = wilc_sdio_disable_interrupt,
964c2dcb476SAjay Singh .hif_reset = wilc_sdio_reset,
96539d0f1b0SAjay Singh .hif_is_init = wilc_sdio_is_init,
9665625f965SAjay Singh };
9675625f965SAjay Singh
wilc_sdio_suspend(struct device * dev)968a814112eSAlexis Lothoré static int wilc_sdio_suspend(struct device *dev)
969a814112eSAlexis Lothoré {
970a814112eSAlexis Lothoré struct sdio_func *func = dev_to_sdio_func(dev);
971a814112eSAlexis Lothoré struct wilc *wilc = sdio_get_drvdata(func);
972a814112eSAlexis Lothoré int ret;
973a814112eSAlexis Lothoré
974a814112eSAlexis Lothoré dev_info(dev, "sdio suspend\n");
975a814112eSAlexis Lothoré
976b0dc7018SMarek Vasut if (!wilc->initialized)
977b0dc7018SMarek Vasut return 0;
978b0dc7018SMarek Vasut
979a814112eSAlexis Lothoré if (!IS_ERR(wilc->rtc_clk))
980a814112eSAlexis Lothoré clk_disable_unprepare(wilc->rtc_clk);
981a814112eSAlexis Lothoré
982a814112eSAlexis Lothoré host_sleep_notify(wilc);
983a814112eSAlexis Lothoré
9845ad8897fSAlexis Lothoré wilc_sdio_disable_interrupt(wilc);
9855ad8897fSAlexis Lothoré
986a814112eSAlexis Lothoré ret = wilc_sdio_reset(wilc);
987a814112eSAlexis Lothoré if (ret) {
988a814112eSAlexis Lothoré dev_err(&func->dev, "Fail reset sdio\n");
989a814112eSAlexis Lothoré return ret;
990a814112eSAlexis Lothoré }
991a814112eSAlexis Lothoré
992a814112eSAlexis Lothoré return 0;
993a814112eSAlexis Lothoré }
994a814112eSAlexis Lothoré
wilc_sdio_resume(struct device * dev)9955625f965SAjay Singh static int wilc_sdio_resume(struct device *dev)
9965625f965SAjay Singh {
9975625f965SAjay Singh struct sdio_func *func = dev_to_sdio_func(dev);
9985625f965SAjay Singh struct wilc *wilc = sdio_get_drvdata(func);
9995625f965SAjay Singh
10005625f965SAjay Singh dev_info(dev, "sdio resume\n");
1001b0dc7018SMarek Vasut
1002b0dc7018SMarek Vasut if (!wilc->initialized)
1003b0dc7018SMarek Vasut return 0;
1004b0dc7018SMarek Vasut
10050c896eceSMarek Vasut if (!IS_ERR(wilc->rtc_clk))
10060c896eceSMarek Vasut clk_prepare_enable(wilc->rtc_clk);
10070c896eceSMarek Vasut
10085625f965SAjay Singh wilc_sdio_init(wilc, true);
10095ad8897fSAlexis Lothoré wilc_sdio_enable_interrupt(wilc);
10105625f965SAjay Singh
10115625f965SAjay Singh host_wakeup_notify(wilc);
10125625f965SAjay Singh
10135625f965SAjay Singh return 0;
10145625f965SAjay Singh }
10155625f965SAjay Singh
10165625f965SAjay Singh static const struct of_device_id wilc_of_match[] = {
10175625f965SAjay Singh { .compatible = "microchip,wilc1000", },
10185625f965SAjay Singh { /* sentinel */ }
10195625f965SAjay Singh };
10205625f965SAjay Singh MODULE_DEVICE_TABLE(of, wilc_of_match);
10215625f965SAjay Singh
10225625f965SAjay Singh static const struct dev_pm_ops wilc_sdio_pm_ops = {
10235625f965SAjay Singh .suspend = wilc_sdio_suspend,
10245625f965SAjay Singh .resume = wilc_sdio_resume,
10255625f965SAjay Singh };
10265625f965SAjay Singh
10275625f965SAjay Singh static struct sdio_driver wilc_sdio_driver = {
10285625f965SAjay Singh .name = SDIO_MODALIAS,
10295625f965SAjay Singh .id_table = wilc_sdio_ids,
10305625f965SAjay Singh .probe = wilc_sdio_probe,
10315625f965SAjay Singh .remove = wilc_sdio_remove,
10325625f965SAjay Singh .drv = {
10335625f965SAjay Singh .pm = &wilc_sdio_pm_ops,
10345625f965SAjay Singh .of_match_table = wilc_of_match,
10355625f965SAjay Singh }
10365625f965SAjay Singh };
1037c33c93e9SKrzysztof Kozlowski module_sdio_driver(wilc_sdio_driver);
1038c33c93e9SKrzysztof Kozlowski
1039c9013880SBreno Leitao MODULE_DESCRIPTION("Atmel WILC1000 SDIO wireless driver");
10405625f965SAjay Singh MODULE_LICENSE("GPL");
1041