1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2018 Nuvoton Technology corporation.
4 #include <linux/kernel.h>
5 #include <linux/bitfield.h>
6 #include <linux/bitops.h>
8 #include <linux/interrupt.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/spi/spi.h>
13 #include <linux/gpio.h>
14 #include <linux/of_gpio.h>
16 #include <asm/unaligned.h>
18 #include <linux/regmap.h>
19 #include <linux/mfd/syscon.h>
22 struct completion xfer_done
;
23 struct regmap
*rst_regmap
;
24 struct spi_master
*master
;
25 unsigned int tx_bytes
;
26 unsigned int rx_bytes
;
38 #define DRIVER_NAME "npcm-pspi"
40 #define NPCM_PSPI_DATA 0x00
41 #define NPCM_PSPI_CTL1 0x02
42 #define NPCM_PSPI_STAT 0x04
44 /* definitions for control and status register */
45 #define NPCM_PSPI_CTL1_SPIEN BIT(0)
46 #define NPCM_PSPI_CTL1_MOD BIT(2)
47 #define NPCM_PSPI_CTL1_EIR BIT(5)
48 #define NPCM_PSPI_CTL1_EIW BIT(6)
49 #define NPCM_PSPI_CTL1_SCM BIT(7)
50 #define NPCM_PSPI_CTL1_SCIDL BIT(8)
51 #define NPCM_PSPI_CTL1_SCDV6_0 GENMASK(15, 9)
53 #define NPCM_PSPI_STAT_BSY BIT(0)
54 #define NPCM_PSPI_STAT_RBF BIT(1)
56 /* general definitions */
57 #define NPCM_PSPI_TIMEOUT_MS 2000
58 #define NPCM_PSPI_MAX_CLK_DIVIDER 256
59 #define NPCM_PSPI_MIN_CLK_DIVIDER 4
60 #define NPCM_PSPI_DEFAULT_CLK 25000000
63 #define NPCM7XX_IPSRST2_OFFSET 0x24
65 #define NPCM7XX_PSPI1_RESET BIT(22)
66 #define NPCM7XX_PSPI2_RESET BIT(23)
68 static inline unsigned int bytes_per_word(unsigned int bits
)
70 return bits
<= 8 ? 1 : 2;
73 static inline void npcm_pspi_irq_enable(struct npcm_pspi
*priv
, u16 mask
)
77 val
= ioread16(priv
->base
+ NPCM_PSPI_CTL1
);
79 iowrite16(val
, priv
->base
+ NPCM_PSPI_CTL1
);
82 static inline void npcm_pspi_irq_disable(struct npcm_pspi
*priv
, u16 mask
)
86 val
= ioread16(priv
->base
+ NPCM_PSPI_CTL1
);
88 iowrite16(val
, priv
->base
+ NPCM_PSPI_CTL1
);
91 static inline void npcm_pspi_enable(struct npcm_pspi
*priv
)
95 val
= ioread16(priv
->base
+ NPCM_PSPI_CTL1
);
96 val
|= NPCM_PSPI_CTL1_SPIEN
;
97 iowrite16(val
, priv
->base
+ NPCM_PSPI_CTL1
);
100 static inline void npcm_pspi_disable(struct npcm_pspi
*priv
)
104 val
= ioread16(priv
->base
+ NPCM_PSPI_CTL1
);
105 val
&= ~NPCM_PSPI_CTL1_SPIEN
;
106 iowrite16(val
, priv
->base
+ NPCM_PSPI_CTL1
);
109 static void npcm_pspi_set_mode(struct spi_device
*spi
)
111 struct npcm_pspi
*priv
= spi_master_get_devdata(spi
->master
);
115 switch (spi
->mode
& (SPI_CPOL
| SPI_CPHA
)) {
120 mode_val
= NPCM_PSPI_CTL1_SCIDL
;
123 mode_val
= NPCM_PSPI_CTL1_SCM
;
126 mode_val
= NPCM_PSPI_CTL1_SCIDL
| NPCM_PSPI_CTL1_SCM
;
130 regtemp
= ioread16(priv
->base
+ NPCM_PSPI_CTL1
);
131 regtemp
&= ~(NPCM_PSPI_CTL1_SCM
| NPCM_PSPI_CTL1_SCIDL
);
132 iowrite16(regtemp
| mode_val
, priv
->base
+ NPCM_PSPI_CTL1
);
135 static void npcm_pspi_set_transfer_size(struct npcm_pspi
*priv
, int size
)
139 regtemp
= ioread16(NPCM_PSPI_CTL1
+ priv
->base
);
143 regtemp
&= ~NPCM_PSPI_CTL1_MOD
;
146 regtemp
|= NPCM_PSPI_CTL1_MOD
;
150 iowrite16(regtemp
, NPCM_PSPI_CTL1
+ priv
->base
);
153 static void npcm_pspi_set_baudrate(struct npcm_pspi
*priv
, unsigned int speed
)
158 /* the supported rates are numbers from 4 to 256. */
159 ckdiv
= DIV_ROUND_CLOSEST(clk_get_rate(priv
->clk
), (2 * speed
)) - 1;
161 regtemp
= ioread16(NPCM_PSPI_CTL1
+ priv
->base
);
162 regtemp
&= ~NPCM_PSPI_CTL1_SCDV6_0
;
163 iowrite16(regtemp
| (ckdiv
<< 9), NPCM_PSPI_CTL1
+ priv
->base
);
166 static void npcm_pspi_setup_transfer(struct spi_device
*spi
,
167 struct spi_transfer
*t
)
169 struct npcm_pspi
*priv
= spi_master_get_devdata(spi
->master
);
171 priv
->tx_buf
= t
->tx_buf
;
172 priv
->rx_buf
= t
->rx_buf
;
173 priv
->tx_bytes
= t
->len
;
174 priv
->rx_bytes
= t
->len
;
176 if (!priv
->is_save_param
|| priv
->mode
!= spi
->mode
) {
177 npcm_pspi_set_mode(spi
);
178 priv
->mode
= spi
->mode
;
181 if (!priv
->is_save_param
|| priv
->bits_per_word
!= t
->bits_per_word
) {
182 npcm_pspi_set_transfer_size(priv
, t
->bits_per_word
);
183 priv
->bits_per_word
= t
->bits_per_word
;
186 if (!priv
->is_save_param
|| priv
->speed_hz
!= t
->speed_hz
) {
187 npcm_pspi_set_baudrate(priv
, t
->speed_hz
);
188 priv
->speed_hz
= t
->speed_hz
;
191 if (!priv
->is_save_param
)
192 priv
->is_save_param
= true;
195 static void npcm_pspi_send(struct npcm_pspi
*priv
)
199 wsize
= min(bytes_per_word(priv
->bits_per_word
), priv
->tx_bytes
);
200 priv
->tx_bytes
-= wsize
;
207 iowrite8(*priv
->tx_buf
, NPCM_PSPI_DATA
+ priv
->base
);
210 iowrite16(*priv
->tx_buf
, NPCM_PSPI_DATA
+ priv
->base
);
217 priv
->tx_buf
+= wsize
;
220 static void npcm_pspi_recv(struct npcm_pspi
*priv
)
225 rsize
= min(bytes_per_word(priv
->bits_per_word
), priv
->rx_bytes
);
226 priv
->rx_bytes
-= rsize
;
233 val
= ioread8(priv
->base
+ NPCM_PSPI_DATA
);
236 val
= ioread16(priv
->base
+ NPCM_PSPI_DATA
);
244 priv
->rx_buf
+= rsize
;
247 static int npcm_pspi_transfer_one(struct spi_master
*master
,
248 struct spi_device
*spi
,
249 struct spi_transfer
*t
)
251 struct npcm_pspi
*priv
= spi_master_get_devdata(master
);
254 npcm_pspi_setup_transfer(spi
, t
);
255 reinit_completion(&priv
->xfer_done
);
256 npcm_pspi_enable(priv
);
257 status
= wait_for_completion_timeout(&priv
->xfer_done
,
259 (NPCM_PSPI_TIMEOUT_MS
));
261 npcm_pspi_disable(priv
);
268 static int npcm_pspi_prepare_transfer_hardware(struct spi_master
*master
)
270 struct npcm_pspi
*priv
= spi_master_get_devdata(master
);
272 npcm_pspi_irq_enable(priv
, NPCM_PSPI_CTL1_EIR
| NPCM_PSPI_CTL1_EIW
);
277 static int npcm_pspi_unprepare_transfer_hardware(struct spi_master
*master
)
279 struct npcm_pspi
*priv
= spi_master_get_devdata(master
);
281 npcm_pspi_irq_disable(priv
, NPCM_PSPI_CTL1_EIR
| NPCM_PSPI_CTL1_EIW
);
286 static void npcm_pspi_reset_hw(struct npcm_pspi
*priv
)
288 regmap_write(priv
->rst_regmap
, NPCM7XX_IPSRST2_OFFSET
,
289 NPCM7XX_PSPI1_RESET
<< priv
->id
);
290 regmap_write(priv
->rst_regmap
, NPCM7XX_IPSRST2_OFFSET
, 0x0);
293 static irqreturn_t
npcm_pspi_handler(int irq
, void *dev_id
)
295 struct npcm_pspi
*priv
= dev_id
;
299 stat
= ioread8(priv
->base
+ NPCM_PSPI_STAT
);
301 if (!priv
->tx_buf
&& !priv
->rx_buf
)
305 if (stat
& NPCM_PSPI_STAT_RBF
) {
306 val
= ioread8(NPCM_PSPI_DATA
+ priv
->base
);
307 if (priv
->tx_bytes
== 0) {
308 npcm_pspi_disable(priv
);
309 complete(&priv
->xfer_done
);
314 if ((stat
& NPCM_PSPI_STAT_BSY
) == 0)
316 npcm_pspi_send(priv
);
320 if (stat
& NPCM_PSPI_STAT_RBF
) {
324 npcm_pspi_recv(priv
);
326 if (!priv
->rx_bytes
) {
327 npcm_pspi_disable(priv
);
328 complete(&priv
->xfer_done
);
333 if (((stat
& NPCM_PSPI_STAT_BSY
) == 0) && !priv
->tx_buf
)
334 iowrite8(0x0, NPCM_PSPI_DATA
+ priv
->base
);
340 static int npcm_pspi_probe(struct platform_device
*pdev
)
342 struct npcm_pspi
*priv
;
343 struct spi_master
*master
;
344 struct resource
*res
;
345 unsigned long clk_hz
;
346 struct device_node
*np
= pdev
->dev
.of_node
;
352 num_cs
= of_gpio_named_count(np
, "cs-gpios");
356 pdev
->id
= of_alias_get_id(np
, "spi");
360 master
= spi_alloc_master(&pdev
->dev
, sizeof(*priv
));
364 platform_set_drvdata(pdev
, master
);
366 priv
= spi_master_get_devdata(master
);
367 priv
->master
= master
;
368 priv
->is_save_param
= false;
371 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
372 priv
->base
= devm_ioremap_resource(&pdev
->dev
, res
);
373 if (IS_ERR(priv
->base
)) {
374 ret
= PTR_ERR(priv
->base
);
378 priv
->clk
= devm_clk_get(&pdev
->dev
, NULL
);
379 if (IS_ERR(priv
->clk
)) {
380 dev_err(&pdev
->dev
, "failed to get clock\n");
381 ret
= PTR_ERR(priv
->clk
);
385 ret
= clk_prepare_enable(priv
->clk
);
389 irq
= platform_get_irq(pdev
, 0);
391 dev_err(&pdev
->dev
, "failed to get IRQ\n");
393 goto out_disable_clk
;
397 syscon_regmap_lookup_by_compatible("nuvoton,npcm750-rst");
398 if (IS_ERR(priv
->rst_regmap
)) {
399 dev_err(&pdev
->dev
, "failed to find nuvoton,npcm750-rst\n");
400 return PTR_ERR(priv
->rst_regmap
);
403 /* reset SPI-HW block */
404 npcm_pspi_reset_hw(priv
);
406 ret
= devm_request_irq(&pdev
->dev
, irq
, npcm_pspi_handler
, 0,
409 dev_err(&pdev
->dev
, "failed to request IRQ\n");
410 goto out_disable_clk
;
413 init_completion(&priv
->xfer_done
);
415 clk_hz
= clk_get_rate(priv
->clk
);
417 master
->max_speed_hz
= DIV_ROUND_UP(clk_hz
, NPCM_PSPI_MIN_CLK_DIVIDER
);
418 master
->min_speed_hz
= DIV_ROUND_UP(clk_hz
, NPCM_PSPI_MAX_CLK_DIVIDER
);
419 master
->mode_bits
= SPI_CPHA
| SPI_CPOL
;
420 master
->dev
.of_node
= pdev
->dev
.of_node
;
421 master
->bus_num
= pdev
->id
;
422 master
->bits_per_word_mask
= SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
423 master
->transfer_one
= npcm_pspi_transfer_one
;
424 master
->prepare_transfer_hardware
=
425 npcm_pspi_prepare_transfer_hardware
;
426 master
->unprepare_transfer_hardware
=
427 npcm_pspi_unprepare_transfer_hardware
;
428 master
->num_chipselect
= num_cs
;
430 for (i
= 0; i
< num_cs
; i
++) {
431 csgpio
= of_get_named_gpio(np
, "cs-gpios", i
);
433 dev_err(&pdev
->dev
, "failed to get csgpio#%u\n", i
);
434 goto out_disable_clk
;
436 dev_dbg(&pdev
->dev
, "csgpio#%u = %d\n", i
, csgpio
);
437 ret
= devm_gpio_request_one(&pdev
->dev
, csgpio
,
438 GPIOF_OUT_INIT_HIGH
, DRIVER_NAME
);
441 "failed to configure csgpio#%u %d\n"
443 goto out_disable_clk
;
447 /* set to default clock rate */
448 npcm_pspi_set_baudrate(priv
, NPCM_PSPI_DEFAULT_CLK
);
450 ret
= devm_spi_register_master(&pdev
->dev
, master
);
452 goto out_disable_clk
;
454 pr_info("NPCM Peripheral SPI %d probed\n", pdev
->id
);
459 clk_disable_unprepare(priv
->clk
);
462 spi_master_put(master
);
466 static int npcm_pspi_remove(struct platform_device
*pdev
)
468 struct npcm_pspi
*priv
= platform_get_drvdata(pdev
);
470 npcm_pspi_reset_hw(priv
);
471 clk_disable_unprepare(priv
->clk
);
476 static const struct of_device_id npcm_pspi_match
[] = {
477 { .compatible
= "nuvoton,npcm750-pspi", .data
= NULL
},
480 MODULE_DEVICE_TABLE(of
, npcm_pspi_match
);
482 static struct platform_driver npcm_pspi_driver
= {
485 .of_match_table
= npcm_pspi_match
,
487 .probe
= npcm_pspi_probe
,
488 .remove
= npcm_pspi_remove
,
490 module_platform_driver(npcm_pspi_driver
);
492 MODULE_DESCRIPTION("NPCM peripheral SPI Controller driver");
493 MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>");
494 MODULE_LICENSE("GPL v2");