xref: /openbmc/linux/drivers/net/wireless/st/cw1200/hwio.c (revision d2912cb1)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2560424e9SKalle Valo /*
3560424e9SKalle Valo  * Low-level device IO routines for ST-Ericsson CW1200 drivers
4560424e9SKalle Valo  *
5560424e9SKalle Valo  * Copyright (c) 2010, ST-Ericsson
6560424e9SKalle Valo  * Author: Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
7560424e9SKalle Valo  *
8560424e9SKalle Valo  * Based on:
9560424e9SKalle Valo  * ST-Ericsson UMAC CW1200 driver, which is
10560424e9SKalle Valo  * Copyright (c) 2010, ST-Ericsson
11560424e9SKalle Valo  * Author: Ajitpal Singh <ajitpal.singh@lockless.no>
12560424e9SKalle Valo  */
13560424e9SKalle Valo 
14560424e9SKalle Valo #include <linux/types.h>
15560424e9SKalle Valo 
16560424e9SKalle Valo #include "cw1200.h"
17560424e9SKalle Valo #include "hwio.h"
18560424e9SKalle Valo #include "hwbus.h"
19560424e9SKalle Valo 
20560424e9SKalle Valo  /* Sdio addr is 4*spi_addr */
21560424e9SKalle Valo #define SPI_REG_ADDR_TO_SDIO(spi_reg_addr) ((spi_reg_addr) << 2)
22560424e9SKalle Valo #define SDIO_ADDR17BIT(buf_id, mpf, rfu, reg_id_ofs) \
23560424e9SKalle Valo 				((((buf_id)    & 0x1F) << 7) \
24560424e9SKalle Valo 				| (((mpf)        & 1) << 6) \
25560424e9SKalle Valo 				| (((rfu)        & 1) << 5) \
26560424e9SKalle Valo 				| (((reg_id_ofs) & 0x1F) << 0))
27560424e9SKalle Valo #define MAX_RETRY		3
28560424e9SKalle Valo 
29560424e9SKalle Valo 
__cw1200_reg_read(struct cw1200_common * priv,u16 addr,void * buf,size_t buf_len,int buf_id)30560424e9SKalle Valo static int __cw1200_reg_read(struct cw1200_common *priv, u16 addr,
31560424e9SKalle Valo 			     void *buf, size_t buf_len, int buf_id)
32560424e9SKalle Valo {
33560424e9SKalle Valo 	u16 addr_sdio;
34560424e9SKalle Valo 	u32 sdio_reg_addr_17bit;
35560424e9SKalle Valo 
36560424e9SKalle Valo 	/* Check if buffer is aligned to 4 byte boundary */
37560424e9SKalle Valo 	if (WARN_ON(((unsigned long)buf & 3) && (buf_len > 4))) {
38560424e9SKalle Valo 		pr_err("buffer is not aligned.\n");
39560424e9SKalle Valo 		return -EINVAL;
40560424e9SKalle Valo 	}
41560424e9SKalle Valo 
42560424e9SKalle Valo 	/* Convert to SDIO Register Address */
43560424e9SKalle Valo 	addr_sdio = SPI_REG_ADDR_TO_SDIO(addr);
44560424e9SKalle Valo 	sdio_reg_addr_17bit = SDIO_ADDR17BIT(buf_id, 0, 0, addr_sdio);
45560424e9SKalle Valo 
46560424e9SKalle Valo 	return priv->hwbus_ops->hwbus_memcpy_fromio(priv->hwbus_priv,
47560424e9SKalle Valo 						  sdio_reg_addr_17bit,
48560424e9SKalle Valo 						  buf, buf_len);
49560424e9SKalle Valo }
50560424e9SKalle Valo 
__cw1200_reg_write(struct cw1200_common * priv,u16 addr,const void * buf,size_t buf_len,int buf_id)51560424e9SKalle Valo static int __cw1200_reg_write(struct cw1200_common *priv, u16 addr,
52560424e9SKalle Valo 				const void *buf, size_t buf_len, int buf_id)
53560424e9SKalle Valo {
54560424e9SKalle Valo 	u16 addr_sdio;
55560424e9SKalle Valo 	u32 sdio_reg_addr_17bit;
56560424e9SKalle Valo 
57560424e9SKalle Valo 	/* Convert to SDIO Register Address */
58560424e9SKalle Valo 	addr_sdio = SPI_REG_ADDR_TO_SDIO(addr);
59560424e9SKalle Valo 	sdio_reg_addr_17bit = SDIO_ADDR17BIT(buf_id, 0, 0, addr_sdio);
60560424e9SKalle Valo 
61560424e9SKalle Valo 	return priv->hwbus_ops->hwbus_memcpy_toio(priv->hwbus_priv,
62560424e9SKalle Valo 						sdio_reg_addr_17bit,
63560424e9SKalle Valo 						buf, buf_len);
64560424e9SKalle Valo }
65560424e9SKalle Valo 
__cw1200_reg_read_32(struct cw1200_common * priv,u16 addr,u32 * val)66560424e9SKalle Valo static inline int __cw1200_reg_read_32(struct cw1200_common *priv,
67560424e9SKalle Valo 					u16 addr, u32 *val)
68560424e9SKalle Valo {
69560424e9SKalle Valo 	__le32 tmp;
70560424e9SKalle Valo 	int i = __cw1200_reg_read(priv, addr, &tmp, sizeof(tmp), 0);
71560424e9SKalle Valo 	*val = le32_to_cpu(tmp);
72560424e9SKalle Valo 	return i;
73560424e9SKalle Valo }
74560424e9SKalle Valo 
__cw1200_reg_write_32(struct cw1200_common * priv,u16 addr,u32 val)75560424e9SKalle Valo static inline int __cw1200_reg_write_32(struct cw1200_common *priv,
76560424e9SKalle Valo 					u16 addr, u32 val)
77560424e9SKalle Valo {
78560424e9SKalle Valo 	__le32 tmp = cpu_to_le32(val);
79560424e9SKalle Valo 	return __cw1200_reg_write(priv, addr, &tmp, sizeof(tmp), 0);
80560424e9SKalle Valo }
81560424e9SKalle Valo 
__cw1200_reg_read_16(struct cw1200_common * priv,u16 addr,u16 * val)82560424e9SKalle Valo static inline int __cw1200_reg_read_16(struct cw1200_common *priv,
83560424e9SKalle Valo 					u16 addr, u16 *val)
84560424e9SKalle Valo {
85560424e9SKalle Valo 	__le16 tmp;
86560424e9SKalle Valo 	int i = __cw1200_reg_read(priv, addr, &tmp, sizeof(tmp), 0);
87560424e9SKalle Valo 	*val = le16_to_cpu(tmp);
88560424e9SKalle Valo 	return i;
89560424e9SKalle Valo }
90560424e9SKalle Valo 
__cw1200_reg_write_16(struct cw1200_common * priv,u16 addr,u16 val)91560424e9SKalle Valo static inline int __cw1200_reg_write_16(struct cw1200_common *priv,
92560424e9SKalle Valo 					u16 addr, u16 val)
93560424e9SKalle Valo {
94560424e9SKalle Valo 	__le16 tmp = cpu_to_le16(val);
95560424e9SKalle Valo 	return __cw1200_reg_write(priv, addr, &tmp, sizeof(tmp), 0);
96560424e9SKalle Valo }
97560424e9SKalle Valo 
cw1200_reg_read(struct cw1200_common * priv,u16 addr,void * buf,size_t buf_len)98560424e9SKalle Valo int cw1200_reg_read(struct cw1200_common *priv, u16 addr, void *buf,
99560424e9SKalle Valo 			size_t buf_len)
100560424e9SKalle Valo {
101560424e9SKalle Valo 	int ret;
102560424e9SKalle Valo 	priv->hwbus_ops->lock(priv->hwbus_priv);
103560424e9SKalle Valo 	ret = __cw1200_reg_read(priv, addr, buf, buf_len, 0);
104560424e9SKalle Valo 	priv->hwbus_ops->unlock(priv->hwbus_priv);
105560424e9SKalle Valo 	return ret;
106560424e9SKalle Valo }
107560424e9SKalle Valo 
cw1200_reg_write(struct cw1200_common * priv,u16 addr,const void * buf,size_t buf_len)108560424e9SKalle Valo int cw1200_reg_write(struct cw1200_common *priv, u16 addr, const void *buf,
109560424e9SKalle Valo 			size_t buf_len)
110560424e9SKalle Valo {
111560424e9SKalle Valo 	int ret;
112560424e9SKalle Valo 	priv->hwbus_ops->lock(priv->hwbus_priv);
113560424e9SKalle Valo 	ret = __cw1200_reg_write(priv, addr, buf, buf_len, 0);
114560424e9SKalle Valo 	priv->hwbus_ops->unlock(priv->hwbus_priv);
115560424e9SKalle Valo 	return ret;
116560424e9SKalle Valo }
117560424e9SKalle Valo 
cw1200_data_read(struct cw1200_common * priv,void * buf,size_t buf_len)118560424e9SKalle Valo int cw1200_data_read(struct cw1200_common *priv, void *buf, size_t buf_len)
119560424e9SKalle Valo {
120560424e9SKalle Valo 	int ret, retry = 1;
121560424e9SKalle Valo 	int buf_id_rx = priv->buf_id_rx;
122560424e9SKalle Valo 
123560424e9SKalle Valo 	priv->hwbus_ops->lock(priv->hwbus_priv);
124560424e9SKalle Valo 
125560424e9SKalle Valo 	while (retry <= MAX_RETRY) {
126560424e9SKalle Valo 		ret = __cw1200_reg_read(priv,
127560424e9SKalle Valo 					ST90TDS_IN_OUT_QUEUE_REG_ID, buf,
128560424e9SKalle Valo 					buf_len, buf_id_rx + 1);
129560424e9SKalle Valo 		if (!ret) {
130560424e9SKalle Valo 			buf_id_rx = (buf_id_rx + 1) & 3;
131560424e9SKalle Valo 			priv->buf_id_rx = buf_id_rx;
132560424e9SKalle Valo 			break;
133560424e9SKalle Valo 		} else {
134560424e9SKalle Valo 			retry++;
135560424e9SKalle Valo 			mdelay(1);
136560424e9SKalle Valo 			pr_err("error :[%d]\n", ret);
137560424e9SKalle Valo 		}
138560424e9SKalle Valo 	}
139560424e9SKalle Valo 
140560424e9SKalle Valo 	priv->hwbus_ops->unlock(priv->hwbus_priv);
141560424e9SKalle Valo 	return ret;
142560424e9SKalle Valo }
143560424e9SKalle Valo 
cw1200_data_write(struct cw1200_common * priv,const void * buf,size_t buf_len)144560424e9SKalle Valo int cw1200_data_write(struct cw1200_common *priv, const void *buf,
145560424e9SKalle Valo 			size_t buf_len)
146560424e9SKalle Valo {
147560424e9SKalle Valo 	int ret, retry = 1;
148560424e9SKalle Valo 	int buf_id_tx = priv->buf_id_tx;
149560424e9SKalle Valo 
150560424e9SKalle Valo 	priv->hwbus_ops->lock(priv->hwbus_priv);
151560424e9SKalle Valo 
152560424e9SKalle Valo 	while (retry <= MAX_RETRY) {
153560424e9SKalle Valo 		ret = __cw1200_reg_write(priv,
154560424e9SKalle Valo 					 ST90TDS_IN_OUT_QUEUE_REG_ID, buf,
155560424e9SKalle Valo 					 buf_len, buf_id_tx);
156560424e9SKalle Valo 		if (!ret) {
157560424e9SKalle Valo 			buf_id_tx = (buf_id_tx + 1) & 31;
158560424e9SKalle Valo 			priv->buf_id_tx = buf_id_tx;
159560424e9SKalle Valo 			break;
160560424e9SKalle Valo 		} else {
161560424e9SKalle Valo 			retry++;
162560424e9SKalle Valo 			mdelay(1);
163560424e9SKalle Valo 			pr_err("error :[%d]\n", ret);
164560424e9SKalle Valo 		}
165560424e9SKalle Valo 	}
166560424e9SKalle Valo 
167560424e9SKalle Valo 	priv->hwbus_ops->unlock(priv->hwbus_priv);
168560424e9SKalle Valo 	return ret;
169560424e9SKalle Valo }
170560424e9SKalle Valo 
cw1200_indirect_read(struct cw1200_common * priv,u32 addr,void * buf,size_t buf_len,u32 prefetch,u16 port_addr)171560424e9SKalle Valo int cw1200_indirect_read(struct cw1200_common *priv, u32 addr, void *buf,
172560424e9SKalle Valo 			 size_t buf_len, u32 prefetch, u16 port_addr)
173560424e9SKalle Valo {
174560424e9SKalle Valo 	u32 val32 = 0;
175560424e9SKalle Valo 	int i, ret;
176560424e9SKalle Valo 
177560424e9SKalle Valo 	if ((buf_len / 2) >= 0x1000) {
178560424e9SKalle Valo 		pr_err("Can't read more than 0xfff words.\n");
179560424e9SKalle Valo 		return -EINVAL;
180560424e9SKalle Valo 	}
181560424e9SKalle Valo 
182560424e9SKalle Valo 	priv->hwbus_ops->lock(priv->hwbus_priv);
183560424e9SKalle Valo 	/* Write address */
184560424e9SKalle Valo 	ret = __cw1200_reg_write_32(priv, ST90TDS_SRAM_BASE_ADDR_REG_ID, addr);
185560424e9SKalle Valo 	if (ret < 0) {
186560424e9SKalle Valo 		pr_err("Can't write address register.\n");
187560424e9SKalle Valo 		goto out;
188560424e9SKalle Valo 	}
189560424e9SKalle Valo 
190560424e9SKalle Valo 	/* Read CONFIG Register Value - We will read 32 bits */
191560424e9SKalle Valo 	ret = __cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, &val32);
192560424e9SKalle Valo 	if (ret < 0) {
193560424e9SKalle Valo 		pr_err("Can't read config register.\n");
194560424e9SKalle Valo 		goto out;
195560424e9SKalle Valo 	}
196560424e9SKalle Valo 
197560424e9SKalle Valo 	/* Set PREFETCH bit */
198560424e9SKalle Valo 	ret = __cw1200_reg_write_32(priv, ST90TDS_CONFIG_REG_ID,
199560424e9SKalle Valo 					val32 | prefetch);
200560424e9SKalle Valo 	if (ret < 0) {
201560424e9SKalle Valo 		pr_err("Can't write prefetch bit.\n");
202560424e9SKalle Valo 		goto out;
203560424e9SKalle Valo 	}
204560424e9SKalle Valo 
205560424e9SKalle Valo 	/* Check for PRE-FETCH bit to be cleared */
206560424e9SKalle Valo 	for (i = 0; i < 20; i++) {
207560424e9SKalle Valo 		ret = __cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, &val32);
208560424e9SKalle Valo 		if (ret < 0) {
209560424e9SKalle Valo 			pr_err("Can't check prefetch bit.\n");
210560424e9SKalle Valo 			goto out;
211560424e9SKalle Valo 		}
212560424e9SKalle Valo 		if (!(val32 & prefetch))
213560424e9SKalle Valo 			break;
214560424e9SKalle Valo 
215560424e9SKalle Valo 		mdelay(i);
216560424e9SKalle Valo 	}
217560424e9SKalle Valo 
218560424e9SKalle Valo 	if (val32 & prefetch) {
219560424e9SKalle Valo 		pr_err("Prefetch bit is not cleared.\n");
220560424e9SKalle Valo 		goto out;
221560424e9SKalle Valo 	}
222560424e9SKalle Valo 
223560424e9SKalle Valo 	/* Read data port */
224560424e9SKalle Valo 	ret = __cw1200_reg_read(priv, port_addr, buf, buf_len, 0);
225560424e9SKalle Valo 	if (ret < 0) {
226560424e9SKalle Valo 		pr_err("Can't read data port.\n");
227560424e9SKalle Valo 		goto out;
228560424e9SKalle Valo 	}
229560424e9SKalle Valo 
230560424e9SKalle Valo out:
231560424e9SKalle Valo 	priv->hwbus_ops->unlock(priv->hwbus_priv);
232560424e9SKalle Valo 	return ret;
233560424e9SKalle Valo }
234560424e9SKalle Valo 
cw1200_apb_write(struct cw1200_common * priv,u32 addr,const void * buf,size_t buf_len)235560424e9SKalle Valo int cw1200_apb_write(struct cw1200_common *priv, u32 addr, const void *buf,
236560424e9SKalle Valo 			size_t buf_len)
237560424e9SKalle Valo {
238560424e9SKalle Valo 	int ret;
239560424e9SKalle Valo 
240560424e9SKalle Valo 	if ((buf_len / 2) >= 0x1000) {
241560424e9SKalle Valo 		pr_err("Can't write more than 0xfff words.\n");
242560424e9SKalle Valo 		return -EINVAL;
243560424e9SKalle Valo 	}
244560424e9SKalle Valo 
245560424e9SKalle Valo 	priv->hwbus_ops->lock(priv->hwbus_priv);
246560424e9SKalle Valo 
247560424e9SKalle Valo 	/* Write address */
248560424e9SKalle Valo 	ret = __cw1200_reg_write_32(priv, ST90TDS_SRAM_BASE_ADDR_REG_ID, addr);
249560424e9SKalle Valo 	if (ret < 0) {
250560424e9SKalle Valo 		pr_err("Can't write address register.\n");
251560424e9SKalle Valo 		goto out;
252560424e9SKalle Valo 	}
253560424e9SKalle Valo 
254560424e9SKalle Valo 	/* Write data port */
255560424e9SKalle Valo 	ret = __cw1200_reg_write(priv, ST90TDS_SRAM_DPORT_REG_ID,
256560424e9SKalle Valo 					buf, buf_len, 0);
257560424e9SKalle Valo 	if (ret < 0) {
258560424e9SKalle Valo 		pr_err("Can't write data port.\n");
259560424e9SKalle Valo 		goto out;
260560424e9SKalle Valo 	}
261560424e9SKalle Valo 
262560424e9SKalle Valo out:
263560424e9SKalle Valo 	priv->hwbus_ops->unlock(priv->hwbus_priv);
264560424e9SKalle Valo 	return ret;
265560424e9SKalle Valo }
266560424e9SKalle Valo 
__cw1200_irq_enable(struct cw1200_common * priv,int enable)267560424e9SKalle Valo int __cw1200_irq_enable(struct cw1200_common *priv, int enable)
268560424e9SKalle Valo {
269560424e9SKalle Valo 	u32 val32;
270560424e9SKalle Valo 	u16 val16;
271560424e9SKalle Valo 	int ret;
272560424e9SKalle Valo 
273560424e9SKalle Valo 	if (HIF_8601_SILICON == priv->hw_type) {
274560424e9SKalle Valo 		ret = __cw1200_reg_read_32(priv, ST90TDS_CONFIG_REG_ID, &val32);
275560424e9SKalle Valo 		if (ret < 0) {
276560424e9SKalle Valo 			pr_err("Can't read config register.\n");
277560424e9SKalle Valo 			return ret;
278560424e9SKalle Valo 		}
279560424e9SKalle Valo 
280560424e9SKalle Valo 		if (enable)
281560424e9SKalle Valo 			val32 |= ST90TDS_CONF_IRQ_RDY_ENABLE;
282560424e9SKalle Valo 		else
283560424e9SKalle Valo 			val32 &= ~ST90TDS_CONF_IRQ_RDY_ENABLE;
284560424e9SKalle Valo 
285560424e9SKalle Valo 		ret = __cw1200_reg_write_32(priv, ST90TDS_CONFIG_REG_ID, val32);
286560424e9SKalle Valo 		if (ret < 0) {
287560424e9SKalle Valo 			pr_err("Can't write config register.\n");
288560424e9SKalle Valo 			return ret;
289560424e9SKalle Valo 		}
290560424e9SKalle Valo 	} else {
291560424e9SKalle Valo 		ret = __cw1200_reg_read_16(priv, ST90TDS_CONFIG_REG_ID, &val16);
292560424e9SKalle Valo 		if (ret < 0) {
293560424e9SKalle Valo 			pr_err("Can't read control register.\n");
294560424e9SKalle Valo 			return ret;
295560424e9SKalle Valo 		}
296560424e9SKalle Valo 
297560424e9SKalle Valo 		if (enable)
298560424e9SKalle Valo 			val16 |= ST90TDS_CONT_IRQ_RDY_ENABLE;
299560424e9SKalle Valo 		else
300560424e9SKalle Valo 			val16 &= ~ST90TDS_CONT_IRQ_RDY_ENABLE;
301560424e9SKalle Valo 
302560424e9SKalle Valo 		ret = __cw1200_reg_write_16(priv, ST90TDS_CONFIG_REG_ID, val16);
303560424e9SKalle Valo 		if (ret < 0) {
304560424e9SKalle Valo 			pr_err("Can't write control register.\n");
305560424e9SKalle Valo 			return ret;
306560424e9SKalle Valo 		}
307560424e9SKalle Valo 	}
308560424e9SKalle Valo 	return 0;
309560424e9SKalle Valo }
310