xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/st/cw1200/hwio.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Low-level device IO routines for ST-Ericsson CW1200 drivers
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2010, ST-Ericsson
6*4882a593Smuzhiyun  * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Based on:
9*4882a593Smuzhiyun  * ST-Ericsson UMAC CW1200 driver, which is
10*4882a593Smuzhiyun  * Copyright (c) 2010, ST-Ericsson
11*4882a593Smuzhiyun  * Author: Ajitpal Singh <ajitpal.singh@lockless.no>
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <linux/types.h>
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include "cw1200.h"
17*4882a593Smuzhiyun #include "hwio.h"
18*4882a593Smuzhiyun #include "hwbus.h"
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun  /* Sdio addr is 4*spi_addr */
21*4882a593Smuzhiyun #define SPI_REG_ADDR_TO_SDIO(spi_reg_addr) ((spi_reg_addr) << 2)
22*4882a593Smuzhiyun #define SDIO_ADDR17BIT(buf_id, mpf, rfu, reg_id_ofs) \
23*4882a593Smuzhiyun 				((((buf_id)    & 0x1F) << 7) \
24*4882a593Smuzhiyun 				| (((mpf)        & 1) << 6) \
25*4882a593Smuzhiyun 				| (((rfu)        & 1) << 5) \
26*4882a593Smuzhiyun 				| (((reg_id_ofs) & 0x1F) << 0))
27*4882a593Smuzhiyun #define MAX_RETRY		3
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun 
__cw1200_reg_read(struct cw1200_common * priv,u16 addr,void * buf,size_t buf_len,int buf_id)30*4882a593Smuzhiyun static int __cw1200_reg_read(struct cw1200_common *priv, u16 addr,
31*4882a593Smuzhiyun 			     void *buf, size_t buf_len, int buf_id)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun 	u16 addr_sdio;
34*4882a593Smuzhiyun 	u32 sdio_reg_addr_17bit;
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun 	/* Check if buffer is aligned to 4 byte boundary */
37*4882a593Smuzhiyun 	if (WARN_ON(((unsigned long)buf & 3) && (buf_len > 4))) {
38*4882a593Smuzhiyun 		pr_err("buffer is not aligned.\n");
39*4882a593Smuzhiyun 		return -EINVAL;
40*4882a593Smuzhiyun 	}
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	/* Convert to SDIO Register Address */
43*4882a593Smuzhiyun 	addr_sdio = SPI_REG_ADDR_TO_SDIO(addr);
44*4882a593Smuzhiyun 	sdio_reg_addr_17bit = SDIO_ADDR17BIT(buf_id, 0, 0, addr_sdio);
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	return priv->hwbus_ops->hwbus_memcpy_fromio(priv->hwbus_priv,
47*4882a593Smuzhiyun 						  sdio_reg_addr_17bit,
48*4882a593Smuzhiyun 						  buf, buf_len);
49*4882a593Smuzhiyun }
50*4882a593Smuzhiyun 
__cw1200_reg_write(struct cw1200_common * priv,u16 addr,const void * buf,size_t buf_len,int buf_id)51*4882a593Smuzhiyun static int __cw1200_reg_write(struct cw1200_common *priv, u16 addr,
52*4882a593Smuzhiyun 				const void *buf, size_t buf_len, int buf_id)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun 	u16 addr_sdio;
55*4882a593Smuzhiyun 	u32 sdio_reg_addr_17bit;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	/* Convert to SDIO Register Address */
58*4882a593Smuzhiyun 	addr_sdio = SPI_REG_ADDR_TO_SDIO(addr);
59*4882a593Smuzhiyun 	sdio_reg_addr_17bit = SDIO_ADDR17BIT(buf_id, 0, 0, addr_sdio);
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun 	return priv->hwbus_ops->hwbus_memcpy_toio(priv->hwbus_priv,
62*4882a593Smuzhiyun 						sdio_reg_addr_17bit,
63*4882a593Smuzhiyun 						buf, buf_len);
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun 
__cw1200_reg_read_32(struct cw1200_common * priv,u16 addr,u32 * val)66*4882a593Smuzhiyun static inline int __cw1200_reg_read_32(struct cw1200_common *priv,
67*4882a593Smuzhiyun 					u16 addr, u32 *val)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun 	__le32 tmp;
70*4882a593Smuzhiyun 	int i = __cw1200_reg_read(priv, addr, &tmp, sizeof(tmp), 0);
71*4882a593Smuzhiyun 	*val = le32_to_cpu(tmp);
72*4882a593Smuzhiyun 	return i;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun 
__cw1200_reg_write_32(struct cw1200_common * priv,u16 addr,u32 val)75*4882a593Smuzhiyun static inline int __cw1200_reg_write_32(struct cw1200_common *priv,
76*4882a593Smuzhiyun 					u16 addr, u32 val)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun 	__le32 tmp = cpu_to_le32(val);
79*4882a593Smuzhiyun 	return __cw1200_reg_write(priv, addr, &tmp, sizeof(tmp), 0);
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun 
__cw1200_reg_read_16(struct cw1200_common * priv,u16 addr,u16 * val)82*4882a593Smuzhiyun static inline int __cw1200_reg_read_16(struct cw1200_common *priv,
83*4882a593Smuzhiyun 					u16 addr, u16 *val)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 	__le16 tmp;
86*4882a593Smuzhiyun 	int i = __cw1200_reg_read(priv, addr, &tmp, sizeof(tmp), 0);
87*4882a593Smuzhiyun 	*val = le16_to_cpu(tmp);
88*4882a593Smuzhiyun 	return i;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun 
__cw1200_reg_write_16(struct cw1200_common * priv,u16 addr,u16 val)91*4882a593Smuzhiyun static inline int __cw1200_reg_write_16(struct cw1200_common *priv,
92*4882a593Smuzhiyun 					u16 addr, u16 val)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun 	__le16 tmp = cpu_to_le16(val);
95*4882a593Smuzhiyun 	return __cw1200_reg_write(priv, addr, &tmp, sizeof(tmp), 0);
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
cw1200_reg_read(struct cw1200_common * priv,u16 addr,void * buf,size_t buf_len)98*4882a593Smuzhiyun int cw1200_reg_read(struct cw1200_common *priv, u16 addr, void *buf,
99*4882a593Smuzhiyun 			size_t buf_len)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun 	int ret;
102*4882a593Smuzhiyun 	priv->hwbus_ops->lock(priv->hwbus_priv);
103*4882a593Smuzhiyun 	ret = __cw1200_reg_read(priv, addr, buf, buf_len, 0);
104*4882a593Smuzhiyun 	priv->hwbus_ops->unlock(priv->hwbus_priv);
105*4882a593Smuzhiyun 	return ret;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
cw1200_reg_write(struct cw1200_common * priv,u16 addr,const void * buf,size_t buf_len)108*4882a593Smuzhiyun int cw1200_reg_write(struct cw1200_common *priv, u16 addr, const void *buf,
109*4882a593Smuzhiyun 			size_t buf_len)
110*4882a593Smuzhiyun {
111*4882a593Smuzhiyun 	int ret;
112*4882a593Smuzhiyun 	priv->hwbus_ops->lock(priv->hwbus_priv);
113*4882a593Smuzhiyun 	ret = __cw1200_reg_write(priv, addr, buf, buf_len, 0);
114*4882a593Smuzhiyun 	priv->hwbus_ops->unlock(priv->hwbus_priv);
115*4882a593Smuzhiyun 	return ret;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun 
cw1200_data_read(struct cw1200_common * priv,void * buf,size_t buf_len)118*4882a593Smuzhiyun int cw1200_data_read(struct cw1200_common *priv, void *buf, size_t buf_len)
119*4882a593Smuzhiyun {
120*4882a593Smuzhiyun 	int ret, retry = 1;
121*4882a593Smuzhiyun 	int buf_id_rx = priv->buf_id_rx;
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	priv->hwbus_ops->lock(priv->hwbus_priv);
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	while (retry <= MAX_RETRY) {
126*4882a593Smuzhiyun 		ret = __cw1200_reg_read(priv,
127*4882a593Smuzhiyun 					ST90TDS_IN_OUT_QUEUE_REG_ID, buf,
128*4882a593Smuzhiyun 					buf_len, buf_id_rx + 1);
129*4882a593Smuzhiyun 		if (!ret) {
130*4882a593Smuzhiyun 			buf_id_rx = (buf_id_rx + 1) & 3;
131*4882a593Smuzhiyun 			priv->buf_id_rx = buf_id_rx;
132*4882a593Smuzhiyun 			break;
133*4882a593Smuzhiyun 		} else {
134*4882a593Smuzhiyun 			retry++;
135*4882a593Smuzhiyun 			mdelay(1);
136*4882a593Smuzhiyun 			pr_err("error :[%d]\n", ret);
137*4882a593Smuzhiyun 		}
138*4882a593Smuzhiyun 	}
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun 	priv->hwbus_ops->unlock(priv->hwbus_priv);
141*4882a593Smuzhiyun 	return ret;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun 
cw1200_data_write(struct cw1200_common * priv,const void * buf,size_t buf_len)144*4882a593Smuzhiyun int cw1200_data_write(struct cw1200_common *priv, const void *buf,
145*4882a593Smuzhiyun 			size_t buf_len)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun 	int ret, retry = 1;
148*4882a593Smuzhiyun 	int buf_id_tx = priv->buf_id_tx;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	priv->hwbus_ops->lock(priv->hwbus_priv);
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	while (retry <= MAX_RETRY) {
153*4882a593Smuzhiyun 		ret = __cw1200_reg_write(priv,
154*4882a593Smuzhiyun 					 ST90TDS_IN_OUT_QUEUE_REG_ID, buf,
155*4882a593Smuzhiyun 					 buf_len, buf_id_tx);
156*4882a593Smuzhiyun 		if (!ret) {
157*4882a593Smuzhiyun 			buf_id_tx = (buf_id_tx + 1) & 31;
158*4882a593Smuzhiyun 			priv->buf_id_tx = buf_id_tx;
159*4882a593Smuzhiyun 			break;
160*4882a593Smuzhiyun 		} else {
161*4882a593Smuzhiyun 			retry++;
162*4882a593Smuzhiyun 			mdelay(1);
163*4882a593Smuzhiyun 			pr_err("error :[%d]\n", ret);
164*4882a593Smuzhiyun 		}
165*4882a593Smuzhiyun 	}
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	priv->hwbus_ops->unlock(priv->hwbus_priv);
168*4882a593Smuzhiyun 	return ret;
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun 
cw1200_indirect_read(struct cw1200_common * priv,u32 addr,void * buf,size_t buf_len,u32 prefetch,u16 port_addr)171*4882a593Smuzhiyun int cw1200_indirect_read(struct cw1200_common *priv, u32 addr, void *buf,
172*4882a593Smuzhiyun 			 size_t buf_len, u32 prefetch, u16 port_addr)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun 	u32 val32 = 0;
175*4882a593Smuzhiyun 	int i, ret;
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	if ((buf_len / 2) >= 0x1000) {
178*4882a593Smuzhiyun 		pr_err("Can't read more than 0xfff words.\n");
179*4882a593Smuzhiyun 		return -EINVAL;
180*4882a593Smuzhiyun 	}
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	priv->hwbus_ops->lock(priv->hwbus_priv);
183*4882a593Smuzhiyun 	/* Write address */
184*4882a593Smuzhiyun 	ret = __cw1200_reg_write_32(priv, ST90TDS_SRAM_BASE_ADDR_REG_ID, addr);
185*4882a593Smuzhiyun 	if (ret < 0) {
186*4882a593Smuzhiyun 		pr_err("Can't write address register.\n");
187*4882a593Smuzhiyun 		goto out;
188*4882a593Smuzhiyun 	}
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	/* Read CONFIG Register Value - We will read 32 bits */
191*4882a593Smuzhiyun 	ret = __cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, &val32);
192*4882a593Smuzhiyun 	if (ret < 0) {
193*4882a593Smuzhiyun 		pr_err("Can't read config register.\n");
194*4882a593Smuzhiyun 		goto out;
195*4882a593Smuzhiyun 	}
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	/* Set PREFETCH bit */
198*4882a593Smuzhiyun 	ret = __cw1200_reg_write_32(priv, ST90TDS_CONFIG_REG_ID,
199*4882a593Smuzhiyun 					val32 | prefetch);
200*4882a593Smuzhiyun 	if (ret < 0) {
201*4882a593Smuzhiyun 		pr_err("Can't write prefetch bit.\n");
202*4882a593Smuzhiyun 		goto out;
203*4882a593Smuzhiyun 	}
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	/* Check for PRE-FETCH bit to be cleared */
206*4882a593Smuzhiyun 	for (i = 0; i < 20; i++) {
207*4882a593Smuzhiyun 		ret = __cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, &val32);
208*4882a593Smuzhiyun 		if (ret < 0) {
209*4882a593Smuzhiyun 			pr_err("Can't check prefetch bit.\n");
210*4882a593Smuzhiyun 			goto out;
211*4882a593Smuzhiyun 		}
212*4882a593Smuzhiyun 		if (!(val32 & prefetch))
213*4882a593Smuzhiyun 			break;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 		mdelay(i);
216*4882a593Smuzhiyun 	}
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	if (val32 & prefetch) {
219*4882a593Smuzhiyun 		pr_err("Prefetch bit is not cleared.\n");
220*4882a593Smuzhiyun 		goto out;
221*4882a593Smuzhiyun 	}
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	/* Read data port */
224*4882a593Smuzhiyun 	ret = __cw1200_reg_read(priv, port_addr, buf, buf_len, 0);
225*4882a593Smuzhiyun 	if (ret < 0) {
226*4882a593Smuzhiyun 		pr_err("Can't read data port.\n");
227*4882a593Smuzhiyun 		goto out;
228*4882a593Smuzhiyun 	}
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun out:
231*4882a593Smuzhiyun 	priv->hwbus_ops->unlock(priv->hwbus_priv);
232*4882a593Smuzhiyun 	return ret;
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun 
cw1200_apb_write(struct cw1200_common * priv,u32 addr,const void * buf,size_t buf_len)235*4882a593Smuzhiyun int cw1200_apb_write(struct cw1200_common *priv, u32 addr, const void *buf,
236*4882a593Smuzhiyun 			size_t buf_len)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun 	int ret;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	if ((buf_len / 2) >= 0x1000) {
241*4882a593Smuzhiyun 		pr_err("Can't write more than 0xfff words.\n");
242*4882a593Smuzhiyun 		return -EINVAL;
243*4882a593Smuzhiyun 	}
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	priv->hwbus_ops->lock(priv->hwbus_priv);
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	/* Write address */
248*4882a593Smuzhiyun 	ret = __cw1200_reg_write_32(priv, ST90TDS_SRAM_BASE_ADDR_REG_ID, addr);
249*4882a593Smuzhiyun 	if (ret < 0) {
250*4882a593Smuzhiyun 		pr_err("Can't write address register.\n");
251*4882a593Smuzhiyun 		goto out;
252*4882a593Smuzhiyun 	}
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	/* Write data port */
255*4882a593Smuzhiyun 	ret = __cw1200_reg_write(priv, ST90TDS_SRAM_DPORT_REG_ID,
256*4882a593Smuzhiyun 					buf, buf_len, 0);
257*4882a593Smuzhiyun 	if (ret < 0) {
258*4882a593Smuzhiyun 		pr_err("Can't write data port.\n");
259*4882a593Smuzhiyun 		goto out;
260*4882a593Smuzhiyun 	}
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun out:
263*4882a593Smuzhiyun 	priv->hwbus_ops->unlock(priv->hwbus_priv);
264*4882a593Smuzhiyun 	return ret;
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun 
__cw1200_irq_enable(struct cw1200_common * priv,int enable)267*4882a593Smuzhiyun int __cw1200_irq_enable(struct cw1200_common *priv, int enable)
268*4882a593Smuzhiyun {
269*4882a593Smuzhiyun 	u32 val32;
270*4882a593Smuzhiyun 	u16 val16;
271*4882a593Smuzhiyun 	int ret;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	if (HIF_8601_SILICON == priv->hw_type) {
274*4882a593Smuzhiyun 		ret = __cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, &val32);
275*4882a593Smuzhiyun 		if (ret < 0) {
276*4882a593Smuzhiyun 			pr_err("Can't read config register.\n");
277*4882a593Smuzhiyun 			return ret;
278*4882a593Smuzhiyun 		}
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 		if (enable)
281*4882a593Smuzhiyun 			val32 |= ST90TDS_CONF_IRQ_RDY_ENABLE;
282*4882a593Smuzhiyun 		else
283*4882a593Smuzhiyun 			val32 &= ~ST90TDS_CONF_IRQ_RDY_ENABLE;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 		ret = __cw1200_reg_write_32(priv, ST90TDS_CONFIG_REG_ID, val32);
286*4882a593Smuzhiyun 		if (ret < 0) {
287*4882a593Smuzhiyun 			pr_err("Can't write config register.\n");
288*4882a593Smuzhiyun 			return ret;
289*4882a593Smuzhiyun 		}
290*4882a593Smuzhiyun 	} else {
291*4882a593Smuzhiyun 		ret = __cw1200_reg_read_16(priv, ST90TDS_CONFIG_REG_ID, &val16);
292*4882a593Smuzhiyun 		if (ret < 0) {
293*4882a593Smuzhiyun 			pr_err("Can't read control register.\n");
294*4882a593Smuzhiyun 			return ret;
295*4882a593Smuzhiyun 		}
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 		if (enable)
298*4882a593Smuzhiyun 			val16 |= ST90TDS_CONT_IRQ_RDY_ENABLE;
299*4882a593Smuzhiyun 		else
300*4882a593Smuzhiyun 			val16 &= ~ST90TDS_CONT_IRQ_RDY_ENABLE;
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 		ret = __cw1200_reg_write_16(priv, ST90TDS_CONFIG_REG_ID, val16);
303*4882a593Smuzhiyun 		if (ret < 0) {
304*4882a593Smuzhiyun 			pr_err("Can't write control register.\n");
305*4882a593Smuzhiyun 			return ret;
306*4882a593Smuzhiyun 		}
307*4882a593Smuzhiyun 	}
308*4882a593Smuzhiyun 	return 0;
309*4882a593Smuzhiyun }
310