]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - drivers/spi/zynq_spi.c
usb: dwc2: implement interrupt transfers
[karo-tx-uboot.git] / drivers / spi / zynq_spi.c
1 /*
2  * (C) Copyright 2013 Inc.
3  *
4  * Xilinx Zynq PS SPI controller driver (master mode only)
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <config.h>
10 #include <common.h>
11 #include <malloc.h>
12 #include <spi.h>
13 #include <asm/io.h>
14 #include <asm/arch/hardware.h>
15
16 /* zynq spi register bit masks ZYNQ_SPI_<REG>_<BIT>_MASK */
17 #define ZYNQ_SPI_CR_MSA_MASK            (1 << 15)       /* Manual start enb */
18 #define ZYNQ_SPI_CR_MCS_MASK            (1 << 14)       /* Manual chip select */
19 #define ZYNQ_SPI_CR_CS_MASK             (0xF << 10)     /* Chip select */
20 #define ZYNQ_SPI_CR_BRD_MASK            (0x7 << 3)      /* Baud rate div */
21 #define ZYNQ_SPI_CR_CPHA_MASK           (1 << 2)        /* Clock phase */
22 #define ZYNQ_SPI_CR_CPOL_MASK           (1 << 1)        /* Clock polarity */
23 #define ZYNQ_SPI_CR_MSTREN_MASK         (1 << 0)        /* Mode select */
24 #define ZYNQ_SPI_IXR_RXNEMPTY_MASK      (1 << 4)        /* RX_FIFO_not_empty */
25 #define ZYNQ_SPI_IXR_TXOW_MASK          (1 << 2)        /* TX_FIFO_not_full */
26 #define ZYNQ_SPI_IXR_ALL_MASK           0x7F            /* All IXR bits */
27 #define ZYNQ_SPI_ENR_SPI_EN_MASK        (1 << 0)        /* SPI Enable */
28
29 #define ZYNQ_SPI_FIFO_DEPTH             128
30 #ifndef CONFIG_SYS_ZYNQ_SPI_WAIT
31 #define CONFIG_SYS_ZYNQ_SPI_WAIT        (CONFIG_SYS_HZ/100)     /* 10 ms */
32 #endif
33
34 /* zynq spi register set */
35 struct zynq_spi_regs {
36         u32 cr;         /* 0x00 */
37         u32 isr;        /* 0x04 */
38         u32 ier;        /* 0x08 */
39         u32 idr;        /* 0x0C */
40         u32 imr;        /* 0x10 */
41         u32 enr;        /* 0x14 */
42         u32 dr;         /* 0x18 */
43         u32 txdr;       /* 0x1C */
44         u32 rxdr;       /* 0x20 */
45 };
46
47 /* zynq spi slave */
48 struct zynq_spi_slave {
49         struct spi_slave slave;
50         struct zynq_spi_regs *base;
51         u8 mode;
52         u8 fifo_depth;
53         u32 speed_hz;
54         u32 input_hz;
55         u32 req_hz;
56 };
57
58 static inline struct zynq_spi_slave *to_zynq_spi_slave(struct spi_slave *slave)
59 {
60         return container_of(slave, struct zynq_spi_slave, slave);
61 }
62
63 static inline struct zynq_spi_regs *get_zynq_spi_base(int dev)
64 {
65         if (dev)
66                 return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR1;
67         else
68                 return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR0;
69 }
70
71 static void zynq_spi_init_hw(struct zynq_spi_slave *zslave)
72 {
73         u32 confr;
74
75         /* Disable SPI */
76         writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
77
78         /* Disable Interrupts */
79         writel(ZYNQ_SPI_IXR_ALL_MASK, &zslave->base->idr);
80
81         /* Clear RX FIFO */
82         while (readl(&zslave->base->isr) &
83                         ZYNQ_SPI_IXR_RXNEMPTY_MASK)
84                 readl(&zslave->base->rxdr);
85
86         /* Clear Interrupts */
87         writel(ZYNQ_SPI_IXR_ALL_MASK, &zslave->base->isr);
88
89         /* Manual slave select and Auto start */
90         confr = ZYNQ_SPI_CR_MCS_MASK | ZYNQ_SPI_CR_CS_MASK |
91                 ZYNQ_SPI_CR_MSTREN_MASK;
92         confr &= ~ZYNQ_SPI_CR_MSA_MASK;
93         writel(confr, &zslave->base->cr);
94
95         /* Enable SPI */
96         writel(ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
97 }
98
99 int spi_cs_is_valid(unsigned int bus, unsigned int cs)
100 {
101         /* 2 bus with 3 chipselect */
102         return bus < 2 && cs < 3;
103 }
104
105 void spi_cs_activate(struct spi_slave *slave)
106 {
107         struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
108         u32 cr;
109
110         debug("spi_cs_activate: 0x%08x\n", (u32)slave);
111
112         clrbits_le32(&zslave->base->cr, ZYNQ_SPI_CR_CS_MASK);
113         cr = readl(&zslave->base->cr);
114         /*
115          * CS cal logic: CS[13:10]
116          * xxx0 - cs0
117          * xx01 - cs1
118          * x011 - cs2
119          */
120         cr |= (~(0x1 << slave->cs) << 10) & ZYNQ_SPI_CR_CS_MASK;
121         writel(cr, &zslave->base->cr);
122 }
123
124 void spi_cs_deactivate(struct spi_slave *slave)
125 {
126         struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
127
128         debug("spi_cs_deactivate: 0x%08x\n", (u32)slave);
129
130         setbits_le32(&zslave->base->cr, ZYNQ_SPI_CR_CS_MASK);
131 }
132
133 void spi_init()
134 {
135         /* nothing to do */
136 }
137
138 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
139                 unsigned int max_hz, unsigned int mode)
140 {
141         struct zynq_spi_slave *zslave;
142
143         if (!spi_cs_is_valid(bus, cs))
144                 return NULL;
145
146         zslave = spi_alloc_slave(struct zynq_spi_slave, bus, cs);
147         if (!zslave) {
148                 printf("SPI_error: Fail to allocate zynq_spi_slave\n");
149                 return NULL;
150         }
151
152         zslave->base = get_zynq_spi_base(bus);
153         zslave->mode = mode;
154         zslave->fifo_depth = ZYNQ_SPI_FIFO_DEPTH;
155         zslave->input_hz = 166666700;
156         zslave->speed_hz = zslave->input_hz / 2;
157         zslave->req_hz = max_hz;
158
159         /* init the zynq spi hw */
160         zynq_spi_init_hw(zslave);
161
162         return &zslave->slave;
163 }
164
165 void spi_free_slave(struct spi_slave *slave)
166 {
167         struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
168
169         debug("spi_free_slave: 0x%08x\n", (u32)slave);
170         free(zslave);
171 }
172
173 int spi_claim_bus(struct spi_slave *slave)
174 {
175         struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
176         u32 confr = 0;
177         u8 baud_rate_val = 0;
178
179         writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
180
181         /* Set the SPI Clock phase and polarities */
182         confr = readl(&zslave->base->cr);
183         confr &= ~(ZYNQ_SPI_CR_CPHA_MASK | ZYNQ_SPI_CR_CPOL_MASK);
184         if (zslave->mode & SPI_CPHA)
185                 confr |= ZYNQ_SPI_CR_CPHA_MASK;
186         if (zslave->mode & SPI_CPOL)
187                 confr |= ZYNQ_SPI_CR_CPOL_MASK;
188
189         /* Set the clock frequency */
190         if (zslave->req_hz == 0) {
191                 /* Set baudrate x8, if the req_hz is 0 */
192                 baud_rate_val = 0x2;
193         } else if (zslave->speed_hz != zslave->req_hz) {
194                 while ((baud_rate_val < 8) &&
195                                 ((zslave->input_hz /
196                                 (2 << baud_rate_val)) > zslave->req_hz))
197                         baud_rate_val++;
198                 zslave->speed_hz = zslave->req_hz / (2 << baud_rate_val);
199         }
200         confr &= ~ZYNQ_SPI_CR_BRD_MASK;
201         confr |= (baud_rate_val << 3);
202         writel(confr, &zslave->base->cr);
203
204         writel(ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
205
206         return 0;
207 }
208
209 void spi_release_bus(struct spi_slave *slave)
210 {
211         struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
212
213         debug("spi_release_bus: 0x%08x\n", (u32)slave);
214         writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
215 }
216
217 int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
218                 void *din, unsigned long flags)
219 {
220         struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
221         u32 len = bitlen / 8;
222         u32 tx_len = len, rx_len = len, tx_tvl;
223         const u8 *tx_buf = dout;
224         u8 *rx_buf = din, buf;
225         u32 ts, status;
226
227         debug("spi_xfer: bus:%i cs:%i bitlen:%i len:%i flags:%lx\n",
228               slave->bus, slave->cs, bitlen, len, flags);
229
230         if (bitlen == 0)
231                 return -1;
232
233         if (bitlen % 8) {
234                 debug("spi_xfer: Non byte aligned SPI transfer\n");
235                 return -1;
236         }
237
238         if (flags & SPI_XFER_BEGIN)
239                 spi_cs_activate(slave);
240
241         while (rx_len > 0) {
242                 /* Write the data into TX FIFO - tx threshold is fifo_depth */
243                 tx_tvl = 0;
244                 while ((tx_tvl < zslave->fifo_depth) && tx_len) {
245                         if (tx_buf)
246                                 buf = *tx_buf++;
247                         else
248                                 buf = 0;
249                         writel(buf, &zslave->base->txdr);
250                         tx_len--;
251                         tx_tvl++;
252                 }
253
254                 /* Check TX FIFO completion */
255                 ts = get_timer(0);
256                 status = readl(&zslave->base->isr);
257                 while (!(status & ZYNQ_SPI_IXR_TXOW_MASK)) {
258                         if (get_timer(ts) > CONFIG_SYS_ZYNQ_SPI_WAIT) {
259                                 printf("spi_xfer: Timeout! TX FIFO not full\n");
260                                 return -1;
261                         }
262                         status = readl(&zslave->base->isr);
263                 }
264
265                 /* Read the data from RX FIFO */
266                 status = readl(&zslave->base->isr);
267                 while (status & ZYNQ_SPI_IXR_RXNEMPTY_MASK) {
268                         buf = readl(&zslave->base->rxdr);
269                         if (rx_buf)
270                                 *rx_buf++ = buf;
271                         status = readl(&zslave->base->isr);
272                         rx_len--;
273                 }
274         }
275
276         if (flags & SPI_XFER_END)
277                 spi_cs_deactivate(slave);
278
279         return 0;
280 }