xref: /linux/drivers/spi/spi-sg2044-nor.c (revision 1260ed77798502de9c98020040d2995008de10cc)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * SG2044 SPI NOR controller driver
4  *
5  * Copyright (c) 2025 Longbin Li <looong.bin@gmail.com>
6  */
7 
8 #include <linux/bitfield.h>
9 #include <linux/clk.h>
10 #include <linux/iopoll.h>
11 #include <linux/module.h>
12 #include <linux/of.h>
13 #include <linux/platform_device.h>
14 #include <linux/spi/spi-mem.h>
15 
16 /* Hardware register definitions */
17 #define SPIFMC_CTRL				0x00
18 #define SPIFMC_CTRL_CPHA			BIT(12)
19 #define SPIFMC_CTRL_CPOL			BIT(13)
20 #define SPIFMC_CTRL_HOLD_OL			BIT(14)
21 #define SPIFMC_CTRL_WP_OL			BIT(15)
22 #define SPIFMC_CTRL_LSBF			BIT(20)
23 #define SPIFMC_CTRL_SRST			BIT(21)
24 #define SPIFMC_CTRL_SCK_DIV_SHIFT		0
25 #define SPIFMC_CTRL_FRAME_LEN_SHIFT		16
26 #define SPIFMC_CTRL_SCK_DIV_MASK		0x7FF
27 
28 #define SPIFMC_CE_CTRL				0x04
29 #define SPIFMC_CE_CTRL_CEMANUAL			BIT(0)
30 #define SPIFMC_CE_CTRL_CEMANUAL_EN		BIT(1)
31 
32 #define SPIFMC_DLY_CTRL				0x08
33 #define SPIFMC_CTRL_FM_INTVL_MASK		0x000f
34 #define SPIFMC_CTRL_FM_INTVL			BIT(0)
35 #define SPIFMC_CTRL_CET_MASK			0x0f00
36 #define SPIFMC_CTRL_CET				BIT(8)
37 
38 #define SPIFMC_DMMR				0x0c
39 
40 #define SPIFMC_TRAN_CSR				0x10
41 #define SPIFMC_TRAN_CSR_TRAN_MODE_MASK		GENMASK(1, 0)
42 #define SPIFMC_TRAN_CSR_TRAN_MODE_RX		BIT(0)
43 #define SPIFMC_TRAN_CSR_TRAN_MODE_TX		BIT(1)
44 #define SPIFMC_TRAN_CSR_FAST_MODE		BIT(3)
45 #define SPIFMC_TRAN_CSR_BUS_WIDTH_1_BIT		(0x00 << 4)
46 #define SPIFMC_TRAN_CSR_BUS_WIDTH_2_BIT		(0x01 << 4)
47 #define SPIFMC_TRAN_CSR_BUS_WIDTH_4_BIT		(0x02 << 4)
48 #define SPIFMC_TRAN_CSR_DMA_EN			BIT(6)
49 #define SPIFMC_TRAN_CSR_MISO_LEVEL		BIT(7)
50 #define SPIFMC_TRAN_CSR_ADDR_BYTES_MASK		GENMASK(10, 8)
51 #define SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT	8
52 #define SPIFMC_TRAN_CSR_WITH_CMD		BIT(11)
53 #define SPIFMC_TRAN_CSR_FIFO_TRG_LVL_MASK	GENMASK(13, 12)
54 #define SPIFMC_TRAN_CSR_FIFO_TRG_LVL_1_BYTE	(0x00 << 12)
55 #define SPIFMC_TRAN_CSR_FIFO_TRG_LVL_2_BYTE	(0x01 << 12)
56 #define SPIFMC_TRAN_CSR_FIFO_TRG_LVL_4_BYTE	(0x02 << 12)
57 #define SPIFMC_TRAN_CSR_FIFO_TRG_LVL_8_BYTE	(0x03 << 12)
58 #define SPIFMC_TRAN_CSR_GO_BUSY			BIT(15)
59 #define SPIFMC_TRAN_CSR_ADDR4B_SHIFT		20
60 #define SPIFMC_TRAN_CSR_CMD4B_SHIFT		21
61 
62 #define SPIFMC_TRAN_NUM				0x14
63 #define SPIFMC_FIFO_PORT			0x18
64 #define SPIFMC_FIFO_PT				0x20
65 
66 #define SPIFMC_INT_STS				0x28
67 #define SPIFMC_INT_TRAN_DONE			BIT(0)
68 #define SPIFMC_INT_RD_FIFO			BIT(2)
69 #define SPIFMC_INT_WR_FIFO			BIT(3)
70 #define SPIFMC_INT_RX_FRAME			BIT(4)
71 #define SPIFMC_INT_TX_FRAME			BIT(5)
72 
73 #define SPIFMC_INT_EN				0x2c
74 #define SPIFMC_INT_TRAN_DONE_EN			BIT(0)
75 #define SPIFMC_INT_RD_FIFO_EN			BIT(2)
76 #define SPIFMC_INT_WR_FIFO_EN			BIT(3)
77 #define SPIFMC_INT_RX_FRAME_EN			BIT(4)
78 #define SPIFMC_INT_TX_FRAME_EN			BIT(5)
79 
80 #define SPIFMC_OPT				0x030
81 #define SPIFMC_OPT_DISABLE_FIFO_FLUSH		BIT(1)
82 
83 #define SPIFMC_MAX_FIFO_DEPTH			8
84 
85 #define SPIFMC_MAX_READ_SIZE			0x10000
86 
87 struct sg2044_spifmc {
88 	struct spi_controller *ctrl;
89 	void __iomem *io_base;
90 	struct device *dev;
91 	struct mutex lock;
92 	struct clk *clk;
93 };
94 
95 static int sg2044_spifmc_wait_int(struct sg2044_spifmc *spifmc, u8 int_type)
96 {
97 	u32 stat;
98 
99 	return readl_poll_timeout(spifmc->io_base + SPIFMC_INT_STS, stat,
100 				  (stat & int_type), 0, 1000000);
101 }
102 
103 static int sg2044_spifmc_wait_xfer_size(struct sg2044_spifmc *spifmc,
104 					int xfer_size)
105 {
106 	u8 stat;
107 
108 	return readl_poll_timeout(spifmc->io_base + SPIFMC_FIFO_PT, stat,
109 				  ((stat & 0xf) == xfer_size), 1, 1000000);
110 }
111 
112 static u32 sg2044_spifmc_init_reg(struct sg2044_spifmc *spifmc)
113 {
114 	u32 reg;
115 
116 	reg = readl(spifmc->io_base + SPIFMC_TRAN_CSR);
117 	reg &= ~(SPIFMC_TRAN_CSR_TRAN_MODE_MASK |
118 		 SPIFMC_TRAN_CSR_FAST_MODE |
119 		 SPIFMC_TRAN_CSR_BUS_WIDTH_2_BIT |
120 		 SPIFMC_TRAN_CSR_BUS_WIDTH_4_BIT |
121 		 SPIFMC_TRAN_CSR_DMA_EN |
122 		 SPIFMC_TRAN_CSR_ADDR_BYTES_MASK |
123 		 SPIFMC_TRAN_CSR_WITH_CMD |
124 		 SPIFMC_TRAN_CSR_FIFO_TRG_LVL_MASK);
125 
126 	writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
127 
128 	return reg;
129 }
130 
131 static ssize_t sg2044_spifmc_read_64k(struct sg2044_spifmc *spifmc,
132 				      const struct spi_mem_op *op, loff_t from,
133 				      size_t len, u_char *buf)
134 {
135 	int xfer_size, offset;
136 	u32 reg;
137 	int ret;
138 	int i;
139 
140 	reg = sg2044_spifmc_init_reg(spifmc);
141 	reg |= (op->addr.nbytes + op->dummy.nbytes) << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT;
142 	reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_8_BYTE;
143 	reg |= SPIFMC_TRAN_CSR_WITH_CMD;
144 	reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX;
145 
146 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
147 	writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT);
148 
149 	for (i = op->addr.nbytes - 1; i >= 0; i--)
150 		writeb((from >> i * 8) & 0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
151 
152 	for (i = 0; i < op->dummy.nbytes; i++)
153 		writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
154 
155 	writel(len, spifmc->io_base + SPIFMC_TRAN_NUM);
156 	writel(0, spifmc->io_base + SPIFMC_INT_STS);
157 	reg |= SPIFMC_TRAN_CSR_GO_BUSY;
158 	writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
159 
160 	ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_RD_FIFO);
161 	if (ret < 0)
162 		return ret;
163 
164 	offset = 0;
165 	while (offset < len) {
166 		xfer_size = min_t(size_t, SPIFMC_MAX_FIFO_DEPTH, len - offset);
167 
168 		ret = sg2044_spifmc_wait_xfer_size(spifmc, xfer_size);
169 		if (ret < 0)
170 			return ret;
171 
172 		for (i = 0; i < xfer_size; i++)
173 			buf[i + offset] = readb(spifmc->io_base + SPIFMC_FIFO_PORT);
174 
175 		offset += xfer_size;
176 	}
177 
178 	ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE);
179 	if (ret < 0)
180 		return ret;
181 
182 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
183 
184 	return len;
185 }
186 
187 static ssize_t sg2044_spifmc_read(struct sg2044_spifmc *spifmc,
188 				  const struct spi_mem_op *op)
189 {
190 	size_t xfer_size;
191 	size_t offset;
192 	loff_t from = op->addr.val;
193 	size_t len = op->data.nbytes;
194 	int ret;
195 	u8 *din = op->data.buf.in;
196 
197 	offset = 0;
198 	while (offset < len) {
199 		xfer_size = min_t(size_t, SPIFMC_MAX_READ_SIZE, len - offset);
200 
201 		ret = sg2044_spifmc_read_64k(spifmc, op, from, xfer_size, din);
202 		if (ret < 0)
203 			return ret;
204 
205 		offset += xfer_size;
206 		din += xfer_size;
207 		from += xfer_size;
208 	}
209 
210 	return 0;
211 }
212 
213 static ssize_t sg2044_spifmc_write(struct sg2044_spifmc *spifmc,
214 				   const struct spi_mem_op *op)
215 {
216 	size_t xfer_size;
217 	const u8 *dout = op->data.buf.out;
218 	int i, offset;
219 	int ret;
220 	u32 reg;
221 
222 	reg = sg2044_spifmc_init_reg(spifmc);
223 	reg |= (op->addr.nbytes + op->dummy.nbytes) << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT;
224 	reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_8_BYTE;
225 	reg |= SPIFMC_TRAN_CSR_WITH_CMD;
226 	reg |= SPIFMC_TRAN_CSR_TRAN_MODE_TX;
227 
228 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
229 	writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT);
230 
231 	for (i = op->addr.nbytes - 1; i >= 0; i--)
232 		writeb((op->addr.val >> i * 8) & 0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
233 
234 	for (i = 0; i < op->dummy.nbytes; i++)
235 		writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
236 
237 	writel(0, spifmc->io_base + SPIFMC_INT_STS);
238 	writel(op->data.nbytes, spifmc->io_base + SPIFMC_TRAN_NUM);
239 	reg |= SPIFMC_TRAN_CSR_GO_BUSY;
240 	writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
241 
242 	ret = sg2044_spifmc_wait_xfer_size(spifmc, 0);
243 	if (ret < 0)
244 		return ret;
245 
246 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
247 
248 	offset = 0;
249 	while (offset < op->data.nbytes) {
250 		xfer_size = min_t(size_t, SPIFMC_MAX_FIFO_DEPTH, op->data.nbytes - offset);
251 
252 		ret = sg2044_spifmc_wait_xfer_size(spifmc, 0);
253 		if (ret < 0)
254 			return ret;
255 
256 		for (i = 0; i < xfer_size; i++)
257 			writeb(dout[i + offset], spifmc->io_base + SPIFMC_FIFO_PORT);
258 
259 		offset += xfer_size;
260 	}
261 
262 	ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE);
263 	if (ret < 0)
264 		return ret;
265 
266 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
267 
268 	return 0;
269 }
270 
271 static ssize_t sg2044_spifmc_tran_cmd(struct sg2044_spifmc *spifmc,
272 				      const struct spi_mem_op *op)
273 {
274 	int i, ret;
275 	u32 reg;
276 
277 	reg = sg2044_spifmc_init_reg(spifmc);
278 	reg |= (op->addr.nbytes + op->dummy.nbytes) << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT;
279 	reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_1_BYTE;
280 	reg |= SPIFMC_TRAN_CSR_WITH_CMD;
281 
282 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
283 	writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT);
284 
285 	for (i = op->addr.nbytes - 1; i >= 0; i--)
286 		writeb((op->addr.val >> i * 8) & 0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
287 
288 	for (i = 0; i < op->dummy.nbytes; i++)
289 		writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
290 
291 	writel(0, spifmc->io_base + SPIFMC_INT_STS);
292 	reg |= SPIFMC_TRAN_CSR_GO_BUSY;
293 	writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
294 
295 	ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE);
296 	if (ret < 0)
297 		return ret;
298 
299 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
300 
301 	return 0;
302 }
303 
304 static void sg2044_spifmc_trans(struct sg2044_spifmc *spifmc,
305 				const struct spi_mem_op *op)
306 {
307 	if (op->data.dir == SPI_MEM_DATA_IN)
308 		sg2044_spifmc_read(spifmc, op);
309 	else if (op->data.dir == SPI_MEM_DATA_OUT)
310 		sg2044_spifmc_write(spifmc, op);
311 	else
312 		sg2044_spifmc_tran_cmd(spifmc, op);
313 }
314 
315 static ssize_t sg2044_spifmc_trans_reg(struct sg2044_spifmc *spifmc,
316 				       const struct spi_mem_op *op)
317 {
318 	const u8 *dout = NULL;
319 	u8 *din = NULL;
320 	size_t len = op->data.nbytes;
321 	int ret, i;
322 	u32 reg;
323 
324 	if (op->data.dir == SPI_MEM_DATA_IN)
325 		din = op->data.buf.in;
326 	else
327 		dout = op->data.buf.out;
328 
329 	reg = sg2044_spifmc_init_reg(spifmc);
330 	reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_1_BYTE;
331 	reg |= SPIFMC_TRAN_CSR_WITH_CMD;
332 
333 	if (din) {
334 		reg |= SPIFMC_TRAN_CSR_BUS_WIDTH_1_BIT;
335 		reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX;
336 		reg |= SPIFMC_TRAN_CSR_TRAN_MODE_TX;
337 
338 		writel(SPIFMC_OPT_DISABLE_FIFO_FLUSH, spifmc->io_base + SPIFMC_OPT);
339 	} else {
340 		/*
341 		 * If write values to the Status Register,
342 		 * configure TRAN_CSR register as the same as
343 		 * sg2044_spifmc_read_reg.
344 		 */
345 		if (op->cmd.opcode == 0x01) {
346 			reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX;
347 			reg |= SPIFMC_TRAN_CSR_TRAN_MODE_TX;
348 			writel(len, spifmc->io_base + SPIFMC_TRAN_NUM);
349 		}
350 	}
351 
352 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
353 	writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT);
354 
355 	for (i = 0; i < len; i++) {
356 		if (din)
357 			writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
358 		else
359 			writeb(dout[i], spifmc->io_base + SPIFMC_FIFO_PORT);
360 	}
361 
362 	writel(0, spifmc->io_base + SPIFMC_INT_STS);
363 	writel(len, spifmc->io_base + SPIFMC_TRAN_NUM);
364 	reg |= SPIFMC_TRAN_CSR_GO_BUSY;
365 	writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
366 
367 	ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE);
368 	if (ret < 0)
369 		return ret;
370 
371 	if (din) {
372 		while (len--)
373 			*din++ = readb(spifmc->io_base + SPIFMC_FIFO_PORT);
374 	}
375 
376 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
377 
378 	return 0;
379 }
380 
381 static int sg2044_spifmc_exec_op(struct spi_mem *mem,
382 				 const struct spi_mem_op *op)
383 {
384 	struct sg2044_spifmc *spifmc;
385 
386 	spifmc = spi_controller_get_devdata(mem->spi->controller);
387 
388 	mutex_lock(&spifmc->lock);
389 
390 	if (op->addr.nbytes == 0)
391 		sg2044_spifmc_trans_reg(spifmc, op);
392 	else
393 		sg2044_spifmc_trans(spifmc, op);
394 
395 	mutex_unlock(&spifmc->lock);
396 
397 	return 0;
398 }
399 
400 static const struct spi_controller_mem_ops sg2044_spifmc_mem_ops = {
401 	.exec_op = sg2044_spifmc_exec_op,
402 };
403 
404 static void sg2044_spifmc_init(struct sg2044_spifmc *spifmc)
405 {
406 	u32 tran_csr;
407 	u32 reg;
408 
409 	writel(0, spifmc->io_base + SPIFMC_DMMR);
410 
411 	reg = readl(spifmc->io_base + SPIFMC_CTRL);
412 	reg |= SPIFMC_CTRL_SRST;
413 	reg &= ~(SPIFMC_CTRL_SCK_DIV_MASK);
414 	reg |= 1;
415 	writel(reg, spifmc->io_base + SPIFMC_CTRL);
416 
417 	writel(0, spifmc->io_base + SPIFMC_CE_CTRL);
418 
419 	tran_csr = readl(spifmc->io_base + SPIFMC_TRAN_CSR);
420 	tran_csr |= (0 << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT);
421 	tran_csr |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_4_BYTE;
422 	tran_csr |= SPIFMC_TRAN_CSR_WITH_CMD;
423 	writel(tran_csr, spifmc->io_base + SPIFMC_TRAN_CSR);
424 }
425 
426 static int sg2044_spifmc_probe(struct platform_device *pdev)
427 {
428 	struct device *dev = &pdev->dev;
429 	struct spi_controller *ctrl;
430 	struct sg2044_spifmc *spifmc;
431 	int ret;
432 
433 	ctrl = devm_spi_alloc_host(&pdev->dev, sizeof(*spifmc));
434 	if (!ctrl)
435 		return -ENOMEM;
436 
437 	spifmc = spi_controller_get_devdata(ctrl);
438 
439 	spifmc->clk = devm_clk_get_enabled(&pdev->dev, NULL);
440 	if (IS_ERR(spifmc->clk))
441 		return dev_err_probe(dev, PTR_ERR(spifmc->clk), "Cannot get and enable AHB clock\n");
442 
443 	spifmc->dev = &pdev->dev;
444 	spifmc->ctrl = ctrl;
445 
446 	spifmc->io_base = devm_platform_ioremap_resource(pdev, 0);
447 	if (IS_ERR(spifmc->io_base))
448 		return PTR_ERR(spifmc->io_base);
449 
450 	ctrl->num_chipselect = 1;
451 	ctrl->dev.of_node = pdev->dev.of_node;
452 	ctrl->bits_per_word_mask = SPI_BPW_MASK(8);
453 	ctrl->auto_runtime_pm = false;
454 	ctrl->mem_ops = &sg2044_spifmc_mem_ops;
455 	ctrl->mode_bits = SPI_RX_DUAL | SPI_TX_DUAL | SPI_RX_QUAD | SPI_TX_QUAD;
456 
457 	ret = devm_mutex_init(dev, &spifmc->lock);
458 	if (ret)
459 		return ret;
460 
461 	sg2044_spifmc_init(spifmc);
462 	sg2044_spifmc_init_reg(spifmc);
463 
464 	ret = devm_spi_register_controller(&pdev->dev, ctrl);
465 	if (ret)
466 		return dev_err_probe(dev, ret, "spi_register_controller failed\n");
467 
468 	return 0;
469 }
470 
471 static const struct of_device_id sg2044_spifmc_match[] = {
472 	{ .compatible = "sophgo,sg2044-spifmc-nor" },
473 	{ /* sentinel */ }
474 };
475 MODULE_DEVICE_TABLE(of, sg2044_spifmc_match);
476 
477 static struct platform_driver sg2044_nor_driver = {
478 	.driver = {
479 		.name = "sg2044,spifmc-nor",
480 		.of_match_table = sg2044_spifmc_match,
481 	},
482 	.probe = sg2044_spifmc_probe,
483 };
484 module_platform_driver(sg2044_nor_driver);
485 
486 MODULE_DESCRIPTION("SG2044 SPI NOR controller driver");
487 MODULE_AUTHOR("Longbin Li <looong.bin@gmail.com>");
488 MODULE_LICENSE("GPL");
489