xref: /openbmc/u-boot/drivers/spi/pl022_spi.c (revision 9450ab2ba8d720bd9f73bccc0af2e2b5a2c2aaf1)
1  // SPDX-License-Identifier: GPL-2.0+
2  /*
3   * (C) Copyright 2012
4   * Armando Visconti, ST Microelectronics, armando.visconti@st.com.
5   *
6   * (C) Copyright 2018
7   * Quentin Schulz, Bootlin, quentin.schulz@bootlin.com
8   *
9   * Driver for ARM PL022 SPI Controller.
10   */
11  
12  #include <clk.h>
13  #include <common.h>
14  #include <dm.h>
15  #include <dm/platform_data/spi_pl022.h>
16  #include <linux/io.h>
17  #include <spi.h>
18  
19  #define SSP_CR0		0x000
20  #define SSP_CR1		0x004
21  #define SSP_DR		0x008
22  #define SSP_SR		0x00C
23  #define SSP_CPSR	0x010
24  #define SSP_IMSC	0x014
25  #define SSP_RIS		0x018
26  #define SSP_MIS		0x01C
27  #define SSP_ICR		0x020
28  #define SSP_DMACR	0x024
29  #define SSP_CSR		0x030 /* vendor extension */
30  #define SSP_ITCR	0x080
31  #define SSP_ITIP	0x084
32  #define SSP_ITOP	0x088
33  #define SSP_TDR		0x08C
34  
35  #define SSP_PID0	0xFE0
36  #define SSP_PID1	0xFE4
37  #define SSP_PID2	0xFE8
38  #define SSP_PID3	0xFEC
39  
40  #define SSP_CID0	0xFF0
41  #define SSP_CID1	0xFF4
42  #define SSP_CID2	0xFF8
43  #define SSP_CID3	0xFFC
44  
45  /* SSP Control Register 0  - SSP_CR0 */
46  #define SSP_CR0_SPO		(0x1 << 6)
47  #define SSP_CR0_SPH		(0x1 << 7)
48  #define SSP_CR0_BIT_MODE(x)	((x) - 1)
49  #define SSP_SCR_MIN		(0x00)
50  #define SSP_SCR_MAX		(0xFF)
51  #define SSP_SCR_SHFT		8
52  #define DFLT_CLKRATE		2
53  
54  /* SSP Control Register 1  - SSP_CR1 */
55  #define SSP_CR1_MASK_SSE	(0x1 << 1)
56  
57  #define SSP_CPSR_MIN		(0x02)
58  #define SSP_CPSR_MAX		(0xFE)
59  #define DFLT_PRESCALE		(0x40)
60  
61  /* SSP Status Register - SSP_SR */
62  #define SSP_SR_MASK_TFE		(0x1 << 0) /* Transmit FIFO empty */
63  #define SSP_SR_MASK_TNF		(0x1 << 1) /* Transmit FIFO not full */
64  #define SSP_SR_MASK_RNE		(0x1 << 2) /* Receive FIFO not empty */
65  #define SSP_SR_MASK_RFF		(0x1 << 3) /* Receive FIFO full */
66  #define SSP_SR_MASK_BSY		(0x1 << 4) /* Busy Flag */
67  
68  struct pl022_spi_slave {
69  	void *base;
70  	unsigned int freq;
71  };
72  
73  /*
74   * ARM PL022 exists in different 'flavors'.
75   * This drivers currently support the standard variant (0x00041022), that has a
76   * 16bit wide and 8 locations deep TX/RX FIFO.
77   */
pl022_is_supported(struct pl022_spi_slave * ps)78  static int pl022_is_supported(struct pl022_spi_slave *ps)
79  {
80  	/* PL022 version is 0x00041022 */
81  	if ((readw(ps->base + SSP_PID0) == 0x22) &&
82  	    (readw(ps->base + SSP_PID1) == 0x10) &&
83  	    ((readw(ps->base + SSP_PID2) & 0xf) == 0x04) &&
84  	    (readw(ps->base + SSP_PID3) == 0x00))
85  		return 1;
86  
87  	return 0;
88  }
89  
pl022_spi_probe(struct udevice * bus)90  static int pl022_spi_probe(struct udevice *bus)
91  {
92  	struct pl022_spi_pdata *plat = dev_get_platdata(bus);
93  	struct pl022_spi_slave *ps = dev_get_priv(bus);
94  
95  	ps->base = ioremap(plat->addr, plat->size);
96  	ps->freq = plat->freq;
97  
98  	/* Check the PL022 version */
99  	if (!pl022_is_supported(ps))
100  		return -ENOTSUPP;
101  
102  	/* 8 bits per word, high polarity and default clock rate */
103  	writew(SSP_CR0_BIT_MODE(8), ps->base + SSP_CR0);
104  	writew(DFLT_PRESCALE, ps->base + SSP_CPSR);
105  
106  	return 0;
107  }
108  
flush(struct pl022_spi_slave * ps)109  static void flush(struct pl022_spi_slave *ps)
110  {
111  	do {
112  		while (readw(ps->base + SSP_SR) & SSP_SR_MASK_RNE)
113  			readw(ps->base + SSP_DR);
114  	} while (readw(ps->base + SSP_SR) & SSP_SR_MASK_BSY);
115  }
116  
pl022_spi_claim_bus(struct udevice * dev)117  static int pl022_spi_claim_bus(struct udevice *dev)
118  {
119  	struct udevice *bus = dev->parent;
120  	struct pl022_spi_slave *ps = dev_get_priv(bus);
121  	u16 reg;
122  
123  	/* Enable the SPI hardware */
124  	reg = readw(ps->base + SSP_CR1);
125  	reg |= SSP_CR1_MASK_SSE;
126  	writew(reg, ps->base + SSP_CR1);
127  
128  	flush(ps);
129  
130  	return 0;
131  }
132  
pl022_spi_release_bus(struct udevice * dev)133  static int pl022_spi_release_bus(struct udevice *dev)
134  {
135  	struct udevice *bus = dev->parent;
136  	struct pl022_spi_slave *ps = dev_get_priv(bus);
137  	u16 reg;
138  
139  	flush(ps);
140  
141  	/* Disable the SPI hardware */
142  	reg = readw(ps->base + SSP_CR1);
143  	reg &= ~SSP_CR1_MASK_SSE;
144  	writew(reg, ps->base + SSP_CR1);
145  
146  	return 0;
147  }
148  
pl022_spi_xfer(struct udevice * dev,unsigned int bitlen,const void * dout,void * din,unsigned long flags)149  static int pl022_spi_xfer(struct udevice *dev, unsigned int bitlen,
150  			  const void *dout, void *din, unsigned long flags)
151  {
152  	struct udevice *bus = dev->parent;
153  	struct pl022_spi_slave *ps = dev_get_priv(bus);
154  	u32		len_tx = 0, len_rx = 0, len;
155  	u32		ret = 0;
156  	const u8	*txp = dout;
157  	u8		*rxp = din, value;
158  
159  	if (bitlen == 0)
160  		/* Finish any previously submitted transfers */
161  		return 0;
162  
163  	/*
164  	 * TODO: The controller can do non-multiple-of-8 bit
165  	 * transfers, but this driver currently doesn't support it.
166  	 *
167  	 * It's also not clear how such transfers are supposed to be
168  	 * represented as a stream of bytes...this is a limitation of
169  	 * the current SPI interface.
170  	 */
171  	if (bitlen % 8) {
172  		/* Errors always terminate an ongoing transfer */
173  		flags |= SPI_XFER_END;
174  		return -1;
175  	}
176  
177  	len = bitlen / 8;
178  
179  	while (len_tx < len) {
180  		if (readw(ps->base + SSP_SR) & SSP_SR_MASK_TNF) {
181  			value = txp ? *txp++ : 0;
182  			writew(value, ps->base + SSP_DR);
183  			len_tx++;
184  		}
185  
186  		if (readw(ps->base + SSP_SR) & SSP_SR_MASK_RNE) {
187  			value = readw(ps->base + SSP_DR);
188  			if (rxp)
189  				*rxp++ = value;
190  			len_rx++;
191  		}
192  	}
193  
194  	while (len_rx < len_tx) {
195  		if (readw(ps->base + SSP_SR) & SSP_SR_MASK_RNE) {
196  			value = readw(ps->base + SSP_DR);
197  			if (rxp)
198  				*rxp++ = value;
199  			len_rx++;
200  		}
201  	}
202  
203  	return ret;
204  }
205  
spi_rate(u32 rate,u16 cpsdvsr,u16 scr)206  static inline u32 spi_rate(u32 rate, u16 cpsdvsr, u16 scr)
207  {
208  	return rate / (cpsdvsr * (1 + scr));
209  }
210  
pl022_spi_set_speed(struct udevice * bus,uint speed)211  static int pl022_spi_set_speed(struct udevice *bus, uint speed)
212  {
213  	struct pl022_spi_slave *ps = dev_get_priv(bus);
214  	u16 scr = SSP_SCR_MIN, cr0 = 0, cpsr = SSP_CPSR_MIN, best_scr = scr,
215  	    best_cpsr = cpsr;
216  	u32 min, max, best_freq = 0, tmp;
217  	u32 rate = ps->freq;
218  	bool found = false;
219  
220  	max = spi_rate(rate, SSP_CPSR_MIN, SSP_SCR_MIN);
221  	min = spi_rate(rate, SSP_CPSR_MAX, SSP_SCR_MAX);
222  
223  	if (speed > max || speed < min) {
224  		pr_err("Tried to set speed to %dHz but min=%d and max=%d\n",
225  		       speed, min, max);
226  		return -EINVAL;
227  	}
228  
229  	while (cpsr <= SSP_CPSR_MAX && !found) {
230  		while (scr <= SSP_SCR_MAX) {
231  			tmp = spi_rate(rate, cpsr, scr);
232  
233  			if (abs(speed - tmp) < abs(speed - best_freq)) {
234  				best_freq = tmp;
235  				best_cpsr = cpsr;
236  				best_scr = scr;
237  
238  				if (tmp == speed) {
239  					found = true;
240  					break;
241  				}
242  			}
243  
244  			scr++;
245  		}
246  		cpsr += 2;
247  		scr = SSP_SCR_MIN;
248  	}
249  
250  	writew(best_cpsr, ps->base + SSP_CPSR);
251  	cr0 = readw(ps->base + SSP_CR0);
252  	writew(cr0 | (best_scr << SSP_SCR_SHFT), ps->base + SSP_CR0);
253  
254  	return 0;
255  }
256  
pl022_spi_set_mode(struct udevice * bus,uint mode)257  static int pl022_spi_set_mode(struct udevice *bus, uint mode)
258  {
259  	struct pl022_spi_slave *ps = dev_get_priv(bus);
260  	u16 reg;
261  
262  	reg = readw(ps->base + SSP_CR0);
263  	reg &= ~(SSP_CR0_SPH | SSP_CR0_SPO);
264  	if (mode & SPI_CPHA)
265  		reg |= SSP_CR0_SPH;
266  	if (mode & SPI_CPOL)
267  		reg |= SSP_CR0_SPO;
268  	writew(reg, ps->base + SSP_CR0);
269  
270  	return 0;
271  }
272  
pl022_cs_info(struct udevice * bus,uint cs,struct spi_cs_info * info)273  static int pl022_cs_info(struct udevice *bus, uint cs,
274  			 struct spi_cs_info *info)
275  {
276  	return 0;
277  }
278  
279  static const struct dm_spi_ops pl022_spi_ops = {
280  	.claim_bus      = pl022_spi_claim_bus,
281  	.release_bus    = pl022_spi_release_bus,
282  	.xfer           = pl022_spi_xfer,
283  	.set_speed      = pl022_spi_set_speed,
284  	.set_mode       = pl022_spi_set_mode,
285  	.cs_info        = pl022_cs_info,
286  };
287  
288  #if !CONFIG_IS_ENABLED(OF_PLATDATA)
pl022_spi_ofdata_to_platdata(struct udevice * bus)289  static int pl022_spi_ofdata_to_platdata(struct udevice *bus)
290  {
291  	struct pl022_spi_pdata *plat = bus->platdata;
292  	const void *fdt = gd->fdt_blob;
293  	int node = dev_of_offset(bus);
294  	struct clk clkdev;
295  	int ret;
296  
297  	plat->addr = fdtdec_get_addr_size(fdt, node, "reg", &plat->size);
298  
299  	ret = clk_get_by_index(bus, 0, &clkdev);
300  	if (ret)
301  		return ret;
302  
303  	plat->freq = clk_get_rate(&clkdev);
304  
305  	return 0;
306  }
307  
308  static const struct udevice_id pl022_spi_ids[] = {
309  	{ .compatible = "arm,pl022-spi" },
310  	{ }
311  };
312  #endif
313  
314  U_BOOT_DRIVER(pl022_spi) = {
315  	.name   = "pl022_spi",
316  	.id     = UCLASS_SPI,
317  #if !CONFIG_IS_ENABLED(OF_PLATDATA)
318  	.of_match = pl022_spi_ids,
319  	.ofdata_to_platdata = pl022_spi_ofdata_to_platdata,
320  #endif
321  	.ops    = &pl022_spi_ops,
322  	.platdata_auto_alloc_size = sizeof(struct pl022_spi_pdata),
323  	.priv_auto_alloc_size = sizeof(struct pl022_spi_slave),
324  	.probe  = pl022_spi_probe,
325  };
326