~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/drivers/spi/cf_spi.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 * (C) Copyright 2000-2003
 
4
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 
5
 *
 
6
 * Copyright (C) 2004-2009 Freescale Semiconductor, Inc.
 
7
 * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
 
8
 *
 
9
 * SPDX-License-Identifier:     GPL-2.0+
 
10
 */
 
11
 
 
12
#include <common.h>
 
13
#include <spi.h>
 
14
#include <malloc.h>
 
15
#include <asm/immap.h>
 
16
 
 
17
struct cf_spi_slave {
 
18
        struct spi_slave slave;
 
19
        uint baudrate;
 
20
        int charbit;
 
21
};
 
22
 
 
23
int cfspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout,
 
24
               void *din, ulong flags);
 
25
struct spi_slave *cfspi_setup_slave(struct cf_spi_slave *cfslave, uint mode);
 
26
void cfspi_init(void);
 
27
void cfspi_tx(u32 ctrl, u16 data);
 
28
u16 cfspi_rx(void);
 
29
 
 
30
extern void cfspi_port_conf(void);
 
31
extern int cfspi_claim_bus(uint bus, uint cs);
 
32
extern void cfspi_release_bus(uint bus, uint cs);
 
33
 
 
34
DECLARE_GLOBAL_DATA_PTR;
 
35
 
 
36
#ifndef CONFIG_SPI_IDLE_VAL
 
37
#if defined(CONFIG_SPI_MMC)
 
38
#define CONFIG_SPI_IDLE_VAL     0xFFFF
 
39
#else
 
40
#define CONFIG_SPI_IDLE_VAL     0x0
 
41
#endif
 
42
#endif
 
43
 
 
44
#if defined(CONFIG_CF_DSPI)
 
45
/* DSPI specific mode */
 
46
#define SPI_MODE_MOD    0x00200000
 
47
#define SPI_DBLRATE     0x00100000
 
48
 
 
49
void cfspi_init(void)
 
50
{
 
51
        volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI;
 
52
 
 
53
        cfspi_port_conf();      /* port configuration */
 
54
 
 
55
        dspi->mcr = DSPI_MCR_MSTR | DSPI_MCR_CSIS7 | DSPI_MCR_CSIS6 |
 
56
            DSPI_MCR_CSIS5 | DSPI_MCR_CSIS4 | DSPI_MCR_CSIS3 |
 
57
            DSPI_MCR_CSIS2 | DSPI_MCR_CSIS1 | DSPI_MCR_CSIS0 |
 
58
            DSPI_MCR_CRXF | DSPI_MCR_CTXF;
 
59
 
 
60
        /* Default setting in platform configuration */
 
61
#ifdef CONFIG_SYS_DSPI_CTAR0
 
62
        dspi->ctar[0] = CONFIG_SYS_DSPI_CTAR0;
 
63
#endif
 
64
#ifdef CONFIG_SYS_DSPI_CTAR1
 
65
        dspi->ctar[1] = CONFIG_SYS_DSPI_CTAR1;
 
66
#endif
 
67
#ifdef CONFIG_SYS_DSPI_CTAR2
 
68
        dspi->ctar[2] = CONFIG_SYS_DSPI_CTAR2;
 
69
#endif
 
70
#ifdef CONFIG_SYS_DSPI_CTAR3
 
71
        dspi->ctar[3] = CONFIG_SYS_DSPI_CTAR3;
 
72
#endif
 
73
#ifdef CONFIG_SYS_DSPI_CTAR4
 
74
        dspi->ctar[4] = CONFIG_SYS_DSPI_CTAR4;
 
75
#endif
 
76
#ifdef CONFIG_SYS_DSPI_CTAR5
 
77
        dspi->ctar[5] = CONFIG_SYS_DSPI_CTAR5;
 
78
#endif
 
79
#ifdef CONFIG_SYS_DSPI_CTAR6
 
80
        dspi->ctar[6] = CONFIG_SYS_DSPI_CTAR6;
 
81
#endif
 
82
#ifdef CONFIG_SYS_DSPI_CTAR7
 
83
        dspi->ctar[7] = CONFIG_SYS_DSPI_CTAR7;
 
84
#endif
 
85
}
 
86
 
 
87
void cfspi_tx(u32 ctrl, u16 data)
 
88
{
 
89
        volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI;
 
90
 
 
91
        while ((dspi->sr & 0x0000F000) >= 4) ;
 
92
 
 
93
        dspi->tfr = (ctrl | data);
 
94
}
 
95
 
 
96
u16 cfspi_rx(void)
 
97
{
 
98
        volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI;
 
99
 
 
100
        while ((dspi->sr & 0x000000F0) == 0) ;
 
101
 
 
102
        return (dspi->rfr & 0xFFFF);
 
103
}
 
104
 
 
105
int cfspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout,
 
106
               void *din, ulong flags)
 
107
{
 
108
        struct cf_spi_slave *cfslave = (struct cf_spi_slave *)slave;
 
109
        u16 *spi_rd16 = NULL, *spi_wr16 = NULL;
 
110
        u8 *spi_rd = NULL, *spi_wr = NULL;
 
111
        static u32 ctrl = 0;
 
112
        uint len = bitlen >> 3;
 
113
 
 
114
        if (cfslave->charbit == 16) {
 
115
                bitlen >>= 1;
 
116
                spi_wr16 = (u16 *) dout;
 
117
                spi_rd16 = (u16 *) din;
 
118
        } else {
 
119
                spi_wr = (u8 *) dout;
 
120
                spi_rd = (u8 *) din;
 
121
        }
 
122
 
 
123
        if ((flags & SPI_XFER_BEGIN) == SPI_XFER_BEGIN)
 
124
                ctrl |= DSPI_TFR_CONT;
 
125
 
 
126
        ctrl = (ctrl & 0xFF000000) | ((1 << slave->cs) << 16);
 
127
 
 
128
        if (len > 1) {
 
129
                int tmp_len = len - 1;
 
130
                while (tmp_len--) {
 
131
                        if (dout != NULL) {
 
132
                                if (cfslave->charbit == 16)
 
133
                                        cfspi_tx(ctrl, *spi_wr16++);
 
134
                                else
 
135
                                        cfspi_tx(ctrl, *spi_wr++);
 
136
                                cfspi_rx();
 
137
                        }
 
138
 
 
139
                        if (din != NULL) {
 
140
                                cfspi_tx(ctrl, CONFIG_SPI_IDLE_VAL);
 
141
                                if (cfslave->charbit == 16)
 
142
                                        *spi_rd16++ = cfspi_rx();
 
143
                                else
 
144
                                        *spi_rd++ = cfspi_rx();
 
145
                        }
 
146
                }
 
147
 
 
148
                len = 1;        /* remaining byte */
 
149
        }
 
150
 
 
151
        if ((flags & SPI_XFER_END) == SPI_XFER_END)
 
152
                ctrl &= ~DSPI_TFR_CONT;
 
153
 
 
154
        if (len) {
 
155
                if (dout != NULL) {
 
156
                        if (cfslave->charbit == 16)
 
157
                                cfspi_tx(ctrl, *spi_wr16);
 
158
                        else
 
159
                                cfspi_tx(ctrl, *spi_wr);
 
160
                        cfspi_rx();
 
161
                }
 
162
 
 
163
                if (din != NULL) {
 
164
                        cfspi_tx(ctrl, CONFIG_SPI_IDLE_VAL);
 
165
                        if (cfslave->charbit == 16)
 
166
                                *spi_rd16 = cfspi_rx();
 
167
                        else
 
168
                                *spi_rd = cfspi_rx();
 
169
                }
 
170
        } else {
 
171
                /* dummy read */
 
172
                cfspi_tx(ctrl, CONFIG_SPI_IDLE_VAL);
 
173
                cfspi_rx();
 
174
        }
 
175
 
 
176
        return 0;
 
177
}
 
178
 
 
179
struct spi_slave *cfspi_setup_slave(struct cf_spi_slave *cfslave, uint mode)
 
180
{
 
181
        /*
 
182
         * bit definition for mode:
 
183
         * bit 31 - 28: Transfer size 3 to 16 bits
 
184
         *     27 - 26: PCS to SCK delay prescaler
 
185
         *     25 - 24: After SCK delay prescaler
 
186
         *     23 - 22: Delay after transfer prescaler
 
187
         *     21     : Allow overwrite for bit 31-22 and bit 20-8
 
188
         *     20     : Double baud rate
 
189
         *     19 - 16: PCS to SCK delay scaler
 
190
         *     15 - 12: After SCK delay scaler
 
191
         *     11 -  8: Delay after transfer scaler
 
192
         *      7 -  0: SPI_CPHA, SPI_CPOL, SPI_LSB_FIRST
 
193
         */
 
194
        volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI;
 
195
        int prescaler[] = { 2, 3, 5, 7 };
 
196
        int scaler[] = {
 
197
                2, 4, 6, 8,
 
198
                16, 32, 64, 128,
 
199
                256, 512, 1024, 2048,
 
200
                4096, 8192, 16384, 32768
 
201
        };
 
202
        int i, j, pbrcnt, brcnt, diff, tmp, dbr = 0;
 
203
        int best_i, best_j, bestmatch = 0x7FFFFFFF, baud_speed;
 
204
        u32 bus_setup = 0;
 
205
 
 
206
        tmp = (prescaler[3] * scaler[15]);
 
207
        /* Maximum and minimum baudrate it can handle */
 
208
        if ((cfslave->baudrate > (gd->bus_clk >> 1)) ||
 
209
            (cfslave->baudrate < (gd->bus_clk / tmp))) {
 
210
                printf("Exceed baudrate limitation: Max %d - Min %d\n",
 
211
                       (int)(gd->bus_clk >> 1), (int)(gd->bus_clk / tmp));
 
212
                return NULL;
 
213
        }
 
214
 
 
215
        /* Activate Double Baud when it exceed 1/4 the bus clk */
 
216
        if ((CONFIG_SYS_DSPI_CTAR0 & DSPI_CTAR_DBR) ||
 
217
            (cfslave->baudrate > (gd->bus_clk / (prescaler[0] * scaler[0])))) {
 
218
                bus_setup |= DSPI_CTAR_DBR;
 
219
                dbr = 1;
 
220
        }
 
221
 
 
222
        if (mode & SPI_CPOL)
 
223
                bus_setup |= DSPI_CTAR_CPOL;
 
224
        if (mode & SPI_CPHA)
 
225
                bus_setup |= DSPI_CTAR_CPHA;
 
226
        if (mode & SPI_LSB_FIRST)
 
227
                bus_setup |= DSPI_CTAR_LSBFE;
 
228
 
 
229
        /* Overwrite default value set in platform configuration file */
 
230
        if (mode & SPI_MODE_MOD) {
 
231
 
 
232
                if ((mode & 0xF0000000) == 0)
 
233
                        bus_setup |=
 
234
                            dspi->ctar[cfslave->slave.bus] & 0x78000000;
 
235
                else
 
236
                        bus_setup |= ((mode & 0xF0000000) >> 1);
 
237
 
 
238
                /*
 
239
                 * Check to see if it is enabled by default in platform
 
240
                 * config, or manual setting passed by mode parameter
 
241
                 */
 
242
                if (mode & SPI_DBLRATE) {
 
243
                        bus_setup |= DSPI_CTAR_DBR;
 
244
                        dbr = 1;
 
245
                }
 
246
                bus_setup |= (mode & 0x0FC00000) >> 4;  /* PSCSCK, PASC, PDT */
 
247
                bus_setup |= (mode & 0x000FFF00) >> 4;  /* CSSCK, ASC, DT */
 
248
        } else
 
249
                bus_setup |= (dspi->ctar[cfslave->slave.bus] & 0x78FCFFF0);
 
250
 
 
251
        cfslave->charbit =
 
252
            ((dspi->ctar[cfslave->slave.bus] & 0x78000000) ==
 
253
             0x78000000) ? 16 : 8;
 
254
 
 
255
        pbrcnt = sizeof(prescaler) / sizeof(int);
 
256
        brcnt = sizeof(scaler) / sizeof(int);
 
257
 
 
258
        /* baudrate calculation - to closer value, may not be exact match */
 
259
        for (best_i = 0, best_j = 0, i = 0; i < pbrcnt; i++) {
 
260
                baud_speed = gd->bus_clk / prescaler[i];
 
261
                for (j = 0; j < brcnt; j++) {
 
262
                        tmp = (baud_speed / scaler[j]) * (1 + dbr);
 
263
 
 
264
                        if (tmp > cfslave->baudrate)
 
265
                                diff = tmp - cfslave->baudrate;
 
266
                        else
 
267
                                diff = cfslave->baudrate - tmp;
 
268
 
 
269
                        if (diff < bestmatch) {
 
270
                                bestmatch = diff;
 
271
                                best_i = i;
 
272
                                best_j = j;
 
273
                        }
 
274
                }
 
275
        }
 
276
        bus_setup |= (DSPI_CTAR_PBR(best_i) | DSPI_CTAR_BR(best_j));
 
277
        dspi->ctar[cfslave->slave.bus] = bus_setup;
 
278
 
 
279
        return &cfslave->slave;
 
280
}
 
281
#endif                          /* CONFIG_CF_DSPI */
 
282
 
 
283
#ifdef CONFIG_CF_QSPI
 
284
/* 52xx, 53xx */
 
285
#endif                          /* CONFIG_CF_QSPI */
 
286
 
 
287
#ifdef CONFIG_CMD_SPI
 
288
int spi_cs_is_valid(unsigned int bus, unsigned int cs)
 
289
{
 
290
        if (((cs >= 0) && (cs < 8)) && ((bus >= 0) && (bus < 8)))
 
291
                return 1;
 
292
        else
 
293
                return 0;
 
294
}
 
295
 
 
296
void spi_init_f(void)
 
297
{
 
298
}
 
299
 
 
300
void spi_init_r(void)
 
301
{
 
302
}
 
303
 
 
304
void spi_init(void)
 
305
{
 
306
        cfspi_init();
 
307
}
 
308
 
 
309
struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
 
310
                                  unsigned int max_hz, unsigned int mode)
 
311
{
 
312
        struct cf_spi_slave *cfslave;
 
313
 
 
314
        if (!spi_cs_is_valid(bus, cs))
 
315
                return NULL;
 
316
 
 
317
        cfslave = spi_alloc_slave(struct cf_spi_slave, bus, cs);
 
318
        if (!cfslave)
 
319
                return NULL;
 
320
 
 
321
        cfslave->baudrate = max_hz;
 
322
 
 
323
        /* specific setup */
 
324
        return cfspi_setup_slave(cfslave, mode);
 
325
}
 
326
 
 
327
void spi_free_slave(struct spi_slave *slave)
 
328
{
 
329
        free(slave);
 
330
}
 
331
 
 
332
int spi_claim_bus(struct spi_slave *slave)
 
333
{
 
334
        return cfspi_claim_bus(slave->bus, slave->cs);
 
335
}
 
336
 
 
337
void spi_release_bus(struct spi_slave *slave)
 
338
{
 
339
        cfspi_release_bus(slave->bus, slave->cs);
 
340
}
 
341
 
 
342
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
 
343
             void *din, unsigned long flags)
 
344
{
 
345
        return cfspi_xfer(slave, bitlen, dout, din, flags);
 
346
}
 
347
#endif                          /* CONFIG_CMD_SPI */