xref: /OK3568_Linux_fs/kernel/drivers/spi/spi-npcm-pspi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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