1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun // Copyright (c) 2018 Nuvoton Technology corporation.
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun #include <linux/kernel.h>
5*4882a593Smuzhiyun #include <linux/bitfield.h>
6*4882a593Smuzhiyun #include <linux/bitops.h>
7*4882a593Smuzhiyun #include <linux/clk.h>
8*4882a593Smuzhiyun #include <linux/interrupt.h>
9*4882a593Smuzhiyun #include <linux/io.h>
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/platform_device.h>
12*4882a593Smuzhiyun #include <linux/spi/spi.h>
13*4882a593Smuzhiyun #include <linux/reset.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include <asm/unaligned.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #include <linux/regmap.h>
18*4882a593Smuzhiyun #include <linux/mfd/syscon.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun struct npcm_pspi {
21*4882a593Smuzhiyun struct completion xfer_done;
22*4882a593Smuzhiyun struct reset_control *reset;
23*4882a593Smuzhiyun struct spi_master *master;
24*4882a593Smuzhiyun unsigned int tx_bytes;
25*4882a593Smuzhiyun unsigned int rx_bytes;
26*4882a593Smuzhiyun void __iomem *base;
27*4882a593Smuzhiyun bool is_save_param;
28*4882a593Smuzhiyun u8 bits_per_word;
29*4882a593Smuzhiyun const u8 *tx_buf;
30*4882a593Smuzhiyun struct clk *clk;
31*4882a593Smuzhiyun u32 speed_hz;
32*4882a593Smuzhiyun u8 *rx_buf;
33*4882a593Smuzhiyun u16 mode;
34*4882a593Smuzhiyun u32 id;
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #define DRIVER_NAME "npcm-pspi"
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun #define NPCM_PSPI_DATA 0x00
40*4882a593Smuzhiyun #define NPCM_PSPI_CTL1 0x02
41*4882a593Smuzhiyun #define NPCM_PSPI_STAT 0x04
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun /* definitions for control and status register */
44*4882a593Smuzhiyun #define NPCM_PSPI_CTL1_SPIEN BIT(0)
45*4882a593Smuzhiyun #define NPCM_PSPI_CTL1_MOD BIT(2)
46*4882a593Smuzhiyun #define NPCM_PSPI_CTL1_EIR BIT(5)
47*4882a593Smuzhiyun #define NPCM_PSPI_CTL1_EIW BIT(6)
48*4882a593Smuzhiyun #define NPCM_PSPI_CTL1_SCM BIT(7)
49*4882a593Smuzhiyun #define NPCM_PSPI_CTL1_SCIDL BIT(8)
50*4882a593Smuzhiyun #define NPCM_PSPI_CTL1_SCDV6_0 GENMASK(15, 9)
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun #define NPCM_PSPI_STAT_BSY BIT(0)
53*4882a593Smuzhiyun #define NPCM_PSPI_STAT_RBF BIT(1)
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun /* general definitions */
56*4882a593Smuzhiyun #define NPCM_PSPI_TIMEOUT_MS 2000
57*4882a593Smuzhiyun #define NPCM_PSPI_MAX_CLK_DIVIDER 256
58*4882a593Smuzhiyun #define NPCM_PSPI_MIN_CLK_DIVIDER 4
59*4882a593Smuzhiyun #define NPCM_PSPI_DEFAULT_CLK 25000000
60*4882a593Smuzhiyun
bytes_per_word(unsigned int bits)61*4882a593Smuzhiyun static inline unsigned int bytes_per_word(unsigned int bits)
62*4882a593Smuzhiyun {
63*4882a593Smuzhiyun return bits <= 8 ? 1 : 2;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun
npcm_pspi_irq_enable(struct npcm_pspi * priv,u16 mask)66*4882a593Smuzhiyun static inline void npcm_pspi_irq_enable(struct npcm_pspi *priv, u16 mask)
67*4882a593Smuzhiyun {
68*4882a593Smuzhiyun u16 val;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun val = ioread16(priv->base + NPCM_PSPI_CTL1);
71*4882a593Smuzhiyun val |= mask;
72*4882a593Smuzhiyun iowrite16(val, priv->base + NPCM_PSPI_CTL1);
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun
npcm_pspi_irq_disable(struct npcm_pspi * priv,u16 mask)75*4882a593Smuzhiyun static inline void npcm_pspi_irq_disable(struct npcm_pspi *priv, u16 mask)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun u16 val;
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun val = ioread16(priv->base + NPCM_PSPI_CTL1);
80*4882a593Smuzhiyun val &= ~mask;
81*4882a593Smuzhiyun iowrite16(val, priv->base + NPCM_PSPI_CTL1);
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
npcm_pspi_enable(struct npcm_pspi * priv)84*4882a593Smuzhiyun static inline void npcm_pspi_enable(struct npcm_pspi *priv)
85*4882a593Smuzhiyun {
86*4882a593Smuzhiyun u16 val;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun val = ioread16(priv->base + NPCM_PSPI_CTL1);
89*4882a593Smuzhiyun val |= NPCM_PSPI_CTL1_SPIEN;
90*4882a593Smuzhiyun iowrite16(val, priv->base + NPCM_PSPI_CTL1);
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
npcm_pspi_disable(struct npcm_pspi * priv)93*4882a593Smuzhiyun static inline void npcm_pspi_disable(struct npcm_pspi *priv)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun u16 val;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun val = ioread16(priv->base + NPCM_PSPI_CTL1);
98*4882a593Smuzhiyun val &= ~NPCM_PSPI_CTL1_SPIEN;
99*4882a593Smuzhiyun iowrite16(val, priv->base + NPCM_PSPI_CTL1);
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
npcm_pspi_set_mode(struct spi_device * spi)102*4882a593Smuzhiyun static void npcm_pspi_set_mode(struct spi_device *spi)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun struct npcm_pspi *priv = spi_master_get_devdata(spi->master);
105*4882a593Smuzhiyun u16 regtemp;
106*4882a593Smuzhiyun u16 mode_val;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun switch (spi->mode & (SPI_CPOL | SPI_CPHA)) {
109*4882a593Smuzhiyun case SPI_MODE_0:
110*4882a593Smuzhiyun mode_val = 0;
111*4882a593Smuzhiyun break;
112*4882a593Smuzhiyun case SPI_MODE_1:
113*4882a593Smuzhiyun mode_val = NPCM_PSPI_CTL1_SCIDL;
114*4882a593Smuzhiyun break;
115*4882a593Smuzhiyun case SPI_MODE_2:
116*4882a593Smuzhiyun mode_val = NPCM_PSPI_CTL1_SCM;
117*4882a593Smuzhiyun break;
118*4882a593Smuzhiyun case SPI_MODE_3:
119*4882a593Smuzhiyun mode_val = NPCM_PSPI_CTL1_SCIDL | NPCM_PSPI_CTL1_SCM;
120*4882a593Smuzhiyun break;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun regtemp = ioread16(priv->base + NPCM_PSPI_CTL1);
124*4882a593Smuzhiyun regtemp &= ~(NPCM_PSPI_CTL1_SCM | NPCM_PSPI_CTL1_SCIDL);
125*4882a593Smuzhiyun iowrite16(regtemp | mode_val, priv->base + NPCM_PSPI_CTL1);
126*4882a593Smuzhiyun }
127*4882a593Smuzhiyun
npcm_pspi_set_transfer_size(struct npcm_pspi * priv,int size)128*4882a593Smuzhiyun static void npcm_pspi_set_transfer_size(struct npcm_pspi *priv, int size)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun u16 regtemp;
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun regtemp = ioread16(NPCM_PSPI_CTL1 + priv->base);
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun switch (size) {
135*4882a593Smuzhiyun case 8:
136*4882a593Smuzhiyun regtemp &= ~NPCM_PSPI_CTL1_MOD;
137*4882a593Smuzhiyun break;
138*4882a593Smuzhiyun case 16:
139*4882a593Smuzhiyun regtemp |= NPCM_PSPI_CTL1_MOD;
140*4882a593Smuzhiyun break;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun iowrite16(regtemp, NPCM_PSPI_CTL1 + priv->base);
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
npcm_pspi_set_baudrate(struct npcm_pspi * priv,unsigned int speed)146*4882a593Smuzhiyun static void npcm_pspi_set_baudrate(struct npcm_pspi *priv, unsigned int speed)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun u32 ckdiv;
149*4882a593Smuzhiyun u16 regtemp;
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun /* the supported rates are numbers from 4 to 256. */
152*4882a593Smuzhiyun ckdiv = DIV_ROUND_CLOSEST(clk_get_rate(priv->clk), (2 * speed)) - 1;
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun regtemp = ioread16(NPCM_PSPI_CTL1 + priv->base);
155*4882a593Smuzhiyun regtemp &= ~NPCM_PSPI_CTL1_SCDV6_0;
156*4882a593Smuzhiyun iowrite16(regtemp | (ckdiv << 9), NPCM_PSPI_CTL1 + priv->base);
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun
npcm_pspi_setup_transfer(struct spi_device * spi,struct spi_transfer * t)159*4882a593Smuzhiyun static void npcm_pspi_setup_transfer(struct spi_device *spi,
160*4882a593Smuzhiyun struct spi_transfer *t)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun struct npcm_pspi *priv = spi_master_get_devdata(spi->master);
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun priv->tx_buf = t->tx_buf;
165*4882a593Smuzhiyun priv->rx_buf = t->rx_buf;
166*4882a593Smuzhiyun priv->tx_bytes = t->len;
167*4882a593Smuzhiyun priv->rx_bytes = t->len;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun if (!priv->is_save_param || priv->mode != spi->mode) {
170*4882a593Smuzhiyun npcm_pspi_set_mode(spi);
171*4882a593Smuzhiyun priv->mode = spi->mode;
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun /*
175*4882a593Smuzhiyun * If transfer is even length, and 8 bits per word transfer,
176*4882a593Smuzhiyun * then implement 16 bits-per-word transfer.
177*4882a593Smuzhiyun */
178*4882a593Smuzhiyun if (priv->bits_per_word == 8 && !(t->len & 0x1))
179*4882a593Smuzhiyun t->bits_per_word = 16;
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun if (!priv->is_save_param || priv->bits_per_word != t->bits_per_word) {
182*4882a593Smuzhiyun npcm_pspi_set_transfer_size(priv, t->bits_per_word);
183*4882a593Smuzhiyun priv->bits_per_word = t->bits_per_word;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun if (!priv->is_save_param || priv->speed_hz != t->speed_hz) {
187*4882a593Smuzhiyun npcm_pspi_set_baudrate(priv, t->speed_hz);
188*4882a593Smuzhiyun priv->speed_hz = t->speed_hz;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun if (!priv->is_save_param)
192*4882a593Smuzhiyun priv->is_save_param = true;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
npcm_pspi_send(struct npcm_pspi * priv)195*4882a593Smuzhiyun static void npcm_pspi_send(struct npcm_pspi *priv)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun int wsize;
198*4882a593Smuzhiyun u16 val;
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun wsize = min(bytes_per_word(priv->bits_per_word), priv->tx_bytes);
201*4882a593Smuzhiyun priv->tx_bytes -= wsize;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun if (!priv->tx_buf)
204*4882a593Smuzhiyun return;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun switch (wsize) {
207*4882a593Smuzhiyun case 1:
208*4882a593Smuzhiyun val = *priv->tx_buf++;
209*4882a593Smuzhiyun iowrite8(val, NPCM_PSPI_DATA + priv->base);
210*4882a593Smuzhiyun break;
211*4882a593Smuzhiyun case 2:
212*4882a593Smuzhiyun val = *priv->tx_buf++;
213*4882a593Smuzhiyun val = *priv->tx_buf++ | (val << 8);
214*4882a593Smuzhiyun iowrite16(val, NPCM_PSPI_DATA + priv->base);
215*4882a593Smuzhiyun break;
216*4882a593Smuzhiyun default:
217*4882a593Smuzhiyun WARN_ON_ONCE(1);
218*4882a593Smuzhiyun return;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
npcm_pspi_recv(struct npcm_pspi * priv)222*4882a593Smuzhiyun static void npcm_pspi_recv(struct npcm_pspi *priv)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun int rsize;
225*4882a593Smuzhiyun u16 val;
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun rsize = min(bytes_per_word(priv->bits_per_word), priv->rx_bytes);
228*4882a593Smuzhiyun priv->rx_bytes -= rsize;
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun if (!priv->rx_buf)
231*4882a593Smuzhiyun return;
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun switch (rsize) {
234*4882a593Smuzhiyun case 1:
235*4882a593Smuzhiyun *priv->rx_buf++ = ioread8(priv->base + NPCM_PSPI_DATA);
236*4882a593Smuzhiyun break;
237*4882a593Smuzhiyun case 2:
238*4882a593Smuzhiyun val = ioread16(priv->base + NPCM_PSPI_DATA);
239*4882a593Smuzhiyun *priv->rx_buf++ = (val >> 8);
240*4882a593Smuzhiyun *priv->rx_buf++ = val & 0xff;
241*4882a593Smuzhiyun break;
242*4882a593Smuzhiyun default:
243*4882a593Smuzhiyun WARN_ON_ONCE(1);
244*4882a593Smuzhiyun return;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun
npcm_pspi_transfer_one(struct spi_master * master,struct spi_device * spi,struct spi_transfer * t)248*4882a593Smuzhiyun static int npcm_pspi_transfer_one(struct spi_master *master,
249*4882a593Smuzhiyun struct spi_device *spi,
250*4882a593Smuzhiyun struct spi_transfer *t)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun struct npcm_pspi *priv = spi_master_get_devdata(master);
253*4882a593Smuzhiyun int status;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun npcm_pspi_setup_transfer(spi, t);
256*4882a593Smuzhiyun reinit_completion(&priv->xfer_done);
257*4882a593Smuzhiyun npcm_pspi_enable(priv);
258*4882a593Smuzhiyun status = wait_for_completion_timeout(&priv->xfer_done,
259*4882a593Smuzhiyun msecs_to_jiffies
260*4882a593Smuzhiyun (NPCM_PSPI_TIMEOUT_MS));
261*4882a593Smuzhiyun if (status == 0) {
262*4882a593Smuzhiyun npcm_pspi_disable(priv);
263*4882a593Smuzhiyun return -ETIMEDOUT;
264*4882a593Smuzhiyun }
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun return 0;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun
npcm_pspi_prepare_transfer_hardware(struct spi_master * master)269*4882a593Smuzhiyun static int npcm_pspi_prepare_transfer_hardware(struct spi_master *master)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun struct npcm_pspi *priv = spi_master_get_devdata(master);
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun npcm_pspi_irq_enable(priv, NPCM_PSPI_CTL1_EIR | NPCM_PSPI_CTL1_EIW);
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun return 0;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
npcm_pspi_unprepare_transfer_hardware(struct spi_master * master)278*4882a593Smuzhiyun static int npcm_pspi_unprepare_transfer_hardware(struct spi_master *master)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun struct npcm_pspi *priv = spi_master_get_devdata(master);
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun npcm_pspi_irq_disable(priv, NPCM_PSPI_CTL1_EIR | NPCM_PSPI_CTL1_EIW);
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun return 0;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun
npcm_pspi_reset_hw(struct npcm_pspi * priv)287*4882a593Smuzhiyun static void npcm_pspi_reset_hw(struct npcm_pspi *priv)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun reset_control_assert(priv->reset);
290*4882a593Smuzhiyun udelay(5);
291*4882a593Smuzhiyun reset_control_deassert(priv->reset);
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun
npcm_pspi_handler(int irq,void * dev_id)294*4882a593Smuzhiyun static irqreturn_t npcm_pspi_handler(int irq, void *dev_id)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun struct npcm_pspi *priv = dev_id;
297*4882a593Smuzhiyun u8 stat;
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun stat = ioread8(priv->base + NPCM_PSPI_STAT);
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun if (!priv->tx_buf && !priv->rx_buf)
302*4882a593Smuzhiyun return IRQ_NONE;
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun if (priv->tx_buf) {
305*4882a593Smuzhiyun if (stat & NPCM_PSPI_STAT_RBF) {
306*4882a593Smuzhiyun ioread8(NPCM_PSPI_DATA + priv->base);
307*4882a593Smuzhiyun if (priv->tx_bytes == 0) {
308*4882a593Smuzhiyun npcm_pspi_disable(priv);
309*4882a593Smuzhiyun complete(&priv->xfer_done);
310*4882a593Smuzhiyun return IRQ_HANDLED;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun if ((stat & NPCM_PSPI_STAT_BSY) == 0)
315*4882a593Smuzhiyun if (priv->tx_bytes)
316*4882a593Smuzhiyun npcm_pspi_send(priv);
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun if (priv->rx_buf) {
320*4882a593Smuzhiyun if (stat & NPCM_PSPI_STAT_RBF) {
321*4882a593Smuzhiyun if (!priv->rx_bytes)
322*4882a593Smuzhiyun return IRQ_NONE;
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun npcm_pspi_recv(priv);
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun if (!priv->rx_bytes) {
327*4882a593Smuzhiyun npcm_pspi_disable(priv);
328*4882a593Smuzhiyun complete(&priv->xfer_done);
329*4882a593Smuzhiyun return IRQ_HANDLED;
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun if (((stat & NPCM_PSPI_STAT_BSY) == 0) && !priv->tx_buf)
334*4882a593Smuzhiyun iowrite8(0x0, NPCM_PSPI_DATA + priv->base);
335*4882a593Smuzhiyun }
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun return IRQ_HANDLED;
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun
npcm_pspi_probe(struct platform_device * pdev)340*4882a593Smuzhiyun static int npcm_pspi_probe(struct platform_device *pdev)
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun struct npcm_pspi *priv;
343*4882a593Smuzhiyun struct spi_master *master;
344*4882a593Smuzhiyun unsigned long clk_hz;
345*4882a593Smuzhiyun int irq;
346*4882a593Smuzhiyun int ret;
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun master = spi_alloc_master(&pdev->dev, sizeof(*priv));
349*4882a593Smuzhiyun if (!master)
350*4882a593Smuzhiyun return -ENOMEM;
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun platform_set_drvdata(pdev, master);
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun priv = spi_master_get_devdata(master);
355*4882a593Smuzhiyun priv->master = master;
356*4882a593Smuzhiyun priv->is_save_param = false;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun priv->base = devm_platform_ioremap_resource(pdev, 0);
359*4882a593Smuzhiyun if (IS_ERR(priv->base)) {
360*4882a593Smuzhiyun ret = PTR_ERR(priv->base);
361*4882a593Smuzhiyun goto out_master_put;
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun priv->clk = devm_clk_get(&pdev->dev, NULL);
365*4882a593Smuzhiyun if (IS_ERR(priv->clk)) {
366*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to get clock\n");
367*4882a593Smuzhiyun ret = PTR_ERR(priv->clk);
368*4882a593Smuzhiyun goto out_master_put;
369*4882a593Smuzhiyun }
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun ret = clk_prepare_enable(priv->clk);
372*4882a593Smuzhiyun if (ret)
373*4882a593Smuzhiyun goto out_master_put;
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun irq = platform_get_irq(pdev, 0);
376*4882a593Smuzhiyun if (irq < 0) {
377*4882a593Smuzhiyun ret = irq;
378*4882a593Smuzhiyun goto out_disable_clk;
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun priv->reset = devm_reset_control_get(&pdev->dev, NULL);
382*4882a593Smuzhiyun if (IS_ERR(priv->reset)) {
383*4882a593Smuzhiyun ret = PTR_ERR(priv->reset);
384*4882a593Smuzhiyun goto out_disable_clk;
385*4882a593Smuzhiyun }
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun /* reset SPI-HW block */
388*4882a593Smuzhiyun npcm_pspi_reset_hw(priv);
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun ret = devm_request_irq(&pdev->dev, irq, npcm_pspi_handler, 0,
391*4882a593Smuzhiyun "npcm-pspi", priv);
392*4882a593Smuzhiyun if (ret) {
393*4882a593Smuzhiyun dev_err(&pdev->dev, "failed to request IRQ\n");
394*4882a593Smuzhiyun goto out_disable_clk;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun
397*4882a593Smuzhiyun init_completion(&priv->xfer_done);
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun clk_hz = clk_get_rate(priv->clk);
400*4882a593Smuzhiyun
401*4882a593Smuzhiyun master->max_speed_hz = DIV_ROUND_UP(clk_hz, NPCM_PSPI_MIN_CLK_DIVIDER);
402*4882a593Smuzhiyun master->min_speed_hz = DIV_ROUND_UP(clk_hz, NPCM_PSPI_MAX_CLK_DIVIDER);
403*4882a593Smuzhiyun master->mode_bits = SPI_CPHA | SPI_CPOL;
404*4882a593Smuzhiyun master->dev.of_node = pdev->dev.of_node;
405*4882a593Smuzhiyun master->bus_num = -1;
406*4882a593Smuzhiyun master->bits_per_word_mask = SPI_BPW_MASK(8) | SPI_BPW_MASK(16);
407*4882a593Smuzhiyun master->transfer_one = npcm_pspi_transfer_one;
408*4882a593Smuzhiyun master->prepare_transfer_hardware =
409*4882a593Smuzhiyun npcm_pspi_prepare_transfer_hardware;
410*4882a593Smuzhiyun master->unprepare_transfer_hardware =
411*4882a593Smuzhiyun npcm_pspi_unprepare_transfer_hardware;
412*4882a593Smuzhiyun master->use_gpio_descriptors = true;
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun /* set to default clock rate */
415*4882a593Smuzhiyun npcm_pspi_set_baudrate(priv, NPCM_PSPI_DEFAULT_CLK);
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun ret = devm_spi_register_master(&pdev->dev, master);
418*4882a593Smuzhiyun if (ret)
419*4882a593Smuzhiyun goto out_disable_clk;
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun pr_info("NPCM Peripheral SPI %d probed\n", master->bus_num);
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun return 0;
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun out_disable_clk:
426*4882a593Smuzhiyun clk_disable_unprepare(priv->clk);
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun out_master_put:
429*4882a593Smuzhiyun spi_master_put(master);
430*4882a593Smuzhiyun return ret;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun
npcm_pspi_remove(struct platform_device * pdev)433*4882a593Smuzhiyun static int npcm_pspi_remove(struct platform_device *pdev)
434*4882a593Smuzhiyun {
435*4882a593Smuzhiyun struct spi_master *master = platform_get_drvdata(pdev);
436*4882a593Smuzhiyun struct npcm_pspi *priv = spi_master_get_devdata(master);
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun npcm_pspi_reset_hw(priv);
439*4882a593Smuzhiyun clk_disable_unprepare(priv->clk);
440*4882a593Smuzhiyun
441*4882a593Smuzhiyun return 0;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun static const struct of_device_id npcm_pspi_match[] = {
445*4882a593Smuzhiyun { .compatible = "nuvoton,npcm750-pspi", .data = NULL },
446*4882a593Smuzhiyun {}
447*4882a593Smuzhiyun };
448*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, npcm_pspi_match);
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun static struct platform_driver npcm_pspi_driver = {
451*4882a593Smuzhiyun .driver = {
452*4882a593Smuzhiyun .name = DRIVER_NAME,
453*4882a593Smuzhiyun .of_match_table = npcm_pspi_match,
454*4882a593Smuzhiyun },
455*4882a593Smuzhiyun .probe = npcm_pspi_probe,
456*4882a593Smuzhiyun .remove = npcm_pspi_remove,
457*4882a593Smuzhiyun };
458*4882a593Smuzhiyun module_platform_driver(npcm_pspi_driver);
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun MODULE_DESCRIPTION("NPCM peripheral SPI Controller driver");
461*4882a593Smuzhiyun MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>");
462*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
463*4882a593Smuzhiyun
464