xref: /linux/drivers/spi/spi-sg2044-nor.c (revision 0262163136de813894cb172aa8ccf762b92e5fd7)
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 sg204x_spifmc_chip_info {
88 	bool has_opt_reg;
89 	u32 rd_fifo_int_trigger_level;
90 };
91 
92 struct sg2044_spifmc {
93 	struct spi_controller *ctrl;
94 	void __iomem *io_base;
95 	struct device *dev;
96 	struct mutex lock;
97 	struct clk *clk;
98 	const struct sg204x_spifmc_chip_info *chip_info;
99 };
100 
sg2044_spifmc_wait_int(struct sg2044_spifmc * spifmc,u8 int_type)101 static int sg2044_spifmc_wait_int(struct sg2044_spifmc *spifmc, u8 int_type)
102 {
103 	u32 stat;
104 
105 	return readl_poll_timeout(spifmc->io_base + SPIFMC_INT_STS, stat,
106 				  (stat & int_type), 0, 1000000);
107 }
108 
sg2044_spifmc_wait_xfer_size(struct sg2044_spifmc * spifmc,int xfer_size)109 static int sg2044_spifmc_wait_xfer_size(struct sg2044_spifmc *spifmc,
110 					int xfer_size)
111 {
112 	u8 stat;
113 
114 	return readl_poll_timeout(spifmc->io_base + SPIFMC_FIFO_PT, stat,
115 				  ((stat & 0xf) == xfer_size), 1, 1000000);
116 }
117 
sg2044_spifmc_init_reg(struct sg2044_spifmc * spifmc)118 static u32 sg2044_spifmc_init_reg(struct sg2044_spifmc *spifmc)
119 {
120 	u32 reg;
121 
122 	reg = readl(spifmc->io_base + SPIFMC_TRAN_CSR);
123 	reg &= ~(SPIFMC_TRAN_CSR_TRAN_MODE_MASK |
124 		 SPIFMC_TRAN_CSR_FAST_MODE |
125 		 SPIFMC_TRAN_CSR_BUS_WIDTH_2_BIT |
126 		 SPIFMC_TRAN_CSR_BUS_WIDTH_4_BIT |
127 		 SPIFMC_TRAN_CSR_DMA_EN |
128 		 SPIFMC_TRAN_CSR_ADDR_BYTES_MASK |
129 		 SPIFMC_TRAN_CSR_WITH_CMD |
130 		 SPIFMC_TRAN_CSR_FIFO_TRG_LVL_MASK);
131 
132 	writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
133 
134 	return reg;
135 }
136 
sg2044_spifmc_read_64k(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op,loff_t from,size_t len,u_char * buf)137 static ssize_t sg2044_spifmc_read_64k(struct sg2044_spifmc *spifmc,
138 				      const struct spi_mem_op *op, loff_t from,
139 				      size_t len, u_char *buf)
140 {
141 	int xfer_size, offset;
142 	u32 reg;
143 	int ret;
144 	int i;
145 
146 	reg = sg2044_spifmc_init_reg(spifmc);
147 	reg |= (op->addr.nbytes + op->dummy.nbytes) << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT;
148 	reg |= spifmc->chip_info->rd_fifo_int_trigger_level;
149 	reg |= SPIFMC_TRAN_CSR_WITH_CMD;
150 	reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX;
151 
152 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
153 	writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT);
154 
155 	for (i = op->addr.nbytes - 1; i >= 0; i--)
156 		writeb((from >> i * 8) & 0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
157 
158 	for (i = 0; i < op->dummy.nbytes; i++)
159 		writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
160 
161 	writel(len, spifmc->io_base + SPIFMC_TRAN_NUM);
162 	writel(0, spifmc->io_base + SPIFMC_INT_STS);
163 	reg |= SPIFMC_TRAN_CSR_GO_BUSY;
164 	writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
165 
166 	ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_RD_FIFO);
167 	if (ret < 0)
168 		return ret;
169 
170 	offset = 0;
171 	while (offset < len) {
172 		xfer_size = min_t(size_t, SPIFMC_MAX_FIFO_DEPTH, len - offset);
173 
174 		ret = sg2044_spifmc_wait_xfer_size(spifmc, xfer_size);
175 		if (ret < 0)
176 			return ret;
177 
178 		for (i = 0; i < xfer_size; i++)
179 			buf[i + offset] = readb(spifmc->io_base + SPIFMC_FIFO_PORT);
180 
181 		offset += xfer_size;
182 	}
183 
184 	ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE);
185 	if (ret < 0)
186 		return ret;
187 
188 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
189 
190 	return len;
191 }
192 
sg2044_spifmc_read(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op)193 static ssize_t sg2044_spifmc_read(struct sg2044_spifmc *spifmc,
194 				  const struct spi_mem_op *op)
195 {
196 	size_t xfer_size;
197 	size_t offset;
198 	loff_t from = op->addr.val;
199 	size_t len = op->data.nbytes;
200 	int ret;
201 	u8 *din = op->data.buf.in;
202 
203 	offset = 0;
204 	while (offset < len) {
205 		xfer_size = min_t(size_t, SPIFMC_MAX_READ_SIZE, len - offset);
206 
207 		ret = sg2044_spifmc_read_64k(spifmc, op, from, xfer_size, din);
208 		if (ret < 0)
209 			return ret;
210 
211 		offset += xfer_size;
212 		din += xfer_size;
213 		from += xfer_size;
214 	}
215 
216 	return 0;
217 }
218 
sg2044_spifmc_write(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op)219 static ssize_t sg2044_spifmc_write(struct sg2044_spifmc *spifmc,
220 				   const struct spi_mem_op *op)
221 {
222 	size_t xfer_size;
223 	const u8 *dout = op->data.buf.out;
224 	int i, offset;
225 	int ret;
226 	u32 reg;
227 
228 	reg = sg2044_spifmc_init_reg(spifmc);
229 	reg |= (op->addr.nbytes + op->dummy.nbytes) << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT;
230 	reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_8_BYTE;
231 	reg |= SPIFMC_TRAN_CSR_WITH_CMD;
232 	reg |= SPIFMC_TRAN_CSR_TRAN_MODE_TX;
233 
234 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
235 	writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT);
236 
237 	for (i = op->addr.nbytes - 1; i >= 0; i--)
238 		writeb((op->addr.val >> i * 8) & 0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
239 
240 	for (i = 0; i < op->dummy.nbytes; i++)
241 		writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
242 
243 	writel(0, spifmc->io_base + SPIFMC_INT_STS);
244 	writel(op->data.nbytes, spifmc->io_base + SPIFMC_TRAN_NUM);
245 	reg |= SPIFMC_TRAN_CSR_GO_BUSY;
246 	writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
247 
248 	ret = sg2044_spifmc_wait_xfer_size(spifmc, 0);
249 	if (ret < 0)
250 		return ret;
251 
252 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
253 
254 	offset = 0;
255 	while (offset < op->data.nbytes) {
256 		xfer_size = min_t(size_t, SPIFMC_MAX_FIFO_DEPTH, op->data.nbytes - offset);
257 
258 		ret = sg2044_spifmc_wait_xfer_size(spifmc, 0);
259 		if (ret < 0)
260 			return ret;
261 
262 		for (i = 0; i < xfer_size; i++)
263 			writeb(dout[i + offset], spifmc->io_base + SPIFMC_FIFO_PORT);
264 
265 		offset += xfer_size;
266 	}
267 
268 	ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE);
269 	if (ret < 0)
270 		return ret;
271 
272 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
273 
274 	return 0;
275 }
276 
sg2044_spifmc_tran_cmd(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op)277 static ssize_t sg2044_spifmc_tran_cmd(struct sg2044_spifmc *spifmc,
278 				      const struct spi_mem_op *op)
279 {
280 	int i, ret;
281 	u32 reg;
282 
283 	reg = sg2044_spifmc_init_reg(spifmc);
284 	reg |= (op->addr.nbytes + op->dummy.nbytes) << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT;
285 	reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_1_BYTE;
286 	reg |= SPIFMC_TRAN_CSR_WITH_CMD;
287 
288 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
289 	writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT);
290 
291 	for (i = op->addr.nbytes - 1; i >= 0; i--)
292 		writeb((op->addr.val >> i * 8) & 0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
293 
294 	for (i = 0; i < op->dummy.nbytes; i++)
295 		writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
296 
297 	writel(0, spifmc->io_base + SPIFMC_INT_STS);
298 	reg |= SPIFMC_TRAN_CSR_GO_BUSY;
299 	writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
300 
301 	ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE);
302 	if (ret < 0)
303 		return ret;
304 
305 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
306 
307 	return 0;
308 }
309 
sg2044_spifmc_trans(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op)310 static void sg2044_spifmc_trans(struct sg2044_spifmc *spifmc,
311 				const struct spi_mem_op *op)
312 {
313 	if (op->data.dir == SPI_MEM_DATA_IN)
314 		sg2044_spifmc_read(spifmc, op);
315 	else if (op->data.dir == SPI_MEM_DATA_OUT)
316 		sg2044_spifmc_write(spifmc, op);
317 	else
318 		sg2044_spifmc_tran_cmd(spifmc, op);
319 }
320 
sg2044_spifmc_trans_reg(struct sg2044_spifmc * spifmc,const struct spi_mem_op * op)321 static ssize_t sg2044_spifmc_trans_reg(struct sg2044_spifmc *spifmc,
322 				       const struct spi_mem_op *op)
323 {
324 	const u8 *dout = NULL;
325 	u8 *din = NULL;
326 	size_t len = op->data.nbytes;
327 	int ret, i;
328 	u32 reg;
329 
330 	if (op->data.dir == SPI_MEM_DATA_IN)
331 		din = op->data.buf.in;
332 	else
333 		dout = op->data.buf.out;
334 
335 	reg = sg2044_spifmc_init_reg(spifmc);
336 	reg |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_1_BYTE;
337 	reg |= SPIFMC_TRAN_CSR_WITH_CMD;
338 
339 	if (din) {
340 		reg |= SPIFMC_TRAN_CSR_BUS_WIDTH_1_BIT;
341 		reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX;
342 		reg |= SPIFMC_TRAN_CSR_TRAN_MODE_TX;
343 
344 		if (spifmc->chip_info->has_opt_reg)
345 			writel(SPIFMC_OPT_DISABLE_FIFO_FLUSH, spifmc->io_base + SPIFMC_OPT);
346 	} else {
347 		/*
348 		 * If write values to the Status Register,
349 		 * configure TRAN_CSR register as the same as
350 		 * sg2044_spifmc_read_reg.
351 		 */
352 		if (op->cmd.opcode == 0x01) {
353 			reg |= SPIFMC_TRAN_CSR_TRAN_MODE_RX;
354 			reg |= SPIFMC_TRAN_CSR_TRAN_MODE_TX;
355 			writel(len, spifmc->io_base + SPIFMC_TRAN_NUM);
356 		}
357 	}
358 
359 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
360 	writeb(op->cmd.opcode, spifmc->io_base + SPIFMC_FIFO_PORT);
361 
362 	for (i = 0; i < len; i++) {
363 		if (din)
364 			writeb(0xff, spifmc->io_base + SPIFMC_FIFO_PORT);
365 		else
366 			writeb(dout[i], spifmc->io_base + SPIFMC_FIFO_PORT);
367 	}
368 
369 	writel(0, spifmc->io_base + SPIFMC_INT_STS);
370 	writel(len, spifmc->io_base + SPIFMC_TRAN_NUM);
371 	reg |= SPIFMC_TRAN_CSR_GO_BUSY;
372 	writel(reg, spifmc->io_base + SPIFMC_TRAN_CSR);
373 
374 	ret = sg2044_spifmc_wait_int(spifmc, SPIFMC_INT_TRAN_DONE);
375 	if (ret < 0)
376 		return ret;
377 
378 	if (din) {
379 		while (len--)
380 			*din++ = readb(spifmc->io_base + SPIFMC_FIFO_PORT);
381 	}
382 
383 	writel(0, spifmc->io_base + SPIFMC_FIFO_PT);
384 
385 	return 0;
386 }
387 
sg2044_spifmc_exec_op(struct spi_mem * mem,const struct spi_mem_op * op)388 static int sg2044_spifmc_exec_op(struct spi_mem *mem,
389 				 const struct spi_mem_op *op)
390 {
391 	struct sg2044_spifmc *spifmc;
392 
393 	spifmc = spi_controller_get_devdata(mem->spi->controller);
394 
395 	mutex_lock(&spifmc->lock);
396 
397 	if (op->addr.nbytes == 0)
398 		sg2044_spifmc_trans_reg(spifmc, op);
399 	else
400 		sg2044_spifmc_trans(spifmc, op);
401 
402 	mutex_unlock(&spifmc->lock);
403 
404 	return 0;
405 }
406 
407 static const struct spi_controller_mem_ops sg2044_spifmc_mem_ops = {
408 	.exec_op = sg2044_spifmc_exec_op,
409 };
410 
sg2044_spifmc_init(struct sg2044_spifmc * spifmc)411 static void sg2044_spifmc_init(struct sg2044_spifmc *spifmc)
412 {
413 	u32 tran_csr;
414 	u32 reg;
415 
416 	writel(0, spifmc->io_base + SPIFMC_DMMR);
417 
418 	reg = readl(spifmc->io_base + SPIFMC_CTRL);
419 	reg |= SPIFMC_CTRL_SRST;
420 	reg &= ~(SPIFMC_CTRL_SCK_DIV_MASK);
421 	reg |= 1;
422 	writel(reg, spifmc->io_base + SPIFMC_CTRL);
423 
424 	writel(0, spifmc->io_base + SPIFMC_CE_CTRL);
425 
426 	tran_csr = readl(spifmc->io_base + SPIFMC_TRAN_CSR);
427 	tran_csr |= (0 << SPIFMC_TRAN_CSR_ADDR_BYTES_SHIFT);
428 	tran_csr |= SPIFMC_TRAN_CSR_FIFO_TRG_LVL_4_BYTE;
429 	tran_csr |= SPIFMC_TRAN_CSR_WITH_CMD;
430 	writel(tran_csr, spifmc->io_base + SPIFMC_TRAN_CSR);
431 }
432 
sg2044_spifmc_probe(struct platform_device * pdev)433 static int sg2044_spifmc_probe(struct platform_device *pdev)
434 {
435 	struct device *dev = &pdev->dev;
436 	struct spi_controller *ctrl;
437 	struct sg2044_spifmc *spifmc;
438 	int ret;
439 
440 	ctrl = devm_spi_alloc_host(&pdev->dev, sizeof(*spifmc));
441 	if (!ctrl)
442 		return -ENOMEM;
443 
444 	spifmc = spi_controller_get_devdata(ctrl);
445 
446 	spifmc->clk = devm_clk_get_enabled(&pdev->dev, NULL);
447 	if (IS_ERR(spifmc->clk))
448 		return dev_err_probe(dev, PTR_ERR(spifmc->clk), "Cannot get and enable AHB clock\n");
449 
450 	spifmc->dev = &pdev->dev;
451 	spifmc->ctrl = ctrl;
452 
453 	spifmc->io_base = devm_platform_ioremap_resource(pdev, 0);
454 	if (IS_ERR(spifmc->io_base))
455 		return PTR_ERR(spifmc->io_base);
456 
457 	ctrl->num_chipselect = 1;
458 	ctrl->dev.of_node = pdev->dev.of_node;
459 	ctrl->bits_per_word_mask = SPI_BPW_MASK(8);
460 	ctrl->auto_runtime_pm = false;
461 	ctrl->mem_ops = &sg2044_spifmc_mem_ops;
462 	ctrl->mode_bits = SPI_RX_DUAL | SPI_TX_DUAL | SPI_RX_QUAD | SPI_TX_QUAD;
463 
464 	ret = devm_mutex_init(dev, &spifmc->lock);
465 	if (ret)
466 		return ret;
467 	spifmc->chip_info = device_get_match_data(&pdev->dev);
468 	if (!spifmc->chip_info) {
469 		dev_err(&pdev->dev, "Failed to get specific chip info\n");
470 		return -EINVAL;
471 	}
472 
473 	sg2044_spifmc_init(spifmc);
474 	sg2044_spifmc_init_reg(spifmc);
475 
476 	ret = devm_spi_register_controller(&pdev->dev, ctrl);
477 	if (ret)
478 		return dev_err_probe(dev, ret, "spi_register_controller failed\n");
479 
480 	return 0;
481 }
482 
483 static const struct sg204x_spifmc_chip_info sg2044_chip_info = {
484 	.has_opt_reg = true,
485 	.rd_fifo_int_trigger_level = SPIFMC_TRAN_CSR_FIFO_TRG_LVL_8_BYTE,
486 };
487 
488 static const struct sg204x_spifmc_chip_info sg2042_chip_info = {
489 	.has_opt_reg = false,
490 	.rd_fifo_int_trigger_level = SPIFMC_TRAN_CSR_FIFO_TRG_LVL_1_BYTE,
491 };
492 
493 static const struct of_device_id sg2044_spifmc_match[] = {
494 	{ .compatible = "sophgo,sg2044-spifmc-nor", .data = &sg2044_chip_info },
495 	{ .compatible = "sophgo,sg2042-spifmc-nor", .data = &sg2042_chip_info },
496 	{ /* sentinel */ }
497 };
498 MODULE_DEVICE_TABLE(of, sg2044_spifmc_match);
499 
500 static struct platform_driver sg2044_nor_driver = {
501 	.driver = {
502 		.name = "sg2044,spifmc-nor",
503 		.of_match_table = sg2044_spifmc_match,
504 	},
505 	.probe = sg2044_spifmc_probe,
506 };
507 module_platform_driver(sg2044_nor_driver);
508 
509 MODULE_DESCRIPTION("SG2044 SPI NOR controller driver");
510 MODULE_AUTHOR("Longbin Li <looong.bin@gmail.com>");
511 MODULE_LICENSE("GPL");
512