]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/spi/ep93xx_spi.c
nand: mxs: use CONFIG_ARCH_MX6 instead of CONFIG_SOC_MX6Q
[karo-tx-uboot.git] / drivers / spi / ep93xx_spi.c
1 /*
2  * SPI Driver for EP93xx
3  *
4  * Copyright (C) 2013 Sergey Kostanabev <sergey.kostanbaev <at> fairwaves.ru>
5  *
6  * Inspired form linux kernel driver and atmel uboot driver
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  */
10
11 #include <common.h>
12 #include <spi.h>
13 #include <malloc.h>
14
15 #include <asm/io.h>
16
17 #include <asm/arch/ep93xx.h>
18
19
20 #define BIT(x)                  (1<<(x))
21 #define SSPBASE                 SPI_BASE
22
23 #define SSPCR0                  0x0000
24 #define SSPCR0_MODE_SHIFT       6
25 #define SSPCR0_SCR_SHIFT        8
26 #define SSPCR0_SPH              BIT(7)
27 #define SSPCR0_SPO              BIT(6)
28 #define SSPCR0_FRF_SPI          0
29 #define SSPCR0_DSS_8BIT         7
30
31 #define SSPCR1                  0x0004
32 #define SSPCR1_RIE              BIT(0)
33 #define SSPCR1_TIE              BIT(1)
34 #define SSPCR1_RORIE            BIT(2)
35 #define SSPCR1_LBM              BIT(3)
36 #define SSPCR1_SSE              BIT(4)
37 #define SSPCR1_MS               BIT(5)
38 #define SSPCR1_SOD              BIT(6)
39
40 #define SSPDR                   0x0008
41
42 #define SSPSR                   0x000c
43 #define SSPSR_TFE               BIT(0)
44 #define SSPSR_TNF               BIT(1)
45 #define SSPSR_RNE               BIT(2)
46 #define SSPSR_RFF               BIT(3)
47 #define SSPSR_BSY               BIT(4)
48 #define SSPCPSR                 0x0010
49
50 #define SSPIIR                  0x0014
51 #define SSPIIR_RIS              BIT(0)
52 #define SSPIIR_TIS              BIT(1)
53 #define SSPIIR_RORIS            BIT(2)
54 #define SSPICR                  SSPIIR
55
56 #define SSPCLOCK                14745600
57 #define SSP_MAX_RATE            (SSPCLOCK / 2)
58 #define SSP_MIN_RATE            (SSPCLOCK / (254 * 256))
59
60 /* timeout in milliseconds */
61 #define SPI_TIMEOUT             5
62 /* maximum depth of RX/TX FIFO */
63 #define SPI_FIFO_SIZE           8
64
65 struct ep93xx_spi_slave {
66         struct spi_slave slave;
67
68         unsigned sspcr0;
69         unsigned sspcpsr;
70 };
71
72 static inline struct ep93xx_spi_slave *to_ep93xx_spi(struct spi_slave *slave)
73 {
74         return container_of(slave, struct ep93xx_spi_slave, slave);
75 }
76
77 void spi_init()
78 {
79 }
80
81 static inline void ep93xx_spi_write_u8(u16 reg, u8 value)
82 {
83         writel(value, (unsigned int *)(SSPBASE + reg));
84 }
85
86 static inline u8 ep93xx_spi_read_u8(u16 reg)
87 {
88         return readl((unsigned int *)(SSPBASE + reg));
89 }
90
91 static inline void ep93xx_spi_write_u16(u16 reg, u16 value)
92 {
93         writel(value, (unsigned int *)(SSPBASE + reg));
94 }
95
96 static inline u16 ep93xx_spi_read_u16(u16 reg)
97 {
98         return (u16)readl((unsigned int *)(SSPBASE + reg));
99 }
100
101 static int ep93xx_spi_init_hw(unsigned int rate, unsigned int mode,
102                                 struct ep93xx_spi_slave *slave)
103 {
104         unsigned cpsr, scr;
105
106         if (rate > SSP_MAX_RATE)
107                 rate = SSP_MAX_RATE;
108
109         if (rate < SSP_MIN_RATE)
110                 return -1;
111
112         /* Calculate divisors so that we can get speed according the
113          * following formula:
114          *      rate = spi_clock_rate / (cpsr * (1 + scr))
115          *
116          * cpsr must be even number and starts from 2, scr can be any number
117          * between 0 and 255.
118          */
119         for (cpsr = 2; cpsr <= 254; cpsr += 2) {
120                 for (scr = 0; scr <= 255; scr++) {
121                         if ((SSPCLOCK / (cpsr * (scr + 1))) <= rate) {
122                                 /* Set CHPA and CPOL, SPI format and 8bit */
123                                 unsigned sspcr0 = (scr << SSPCR0_SCR_SHIFT) |
124                                         SSPCR0_FRF_SPI | SSPCR0_DSS_8BIT;
125                                 if (mode & SPI_CPHA)
126                                         sspcr0 |= SSPCR0_SPH;
127                                 if (mode & SPI_CPOL)
128                                         sspcr0 |= SSPCR0_SPO;
129
130                                 slave->sspcr0 = sspcr0;
131                                 slave->sspcpsr = cpsr;
132                                 return 0;
133                         }
134                 }
135         }
136
137         return -1;
138 }
139
140 void spi_set_speed(struct spi_slave *slave, unsigned int hz)
141 {
142         struct ep93xx_spi_slave *as = to_ep93xx_spi(slave);
143
144         unsigned int mode = 0;
145         if (as->sspcr0 & SSPCR0_SPH)
146                 mode |= SPI_CPHA;
147         if (as->sspcr0 & SSPCR0_SPO)
148                 mode |= SPI_CPOL;
149
150         ep93xx_spi_init_hw(hz, mode, as);
151 }
152
153 struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
154                         unsigned int max_hz, unsigned int mode)
155 {
156         struct ep93xx_spi_slave *as;
157
158         if (!spi_cs_is_valid(bus, cs))
159                 return NULL;
160
161         as = spi_alloc_slave(struct ep93xx_spi_slave, bus, cs);
162         if (!as)
163                 return NULL;
164
165         if (ep93xx_spi_init_hw(max_hz, mode, as)) {
166                 free(as);
167                 return NULL;
168         }
169
170         return &as->slave;
171 }
172
173 void spi_free_slave(struct spi_slave *slave)
174 {
175         struct ep93xx_spi_slave *as = to_ep93xx_spi(slave);
176
177         free(as);
178 }
179
180 int spi_claim_bus(struct spi_slave *slave)
181 {
182         struct ep93xx_spi_slave *as = to_ep93xx_spi(slave);
183
184         /* Enable the SPI hardware */
185         ep93xx_spi_write_u8(SSPCR1, SSPCR1_SSE);
186
187
188         ep93xx_spi_write_u8(SSPCPSR, as->sspcpsr);
189         ep93xx_spi_write_u16(SSPCR0, as->sspcr0);
190
191         debug("Select CS:%d SSPCPSR=%02x SSPCR0=%04x\n",
192               slave->cs, as->sspcpsr, as->sspcr0);
193         return 0;
194 }
195
196 void spi_release_bus(struct spi_slave *slave)
197 {
198         /* Disable the SPI hardware */
199         ep93xx_spi_write_u8(SSPCR1, 0);
200 }
201
202 int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
203                 const void *dout, void *din, unsigned long flags)
204 {
205         unsigned int    len_tx;
206         unsigned int    len_rx;
207         unsigned int    len;
208         u32             status;
209         const u8        *txp = dout;
210         u8              *rxp = din;
211         u8              value;
212
213         debug("spi_xfer: slave %u:%u dout %p din %p bitlen %u\n",
214               slave->bus, slave->cs, (uint *)dout, (uint *)din, bitlen);
215
216
217         if (bitlen == 0)
218                 /* Finish any previously submitted transfers */
219                 goto out;
220
221         if (bitlen % 8) {
222                 /* Errors always terminate an ongoing transfer */
223                 flags |= SPI_XFER_END;
224                 goto out;
225         }
226
227         len = bitlen / 8;
228
229
230         if (flags & SPI_XFER_BEGIN) {
231                 /* Empty RX FIFO */
232                 while ((ep93xx_spi_read_u8(SSPSR) & SSPSR_RNE))
233                         ep93xx_spi_read_u8(SSPDR);
234
235                 spi_cs_activate(slave);
236         }
237
238         for (len_tx = 0, len_rx = 0; len_rx < len; ) {
239                 status = ep93xx_spi_read_u8(SSPSR);
240
241                 if ((len_tx < len) && (status & SSPSR_TNF)) {
242                         if (txp)
243                                 value = *txp++;
244                         else
245                                 value = 0xff;
246
247                         ep93xx_spi_write_u8(SSPDR, value);
248                         len_tx++;
249                 }
250
251                 if (status & SSPSR_RNE) {
252                         value = ep93xx_spi_read_u8(SSPDR);
253
254                         if (rxp)
255                                 *rxp++ = value;
256                         len_rx++;
257                 }
258         }
259
260 out:
261         if (flags & SPI_XFER_END) {
262                 /*
263                  * Wait until the transfer is completely done before
264                  * we deactivate CS.
265                  */
266                 do {
267                         status = ep93xx_spi_read_u8(SSPSR);
268                 } while (status & SSPSR_BSY);
269
270                 spi_cs_deactivate(slave);
271         }
272
273         return 0;
274 }