dm: treewide: Rename auto_alloc_size members to be shorter
[platform/kernel/u-boot.git] / drivers / spi / kirkwood_spi.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2009
4  * Marvell Semiconductor <www.marvell.com>
5  * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
6  *
7  * Derived from drivers/spi/mpc8xxx_spi.c
8  */
9
10 #include <common.h>
11 #include <dm.h>
12 #include <log.h>
13 #include <malloc.h>
14 #include <spi.h>
15 #include <asm/io.h>
16 #include <asm/arch/soc.h>
17 #ifdef CONFIG_ARCH_KIRKWOOD
18 #include <asm/arch/mpp.h>
19 #endif
20 #include <asm/arch-mvebu/spi.h>
21
22 struct mvebu_spi_dev {
23         bool                    is_errata_50mhz_ac;
24 };
25
26 struct mvebu_spi_platdata {
27         struct kwspi_registers *spireg;
28         bool is_errata_50mhz_ac;
29 };
30
31 struct mvebu_spi_priv {
32         struct kwspi_registers *spireg;
33 };
34
35 static void _spi_cs_activate(struct kwspi_registers *reg)
36 {
37         setbits_le32(&reg->ctrl, KWSPI_CSN_ACT);
38 }
39
40 static void _spi_cs_deactivate(struct kwspi_registers *reg)
41 {
42         clrbits_le32(&reg->ctrl, KWSPI_CSN_ACT);
43 }
44
45 static int _spi_xfer(struct kwspi_registers *reg, unsigned int bitlen,
46                      const void *dout, void *din, unsigned long flags)
47 {
48         unsigned int tmpdout, tmpdin;
49         int tm, isread = 0;
50
51         debug("spi_xfer: dout %p din %p bitlen %u\n", dout, din, bitlen);
52
53         if (flags & SPI_XFER_BEGIN)
54                 _spi_cs_activate(reg);
55
56         /*
57          * handle data in 8-bit chunks
58          * TBD: 2byte xfer mode to be enabled
59          */
60         clrsetbits_le32(&reg->cfg, KWSPI_XFERLEN_MASK, KWSPI_XFERLEN_1BYTE);
61
62         while (bitlen > 4) {
63                 debug("loopstart bitlen %d\n", bitlen);
64                 tmpdout = 0;
65
66                 /* Shift data so it's msb-justified */
67                 if (dout)
68                         tmpdout = *(u32 *)dout & 0xff;
69
70                 clrbits_le32(&reg->irq_cause, KWSPI_SMEMRDIRQ);
71                 writel(tmpdout, &reg->dout);    /* Write the data out */
72                 debug("*** spi_xfer: ... %08x written, bitlen %d\n",
73                       tmpdout, bitlen);
74
75                 /*
76                  * Wait for SPI transmit to get out
77                  * or time out (1 second = 1000 ms)
78                  * The NE event must be read and cleared first
79                  */
80                 for (tm = 0, isread = 0; tm < KWSPI_TIMEOUT; ++tm) {
81                         if (readl(&reg->irq_cause) & KWSPI_SMEMRDIRQ) {
82                                 isread = 1;
83                                 tmpdin = readl(&reg->din);
84                                 debug("spi_xfer: din %p..%08x read\n",
85                                       din, tmpdin);
86
87                                 if (din) {
88                                         *((u8 *)din) = (u8)tmpdin;
89                                         din += 1;
90                                 }
91                                 if (dout)
92                                         dout += 1;
93                                 bitlen -= 8;
94                         }
95                         if (isread)
96                                 break;
97                 }
98                 if (tm >= KWSPI_TIMEOUT)
99                         printf("*** spi_xfer: Time out during SPI transfer\n");
100
101                 debug("loopend bitlen %d\n", bitlen);
102         }
103
104         if (flags & SPI_XFER_END)
105                 _spi_cs_deactivate(reg);
106
107         return 0;
108 }
109
110 static int mvebu_spi_set_speed(struct udevice *bus, uint hz)
111 {
112         struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
113         struct kwspi_registers *reg = plat->spireg;
114         u32 data;
115
116         /* calculate spi clock prescaller using max_hz */
117         data = ((CONFIG_SYS_TCLK / 2) / hz) + 0x10;
118         data = data < KWSPI_CLKPRESCL_MIN ? KWSPI_CLKPRESCL_MIN : data;
119         data = data > KWSPI_CLKPRESCL_MASK ? KWSPI_CLKPRESCL_MASK : data;
120
121         /* program spi clock prescaler using max_hz */
122         writel(KWSPI_ADRLEN_3BYTE | data, &reg->cfg);
123         debug("data = 0x%08x\n", data);
124
125         return 0;
126 }
127
128 static void mvebu_spi_50mhz_ac_timing_erratum(struct udevice *bus, uint mode)
129 {
130         struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
131         struct kwspi_registers *reg = plat->spireg;
132         u32 data;
133
134         /*
135          * Erratum description: (Erratum NO. FE-9144572) The device
136          * SPI interface supports frequencies of up to 50 MHz.
137          * However, due to this erratum, when the device core clock is
138          * 250 MHz and the SPI interfaces is configured for 50MHz SPI
139          * clock and CPOL=CPHA=1 there might occur data corruption on
140          * reads from the SPI device.
141          * Erratum Workaround:
142          * Work in one of the following configurations:
143          * 1. Set CPOL=CPHA=0 in "SPI Interface Configuration
144          * Register".
145          * 2. Set TMISO_SAMPLE value to 0x2 in "SPI Timing Parameters 1
146          * Register" before setting the interface.
147          */
148         data = readl(&reg->timing1);
149         data &= ~KW_SPI_TMISO_SAMPLE_MASK;
150
151         if (CONFIG_SYS_TCLK == 250000000 &&
152             mode & SPI_CPOL &&
153             mode & SPI_CPHA)
154                 data |= KW_SPI_TMISO_SAMPLE_2;
155         else
156                 data |= KW_SPI_TMISO_SAMPLE_1;
157
158         writel(data, &reg->timing1);
159 }
160
161 static int mvebu_spi_set_mode(struct udevice *bus, uint mode)
162 {
163         struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
164         struct kwspi_registers *reg = plat->spireg;
165         u32 data = readl(&reg->cfg);
166
167         data &= ~(KWSPI_CPHA | KWSPI_CPOL | KWSPI_RXLSBF | KWSPI_TXLSBF);
168
169         if (mode & SPI_CPHA)
170                 data |= KWSPI_CPHA;
171         if (mode & SPI_CPOL)
172                 data |= KWSPI_CPOL;
173         if (mode & SPI_LSB_FIRST)
174                 data |= (KWSPI_RXLSBF | KWSPI_TXLSBF);
175
176         writel(data, &reg->cfg);
177
178         if (plat->is_errata_50mhz_ac)
179                 mvebu_spi_50mhz_ac_timing_erratum(bus, mode);
180
181         return 0;
182 }
183
184 static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen,
185                           const void *dout, void *din, unsigned long flags)
186 {
187         struct udevice *bus = dev->parent;
188         struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
189
190         return _spi_xfer(plat->spireg, bitlen, dout, din, flags);
191 }
192
193 __attribute__((weak)) int mvebu_board_spi_claim_bus(struct udevice *dev)
194 {
195         return 0;
196 }
197
198 static int mvebu_spi_claim_bus(struct udevice *dev)
199 {
200         struct udevice *bus = dev->parent;
201         struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
202
203         /* Configure the chip-select in the CTRL register */
204         clrsetbits_le32(&plat->spireg->ctrl,
205                         KWSPI_CS_MASK << KWSPI_CS_SHIFT,
206                         spi_chip_select(dev) << KWSPI_CS_SHIFT);
207
208         return mvebu_board_spi_claim_bus(dev);
209 }
210
211 __attribute__((weak)) int mvebu_board_spi_release_bus(struct udevice *dev)
212 {
213         return 0;
214 }
215
216 static int mvebu_spi_release_bus(struct udevice *dev)
217 {
218         return mvebu_board_spi_release_bus(dev);
219 }
220
221 static int mvebu_spi_probe(struct udevice *bus)
222 {
223         struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
224         struct kwspi_registers *reg = plat->spireg;
225
226         writel(KWSPI_SMEMRDY, &reg->ctrl);
227         writel(KWSPI_SMEMRDIRQ, &reg->irq_cause);
228         writel(KWSPI_IRQMASK, &reg->irq_mask);
229
230         return 0;
231 }
232
233 static int mvebu_spi_ofdata_to_platdata(struct udevice *bus)
234 {
235         struct mvebu_spi_platdata *plat = dev_get_platdata(bus);
236         const struct mvebu_spi_dev *drvdata =
237                 (struct mvebu_spi_dev *)dev_get_driver_data(bus);
238
239         plat->spireg = dev_read_addr_ptr(bus);
240         plat->is_errata_50mhz_ac = drvdata->is_errata_50mhz_ac;
241
242         return 0;
243 }
244
245 static const struct dm_spi_ops mvebu_spi_ops = {
246         .claim_bus      = mvebu_spi_claim_bus,
247         .release_bus    = mvebu_spi_release_bus,
248         .xfer           = mvebu_spi_xfer,
249         .set_speed      = mvebu_spi_set_speed,
250         .set_mode       = mvebu_spi_set_mode,
251         /*
252          * cs_info is not needed, since we require all chip selects to be
253          * in the device tree explicitly
254          */
255 };
256
257 static const struct mvebu_spi_dev armada_spi_dev_data = {
258         .is_errata_50mhz_ac = false,
259 };
260
261 static const struct mvebu_spi_dev armada_xp_spi_dev_data = {
262         .is_errata_50mhz_ac = false,
263 };
264
265 static const struct mvebu_spi_dev armada_375_spi_dev_data = {
266         .is_errata_50mhz_ac = false,
267 };
268
269 static const struct mvebu_spi_dev armada_380_spi_dev_data = {
270         .is_errata_50mhz_ac = true,
271 };
272
273 static const struct udevice_id mvebu_spi_ids[] = {
274         {
275                 .compatible = "marvell,orion-spi",
276                 .data = (ulong)&armada_spi_dev_data,
277         },
278         {
279                 .compatible = "marvell,armada-375-spi",
280                 .data = (ulong)&armada_375_spi_dev_data
281         },
282         {
283                 .compatible = "marvell,armada-380-spi",
284                 .data = (ulong)&armada_380_spi_dev_data
285         },
286         {
287                 .compatible = "marvell,armada-xp-spi",
288                 .data = (ulong)&armada_xp_spi_dev_data
289         },
290         { }
291 };
292
293 U_BOOT_DRIVER(mvebu_spi) = {
294         .name = "mvebu_spi",
295         .id = UCLASS_SPI,
296         .of_match = mvebu_spi_ids,
297         .ops = &mvebu_spi_ops,
298         .ofdata_to_platdata = mvebu_spi_ofdata_to_platdata,
299         .platdata_auto  = sizeof(struct mvebu_spi_platdata),
300         .priv_auto      = sizeof(struct mvebu_spi_priv),
301         .probe = mvebu_spi_probe,
302 };