xref: /linux/drivers/net/wireless/morsemicro/mm81x/sdio.c (revision 91ec2035134982b98fab0609a9fd8480e8217dc1)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2017-2026 Morse Micro
4  */
5 #include <linux/kernel.h>
6 #include <linux/module.h>
7 #include <linux/slab.h>
8 #include <linux/workqueue.h>
9 #include <linux/mmc/card.h>
10 #include <linux/mmc/mmc.h>
11 #include <linux/mmc/host.h>
12 #include <linux/mmc/sdio_func.h>
13 #include <linux/mmc/sdio_ids.h>
14 #include <linux/mmc/sdio.h>
15 #include <linux/mmc/sd.h>
16 #include "hw.h"
17 #include "core.h"
18 #include "bus.h"
19 #include "mac.h"
20 #include "fw.h"
21 #include "hif.h"
22 
23 /*
24  * Value to indicate that the base address for bulk/register
25  * read/writes has yet to be set
26  */
27 #define MM81X_SDIO_BASE_ADDR_UNSET 0xFFFFFFFF
28 
29 #define MM81X_SDIO_ALIGNMENT (8)
30 
31 #define MM81X_SDIO_REG_ADDRESS_BASE 0x10000
32 #define MM81X_SDIO_REG_ADDRESS_WINDOW_0 MM81X_SDIO_REG_ADDRESS_BASE
33 #define MM81X_SDIO_REG_ADDRESS_WINDOW_1 (MM81X_SDIO_REG_ADDRESS_BASE + 1)
34 #define MM81X_SDIO_REG_ADDRESS_CONFIG (MM81X_SDIO_REG_ADDRESS_BASE + 2)
35 
36 struct mm81x_sdio {
37 	bool enabled;
38 	u32 bulk_addr_base;
39 	u32 register_addr_base;
40 	struct sdio_func *func;
41 	const struct sdio_device_id *id;
42 };
43 
irq_handler(struct sdio_func * func1)44 static void irq_handler(struct sdio_func *func1)
45 {
46 	struct sdio_func *func = func1->card->sdio_func[1];
47 	struct mm81x *mors = sdio_get_drvdata(func);
48 
49 	mm81x_hw_irq_handle(mors);
50 }
51 
mm81x_sdio_enable_irq(struct mm81x_sdio * sdio)52 static int mm81x_sdio_enable_irq(struct mm81x_sdio *sdio)
53 {
54 	int ret;
55 	struct sdio_func *func = sdio->func;
56 	struct sdio_func *func1 = func->card->sdio_func[0];
57 	struct mm81x *mors = sdio_get_drvdata(func);
58 
59 	sdio_claim_host(func);
60 	ret = sdio_claim_irq(func1, irq_handler);
61 	if (ret)
62 		dev_err(mors->dev, "Failed to enable sdio irq: %d\n", ret);
63 
64 	sdio_release_host(func);
65 	return ret;
66 }
67 
mm81x_sdio_disable_irq(struct mm81x_sdio * sdio)68 static void mm81x_sdio_disable_irq(struct mm81x_sdio *sdio)
69 {
70 	struct sdio_func *func = sdio->func;
71 	struct sdio_func *func1 = func->card->sdio_func[0];
72 
73 	sdio_claim_host(func);
74 	sdio_release_irq(func1);
75 	sdio_release_host(func);
76 }
77 
mm81x_sdio_set_irq(struct mm81x * mors,bool enable)78 static void mm81x_sdio_set_irq(struct mm81x *mors, bool enable)
79 {
80 	struct mm81x_sdio *sdio = (struct mm81x_sdio *)mors->drv_priv;
81 
82 	if (enable)
83 		mm81x_sdio_enable_irq(sdio);
84 	else
85 		mm81x_sdio_disable_irq(sdio);
86 }
87 
mm81x_sdio_calculate_base_address(u32 address,u8 access)88 static u32 mm81x_sdio_calculate_base_address(u32 address, u8 access)
89 {
90 	return (address & MM81X_SDIO_RW_ADDR_BOUNDARY_MASK) | (access & 0x3);
91 }
92 
mm81x_sdio_reset_base_address(struct mm81x_sdio * sdio)93 static void mm81x_sdio_reset_base_address(struct mm81x_sdio *sdio)
94 {
95 	sdio->bulk_addr_base = MM81X_SDIO_BASE_ADDR_UNSET;
96 	sdio->register_addr_base = MM81X_SDIO_BASE_ADDR_UNSET;
97 }
98 
mm81x_sdio_set_func_address_base(struct mm81x_sdio * sdio,struct sdio_func * func,u32 address,u8 access)99 static int mm81x_sdio_set_func_address_base(struct mm81x_sdio *sdio,
100 					    struct sdio_func *func, u32 address,
101 					    u8 access)
102 {
103 	int ret = 0;
104 	int retries = 0;
105 	static const int max_retries = 3;
106 	struct sdio_func *func2 = sdio->func;
107 	struct mm81x *mors = sdio_get_drvdata(sdio->func);
108 	s32 calculated_addr_base =
109 		mm81x_sdio_calculate_base_address(address, access);
110 	u32 *current_addr_base = func == func2 ? &sdio->bulk_addr_base :
111 						 &sdio->register_addr_base;
112 
113 	if ((*current_addr_base) == calculated_addr_base &&
114 	    *current_addr_base != MM81X_SDIO_BASE_ADDR_UNSET)
115 		return ret;
116 
117 retry:
118 	sdio_writeb(func, (u8)u32_get_bits(address, GENMASK(23, 16)),
119 		    MM81X_SDIO_REG_ADDRESS_WINDOW_0, &ret);
120 	if (ret)
121 		goto err;
122 
123 	sdio_writeb(func, (u8)u32_get_bits(address, GENMASK(31, 24)),
124 		    MM81X_SDIO_REG_ADDRESS_WINDOW_1, &ret);
125 	if (ret)
126 		goto err;
127 
128 	sdio_writeb(func, access & 0x3, MM81X_SDIO_REG_ADDRESS_CONFIG, &ret);
129 	if (ret)
130 		goto err;
131 
132 	*current_addr_base = calculated_addr_base;
133 	if (retries)
134 		dev_dbg(mors->dev, "%s succeeded after %d retries\n", __func__,
135 			retries);
136 
137 	return ret;
138 err:
139 	retries++;
140 	if (ret == -ETIMEDOUT && retries <= max_retries) {
141 		dev_dbg(mors->dev, "%s failed (%d), retrying (%d/%d)\n",
142 			__func__, ret, retries, max_retries);
143 		goto retry;
144 	}
145 
146 	*current_addr_base = MM81X_SDIO_BASE_ADDR_UNSET;
147 	return ret;
148 }
149 
mm81x_sdio_mem_write_block(struct mm81x_sdio * sdio,u32 address,u8 * data,ssize_t size)150 static int mm81x_sdio_mem_write_block(struct mm81x_sdio *sdio, u32 address,
151 				      u8 *data, ssize_t size)
152 {
153 	int ret;
154 	struct sdio_func *func2 = sdio->func;
155 	struct mm81x *mors = sdio_get_drvdata(sdio->func);
156 
157 	mm81x_sdio_set_func_address_base(sdio, func2, address,
158 					 MM81X_CONFIG_ACCESS_4BYTE);
159 	if (unlikely(!IS_ALIGNED((uintptr_t)data,
160 				 mors->bus_ops->bulk_alignment))) {
161 		ret = -EBADE;
162 		goto exit;
163 	}
164 
165 	address &= 0x0000FFFF; /* remove base and keep offset */
166 	ret = sdio_memcpy_toio(func2, address, data, size);
167 	if (ret)
168 		goto exit;
169 
170 	ret = size;
171 exit:
172 	return ret;
173 }
174 
mm81x_sdio_mem_write_byte(struct mm81x_sdio * sdio,u32 address,u8 * data,ssize_t size)175 static int mm81x_sdio_mem_write_byte(struct mm81x_sdio *sdio, u32 address,
176 				     u8 *data, ssize_t size)
177 {
178 	int i, ret;
179 	struct sdio_func *func1 = sdio->func->card->sdio_func[0];
180 
181 	mm81x_sdio_set_func_address_base(sdio, func1, address,
182 					 MM81X_CONFIG_ACCESS_1BYTE);
183 
184 	address &= 0x0000FFFF; /* remove base and keep offset */
185 	for (i = 0; i < size; i++) {
186 		sdio_writeb(func1, data[i], address + i, (int *)&ret);
187 		if (ret)
188 			goto exit;
189 	}
190 
191 	ret = size;
192 exit:
193 	return ret;
194 }
195 
mm81x_sdio_claim_host(struct mm81x * mors)196 static void mm81x_sdio_claim_host(struct mm81x *mors)
197 {
198 	struct mm81x_sdio *sdio = (struct mm81x_sdio *)mors->drv_priv;
199 	struct sdio_func *func = sdio->func;
200 
201 	sdio_claim_host(func);
202 }
203 
mm81x_sdio_release_host(struct mm81x * mors)204 static void mm81x_sdio_release_host(struct mm81x *mors)
205 {
206 	struct mm81x_sdio *sdio = (struct mm81x_sdio *)mors->drv_priv;
207 	struct sdio_func *func = sdio->func;
208 
209 	sdio_release_host(func);
210 }
211 
mm81x_sdio_mem_read_block(struct mm81x_sdio * sdio,u32 address,u8 * data,ssize_t size)212 static int mm81x_sdio_mem_read_block(struct mm81x_sdio *sdio, u32 address,
213 				     u8 *data, ssize_t size)
214 {
215 	int ret;
216 	struct sdio_func *func2 = sdio->func;
217 	struct mm81x *mors = sdio_get_drvdata(sdio->func);
218 
219 	mm81x_sdio_set_func_address_base(sdio, func2, address,
220 					 MM81X_CONFIG_ACCESS_4BYTE);
221 	if (unlikely(!IS_ALIGNED((uintptr_t)data,
222 				 mors->bus_ops->bulk_alignment))) {
223 		ret = -EBADE;
224 		goto exit;
225 	}
226 
227 	address &= 0x0000FFFF; /* remove base and keep offset */
228 	ret = sdio_memcpy_fromio(func2, data, address, size);
229 	if (ret)
230 		goto exit;
231 
232 	/*
233 	 * Observed sometimes that SDIO read repeats the first 4-bytes
234 	 * word twice, overwriting second word (hence, tail will be
235 	 * overwritten with 'sync' byte). When this happens, reading
236 	 * will fetch the correct word. NB: if repeated again, pass it
237 	 * anyway and upper layers will handle it
238 	 */
239 
240 	if (size >= 8 && memcmp(data, data + 4, 4) == 0)
241 		sdio_memcpy_fromio(func2, data, address, 8);
242 
243 	ret = size;
244 exit:
245 	return ret;
246 }
247 
mm81x_sdio_mem_read_byte(struct mm81x_sdio * sdio,u32 address,u8 * data,ssize_t size)248 static int mm81x_sdio_mem_read_byte(struct mm81x_sdio *sdio, u32 address,
249 				    u8 *data, ssize_t size)
250 {
251 	int i, ret;
252 	struct sdio_func *func1 = sdio->func->card->sdio_func[0];
253 
254 	mm81x_sdio_set_func_address_base(sdio, func1, address,
255 					 MM81X_CONFIG_ACCESS_1BYTE);
256 
257 	address &= 0x0000FFFF; /* remove base and keep offset */
258 	for (i = 0; i < size; i++) {
259 		data[i] = sdio_readb(func1, address + i, (int *)&ret);
260 		if (ret)
261 			goto exit;
262 	}
263 
264 	ret = size;
265 exit:
266 	return ret;
267 }
268 
mm81x_sdio_dm_write(struct mm81x * mors,u32 address,const u8 * data,int len)269 static int mm81x_sdio_dm_write(struct mm81x *mors, u32 address, const u8 *data,
270 			       int len)
271 {
272 	int ret = 0;
273 	int block_len, byte_len;
274 	struct mm81x_sdio *sdio = (struct mm81x_sdio *)mors->drv_priv;
275 	int remaining = len;
276 	int offset = 0;
277 
278 	if (remaining > 0 && address & 0x3) {
279 		len = 4 - (address & 0x3);
280 		ret = mm81x_sdio_mem_write_byte(sdio, address, (u8 *)data, len);
281 		if (ret != len)
282 			return -EIO;
283 
284 		offset += len;
285 		remaining -= len;
286 	}
287 
288 	while ((remaining) > 0) {
289 		/*
290 		 * We can only write up to the end of a single window in
291 		 * each write operation.
292 		 */
293 		u32 window_end = (address + offset) |
294 				 ~MM81X_SDIO_RW_ADDR_BOUNDARY_MASK;
295 
296 		len = min(remaining, (int)(window_end + 1 - address - offset));
297 		block_len = len & ~0x3;
298 		byte_len = len & 0x3;
299 
300 		if (block_len) {
301 			ret = mm81x_sdio_mem_write_block(sdio, address + offset,
302 							 (u8 *)(data + offset),
303 							 block_len);
304 			if (ret != block_len)
305 				return -EIO;
306 
307 			offset += block_len;
308 		}
309 
310 		if (byte_len) {
311 			ret = mm81x_sdio_mem_write_byte(sdio, address + offset,
312 							(u8 *)(data + offset),
313 							byte_len);
314 			if (ret != byte_len)
315 				return -EIO;
316 
317 			offset += byte_len;
318 		}
319 
320 		remaining -= len;
321 	}
322 
323 	return 0;
324 }
325 
mm81x_sdio_dm_read(struct mm81x * mors,u32 address,u8 * data,int len)326 static int mm81x_sdio_dm_read(struct mm81x *mors, u32 address, u8 *data,
327 			      int len)
328 {
329 	int ret = 0;
330 	int block_len, byte_len;
331 	struct mm81x_sdio *sdio = (struct mm81x_sdio *)mors->drv_priv;
332 	int remaining = len;
333 	int offset = 0;
334 
335 	if (remaining > 0 && address & 0x3) {
336 		len = 4 - (address & 0x3);
337 		ret = mm81x_sdio_mem_read_byte(sdio, address, data, len);
338 		if (ret != len)
339 			return -EIO;
340 
341 		offset += len;
342 		remaining -= len;
343 	}
344 
345 	while (remaining > 0) {
346 		/*
347 		 * We can only read up to the end of a single window in
348 		 * each read operation.
349 		 */
350 		u32 window_end = (address + offset) |
351 				 ~MM81X_SDIO_RW_ADDR_BOUNDARY_MASK;
352 
353 		len = min(remaining, (int)(window_end + 1 - address - offset));
354 		block_len = len & ~0x3;
355 		byte_len = len & 0x3;
356 
357 		if (block_len) {
358 			ret = mm81x_sdio_mem_read_block(sdio, address + offset,
359 							data + offset,
360 							block_len);
361 			if (ret != block_len)
362 				return -EIO;
363 
364 			offset += block_len;
365 		}
366 
367 		if (byte_len) {
368 			ret = mm81x_sdio_mem_read_byte(sdio, address + offset,
369 						       data + offset, byte_len);
370 			if (ret != byte_len)
371 				return -EIO;
372 
373 			offset += byte_len;
374 		}
375 
376 		remaining -= len;
377 	}
378 
379 	return 0;
380 }
381 
mm81x_sdio_reg32_write(struct mm81x * mors,u32 address,u32 val)382 static int mm81x_sdio_reg32_write(struct mm81x *mors, u32 address, u32 val)
383 {
384 	ssize_t ret = 0;
385 	u32 original_address = address;
386 	struct mm81x_sdio *sdio = (struct mm81x_sdio *)mors->drv_priv;
387 	struct sdio_func *func1 = sdio->func->card->sdio_func[0];
388 
389 	mm81x_sdio_set_func_address_base(sdio, func1, address,
390 					 MM81X_CONFIG_ACCESS_4BYTE);
391 
392 	address &= 0x0000FFFF;
393 	sdio_writel(func1, (__force u32)cpu_to_le32(val),
394 		    (__force u32)cpu_to_le32(address), (int *)&ret);
395 	if (ret)
396 		goto error;
397 
398 	return 0;
399 
400 error:
401 	if (original_address == MM81X_REG_RESET(mors) &&
402 	    val == MM81X_REG_RESET_VALUE(mors)) {
403 		dev_dbg(mors->dev,
404 			"SDIO reset detected, invalidating base addr\n");
405 		mm81x_sdio_reset_base_address(sdio);
406 	}
407 
408 	return -EIO;
409 }
410 
mm81x_sdio_reg32_read(struct mm81x * mors,u32 address,u32 * val)411 static int mm81x_sdio_reg32_read(struct mm81x *mors, u32 address, u32 *val)
412 {
413 	u32 value;
414 	ssize_t ret = 0;
415 	struct mm81x_sdio *sdio = (struct mm81x_sdio *)mors->drv_priv;
416 	struct sdio_func *func1 = sdio->func->card->sdio_func[0];
417 
418 	mm81x_sdio_set_func_address_base(sdio, func1, address,
419 					 MM81X_CONFIG_ACCESS_4BYTE);
420 
421 	address &= 0x0000FFFF;
422 	value = sdio_readl(func1, (__force u32)cpu_to_le32(address),
423 			   (int *)&ret);
424 	if (ret)
425 		return ret;
426 
427 	*val = le32_to_cpup((__le32 *)&value);
428 	return 0;
429 }
430 
mm81x_sdio_bus_enable(struct mm81x * mors,bool enable)431 static void mm81x_sdio_bus_enable(struct mm81x *mors, bool enable)
432 {
433 	struct mm81x_sdio *sdio = (struct mm81x_sdio *)mors->drv_priv;
434 	struct sdio_func *func = sdio->func;
435 	struct mmc_host *host = func->card->host;
436 
437 	sdio_claim_host(func);
438 
439 	if (enable) {
440 		/*
441 		 * No need to do anything special to re-enable the sdio bus.
442 		 * This will happen automatically when a read/write is
443 		 * attempted and sdio->bulk_addr_base == 0.
444 		 */
445 		sdio->enabled = true;
446 		host->ops->enable_sdio_irq(host, 1);
447 		dev_dbg(mors->dev, "%s: enabling bus\n", __func__);
448 	} else {
449 		host->ops->enable_sdio_irq(host, 0);
450 		mm81x_sdio_reset_base_address(sdio);
451 		sdio->enabled = false;
452 		dev_dbg(mors->dev, "%s: disabling bus\n", __func__);
453 	}
454 
455 	sdio_release_host(func);
456 }
457 
mm81x_sdio_reset(struct sdio_func * func)458 static void mm81x_sdio_reset(struct sdio_func *func)
459 {
460 	sdio_claim_host(func);
461 	sdio_disable_func(func);
462 	sdio_release_host(func);
463 
464 	mdelay(20);
465 
466 	sdio_claim_host(func);
467 	sdio_disable_func(func);
468 	mmc_hw_reset(func->card);
469 	sdio_enable_func(func);
470 	sdio_release_host(func);
471 }
472 
mm81x_sdio_config_burst_mode(struct mm81x * mors,bool enable_burst)473 static void mm81x_sdio_config_burst_mode(struct mm81x *mors, bool enable_burst)
474 {
475 	u8 burst_mode = (enable_burst) ? SDIO_WORD_BURST_SIZE_16 :
476 					 SDIO_WORD_BURST_DISABLE;
477 
478 	mm81x_hw_enable_burst_mode(mors, burst_mode);
479 }
480 
481 static const struct mm81x_bus_ops mm81x_sdio_ops = {
482 	.dm_read = mm81x_sdio_dm_read,
483 	.dm_write = mm81x_sdio_dm_write,
484 	.reg32_read = mm81x_sdio_reg32_read,
485 	.reg32_write = mm81x_sdio_reg32_write,
486 	.set_bus_enable = mm81x_sdio_bus_enable,
487 	.claim = mm81x_sdio_claim_host,
488 	.release = mm81x_sdio_release_host,
489 	.config_burst_mode = mm81x_sdio_config_burst_mode,
490 	.set_irq = mm81x_sdio_set_irq,
491 	.bulk_alignment = MM81X_SDIO_ALIGNMENT
492 };
493 
mm81x_sdio_enable(struct mm81x_sdio * sdio)494 static int mm81x_sdio_enable(struct mm81x_sdio *sdio)
495 {
496 	int ret;
497 	struct sdio_func *func = sdio->func;
498 	struct mm81x *mors = sdio_get_drvdata(func);
499 
500 	sdio_claim_host(func);
501 	ret = sdio_enable_func(func);
502 	if (ret)
503 		dev_err(mors->dev, "sdio_enable_func failed: %d\n", ret);
504 	sdio_release_host(func);
505 	return ret;
506 }
507 
mm81x_sdio_release(struct mm81x_sdio * sdio)508 static void mm81x_sdio_release(struct mm81x_sdio *sdio)
509 {
510 	struct sdio_func *func = sdio->func;
511 
512 	sdio_claim_host(func);
513 	sdio_disable_func(func);
514 	sdio_release_host(func);
515 }
516 
mm81x_sdio_probe(struct sdio_func * func,const struct sdio_device_id * id)517 static int mm81x_sdio_probe(struct sdio_func *func,
518 			    const struct sdio_device_id *id)
519 {
520 	int ret = 0;
521 	struct mm81x *mors = NULL;
522 	struct mm81x_sdio *sdio;
523 	struct device *dev = &func->dev;
524 
525 	if (func->num == 1)
526 		return 0;
527 
528 	if (func->num != 2)
529 		return -ENODEV;
530 
531 	mors = mm81x_core_alloc(sizeof(*sdio), dev);
532 	if (!mors)
533 		return -ENOMEM;
534 
535 	mors->bus_ops = &mm81x_sdio_ops;
536 	mors->bus_type = MM81X_BUS_TYPE_SDIO;
537 
538 	sdio = (struct mm81x_sdio *)mors->drv_priv;
539 	sdio->func = func;
540 	sdio->id = id;
541 	sdio->enabled = true;
542 	mm81x_sdio_reset_base_address(sdio);
543 
544 	sdio_set_drvdata(func, mors);
545 
546 	ret = mm81x_sdio_enable(sdio);
547 	if (ret)
548 		goto err_core_free;
549 
550 	mm81x_sdio_config_burst_mode(mors, true);
551 
552 	ret = mm81x_core_init(mors);
553 	if (ret)
554 		goto err_sdio_release;
555 
556 	ret = mm81x_sdio_enable_irq(sdio);
557 	if (ret)
558 		goto err_core_deinit;
559 
560 	ret = mm81x_core_register(mors);
561 	if (ret)
562 		goto err_disable_irq;
563 
564 	return 0;
565 
566 err_disable_irq:
567 	mm81x_sdio_disable_irq(sdio);
568 err_core_deinit:
569 	mm81x_core_deinit(mors);
570 err_sdio_release:
571 	mm81x_sdio_release(sdio);
572 err_core_free:
573 	mm81x_core_free(mors);
574 	return ret;
575 }
576 
mm81x_sdio_remove(struct sdio_func * func)577 static void mm81x_sdio_remove(struct sdio_func *func)
578 {
579 	struct mm81x *mors = sdio_get_drvdata(func);
580 	struct mm81x_sdio *sdio = (struct mm81x_sdio *)mors->drv_priv;
581 
582 	if (!mors)
583 		return;
584 
585 	mm81x_core_unregister(mors);
586 	mm81x_sdio_disable_irq(sdio);
587 	mm81x_core_deinit(mors);
588 	mm81x_sdio_release(sdio);
589 	mm81x_sdio_reset(func);
590 	mm81x_core_free(mors);
591 	sdio_set_drvdata(func, NULL);
592 }
593 
594 static const struct sdio_device_id mm81x_sdio_devices[] = {
595 	{ SDIO_DEVICE(SDIO_VENDOR_ID_MORSEMICRO,
596 		      SDIO_DEVICE_ID_MORSEMICRO_MM8108) },
597 	{},
598 };
599 
600 MODULE_DEVICE_TABLE(sdio, mm81x_sdio_devices);
601 
602 static struct sdio_driver mm81x_sdio_driver = {
603 	.name = "mm81x_sdio",
604 	.id_table = mm81x_sdio_devices,
605 	.probe = mm81x_sdio_probe,
606 	.remove = mm81x_sdio_remove,
607 };
608 
609 module_sdio_driver(mm81x_sdio_driver);
610 
611 MODULE_AUTHOR("Morse Micro");
612 MODULE_DESCRIPTION("Driver support for Morse Micro MM81X SDIO devices");
613 MODULE_LICENSE("Dual BSD/GPL");
614