xref: /openbmc/u-boot/drivers/spi/spi-sunxi.c (revision 606b239a)
1*a51cd54eSJagan Teki /*
2*a51cd54eSJagan Teki  * (C) Copyright 2017 Whitebox Systems / Northend Systems B.V.
3*a51cd54eSJagan Teki  * S.J.R. van Schaik <stephan@whiteboxsystems.nl>
4*a51cd54eSJagan Teki  * M.B.W. Wajer <merlijn@whiteboxsystems.nl>
5*a51cd54eSJagan Teki  *
6*a51cd54eSJagan Teki  * (C) Copyright 2017 Olimex Ltd..
7*a51cd54eSJagan Teki  * Stefan Mavrodiev <stefan@olimex.com>
8*a51cd54eSJagan Teki  *
9*a51cd54eSJagan Teki  * Based on linux spi driver. Original copyright follows:
10*a51cd54eSJagan Teki  * linux/drivers/spi/spi-sun4i.c
11*a51cd54eSJagan Teki  *
12*a51cd54eSJagan Teki  * Copyright (C) 2012 - 2014 Allwinner Tech
13*a51cd54eSJagan Teki  * Pan Nan <pannan@allwinnertech.com>
14*a51cd54eSJagan Teki  *
15*a51cd54eSJagan Teki  * Copyright (C) 2014 Maxime Ripard
16*a51cd54eSJagan Teki  * Maxime Ripard <maxime.ripard@free-electrons.com>
17*a51cd54eSJagan Teki  *
18*a51cd54eSJagan Teki  * SPDX-License-Identifier:	GPL-2.0+
19*a51cd54eSJagan Teki  */
20*a51cd54eSJagan Teki 
21*a51cd54eSJagan Teki #include <common.h>
22*a51cd54eSJagan Teki #include <clk.h>
23*a51cd54eSJagan Teki #include <dm.h>
24*a51cd54eSJagan Teki #include <spi.h>
25*a51cd54eSJagan Teki #include <errno.h>
26*a51cd54eSJagan Teki #include <fdt_support.h>
27*a51cd54eSJagan Teki #include <reset.h>
28*a51cd54eSJagan Teki #include <wait_bit.h>
29*a51cd54eSJagan Teki 
30*a51cd54eSJagan Teki #include <asm/bitops.h>
31*a51cd54eSJagan Teki #include <asm/gpio.h>
32*a51cd54eSJagan Teki #include <asm/io.h>
33*a51cd54eSJagan Teki 
34*a51cd54eSJagan Teki #include <linux/iopoll.h>
35*a51cd54eSJagan Teki 
36*a51cd54eSJagan Teki DECLARE_GLOBAL_DATA_PTR;
37*a51cd54eSJagan Teki 
38*a51cd54eSJagan Teki /* sun4i spi registers */
39*a51cd54eSJagan Teki #define SUN4I_RXDATA_REG		0x00
40*a51cd54eSJagan Teki #define SUN4I_TXDATA_REG		0x04
41*a51cd54eSJagan Teki #define SUN4I_CTL_REG			0x08
42*a51cd54eSJagan Teki #define SUN4I_CLK_CTL_REG		0x1c
43*a51cd54eSJagan Teki #define SUN4I_BURST_CNT_REG		0x20
44*a51cd54eSJagan Teki #define SUN4I_XMIT_CNT_REG		0x24
45*a51cd54eSJagan Teki #define SUN4I_FIFO_STA_REG		0x28
46*a51cd54eSJagan Teki 
47*a51cd54eSJagan Teki /* sun6i spi registers */
48*a51cd54eSJagan Teki #define SUN6I_GBL_CTL_REG		0x04
49*a51cd54eSJagan Teki #define SUN6I_TFR_CTL_REG		0x08
50*a51cd54eSJagan Teki #define SUN6I_FIFO_CTL_REG		0x18
51*a51cd54eSJagan Teki #define SUN6I_FIFO_STA_REG		0x1c
52*a51cd54eSJagan Teki #define SUN6I_CLK_CTL_REG		0x24
53*a51cd54eSJagan Teki #define SUN6I_BURST_CNT_REG		0x30
54*a51cd54eSJagan Teki #define SUN6I_XMIT_CNT_REG		0x34
55*a51cd54eSJagan Teki #define SUN6I_BURST_CTL_REG		0x38
56*a51cd54eSJagan Teki #define SUN6I_TXDATA_REG		0x200
57*a51cd54eSJagan Teki #define SUN6I_RXDATA_REG		0x300
58*a51cd54eSJagan Teki 
59*a51cd54eSJagan Teki /* sun spi bits */
60*a51cd54eSJagan Teki #define SUN4I_CTL_ENABLE		BIT(0)
61*a51cd54eSJagan Teki #define SUN4I_CTL_MASTER		BIT(1)
62*a51cd54eSJagan Teki #define SUN4I_CLK_CTL_CDR2_MASK		0xff
63*a51cd54eSJagan Teki #define SUN4I_CLK_CTL_CDR2(div)		((div) & SUN4I_CLK_CTL_CDR2_MASK)
64*a51cd54eSJagan Teki #define SUN4I_CLK_CTL_CDR1_MASK		0xf
65*a51cd54eSJagan Teki #define SUN4I_CLK_CTL_CDR1(div)		(((div) & SUN4I_CLK_CTL_CDR1_MASK) << 8)
66*a51cd54eSJagan Teki #define SUN4I_CLK_CTL_DRS		BIT(12)
67*a51cd54eSJagan Teki #define SUN4I_MAX_XFER_SIZE		0xffffff
68*a51cd54eSJagan Teki #define SUN4I_BURST_CNT(cnt)		((cnt) & SUN4I_MAX_XFER_SIZE)
69*a51cd54eSJagan Teki #define SUN4I_XMIT_CNT(cnt)		((cnt) & SUN4I_MAX_XFER_SIZE)
70*a51cd54eSJagan Teki #define SUN4I_FIFO_STA_RF_CNT_BITS	0
71*a51cd54eSJagan Teki 
72*a51cd54eSJagan Teki #define SUN4I_SPI_MAX_RATE		24000000
73*a51cd54eSJagan Teki #define SUN4I_SPI_MIN_RATE		3000
74*a51cd54eSJagan Teki #define SUN4I_SPI_DEFAULT_RATE		1000000
75*a51cd54eSJagan Teki #define SUN4I_SPI_TIMEOUT_US		1000000
76*a51cd54eSJagan Teki 
77*a51cd54eSJagan Teki #define SPI_REG(priv, reg)		((priv)->base + \
78*a51cd54eSJagan Teki 					(priv)->variant->regs[reg])
79*a51cd54eSJagan Teki #define SPI_BIT(priv, bit)		((priv)->variant->bits[bit])
80*a51cd54eSJagan Teki #define SPI_CS(priv, cs)		(((cs) << SPI_BIT(priv, SPI_TCR_CS_SEL)) & \
81*a51cd54eSJagan Teki 					SPI_BIT(priv, SPI_TCR_CS_MASK))
82*a51cd54eSJagan Teki 
83*a51cd54eSJagan Teki /* sun spi register set */
84*a51cd54eSJagan Teki enum sun4i_spi_regs {
85*a51cd54eSJagan Teki 	SPI_GCR,
86*a51cd54eSJagan Teki 	SPI_TCR,
87*a51cd54eSJagan Teki 	SPI_FCR,
88*a51cd54eSJagan Teki 	SPI_FSR,
89*a51cd54eSJagan Teki 	SPI_CCR,
90*a51cd54eSJagan Teki 	SPI_BC,
91*a51cd54eSJagan Teki 	SPI_TC,
92*a51cd54eSJagan Teki 	SPI_BCTL,
93*a51cd54eSJagan Teki 	SPI_TXD,
94*a51cd54eSJagan Teki 	SPI_RXD,
95*a51cd54eSJagan Teki };
96*a51cd54eSJagan Teki 
97*a51cd54eSJagan Teki /* sun spi register bits */
98*a51cd54eSJagan Teki enum sun4i_spi_bits {
99*a51cd54eSJagan Teki 	SPI_GCR_TP,
100*a51cd54eSJagan Teki 	SPI_GCR_SRST,
101*a51cd54eSJagan Teki 	SPI_TCR_CPHA,
102*a51cd54eSJagan Teki 	SPI_TCR_CPOL,
103*a51cd54eSJagan Teki 	SPI_TCR_CS_ACTIVE_LOW,
104*a51cd54eSJagan Teki 	SPI_TCR_CS_SEL,
105*a51cd54eSJagan Teki 	SPI_TCR_CS_MASK,
106*a51cd54eSJagan Teki 	SPI_TCR_XCH,
107*a51cd54eSJagan Teki 	SPI_TCR_CS_MANUAL,
108*a51cd54eSJagan Teki 	SPI_TCR_CS_LEVEL,
109*a51cd54eSJagan Teki 	SPI_FCR_TF_RST,
110*a51cd54eSJagan Teki 	SPI_FCR_RF_RST,
111*a51cd54eSJagan Teki 	SPI_FSR_RF_CNT_MASK,
112*a51cd54eSJagan Teki };
113*a51cd54eSJagan Teki 
114*a51cd54eSJagan Teki struct sun4i_spi_variant {
115*a51cd54eSJagan Teki 	const unsigned long *regs;
116*a51cd54eSJagan Teki 	const u32 *bits;
117*a51cd54eSJagan Teki 	u32 fifo_depth;
118*a51cd54eSJagan Teki 	bool has_soft_reset;
119*a51cd54eSJagan Teki 	bool has_burst_ctl;
120*a51cd54eSJagan Teki };
121*a51cd54eSJagan Teki 
122*a51cd54eSJagan Teki struct sun4i_spi_platdata {
123*a51cd54eSJagan Teki 	struct sun4i_spi_variant *variant;
124*a51cd54eSJagan Teki 	u32 base;
125*a51cd54eSJagan Teki 	u32 max_hz;
126*a51cd54eSJagan Teki };
127*a51cd54eSJagan Teki 
128*a51cd54eSJagan Teki struct sun4i_spi_priv {
129*a51cd54eSJagan Teki 	struct sun4i_spi_variant *variant;
130*a51cd54eSJagan Teki 	struct clk clk_ahb, clk_mod;
131*a51cd54eSJagan Teki 	struct reset_ctl reset;
132*a51cd54eSJagan Teki 	u32 base;
133*a51cd54eSJagan Teki 	u32 freq;
134*a51cd54eSJagan Teki 	u32 mode;
135*a51cd54eSJagan Teki 
136*a51cd54eSJagan Teki 	const u8 *tx_buf;
137*a51cd54eSJagan Teki 	u8 *rx_buf;
138*a51cd54eSJagan Teki };
139*a51cd54eSJagan Teki 
sun4i_spi_drain_fifo(struct sun4i_spi_priv * priv,int len)140*a51cd54eSJagan Teki static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len)
141*a51cd54eSJagan Teki {
142*a51cd54eSJagan Teki 	u8 byte;
143*a51cd54eSJagan Teki 
144*a51cd54eSJagan Teki 	while (len--) {
145*a51cd54eSJagan Teki 		byte = readb(SPI_REG(priv, SPI_RXD));
146*a51cd54eSJagan Teki 		if (priv->rx_buf)
147*a51cd54eSJagan Teki 			*priv->rx_buf++ = byte;
148*a51cd54eSJagan Teki 	}
149*a51cd54eSJagan Teki }
150*a51cd54eSJagan Teki 
sun4i_spi_fill_fifo(struct sun4i_spi_priv * priv,int len)151*a51cd54eSJagan Teki static inline void sun4i_spi_fill_fifo(struct sun4i_spi_priv *priv, int len)
152*a51cd54eSJagan Teki {
153*a51cd54eSJagan Teki 	u8 byte;
154*a51cd54eSJagan Teki 
155*a51cd54eSJagan Teki 	while (len--) {
156*a51cd54eSJagan Teki 		byte = priv->tx_buf ? *priv->tx_buf++ : 0;
157*a51cd54eSJagan Teki 		writeb(byte, SPI_REG(priv, SPI_TXD));
158*a51cd54eSJagan Teki 	}
159*a51cd54eSJagan Teki }
160*a51cd54eSJagan Teki 
sun4i_spi_set_cs(struct udevice * bus,u8 cs,bool enable)161*a51cd54eSJagan Teki static void sun4i_spi_set_cs(struct udevice *bus, u8 cs, bool enable)
162*a51cd54eSJagan Teki {
163*a51cd54eSJagan Teki 	struct sun4i_spi_priv *priv = dev_get_priv(bus);
164*a51cd54eSJagan Teki 	u32 reg;
165*a51cd54eSJagan Teki 
166*a51cd54eSJagan Teki 	reg = readl(SPI_REG(priv, SPI_TCR));
167*a51cd54eSJagan Teki 
168*a51cd54eSJagan Teki 	reg &= ~SPI_BIT(priv, SPI_TCR_CS_MASK);
169*a51cd54eSJagan Teki 	reg |= SPI_CS(priv, cs);
170*a51cd54eSJagan Teki 
171*a51cd54eSJagan Teki 	if (enable)
172*a51cd54eSJagan Teki 		reg &= ~SPI_BIT(priv, SPI_TCR_CS_LEVEL);
173*a51cd54eSJagan Teki 	else
174*a51cd54eSJagan Teki 		reg |= SPI_BIT(priv, SPI_TCR_CS_LEVEL);
175*a51cd54eSJagan Teki 
176*a51cd54eSJagan Teki 	writel(reg, SPI_REG(priv, SPI_TCR));
177*a51cd54eSJagan Teki }
178*a51cd54eSJagan Teki 
sun4i_spi_parse_pins(struct udevice * dev)179*a51cd54eSJagan Teki static int sun4i_spi_parse_pins(struct udevice *dev)
180*a51cd54eSJagan Teki {
181*a51cd54eSJagan Teki 	const void *fdt = gd->fdt_blob;
182*a51cd54eSJagan Teki 	const char *pin_name;
183*a51cd54eSJagan Teki 	const fdt32_t *list;
184*a51cd54eSJagan Teki 	u32 phandle;
185*a51cd54eSJagan Teki 	int drive, pull = 0, pin, i;
186*a51cd54eSJagan Teki 	int offset;
187*a51cd54eSJagan Teki 	int size;
188*a51cd54eSJagan Teki 
189*a51cd54eSJagan Teki 	list = fdt_getprop(fdt, dev_of_offset(dev), "pinctrl-0", &size);
190*a51cd54eSJagan Teki 	if (!list) {
191*a51cd54eSJagan Teki 		printf("WARNING: sun4i_spi: cannot find pinctrl-0 node\n");
192*a51cd54eSJagan Teki 		return -EINVAL;
193*a51cd54eSJagan Teki 	}
194*a51cd54eSJagan Teki 
195*a51cd54eSJagan Teki 	while (size) {
196*a51cd54eSJagan Teki 		phandle = fdt32_to_cpu(*list++);
197*a51cd54eSJagan Teki 		size -= sizeof(*list);
198*a51cd54eSJagan Teki 
199*a51cd54eSJagan Teki 		offset = fdt_node_offset_by_phandle(fdt, phandle);
200*a51cd54eSJagan Teki 		if (offset < 0)
201*a51cd54eSJagan Teki 			return offset;
202*a51cd54eSJagan Teki 
203*a51cd54eSJagan Teki 		drive = fdt_getprop_u32_default_node(fdt, offset, 0,
204*a51cd54eSJagan Teki 						     "drive-strength", 0);
205*a51cd54eSJagan Teki 		if (drive) {
206*a51cd54eSJagan Teki 			if (drive <= 10)
207*a51cd54eSJagan Teki 				drive = 0;
208*a51cd54eSJagan Teki 			else if (drive <= 20)
209*a51cd54eSJagan Teki 				drive = 1;
210*a51cd54eSJagan Teki 			else if (drive <= 30)
211*a51cd54eSJagan Teki 				drive = 2;
212*a51cd54eSJagan Teki 			else
213*a51cd54eSJagan Teki 				drive = 3;
214*a51cd54eSJagan Teki 		} else {
215*a51cd54eSJagan Teki 			drive = fdt_getprop_u32_default_node(fdt, offset, 0,
216*a51cd54eSJagan Teki 							     "allwinner,drive",
217*a51cd54eSJagan Teki 							      0);
218*a51cd54eSJagan Teki 			drive = min(drive, 3);
219*a51cd54eSJagan Teki 		}
220*a51cd54eSJagan Teki 
221*a51cd54eSJagan Teki 		if (fdt_get_property(fdt, offset, "bias-disable", NULL))
222*a51cd54eSJagan Teki 			pull = 0;
223*a51cd54eSJagan Teki 		else if (fdt_get_property(fdt, offset, "bias-pull-up", NULL))
224*a51cd54eSJagan Teki 			pull = 1;
225*a51cd54eSJagan Teki 		else if (fdt_get_property(fdt, offset, "bias-pull-down", NULL))
226*a51cd54eSJagan Teki 			pull = 2;
227*a51cd54eSJagan Teki 		else
228*a51cd54eSJagan Teki 			pull = fdt_getprop_u32_default_node(fdt, offset, 0,
229*a51cd54eSJagan Teki 							    "allwinner,pull",
230*a51cd54eSJagan Teki 							     0);
231*a51cd54eSJagan Teki 		pull = min(pull, 2);
232*a51cd54eSJagan Teki 
233*a51cd54eSJagan Teki 		for (i = 0; ; i++) {
234*a51cd54eSJagan Teki 			pin_name = fdt_stringlist_get(fdt, offset,
235*a51cd54eSJagan Teki 						      "pins", i, NULL);
236*a51cd54eSJagan Teki 			if (!pin_name) {
237*a51cd54eSJagan Teki 				pin_name = fdt_stringlist_get(fdt, offset,
238*a51cd54eSJagan Teki 							      "allwinner,pins",
239*a51cd54eSJagan Teki 							       i, NULL);
240*a51cd54eSJagan Teki 				if (!pin_name)
241*a51cd54eSJagan Teki 					break;
242*a51cd54eSJagan Teki 			}
243*a51cd54eSJagan Teki 
244*a51cd54eSJagan Teki 			pin = name_to_gpio(pin_name);
245*a51cd54eSJagan Teki 			if (pin < 0)
246*a51cd54eSJagan Teki 				break;
247*a51cd54eSJagan Teki 
248*a51cd54eSJagan Teki 			if (IS_ENABLED(CONFIG_MACH_SUN50I))
249*a51cd54eSJagan Teki 				sunxi_gpio_set_cfgpin(pin, SUN50I_GPC_SPI0);
250*a51cd54eSJagan Teki 			else
251*a51cd54eSJagan Teki 				sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0);
252*a51cd54eSJagan Teki 			sunxi_gpio_set_drv(pin, drive);
253*a51cd54eSJagan Teki 			sunxi_gpio_set_pull(pin, pull);
254*a51cd54eSJagan Teki 		}
255*a51cd54eSJagan Teki 	}
256*a51cd54eSJagan Teki 	return 0;
257*a51cd54eSJagan Teki }
258*a51cd54eSJagan Teki 
sun4i_spi_set_clock(struct udevice * dev,bool enable)259*a51cd54eSJagan Teki static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable)
260*a51cd54eSJagan Teki {
261*a51cd54eSJagan Teki 	struct sun4i_spi_priv *priv = dev_get_priv(dev);
262*a51cd54eSJagan Teki 	int ret;
263*a51cd54eSJagan Teki 
264*a51cd54eSJagan Teki 	if (!enable) {
265*a51cd54eSJagan Teki 		clk_disable(&priv->clk_ahb);
266*a51cd54eSJagan Teki 		clk_disable(&priv->clk_mod);
267*a51cd54eSJagan Teki 		if (reset_valid(&priv->reset))
268*a51cd54eSJagan Teki 			reset_assert(&priv->reset);
269*a51cd54eSJagan Teki 		return 0;
270*a51cd54eSJagan Teki 	}
271*a51cd54eSJagan Teki 
272*a51cd54eSJagan Teki 	ret = clk_enable(&priv->clk_ahb);
273*a51cd54eSJagan Teki 	if (ret) {
274*a51cd54eSJagan Teki 		dev_err(dev, "failed to enable ahb clock (ret=%d)\n", ret);
275*a51cd54eSJagan Teki 		return ret;
276*a51cd54eSJagan Teki 	}
277*a51cd54eSJagan Teki 
278*a51cd54eSJagan Teki 	ret = clk_enable(&priv->clk_mod);
279*a51cd54eSJagan Teki 	if (ret) {
280*a51cd54eSJagan Teki 		dev_err(dev, "failed to enable mod clock (ret=%d)\n", ret);
281*a51cd54eSJagan Teki 		goto err_ahb;
282*a51cd54eSJagan Teki 	}
283*a51cd54eSJagan Teki 
284*a51cd54eSJagan Teki 	if (reset_valid(&priv->reset)) {
285*a51cd54eSJagan Teki 		ret = reset_deassert(&priv->reset);
286*a51cd54eSJagan Teki 		if (ret) {
287*a51cd54eSJagan Teki 			dev_err(dev, "failed to deassert reset\n");
288*a51cd54eSJagan Teki 			goto err_mod;
289*a51cd54eSJagan Teki 		}
290*a51cd54eSJagan Teki 	}
291*a51cd54eSJagan Teki 
292*a51cd54eSJagan Teki 	return 0;
293*a51cd54eSJagan Teki 
294*a51cd54eSJagan Teki err_mod:
295*a51cd54eSJagan Teki 	clk_disable(&priv->clk_mod);
296*a51cd54eSJagan Teki err_ahb:
297*a51cd54eSJagan Teki 	clk_disable(&priv->clk_ahb);
298*a51cd54eSJagan Teki 	return ret;
299*a51cd54eSJagan Teki }
300*a51cd54eSJagan Teki 
sun4i_spi_claim_bus(struct udevice * dev)301*a51cd54eSJagan Teki static int sun4i_spi_claim_bus(struct udevice *dev)
302*a51cd54eSJagan Teki {
303*a51cd54eSJagan Teki 	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
304*a51cd54eSJagan Teki 	int ret;
305*a51cd54eSJagan Teki 
306*a51cd54eSJagan Teki 	ret = sun4i_spi_set_clock(dev->parent, true);
307*a51cd54eSJagan Teki 	if (ret)
308*a51cd54eSJagan Teki 		return ret;
309*a51cd54eSJagan Teki 
310*a51cd54eSJagan Teki 	setbits_le32(SPI_REG(priv, SPI_GCR), SUN4I_CTL_ENABLE |
311*a51cd54eSJagan Teki 		     SUN4I_CTL_MASTER | SPI_BIT(priv, SPI_GCR_TP));
312*a51cd54eSJagan Teki 
313*a51cd54eSJagan Teki 	if (priv->variant->has_soft_reset)
314*a51cd54eSJagan Teki 		setbits_le32(SPI_REG(priv, SPI_GCR),
315*a51cd54eSJagan Teki 			     SPI_BIT(priv, SPI_GCR_SRST));
316*a51cd54eSJagan Teki 
317*a51cd54eSJagan Teki 	setbits_le32(SPI_REG(priv, SPI_TCR), SPI_BIT(priv, SPI_TCR_CS_MANUAL) |
318*a51cd54eSJagan Teki 		     SPI_BIT(priv, SPI_TCR_CS_ACTIVE_LOW));
319*a51cd54eSJagan Teki 
320*a51cd54eSJagan Teki 	return 0;
321*a51cd54eSJagan Teki }
322*a51cd54eSJagan Teki 
sun4i_spi_release_bus(struct udevice * dev)323*a51cd54eSJagan Teki static int sun4i_spi_release_bus(struct udevice *dev)
324*a51cd54eSJagan Teki {
325*a51cd54eSJagan Teki 	struct sun4i_spi_priv *priv = dev_get_priv(dev->parent);
326*a51cd54eSJagan Teki 
327*a51cd54eSJagan Teki 	clrbits_le32(SPI_REG(priv, SPI_GCR), SUN4I_CTL_ENABLE);
328*a51cd54eSJagan Teki 
329*a51cd54eSJagan Teki 	sun4i_spi_set_clock(dev->parent, false);
330*a51cd54eSJagan Teki 
331*a51cd54eSJagan Teki 	return 0;
332*a51cd54eSJagan Teki }
333*a51cd54eSJagan Teki 
sun4i_spi_xfer(struct udevice * dev,unsigned int bitlen,const void * dout,void * din,unsigned long flags)334*a51cd54eSJagan Teki static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen,
335*a51cd54eSJagan Teki 			  const void *dout, void *din, unsigned long flags)
336*a51cd54eSJagan Teki {
337*a51cd54eSJagan Teki 	struct udevice *bus = dev->parent;
338*a51cd54eSJagan Teki 	struct sun4i_spi_priv *priv = dev_get_priv(bus);
339*a51cd54eSJagan Teki 	struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev);
340*a51cd54eSJagan Teki 
341*a51cd54eSJagan Teki 	u32 len = bitlen / 8;
342*a51cd54eSJagan Teki 	u32 rx_fifocnt;
343*a51cd54eSJagan Teki 	u8 nbytes;
344*a51cd54eSJagan Teki 	int ret;
345*a51cd54eSJagan Teki 
346*a51cd54eSJagan Teki 	priv->tx_buf = dout;
347*a51cd54eSJagan Teki 	priv->rx_buf = din;
348*a51cd54eSJagan Teki 
349*a51cd54eSJagan Teki 	if (bitlen % 8) {
350*a51cd54eSJagan Teki 		debug("%s: non byte-aligned SPI transfer.\n", __func__);
351*a51cd54eSJagan Teki 		return -ENAVAIL;
352*a51cd54eSJagan Teki 	}
353*a51cd54eSJagan Teki 
354*a51cd54eSJagan Teki 	if (flags & SPI_XFER_BEGIN)
355*a51cd54eSJagan Teki 		sun4i_spi_set_cs(bus, slave_plat->cs, true);
356*a51cd54eSJagan Teki 
357*a51cd54eSJagan Teki 	/* Reset FIFOs */
358*a51cd54eSJagan Teki 	setbits_le32(SPI_REG(priv, SPI_FCR), SPI_BIT(priv, SPI_FCR_RF_RST) |
359*a51cd54eSJagan Teki 		     SPI_BIT(priv, SPI_FCR_TF_RST));
360*a51cd54eSJagan Teki 
361*a51cd54eSJagan Teki 	while (len) {
362*a51cd54eSJagan Teki 		/* Setup the transfer now... */
363*a51cd54eSJagan Teki 		nbytes = min(len, (priv->variant->fifo_depth - 1));
364*a51cd54eSJagan Teki 
365*a51cd54eSJagan Teki 		/* Setup the counters */
366*a51cd54eSJagan Teki 		writel(SUN4I_BURST_CNT(nbytes), SPI_REG(priv, SPI_BC));
367*a51cd54eSJagan Teki 		writel(SUN4I_XMIT_CNT(nbytes), SPI_REG(priv, SPI_TC));
368*a51cd54eSJagan Teki 
369*a51cd54eSJagan Teki 		if (priv->variant->has_burst_ctl)
370*a51cd54eSJagan Teki 			writel(SUN4I_BURST_CNT(nbytes),
371*a51cd54eSJagan Teki 			       SPI_REG(priv, SPI_BCTL));
372*a51cd54eSJagan Teki 
373*a51cd54eSJagan Teki 		/* Fill the TX FIFO */
374*a51cd54eSJagan Teki 		sun4i_spi_fill_fifo(priv, nbytes);
375*a51cd54eSJagan Teki 
376*a51cd54eSJagan Teki 		/* Start the transfer */
377*a51cd54eSJagan Teki 		setbits_le32(SPI_REG(priv, SPI_TCR),
378*a51cd54eSJagan Teki 			     SPI_BIT(priv, SPI_TCR_XCH));
379*a51cd54eSJagan Teki 
380*a51cd54eSJagan Teki 		/* Wait till RX FIFO to be empty */
381*a51cd54eSJagan Teki 		ret = readl_poll_timeout(SPI_REG(priv, SPI_FSR),
382*a51cd54eSJagan Teki 					 rx_fifocnt,
383*a51cd54eSJagan Teki 					 (((rx_fifocnt &
384*a51cd54eSJagan Teki 					 SPI_BIT(priv, SPI_FSR_RF_CNT_MASK)) >>
385*a51cd54eSJagan Teki 					 SUN4I_FIFO_STA_RF_CNT_BITS) >= nbytes),
386*a51cd54eSJagan Teki 					 SUN4I_SPI_TIMEOUT_US);
387*a51cd54eSJagan Teki 		if (ret < 0) {
388*a51cd54eSJagan Teki 			printf("ERROR: sun4i_spi: Timeout transferring data\n");
389*a51cd54eSJagan Teki 			sun4i_spi_set_cs(bus, slave_plat->cs, false);
390*a51cd54eSJagan Teki 			return ret;
391*a51cd54eSJagan Teki 		}
392*a51cd54eSJagan Teki 
393*a51cd54eSJagan Teki 		/* Drain the RX FIFO */
394*a51cd54eSJagan Teki 		sun4i_spi_drain_fifo(priv, nbytes);
395*a51cd54eSJagan Teki 
396*a51cd54eSJagan Teki 		len -= nbytes;
397*a51cd54eSJagan Teki 	}
398*a51cd54eSJagan Teki 
399*a51cd54eSJagan Teki 	if (flags & SPI_XFER_END)
400*a51cd54eSJagan Teki 		sun4i_spi_set_cs(bus, slave_plat->cs, false);
401*a51cd54eSJagan Teki 
402*a51cd54eSJagan Teki 	return 0;
403*a51cd54eSJagan Teki }
404*a51cd54eSJagan Teki 
sun4i_spi_set_speed(struct udevice * dev,uint speed)405*a51cd54eSJagan Teki static int sun4i_spi_set_speed(struct udevice *dev, uint speed)
406*a51cd54eSJagan Teki {
407*a51cd54eSJagan Teki 	struct sun4i_spi_platdata *plat = dev_get_platdata(dev);
408*a51cd54eSJagan Teki 	struct sun4i_spi_priv *priv = dev_get_priv(dev);
409*a51cd54eSJagan Teki 	unsigned int div;
410*a51cd54eSJagan Teki 	u32 reg;
411*a51cd54eSJagan Teki 
412*a51cd54eSJagan Teki 	if (speed > plat->max_hz)
413*a51cd54eSJagan Teki 		speed = plat->max_hz;
414*a51cd54eSJagan Teki 
415*a51cd54eSJagan Teki 	if (speed < SUN4I_SPI_MIN_RATE)
416*a51cd54eSJagan Teki 		speed = SUN4I_SPI_MIN_RATE;
417*a51cd54eSJagan Teki 	/*
418*a51cd54eSJagan Teki 	 * Setup clock divider.
419*a51cd54eSJagan Teki 	 *
420*a51cd54eSJagan Teki 	 * We have two choices there. Either we can use the clock
421*a51cd54eSJagan Teki 	 * divide rate 1, which is calculated thanks to this formula:
422*a51cd54eSJagan Teki 	 * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1))
423*a51cd54eSJagan Teki 	 * Or we can use CDR2, which is calculated with the formula:
424*a51cd54eSJagan Teki 	 * SPI_CLK = MOD_CLK / (2 * (cdr + 1))
425*a51cd54eSJagan Teki 	 * Whether we use the former or the latter is set through the
426*a51cd54eSJagan Teki 	 * DRS bit.
427*a51cd54eSJagan Teki 	 *
428*a51cd54eSJagan Teki 	 * First try CDR2, and if we can't reach the expected
429*a51cd54eSJagan Teki 	 * frequency, fall back to CDR1.
430*a51cd54eSJagan Teki 	 */
431*a51cd54eSJagan Teki 
432*a51cd54eSJagan Teki 	div = SUN4I_SPI_MAX_RATE / (2 * speed);
433*a51cd54eSJagan Teki 	reg = readl(SPI_REG(priv, SPI_CCR));
434*a51cd54eSJagan Teki 
435*a51cd54eSJagan Teki 	if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) {
436*a51cd54eSJagan Teki 		if (div > 0)
437*a51cd54eSJagan Teki 			div--;
438*a51cd54eSJagan Teki 
439*a51cd54eSJagan Teki 		reg &= ~(SUN4I_CLK_CTL_CDR2_MASK | SUN4I_CLK_CTL_DRS);
440*a51cd54eSJagan Teki 		reg |= SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS;
441*a51cd54eSJagan Teki 	} else {
442*a51cd54eSJagan Teki 		div = __ilog2(SUN4I_SPI_MAX_RATE) - __ilog2(speed);
443*a51cd54eSJagan Teki 		reg &= ~((SUN4I_CLK_CTL_CDR1_MASK << 8) | SUN4I_CLK_CTL_DRS);
444*a51cd54eSJagan Teki 		reg |= SUN4I_CLK_CTL_CDR1(div);
445*a51cd54eSJagan Teki 	}
446*a51cd54eSJagan Teki 
447*a51cd54eSJagan Teki 	priv->freq = speed;
448*a51cd54eSJagan Teki 	writel(reg, SPI_REG(priv, SPI_CCR));
449*a51cd54eSJagan Teki 
450*a51cd54eSJagan Teki 	return 0;
451*a51cd54eSJagan Teki }
452*a51cd54eSJagan Teki 
sun4i_spi_set_mode(struct udevice * dev,uint mode)453*a51cd54eSJagan Teki static int sun4i_spi_set_mode(struct udevice *dev, uint mode)
454*a51cd54eSJagan Teki {
455*a51cd54eSJagan Teki 	struct sun4i_spi_priv *priv = dev_get_priv(dev);
456*a51cd54eSJagan Teki 	u32 reg;
457*a51cd54eSJagan Teki 
458*a51cd54eSJagan Teki 	reg = readl(SPI_REG(priv, SPI_TCR));
459*a51cd54eSJagan Teki 	reg &= ~(SPI_BIT(priv, SPI_TCR_CPOL) | SPI_BIT(priv, SPI_TCR_CPHA));
460*a51cd54eSJagan Teki 
461*a51cd54eSJagan Teki 	if (mode & SPI_CPOL)
462*a51cd54eSJagan Teki 		reg |= SPI_BIT(priv, SPI_TCR_CPOL);
463*a51cd54eSJagan Teki 
464*a51cd54eSJagan Teki 	if (mode & SPI_CPHA)
465*a51cd54eSJagan Teki 		reg |= SPI_BIT(priv, SPI_TCR_CPHA);
466*a51cd54eSJagan Teki 
467*a51cd54eSJagan Teki 	priv->mode = mode;
468*a51cd54eSJagan Teki 	writel(reg, SPI_REG(priv, SPI_TCR));
469*a51cd54eSJagan Teki 
470*a51cd54eSJagan Teki 	return 0;
471*a51cd54eSJagan Teki }
472*a51cd54eSJagan Teki 
473*a51cd54eSJagan Teki static const struct dm_spi_ops sun4i_spi_ops = {
474*a51cd54eSJagan Teki 	.claim_bus		= sun4i_spi_claim_bus,
475*a51cd54eSJagan Teki 	.release_bus		= sun4i_spi_release_bus,
476*a51cd54eSJagan Teki 	.xfer			= sun4i_spi_xfer,
477*a51cd54eSJagan Teki 	.set_speed		= sun4i_spi_set_speed,
478*a51cd54eSJagan Teki 	.set_mode		= sun4i_spi_set_mode,
479*a51cd54eSJagan Teki };
480*a51cd54eSJagan Teki 
sun4i_spi_probe(struct udevice * bus)481*a51cd54eSJagan Teki static int sun4i_spi_probe(struct udevice *bus)
482*a51cd54eSJagan Teki {
483*a51cd54eSJagan Teki 	struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
484*a51cd54eSJagan Teki 	struct sun4i_spi_priv *priv = dev_get_priv(bus);
485*a51cd54eSJagan Teki 	int ret;
486*a51cd54eSJagan Teki 
487*a51cd54eSJagan Teki 	ret = clk_get_by_name(bus, "ahb", &priv->clk_ahb);
488*a51cd54eSJagan Teki 	if (ret) {
489*a51cd54eSJagan Teki 		dev_err(dev, "failed to get ahb clock\n");
490*a51cd54eSJagan Teki 		return ret;
491*a51cd54eSJagan Teki 	}
492*a51cd54eSJagan Teki 
493*a51cd54eSJagan Teki 	ret = clk_get_by_name(bus, "mod", &priv->clk_mod);
494*a51cd54eSJagan Teki 	if (ret) {
495*a51cd54eSJagan Teki 		dev_err(dev, "failed to get mod clock\n");
496*a51cd54eSJagan Teki 		return ret;
497*a51cd54eSJagan Teki 	}
498*a51cd54eSJagan Teki 
499*a51cd54eSJagan Teki 	ret = reset_get_by_index(bus, 0, &priv->reset);
500*a51cd54eSJagan Teki 	if (ret && ret != -ENOENT) {
501*a51cd54eSJagan Teki 		dev_err(dev, "failed to get reset\n");
502*a51cd54eSJagan Teki 		return ret;
503*a51cd54eSJagan Teki 	}
504*a51cd54eSJagan Teki 
505*a51cd54eSJagan Teki 	sun4i_spi_parse_pins(bus);
506*a51cd54eSJagan Teki 
507*a51cd54eSJagan Teki 	priv->variant = plat->variant;
508*a51cd54eSJagan Teki 	priv->base = plat->base;
509*a51cd54eSJagan Teki 	priv->freq = plat->max_hz;
510*a51cd54eSJagan Teki 
511*a51cd54eSJagan Teki 	return 0;
512*a51cd54eSJagan Teki }
513*a51cd54eSJagan Teki 
sun4i_spi_ofdata_to_platdata(struct udevice * bus)514*a51cd54eSJagan Teki static int sun4i_spi_ofdata_to_platdata(struct udevice *bus)
515*a51cd54eSJagan Teki {
516*a51cd54eSJagan Teki 	struct sun4i_spi_platdata *plat = dev_get_platdata(bus);
517*a51cd54eSJagan Teki 	int node = dev_of_offset(bus);
518*a51cd54eSJagan Teki 
519*a51cd54eSJagan Teki 	plat->base = devfdt_get_addr(bus);
520*a51cd54eSJagan Teki 	plat->variant = (struct sun4i_spi_variant *)dev_get_driver_data(bus);
521*a51cd54eSJagan Teki 	plat->max_hz = fdtdec_get_int(gd->fdt_blob, node,
522*a51cd54eSJagan Teki 				      "spi-max-frequency",
523*a51cd54eSJagan Teki 				      SUN4I_SPI_DEFAULT_RATE);
524*a51cd54eSJagan Teki 
525*a51cd54eSJagan Teki 	if (plat->max_hz > SUN4I_SPI_MAX_RATE)
526*a51cd54eSJagan Teki 		plat->max_hz = SUN4I_SPI_MAX_RATE;
527*a51cd54eSJagan Teki 
528*a51cd54eSJagan Teki 	return 0;
529*a51cd54eSJagan Teki }
530*a51cd54eSJagan Teki 
531*a51cd54eSJagan Teki static const unsigned long sun4i_spi_regs[] = {
532*a51cd54eSJagan Teki 	[SPI_GCR]		= SUN4I_CTL_REG,
533*a51cd54eSJagan Teki 	[SPI_TCR]		= SUN4I_CTL_REG,
534*a51cd54eSJagan Teki 	[SPI_FCR]		= SUN4I_CTL_REG,
535*a51cd54eSJagan Teki 	[SPI_FSR]		= SUN4I_FIFO_STA_REG,
536*a51cd54eSJagan Teki 	[SPI_CCR]		= SUN4I_CLK_CTL_REG,
537*a51cd54eSJagan Teki 	[SPI_BC]		= SUN4I_BURST_CNT_REG,
538*a51cd54eSJagan Teki 	[SPI_TC]		= SUN4I_XMIT_CNT_REG,
539*a51cd54eSJagan Teki 	[SPI_TXD]		= SUN4I_TXDATA_REG,
540*a51cd54eSJagan Teki 	[SPI_RXD]		= SUN4I_RXDATA_REG,
541*a51cd54eSJagan Teki };
542*a51cd54eSJagan Teki 
543*a51cd54eSJagan Teki static const u32 sun4i_spi_bits[] = {
544*a51cd54eSJagan Teki 	[SPI_GCR_TP]		= BIT(18),
545*a51cd54eSJagan Teki 	[SPI_TCR_CPHA]		= BIT(2),
546*a51cd54eSJagan Teki 	[SPI_TCR_CPOL]		= BIT(3),
547*a51cd54eSJagan Teki 	[SPI_TCR_CS_ACTIVE_LOW] = BIT(4),
548*a51cd54eSJagan Teki 	[SPI_TCR_XCH]		= BIT(10),
549*a51cd54eSJagan Teki 	[SPI_TCR_CS_SEL]	= 12,
550*a51cd54eSJagan Teki 	[SPI_TCR_CS_MASK]	= 0x3000,
551*a51cd54eSJagan Teki 	[SPI_TCR_CS_MANUAL]	= BIT(16),
552*a51cd54eSJagan Teki 	[SPI_TCR_CS_LEVEL]	= BIT(17),
553*a51cd54eSJagan Teki 	[SPI_FCR_TF_RST]	= BIT(8),
554*a51cd54eSJagan Teki 	[SPI_FCR_RF_RST]	= BIT(9),
555*a51cd54eSJagan Teki 	[SPI_FSR_RF_CNT_MASK]	= GENMASK(6, 0),
556*a51cd54eSJagan Teki };
557*a51cd54eSJagan Teki 
558*a51cd54eSJagan Teki static const unsigned long sun6i_spi_regs[] = {
559*a51cd54eSJagan Teki 	[SPI_GCR]		= SUN6I_GBL_CTL_REG,
560*a51cd54eSJagan Teki 	[SPI_TCR]		= SUN6I_TFR_CTL_REG,
561*a51cd54eSJagan Teki 	[SPI_FCR]		= SUN6I_FIFO_CTL_REG,
562*a51cd54eSJagan Teki 	[SPI_FSR]		= SUN6I_FIFO_STA_REG,
563*a51cd54eSJagan Teki 	[SPI_CCR]		= SUN6I_CLK_CTL_REG,
564*a51cd54eSJagan Teki 	[SPI_BC]		= SUN6I_BURST_CNT_REG,
565*a51cd54eSJagan Teki 	[SPI_TC]		= SUN6I_XMIT_CNT_REG,
566*a51cd54eSJagan Teki 	[SPI_BCTL]		= SUN6I_BURST_CTL_REG,
567*a51cd54eSJagan Teki 	[SPI_TXD]		= SUN6I_TXDATA_REG,
568*a51cd54eSJagan Teki 	[SPI_RXD]		= SUN6I_RXDATA_REG,
569*a51cd54eSJagan Teki };
570*a51cd54eSJagan Teki 
571*a51cd54eSJagan Teki static const u32 sun6i_spi_bits[] = {
572*a51cd54eSJagan Teki 	[SPI_GCR_TP]		= BIT(7),
573*a51cd54eSJagan Teki 	[SPI_GCR_SRST]		= BIT(31),
574*a51cd54eSJagan Teki 	[SPI_TCR_CPHA]		= BIT(0),
575*a51cd54eSJagan Teki 	[SPI_TCR_CPOL]		= BIT(1),
576*a51cd54eSJagan Teki 	[SPI_TCR_CS_ACTIVE_LOW] = BIT(2),
577*a51cd54eSJagan Teki 	[SPI_TCR_CS_SEL]	= 4,
578*a51cd54eSJagan Teki 	[SPI_TCR_CS_MASK]	= 0x30,
579*a51cd54eSJagan Teki 	[SPI_TCR_CS_MANUAL]	= BIT(6),
580*a51cd54eSJagan Teki 	[SPI_TCR_CS_LEVEL]	= BIT(7),
581*a51cd54eSJagan Teki 	[SPI_TCR_XCH]		= BIT(31),
582*a51cd54eSJagan Teki 	[SPI_FCR_RF_RST]	= BIT(15),
583*a51cd54eSJagan Teki 	[SPI_FCR_TF_RST]	= BIT(31),
584*a51cd54eSJagan Teki 	[SPI_FSR_RF_CNT_MASK]	= GENMASK(7, 0),
585*a51cd54eSJagan Teki };
586*a51cd54eSJagan Teki 
587*a51cd54eSJagan Teki static const struct sun4i_spi_variant sun4i_a10_spi_variant = {
588*a51cd54eSJagan Teki 	.regs			= sun4i_spi_regs,
589*a51cd54eSJagan Teki 	.bits			= sun4i_spi_bits,
590*a51cd54eSJagan Teki 	.fifo_depth		= 64,
591*a51cd54eSJagan Teki };
592*a51cd54eSJagan Teki 
593*a51cd54eSJagan Teki static const struct sun4i_spi_variant sun6i_a31_spi_variant = {
594*a51cd54eSJagan Teki 	.regs			= sun6i_spi_regs,
595*a51cd54eSJagan Teki 	.bits			= sun6i_spi_bits,
596*a51cd54eSJagan Teki 	.fifo_depth		= 128,
597*a51cd54eSJagan Teki 	.has_soft_reset		= true,
598*a51cd54eSJagan Teki 	.has_burst_ctl		= true,
599*a51cd54eSJagan Teki };
600*a51cd54eSJagan Teki 
601*a51cd54eSJagan Teki static const struct sun4i_spi_variant sun8i_h3_spi_variant = {
602*a51cd54eSJagan Teki 	.regs			= sun6i_spi_regs,
603*a51cd54eSJagan Teki 	.bits			= sun6i_spi_bits,
604*a51cd54eSJagan Teki 	.fifo_depth		= 64,
605*a51cd54eSJagan Teki 	.has_soft_reset		= true,
606*a51cd54eSJagan Teki 	.has_burst_ctl		= true,
607*a51cd54eSJagan Teki };
608*a51cd54eSJagan Teki 
609*a51cd54eSJagan Teki static const struct udevice_id sun4i_spi_ids[] = {
610*a51cd54eSJagan Teki 	{
611*a51cd54eSJagan Teki 	  .compatible = "allwinner,sun4i-a10-spi",
612*a51cd54eSJagan Teki 	  .data = (ulong)&sun4i_a10_spi_variant,
613*a51cd54eSJagan Teki 	},
614*a51cd54eSJagan Teki 	{
615*a51cd54eSJagan Teki 	  .compatible = "allwinner,sun6i-a31-spi",
616*a51cd54eSJagan Teki 	  .data = (ulong)&sun6i_a31_spi_variant,
617*a51cd54eSJagan Teki 	},
618*a51cd54eSJagan Teki 	{
619*a51cd54eSJagan Teki 	  .compatible = "allwinner,sun8i-h3-spi",
620*a51cd54eSJagan Teki 	  .data = (ulong)&sun8i_h3_spi_variant,
621*a51cd54eSJagan Teki 	},
622*a51cd54eSJagan Teki 	{ /* sentinel */ }
623*a51cd54eSJagan Teki };
624*a51cd54eSJagan Teki 
625*a51cd54eSJagan Teki U_BOOT_DRIVER(sun4i_spi) = {
626*a51cd54eSJagan Teki 	.name	= "sun4i_spi",
627*a51cd54eSJagan Teki 	.id	= UCLASS_SPI,
628*a51cd54eSJagan Teki 	.of_match	= sun4i_spi_ids,
629*a51cd54eSJagan Teki 	.ops	= &sun4i_spi_ops,
630*a51cd54eSJagan Teki 	.ofdata_to_platdata	= sun4i_spi_ofdata_to_platdata,
631*a51cd54eSJagan Teki 	.platdata_auto_alloc_size	= sizeof(struct sun4i_spi_platdata),
632*a51cd54eSJagan Teki 	.priv_auto_alloc_size	= sizeof(struct sun4i_spi_priv),
633*a51cd54eSJagan Teki 	.probe	= sun4i_spi_probe,
634*a51cd54eSJagan Teki };
635