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, &reg);
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, &reg);
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, &reg);
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