1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2021 Nuvoton Technology.
11 #include <linux/iopoll.h>
15 /* Register offsets */
20 /* PSPI_CTL1 fields */
21 #define PSPI_CTL1_SPIEN BIT(0)
22 #define PSPI_CTL1_SCM BIT(7)
23 #define PSPI_CTL1_SCIDL BIT(8)
24 #define PSPI_CTL1_SCDV_MASK GENMASK(15, 9)
25 #define PSPI_CTL1_SCDV_SHIFT 9
27 /* PSPI_STAT fields */
28 #define PSPI_STAT_BSY BIT(0)
29 #define PSPI_STAT_RBF BIT(1)
31 struct npcm_pspi_priv {
34 struct gpio_desc cs_gpio;
38 static inline void spi_cs_activate(struct udevice *dev)
40 struct udevice *bus = dev->parent;
41 struct npcm_pspi_priv *priv = dev_get_priv(bus);
43 dm_gpio_set_value(&priv->cs_gpio, 0);
46 static inline void spi_cs_deactivate(struct udevice *dev)
48 struct udevice *bus = dev->parent;
49 struct npcm_pspi_priv *priv = dev_get_priv(bus);
51 dm_gpio_set_value(&priv->cs_gpio, 1);
54 static inline void npcm_pspi_enable(struct npcm_pspi_priv *priv)
58 val = readw(priv->base + PSPI_CTL1);
59 val |= PSPI_CTL1_SPIEN;
60 writew(val, priv->base + PSPI_CTL1);
63 static inline void npcm_pspi_disable(struct npcm_pspi_priv *priv)
67 val = readw(priv->base + PSPI_CTL1);
68 val &= ~PSPI_CTL1_SPIEN;
69 writew(val, priv->base + PSPI_CTL1);
72 static int npcm_pspi_xfer(struct udevice *dev, unsigned int bitlen,
73 const void *dout, void *din, unsigned long flags)
75 struct udevice *bus = dev->parent;
76 struct npcm_pspi_priv *priv = dev_get_priv(bus);
77 void __iomem *base = priv->base;
80 u32 bytes = bitlen / 8;
85 npcm_pspi_enable(priv);
87 if (flags & SPI_XFER_BEGIN)
90 for (i = 0; i < bytes; i++) {
91 /* Making sure we can write */
92 ret = readb_poll_timeout(base + PSPI_STAT, val,
93 !(val & PSPI_STAT_BSY),
99 writeb(*tx++, base + PSPI_DATA);
101 writeb(0, base + PSPI_DATA);
103 /* Wait till write completed */
104 ret = readb_poll_timeout(base + PSPI_STAT, val,
105 !(val & PSPI_STAT_BSY),
110 /* Wait till read buffer full */
111 ret = readb_poll_timeout(base + PSPI_STAT, val,
112 (val & PSPI_STAT_RBF),
117 tmp = readb(base + PSPI_DATA);
122 if (flags & SPI_XFER_END)
123 spi_cs_deactivate(dev);
125 npcm_pspi_disable(priv);
130 static int npcm_pspi_set_speed(struct udevice *bus, uint speed)
132 struct npcm_pspi_priv *priv = dev_get_priv(bus);
137 apb_clock = clk_get_rate(&priv->clk);
141 if (speed > priv->max_hz)
142 speed = priv->max_hz;
144 divisor = DIV_ROUND_CLOSEST(apb_clock, (2 * speed) - 1);
145 if (divisor > MAX_DIV)
148 val = readw(priv->base + PSPI_CTL1);
149 val &= ~PSPI_CTL1_SCDV_MASK;
150 val |= divisor << PSPI_CTL1_SCDV_SHIFT;
151 writew(val, priv->base + PSPI_CTL1);
153 debug("%s: apb_clock=%lu speed=%d divisor=%u\n",
154 __func__, apb_clock, speed, divisor);
159 static int npcm_pspi_set_mode(struct udevice *bus, uint mode)
161 struct npcm_pspi_priv *priv = dev_get_priv(bus);
164 switch (mode & (SPI_CPOL | SPI_CPHA)) {
169 pspi_mode = PSPI_CTL1_SCM;
172 pspi_mode = PSPI_CTL1_SCIDL;
175 pspi_mode = PSPI_CTL1_SCIDL | PSPI_CTL1_SCM;
181 val = readw(priv->base + PSPI_CTL1);
182 val &= ~(PSPI_CTL1_SCIDL | PSPI_CTL1_SCM);
184 writew(val, priv->base + PSPI_CTL1);
189 static int npcm_pspi_probe(struct udevice *bus)
191 struct npcm_pspi_priv *priv = dev_get_priv(bus);
192 int node = dev_of_offset(bus);
195 ret = clk_get_by_index(bus, 0, &priv->clk);
199 priv->base = dev_read_addr_ptr(bus);
200 priv->max_hz = dev_read_u32_default(bus, "spi-max-frequency", 0);
201 gpio_request_by_name_nodev(offset_to_ofnode(node), "cs-gpios", 0,
202 &priv->cs_gpio, GPIOD_IS_OUT);
207 static const struct dm_spi_ops npcm_pspi_ops = {
208 .xfer = npcm_pspi_xfer,
209 .set_speed = npcm_pspi_set_speed,
210 .set_mode = npcm_pspi_set_mode,
213 static const struct udevice_id npcm_pspi_ids[] = {
214 { .compatible = "nuvoton,npcm845-pspi"},
215 { .compatible = "nuvoton,npcm750-pspi"},
219 U_BOOT_DRIVER(npcm_pspi) = {
222 .of_match = npcm_pspi_ids,
223 .ops = &npcm_pspi_ops,
224 .priv_auto = sizeof(struct npcm_pspi_priv),
225 .probe = npcm_pspi_probe,