summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMason Yang <masonccyang@mxic.com.tw>2018-10-16 22:08:11 -0400
committerMark Brown <broonie@kernel.org>2018-11-05 06:55:06 -0500
commitb942d80b0a394e8ea18fce3b032b4700439e8ca3 (patch)
treee10daf2e31cce9bc971c28f6d5307d4099714d3b
parentbe0bf62e3df9afcb3f7a72de347770568dd60af6 (diff)
spi: Add MXIC controller driver
Add a driver for Macronix SPI controller IP. Signed-off-by: Mason Yang <masonccyang@mxic.com.tw> Reviewed-by: Boris Brezillon <boris.brezillon@bootlin.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/spi/Kconfig6
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/spi-mxic.c619
3 files changed, 626 insertions, 0 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 7d3a5c94727e..91d45c9ac439 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -684,6 +684,12 @@ config SPI_SUN6I
684 help 684 help
685 This enables using the SPI controller on the Allwinner A31 SoCs. 685 This enables using the SPI controller on the Allwinner A31 SoCs.
686 686
687config SPI_MXIC
688 tristate "Macronix MX25F0A SPI controller"
689 depends on SPI_MASTER
690 help
691 This selects the Macronix MX25F0A SPI controller driver.
692
687config SPI_MXS 693config SPI_MXS
688 tristate "Freescale MXS SPI controller" 694 tristate "Freescale MXS SPI controller"
689 depends on ARCH_MXS 695 depends on ARCH_MXS
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 3575205c5c27..de0be4b64c54 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -58,6 +58,7 @@ obj-$(CONFIG_SPI_MPC512x_PSC) += spi-mpc512x-psc.o
58obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o 58obj-$(CONFIG_SPI_MPC52xx_PSC) += spi-mpc52xx-psc.o
59obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o 59obj-$(CONFIG_SPI_MPC52xx) += spi-mpc52xx.o
60obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o 60obj-$(CONFIG_SPI_MT65XX) += spi-mt65xx.o
61obj-$(CONFIG_SPI_MXIC) += spi-mxic.o
61obj-$(CONFIG_SPI_MXS) += spi-mxs.o 62obj-$(CONFIG_SPI_MXS) += spi-mxs.o
62obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o 63obj-$(CONFIG_SPI_NUC900) += spi-nuc900.o
63obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o 64obj-$(CONFIG_SPI_OC_TINY) += spi-oc-tiny.o
diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c
new file mode 100644
index 000000000000..e41ae6ef0f8a
--- /dev/null
+++ b/drivers/spi/spi-mxic.c
@@ -0,0 +1,619 @@
1// SPDX-License-Identifier: GPL-2.0
2//
3// Copyright (C) 2018 Macronix International Co., Ltd.
4//
5// Authors:
6// Mason Yang <masonccyang@mxic.com.tw>
7// zhengxunli <zhengxunli@mxic.com.tw>
8// Boris Brezillon <boris.brezillon@bootlin.com>
9//
10
11#include <linux/clk.h>
12#include <linux/io.h>
13#include <linux/iopoll.h>
14#include <linux/module.h>
15#include <linux/platform_device.h>
16#include <linux/pm_runtime.h>
17#include <linux/spi/spi.h>
18#include <linux/spi/spi-mem.h>
19
20#define HC_CFG 0x0
21#define HC_CFG_IF_CFG(x) ((x) << 27)
22#define HC_CFG_DUAL_SLAVE BIT(31)
23#define HC_CFG_INDIVIDUAL BIT(30)
24#define HC_CFG_NIO(x) (((x) / 4) << 27)
25#define HC_CFG_TYPE(s, t) ((t) << (23 + ((s) * 2)))
26#define HC_CFG_TYPE_SPI_NOR 0
27#define HC_CFG_TYPE_SPI_NAND 1
28#define HC_CFG_TYPE_SPI_RAM 2
29#define HC_CFG_TYPE_RAW_NAND 3
30#define HC_CFG_SLV_ACT(x) ((x) << 21)
31#define HC_CFG_CLK_PH_EN BIT(20)
32#define HC_CFG_CLK_POL_INV BIT(19)
33#define HC_CFG_BIG_ENDIAN BIT(18)
34#define HC_CFG_DATA_PASS BIT(17)
35#define HC_CFG_IDLE_SIO_LVL(x) ((x) << 16)
36#define HC_CFG_MAN_START_EN BIT(3)
37#define HC_CFG_MAN_START BIT(2)
38#define HC_CFG_MAN_CS_EN BIT(1)
39#define HC_CFG_MAN_CS_ASSERT BIT(0)
40
41#define INT_STS 0x4
42#define INT_STS_EN 0x8
43#define INT_SIG_EN 0xc
44#define INT_STS_ALL GENMASK(31, 0)
45#define INT_RDY_PIN BIT(26)
46#define INT_RDY_SR BIT(25)
47#define INT_LNR_SUSP BIT(24)
48#define INT_ECC_ERR BIT(17)
49#define INT_CRC_ERR BIT(16)
50#define INT_LWR_DIS BIT(12)
51#define INT_LRD_DIS BIT(11)
52#define INT_SDMA_INT BIT(10)
53#define INT_DMA_FINISH BIT(9)
54#define INT_RX_NOT_FULL BIT(3)
55#define INT_RX_NOT_EMPTY BIT(2)
56#define INT_TX_NOT_FULL BIT(1)
57#define INT_TX_EMPTY BIT(0)
58
59#define HC_EN 0x10
60#define HC_EN_BIT BIT(0)
61
62#define TXD(x) (0x14 + ((x) * 4))
63#define RXD 0x24
64
65#define SS_CTRL(s) (0x30 + ((s) * 4))
66#define LRD_CFG 0x44
67#define LWR_CFG 0x80
68#define RWW_CFG 0x70
69#define OP_READ BIT(23)
70#define OP_DUMMY_CYC(x) ((x) << 17)
71#define OP_ADDR_BYTES(x) ((x) << 14)
72#define OP_CMD_BYTES(x) (((x) - 1) << 13)
73#define OP_OCTA_CRC_EN BIT(12)
74#define OP_DQS_EN BIT(11)
75#define OP_ENHC_EN BIT(10)
76#define OP_PREAMBLE_EN BIT(9)
77#define OP_DATA_DDR BIT(8)
78#define OP_DATA_BUSW(x) ((x) << 6)
79#define OP_ADDR_DDR BIT(5)
80#define OP_ADDR_BUSW(x) ((x) << 3)
81#define OP_CMD_DDR BIT(2)
82#define OP_CMD_BUSW(x) (x)
83#define OP_BUSW_1 0
84#define OP_BUSW_2 1
85#define OP_BUSW_4 2
86#define OP_BUSW_8 3
87
88#define OCTA_CRC 0x38
89#define OCTA_CRC_IN_EN(s) BIT(3 + ((s) * 16))
90#define OCTA_CRC_CHUNK(s, x) ((fls((x) / 32)) << (1 + ((s) * 16)))
91#define OCTA_CRC_OUT_EN(s) BIT(0 + ((s) * 16))
92
93#define ONFI_DIN_CNT(s) (0x3c + (s))
94
95#define LRD_CTRL 0x48
96#define RWW_CTRL 0x74
97#define LWR_CTRL 0x84
98#define LMODE_EN BIT(31)
99#define LMODE_SLV_ACT(x) ((x) << 21)
100#define LMODE_CMD1(x) ((x) << 8)
101#define LMODE_CMD0(x) (x)
102
103#define LRD_ADDR 0x4c
104#define LWR_ADDR 0x88
105#define LRD_RANGE 0x50
106#define LWR_RANGE 0x8c
107
108#define AXI_SLV_ADDR 0x54
109
110#define DMAC_RD_CFG 0x58
111#define DMAC_WR_CFG 0x94
112#define DMAC_CFG_PERIPH_EN BIT(31)
113#define DMAC_CFG_ALLFLUSH_EN BIT(30)
114#define DMAC_CFG_LASTFLUSH_EN BIT(29)
115#define DMAC_CFG_QE(x) (((x) + 1) << 16)
116#define DMAC_CFG_BURST_LEN(x) (((x) + 1) << 12)
117#define DMAC_CFG_BURST_SZ(x) ((x) << 8)
118#define DMAC_CFG_DIR_READ BIT(1)
119#define DMAC_CFG_START BIT(0)
120
121#define DMAC_RD_CNT 0x5c
122#define DMAC_WR_CNT 0x98
123
124#define SDMA_ADDR 0x60
125
126#define DMAM_CFG 0x64
127#define DMAM_CFG_START BIT(31)
128#define DMAM_CFG_CONT BIT(30)
129#define DMAM_CFG_SDMA_GAP(x) (fls((x) / 8192) << 2)
130#define DMAM_CFG_DIR_READ BIT(1)
131#define DMAM_CFG_EN BIT(0)
132
133#define DMAM_CNT 0x68
134
135#define LNR_TIMER_TH 0x6c
136
137#define RDM_CFG0 0x78
138#define RDM_CFG0_POLY(x) (x)
139
140#define RDM_CFG1 0x7c
141#define RDM_CFG1_RDM_EN BIT(31)
142#define RDM_CFG1_SEED(x) (x)
143
144#define LWR_SUSP_CTRL 0x90
145#define LWR_SUSP_CTRL_EN BIT(31)
146
147#define DMAS_CTRL 0x9c
148#define DMAS_CTRL_DIR_READ BIT(31)
149#define DMAS_CTRL_EN BIT(30)
150
151#define DATA_STROB 0xa0
152#define DATA_STROB_EDO_EN BIT(2)
153#define DATA_STROB_INV_POL BIT(1)
154#define DATA_STROB_DELAY_2CYC BIT(0)
155
156#define IDLY_CODE(x) (0xa4 + ((x) * 4))
157#define IDLY_CODE_VAL(x, v) ((v) << (((x) % 4) * 8))
158
159#define GPIO 0xc4
160#define GPIO_PT(x) BIT(3 + ((x) * 16))
161#define GPIO_RESET(x) BIT(2 + ((x) * 16))
162#define GPIO_HOLDB(x) BIT(1 + ((x) * 16))
163#define GPIO_WPB(x) BIT((x) * 16)
164
165#define HC_VER 0xd0
166
167#define HW_TEST(x) (0xe0 + ((x) * 4))
168
169struct mxic_spi {
170 struct clk *ps_clk;
171 struct clk *send_clk;
172 struct clk *send_dly_clk;
173 void __iomem *regs;
174 u32 cur_speed_hz;
175};
176
177static int mxic_spi_clk_enable(struct mxic_spi *mxic)
178{
179 int ret;
180
181 ret = clk_prepare_enable(mxic->send_clk);
182 if (ret)
183 return ret;
184
185 ret = clk_prepare_enable(mxic->send_dly_clk);
186 if (ret)
187 goto err_send_dly_clk;
188
189 return ret;
190
191err_send_dly_clk:
192 clk_disable_unprepare(mxic->send_clk);
193
194 return ret;
195}
196
197static void mxic_spi_clk_disable(struct mxic_spi *mxic)
198{
199 clk_disable_unprepare(mxic->send_clk);
200 clk_disable_unprepare(mxic->send_dly_clk);
201}
202
203static void mxic_spi_set_input_delay_dqs(struct mxic_spi *mxic, u8 idly_code)
204{
205 writel(IDLY_CODE_VAL(0, idly_code) |
206 IDLY_CODE_VAL(1, idly_code) |
207 IDLY_CODE_VAL(2, idly_code) |
208 IDLY_CODE_VAL(3, idly_code),
209 mxic->regs + IDLY_CODE(0));
210 writel(IDLY_CODE_VAL(4, idly_code) |
211 IDLY_CODE_VAL(5, idly_code) |
212 IDLY_CODE_VAL(6, idly_code) |
213 IDLY_CODE_VAL(7, idly_code),
214 mxic->regs + IDLY_CODE(1));
215}
216
217static int mxic_spi_clk_setup(struct mxic_spi *mxic, unsigned long freq)
218{
219 int ret;
220
221 ret = clk_set_rate(mxic->send_clk, freq);
222 if (ret)
223 return ret;
224
225 ret = clk_set_rate(mxic->send_dly_clk, freq);
226 if (ret)
227 return ret;
228
229 /*
230 * A constant delay range from 0x0 ~ 0x1F for input delay,
231 * the unit is 78 ps, the max input delay is 2.418 ns.
232 */
233 mxic_spi_set_input_delay_dqs(mxic, 0xf);
234
235 /*
236 * Phase degree = 360 * freq * output-delay
237 * where output-delay is a constant value 1 ns in FPGA.
238 *
239 * Get Phase degree = 360 * freq * 1 ns
240 * = 360 * freq * 1 sec / 1000000000
241 * = 9 * freq / 25000000
242 */
243 ret = clk_set_phase(mxic->send_dly_clk, 9 * freq / 25000000);
244 if (ret)
245 return ret;
246
247 return 0;
248}
249
250static int mxic_spi_set_freq(struct mxic_spi *mxic, unsigned long freq)
251{
252 int ret;
253
254 if (mxic->cur_speed_hz == freq)
255 return 0;
256
257 mxic_spi_clk_disable(mxic);
258 ret = mxic_spi_clk_setup(mxic, freq);
259 if (ret)
260 return ret;
261
262 ret = mxic_spi_clk_enable(mxic);
263 if (ret)
264 return ret;
265
266 mxic->cur_speed_hz = freq;
267
268 return 0;
269}
270
271static void mxic_spi_hw_init(struct mxic_spi *mxic)
272{
273 writel(0, mxic->regs + DATA_STROB);
274 writel(INT_STS_ALL, mxic->regs + INT_STS_EN);
275 writel(0, mxic->regs + HC_EN);
276 writel(0, mxic->regs + LRD_CFG);
277 writel(0, mxic->regs + LRD_CTRL);
278 writel(HC_CFG_NIO(1) | HC_CFG_TYPE(0, HC_CFG_TYPE_SPI_NAND) |
279 HC_CFG_SLV_ACT(0) | HC_CFG_MAN_CS_EN | HC_CFG_IDLE_SIO_LVL(1),
280 mxic->regs + HC_CFG);
281}
282
283static int mxic_spi_data_xfer(struct mxic_spi *mxic, const void *txbuf,
284 void *rxbuf, unsigned int len)
285{
286 unsigned int pos = 0;
287
288 while (pos < len) {
289 unsigned int nbytes = len - pos;
290 u32 data = 0xffffffff;
291 u32 sts;
292 int ret;
293
294 if (nbytes > 4)
295 nbytes = 4;
296
297 if (txbuf)
298 memcpy(&data, txbuf + pos, nbytes);
299
300 ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
301 sts & INT_TX_EMPTY, 0, USEC_PER_SEC);
302 if (ret)
303 return ret;
304
305 writel(data, mxic->regs + TXD(nbytes % 4));
306
307 if (rxbuf) {
308 ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
309 sts & INT_TX_EMPTY, 0,
310 USEC_PER_SEC);
311 if (ret)
312 return ret;
313
314 ret = readl_poll_timeout(mxic->regs + INT_STS, sts,
315 sts & INT_RX_NOT_EMPTY, 0,
316 USEC_PER_SEC);
317 if (ret)
318 return ret;
319
320 data = readl(mxic->regs + RXD);
321 data >>= (8 * (4 - nbytes));
322 memcpy(rxbuf + pos, &data, nbytes);
323 WARN_ON(readl(mxic->regs + INT_STS) & INT_RX_NOT_EMPTY);
324 } else {
325 readl(mxic->regs + RXD);
326 }
327 WARN_ON(readl(mxic->regs + INT_STS) & INT_RX_NOT_EMPTY);
328
329 pos += nbytes;
330 }
331
332 return 0;
333}
334
335static bool mxic_spi_mem_supports_op(struct spi_mem *mem,
336 const struct spi_mem_op *op)
337{
338 if (op->data.buswidth > 4 || op->addr.buswidth > 4 ||
339 op->dummy.buswidth > 4 || op->cmd.buswidth > 4)
340 return false;
341
342 if (op->data.nbytes && op->dummy.nbytes &&
343 op->data.buswidth != op->dummy.buswidth)
344 return false;
345
346 if (op->addr.nbytes > 7)
347 return false;
348
349 return true;
350}
351
352static int mxic_spi_mem_exec_op(struct spi_mem *mem,
353 const struct spi_mem_op *op)
354{
355 struct mxic_spi *mxic = spi_master_get_devdata(mem->spi->master);
356 int nio = 1, i, ret;
357 u32 ss_ctrl;
358 u8 addr[8];
359
360 ret = mxic_spi_set_freq(mxic, mem->spi->max_speed_hz);
361 if (ret)
362 return ret;
363
364 if (mem->spi->mode & (SPI_TX_QUAD | SPI_RX_QUAD))
365 nio = 4;
366 else if (mem->spi->mode & (SPI_TX_DUAL | SPI_RX_DUAL))
367 nio = 2;
368
369 writel(HC_CFG_NIO(nio) |
370 HC_CFG_TYPE(mem->spi->chip_select, HC_CFG_TYPE_SPI_NOR) |
371 HC_CFG_SLV_ACT(mem->spi->chip_select) | HC_CFG_IDLE_SIO_LVL(1) |
372 HC_CFG_MAN_CS_EN,
373 mxic->regs + HC_CFG);
374 writel(HC_EN_BIT, mxic->regs + HC_EN);
375
376 ss_ctrl = OP_CMD_BYTES(1) | OP_CMD_BUSW(fls(op->cmd.buswidth) - 1);
377
378 if (op->addr.nbytes)
379 ss_ctrl |= OP_ADDR_BYTES(op->addr.nbytes) |
380 OP_ADDR_BUSW(fls(op->addr.buswidth) - 1);
381
382 if (op->dummy.nbytes)
383 ss_ctrl |= OP_DUMMY_CYC(op->dummy.nbytes);
384
385 if (op->data.nbytes) {
386 ss_ctrl |= OP_DATA_BUSW(fls(op->data.buswidth) - 1);
387 if (op->data.dir == SPI_MEM_DATA_IN)
388 ss_ctrl |= OP_READ;
389 }
390
391 writel(ss_ctrl, mxic->regs + SS_CTRL(mem->spi->chip_select));
392
393 writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_ASSERT,
394 mxic->regs + HC_CFG);
395
396 ret = mxic_spi_data_xfer(mxic, &op->cmd.opcode, NULL, 1);
397 if (ret)
398 goto out;
399
400 for (i = 0; i < op->addr.nbytes; i++)
401 addr[i] = op->addr.val >> (8 * (op->addr.nbytes - i - 1));
402
403 ret = mxic_spi_data_xfer(mxic, addr, NULL, op->addr.nbytes);
404 if (ret)
405 goto out;
406
407 ret = mxic_spi_data_xfer(mxic, NULL, NULL, op->dummy.nbytes);
408 if (ret)
409 goto out;
410
411 ret = mxic_spi_data_xfer(mxic,
412 op->data.dir == SPI_MEM_DATA_OUT ?
413 op->data.buf.out : NULL,
414 op->data.dir == SPI_MEM_DATA_IN ?
415 op->data.buf.in : NULL,
416 op->data.nbytes);
417
418out:
419 writel(readl(mxic->regs + HC_CFG) & ~HC_CFG_MAN_CS_ASSERT,
420 mxic->regs + HC_CFG);
421 writel(0, mxic->regs + HC_EN);
422
423 return ret;
424}
425
426static const struct spi_controller_mem_ops mxic_spi_mem_ops = {
427 .supports_op = mxic_spi_mem_supports_op,
428 .exec_op = mxic_spi_mem_exec_op,
429};
430
431static void mxic_spi_set_cs(struct spi_device *spi, bool lvl)
432{
433 struct mxic_spi *mxic = spi_master_get_devdata(spi->master);
434
435 if (!lvl) {
436 writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_EN,
437 mxic->regs + HC_CFG);
438 writel(HC_EN_BIT, mxic->regs + HC_EN);
439 writel(readl(mxic->regs + HC_CFG) | HC_CFG_MAN_CS_ASSERT,
440 mxic->regs + HC_CFG);
441 } else {
442 writel(readl(mxic->regs + HC_CFG) & ~HC_CFG_MAN_CS_ASSERT,
443 mxic->regs + HC_CFG);
444 writel(0, mxic->regs + HC_EN);
445 }
446}
447
448static int mxic_spi_transfer_one(struct spi_master *master,
449 struct spi_device *spi,
450 struct spi_transfer *t)
451{
452 struct mxic_spi *mxic = spi_master_get_devdata(master);
453 unsigned int busw = OP_BUSW_1;
454 int ret;
455
456 if (t->rx_buf && t->tx_buf) {
457 if (((spi->mode & SPI_TX_QUAD) &&
458 !(spi->mode & SPI_RX_QUAD)) ||
459 ((spi->mode & SPI_TX_DUAL) &&
460 !(spi->mode & SPI_RX_DUAL)))
461 return -ENOTSUPP;
462 }
463
464 ret = mxic_spi_set_freq(mxic, t->speed_hz);
465 if (ret)
466 return ret;
467
468 if (t->tx_buf) {
469 if (spi->mode & SPI_TX_QUAD)
470 busw = OP_BUSW_4;
471 else if (spi->mode & SPI_TX_DUAL)
472 busw = OP_BUSW_2;
473 } else if (t->rx_buf) {
474 if (spi->mode & SPI_RX_QUAD)
475 busw = OP_BUSW_4;
476 else if (spi->mode & SPI_RX_DUAL)
477 busw = OP_BUSW_2;
478 }
479
480 writel(OP_CMD_BYTES(1) | OP_CMD_BUSW(busw) |
481 OP_DATA_BUSW(busw) | (t->rx_buf ? OP_READ : 0),
482 mxic->regs + SS_CTRL(0));
483
484 ret = mxic_spi_data_xfer(mxic, t->tx_buf, t->rx_buf, t->len);
485 if (ret)
486 return ret;
487
488 spi_finalize_current_transfer(master);
489
490 return 0;
491}
492
493static int __maybe_unused mxic_spi_runtime_suspend(struct device *dev)
494{
495 struct platform_device *pdev = to_platform_device(dev);
496 struct spi_master *master = platform_get_drvdata(pdev);
497 struct mxic_spi *mxic = spi_master_get_devdata(master);
498
499 mxic_spi_clk_disable(mxic);
500 clk_disable_unprepare(mxic->ps_clk);
501
502 return 0;
503}
504
505static int __maybe_unused mxic_spi_runtime_resume(struct device *dev)
506{
507 struct platform_device *pdev = to_platform_device(dev);
508 struct spi_master *master = platform_get_drvdata(pdev);
509 struct mxic_spi *mxic = spi_master_get_devdata(master);
510 int ret;
511
512 ret = clk_prepare_enable(mxic->ps_clk);
513 if (ret) {
514 dev_err(dev, "Cannot enable ps_clock.\n");
515 return ret;
516 }
517
518 return mxic_spi_clk_enable(mxic);
519}
520
521static const struct dev_pm_ops mxic_spi_dev_pm_ops = {
522 SET_RUNTIME_PM_OPS(mxic_spi_runtime_suspend,
523 mxic_spi_runtime_resume, NULL)
524};
525
526static int mxic_spi_probe(struct platform_device *pdev)
527{
528 struct spi_master *master;
529 struct resource *res;
530 struct mxic_spi *mxic;
531 int ret;
532
533 master = spi_alloc_master(&pdev->dev, sizeof(struct mxic_spi));
534 if (!master)
535 return -ENOMEM;
536
537 platform_set_drvdata(pdev, master);
538
539 mxic = spi_master_get_devdata(master);
540
541 master->dev.of_node = pdev->dev.of_node;
542
543 mxic->ps_clk = devm_clk_get(&pdev->dev, "ps_clk");
544 if (IS_ERR(mxic->ps_clk))
545 return PTR_ERR(mxic->ps_clk);
546
547 mxic->send_clk = devm_clk_get(&pdev->dev, "send_clk");
548 if (IS_ERR(mxic->send_clk))
549 return PTR_ERR(mxic->send_clk);
550
551 mxic->send_dly_clk = devm_clk_get(&pdev->dev, "send_dly_clk");
552 if (IS_ERR(mxic->send_dly_clk))
553 return PTR_ERR(mxic->send_dly_clk);
554
555 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
556 mxic->regs = devm_ioremap_resource(&pdev->dev, res);
557 if (IS_ERR(mxic->regs))
558 return PTR_ERR(mxic->regs);
559
560 pm_runtime_enable(&pdev->dev);
561 master->auto_runtime_pm = true;
562
563 master->num_chipselect = 1;
564 master->mem_ops = &mxic_spi_mem_ops;
565
566 master->set_cs = mxic_spi_set_cs;
567 master->transfer_one = mxic_spi_transfer_one;
568 master->bits_per_word_mask = SPI_BPW_MASK(8);
569 master->mode_bits = SPI_CPOL | SPI_CPHA |
570 SPI_RX_DUAL | SPI_TX_DUAL |
571 SPI_RX_QUAD | SPI_TX_QUAD;
572
573 mxic_spi_hw_init(mxic);
574
575 ret = spi_register_master(master);
576 if (ret) {
577 dev_err(&pdev->dev, "spi_register_master failed\n");
578 goto err_put_master;
579 }
580
581 return 0;
582
583err_put_master:
584 spi_master_put(master);
585 pm_runtime_disable(&pdev->dev);
586
587 return ret;
588}
589
590static int mxic_spi_remove(struct platform_device *pdev)
591{
592 struct spi_master *master = platform_get_drvdata(pdev);
593
594 pm_runtime_disable(&pdev->dev);
595 spi_unregister_master(master);
596
597 return 0;
598}
599
600static const struct of_device_id mxic_spi_of_ids[] = {
601 { .compatible = "mxicy,mx25f0a-spi", },
602 { /* sentinel */ }
603};
604MODULE_DEVICE_TABLE(of, mxic_spi_of_ids);
605
606static struct platform_driver mxic_spi_driver = {
607 .probe = mxic_spi_probe,
608 .remove = mxic_spi_remove,
609 .driver = {
610 .name = "mxic-spi",
611 .of_match_table = mxic_spi_of_ids,
612 .pm = &mxic_spi_dev_pm_ops,
613 },
614};
615module_platform_driver(mxic_spi_driver);
616
617MODULE_AUTHOR("Mason Yang <masonccyang@mxic.com.tw>");
618MODULE_DESCRIPTION("MX25F0A SPI controller driver");
619MODULE_LICENSE("GPL v2");