]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/devs/spi/arm/imx/v2_0/src/imx_spi.c
Initial revision
[karo-tx-redboot.git] / packages / devs / spi / arm / imx / v2_0 / src / imx_spi.c
1 #include <redboot.h>
2 #include <stdlib.h>
3 #include <pkgconf/hal.h>
4 #include <cyg/hal/hal_arch.h>
5 #include <cyg/hal/hal_cache.h>
6 #include <cyg/hal/hal_io.h>
7
8 #include <cyg/hal/fsl_board.h>
9 #include <cyg/io/imx_spi.h>
10
11 /*!
12  * Initialization function for a spi slave device. It must be called BEFORE
13  * any spi operations. The SPI module will be -disabled- after this call.
14  */
15 int imx_spi_init_v2_3 (struct imx_spi_dev *dev)
16 {
17     unsigned int clk_src = get_peri_clock(dev->base);
18     unsigned int pre_div = 0, post_div = 0, i, reg_ctrl, reg_config;
19     struct spi_v2_3_reg *reg = (struct spi_v2_3_reg *)dev->reg;
20
21     if (dev->freq == 0) {
22         diag_printf("Error: desired clock is 0\n");
23         return -1;
24     }
25     // iomux config
26     io_cfg_spi(dev);
27
28     reg_ctrl = readl(dev->base + 0x8);
29     // reset the spi
30     writel(0, dev->base + 0x8);
31     writel(reg_ctrl | 0x1, dev->base + 0x8);
32
33     // control register setup
34     if (clk_src > dev->freq) {
35         pre_div = clk_src / dev->freq;
36         if (pre_div > 16) {
37             post_div = pre_div / 16;
38             pre_div = 15;
39         }
40         if (post_div != 0) {
41             for (i = 0; i < 16; i++) {
42                 if ((1 << i) >= post_div)
43                     break;
44             }
45             if (i == 16) {
46                 diag_printf("Error: no divider can meet the freq: %d\n",
47                             dev->freq);
48                 return -1;
49             }
50             post_div = i;
51         }
52     }
53     diag_printf1("pre_div = %d, post_div=%d\n", pre_div, post_div);
54     reg_ctrl = (reg_ctrl & ~(3 << 18)) | dev->ss << 18;
55     reg_ctrl = (reg_ctrl & ~(0xF << 12)) | pre_div << 12;
56     reg_ctrl = (reg_ctrl & ~(0xF << 8)) | post_div << 8;
57     reg_ctrl |= 1 << (dev->ss + 4);     // always set to master mode !!!!
58     reg_ctrl &= ~0x1;                   // disable spi
59
60     reg_config = readl(dev->base + 0xC);
61     // configuration register setup
62     reg_config = (reg_config & ~(1 << ((dev->ss + 12)))) |
63         (dev->ss_pol << (dev->ss + 12));
64     reg_config = (reg_config & ~(1 << ((dev->ss + 20)))) |
65         (dev->in_sctl << (dev->ss + 20));
66     reg_config = (reg_config & ~(1 << ((dev->ss + 16)))) |
67         (dev->in_dctl << (dev->ss + 16));
68     reg_config = (reg_config & ~(1 << ((dev->ss + 8)))) |
69         (dev->ssctl << (dev->ss + 8));
70     reg_config = (reg_config & ~(1 << ((dev->ss + 4)))) |
71         (dev->sclkpol << (dev->ss + 4));
72     reg_config = (reg_config & ~(1 << ((dev->ss + 0)))) |
73         (dev->sclkpha << (dev->ss + 0));
74
75     diag_printf1("reg_ctrl = 0x%x\n", reg_ctrl);
76     writel(reg_ctrl, dev->base + 0x8);
77     diag_printf1("reg_config = 0x%x\n", reg_config);
78     writel(reg_config, dev->base + 0xC);
79     // save config register and control register
80     reg->cfg_reg = reg_config;
81     reg->ctrl_reg = reg_ctrl;
82
83     // clear interrupt reg
84     writel(0, dev->base + 0x10);
85     writel(3 << 6, dev->base + 0x18);
86
87     return 0;
88 }
89
90 /*!
91  * This function should only be called after the imx_spi_init_xxx().
92  * It sets up the spi module according to the initialized value and then
93  * enables the SPI module. This function is called by the xfer function.
94  *
95  * Note: If one wants to change the SPI parameters such as clock, the 
96  *       imx_spi_init_xxx() needs to be called again.
97  */
98 static void spi_start_v2_3(struct imx_spi_dev *dev,
99                            struct spi_v2_3_reg *reg, int len)
100 {
101     if (reg->ctrl_reg == 0) {
102         diag_printf("Error: spi(base=0x%x) has not been initialized yet\n",
103                     dev->base);
104         return;
105     }
106     // iomux config
107     io_cfg_spi(dev);
108     reg->ctrl_reg = (reg->ctrl_reg & ~0xFFF00000) | ((len * 8 - 1) << 20);
109
110     writel(reg->ctrl_reg | 0x1, dev->base + 0x8);
111     writel(reg->cfg_reg, dev->base + 0xC);
112     diag_printf1("ctrl_reg=0x%x, cfg_reg=0x%x\n",
113                  readl(dev->base + 0x8), readl(dev->base + 0xC));
114 }
115
116 /*!
117  * Stop the SPI module that the slave device is connected to.
118  */
119 static void spi_stop_v2_3(struct imx_spi_dev *dev)
120 {
121     writel(0, dev->base + 0x8);
122 }
123
124 /*!
125  * Transfer up to burst_bytes bytes data via spi. The amount of data
126  * is the sum of both the tx and rx.
127  * After this call, the SPI module that the slave is connected to will
128  * be -disabled- again.
129  */
130 int imx_spi_xfer_v2_3 (
131     struct imx_spi_dev *dev,    // spi device pointer
132     unsigned char *tx_buf,      // tx buffer (has to be 4-byte aligned)
133     unsigned char *rx_buf,      // rx buffer (has to be 4-byte aligned)
134     int burst_bytes             // total number of bytes in one burst (or xfer)
135     )
136 {
137     int val = SPI_RETRY_TIMES;
138     unsigned int *p_buf;
139     unsigned int reg;
140     int len, ret_val = 0;
141
142     if (burst_bytes > dev->fifo_sz) {
143         diag_printf("Error: maximum burst size is 0x%x bytes, asking 0x%x\n",
144                     dev->fifo_sz, burst_bytes);
145         return -1;
146     }
147
148     spi_start_v2_3(dev, dev->reg, burst_bytes);
149
150     // move data to the tx fifo
151     for (p_buf = (unsigned int *)tx_buf, len = burst_bytes; len > 0;
152          p_buf++, len -= 4) {
153         writel(*p_buf, dev->base + 0x4);
154     }
155     reg = readl(dev->base + 0x8);
156     reg |= (1 << 2); // set xch bit
157     diag_printf1("control reg = 0x%08x\n", reg);
158     writel(reg, dev->base + 0x8);
159
160     // poll on the TC bit (transfer complete)
161     while ((val-- > 0) && (readl(dev->base + 0x18) & (1 << 7)) == 0) {
162         if (dev->us_delay != 0) {
163             hal_delay_us(dev->us_delay);
164         }
165     }
166
167     // clear the TC bit
168     writel(3 << 6, dev->base + 0x18);
169     if (val == 0) {
170         diag_printf("Error: re-tried %d times without response. Give up\n", SPI_RETRY_TIMES);
171         ret_val = -1;
172         goto error;
173     }
174
175     // move data in the rx buf
176     for (p_buf = (unsigned int *)rx_buf, len = burst_bytes; len > 0;
177          p_buf++, len -= 4) {
178         *p_buf = readl(dev->base + 0x0);
179     }
180 error:
181     spi_stop_v2_3(dev);
182     return ret_val;
183 }
184
185 #ifdef PMIC_SPI_BASE
186 extern imx_spi_init_func_t *spi_pmic_init;
187 extern imx_spi_xfer_func_t *spi_pmic_xfer;
188 extern struct imx_spi_dev imx_spi_pmic;
189
190 static void show_pmic_info(void)
191 {
192     volatile unsigned int rev_id;
193
194     spi_pmic_init(&imx_spi_pmic);
195     rev_id = pmic_reg(7, 0, 0);
196     diag_printf("PMIC ID: 0x%08x [Rev: ", rev_id);
197     switch (rev_id & 0x1F) {
198     case 0x1:
199         diag_printf("1.0");
200         break;
201     case 0x9:
202         diag_printf("1.1");
203         break;
204     case 0xA:
205         diag_printf("1.2");
206         break;
207     case 0x10:
208         diag_printf("2.0");
209         break;
210     case 0x11:
211         diag_printf("2.1");
212         break;
213     case 0x18:
214         diag_printf("3.0");
215         break;
216     case 0x19:
217         diag_printf("3.1");
218         break;
219     case 0x1A:
220         diag_printf("3.2");
221         break;
222     case 0x2:
223         diag_printf("3.2A");
224         break;
225     case 0x1B:
226         diag_printf("3.3");
227         break;
228     case 0x1D:
229         diag_printf("3.5");
230         break;
231     default:
232         diag_printf("unknown");
233         break;
234     }
235     diag_printf("]\n");
236 }
237
238 RedBoot_init(show_pmic_info, RedBoot_INIT_PRIO(100));
239
240 static void do_pmic(int argc, char *argv[]);
241 RedBoot_cmd("pmic",
242             "Read/Write internal PMIC register",
243             "<reg num> [value to be written]",
244             do_pmic
245            );
246
247 static void do_pmic(int argc, char *argv[])
248 {
249     unsigned int reg, temp, val = 0, write = 0;
250
251     if (argc == 1) {
252         diag_printf("\tRead:  pmic <reg num>\n");
253         diag_printf("\tWrite: pmic <reg num> <value to be written>\n");
254         return;
255     }
256
257     if (!parse_num(*(&argv[1]), (unsigned long *)&reg, &argv[1], ":")) {
258         diag_printf("Error: Invalid parameter\n");
259         return;
260     }
261
262     if (argc == 3) {
263         if (!parse_num(*(&argv[2]), (unsigned long *)&val, &argv[2], ":")) {
264             diag_printf("Error: Invalid parameter\n");
265             return;
266         }
267         write = 1;
268     }
269
270     spi_pmic_init(&imx_spi_pmic);
271     temp = pmic_reg(reg, val, write);
272
273     diag_printf("\tval: 0x%08x\n\n", temp);
274 }
275
276 static unsigned int pmic_tx, pmic_rx;
277 /*!
278  * To read/write to a PMIC register. For write, it does another read for the
279  * actual register value.
280  *
281  * @param   reg         register number inside the PMIC
282  * @param   val         data to be written to the register; don't care for read
283  * @param   write       0 for read; 1 for write
284  *
285  * @return              the actual data in the PMIC register
286  */
287 unsigned int pmic_reg(unsigned int reg, unsigned int val, unsigned int write)
288 {
289     if (reg > 63 || write > 1 ) {
290         diag_printf("<reg num> = %d is invalide. Should be less then 63\n", reg);
291         return 0;
292     }
293     pmic_tx = (write << 31) | (reg << 25) | (val & 0x00FFFFFF);
294     diag_printf1("reg=0x%x, val=0x%08x\n", reg, pmic_tx);
295
296     spi_pmic_xfer(&imx_spi_pmic, (unsigned char *)&pmic_tx,
297                   (unsigned char *)&pmic_rx, 4);
298
299     if (write) {
300         pmic_tx &= ~(1 << 31);
301         spi_pmic_xfer(&imx_spi_pmic, (unsigned char *)&pmic_tx,
302                       (unsigned char *)&pmic_rx, 4);
303     }
304
305     return pmic_rx;
306 }
307 #endif // PMIC_SPI_BASE
308
309 #ifdef CPLD_SPI_BASE
310
311 unsigned int spi_cpld_xchg_single(unsigned int data, unsigned int data1, unsigned int base)
312 {
313     volatile unsigned int cfg_reg = readl(base + SPI_CTRL_REG_OFF);
314     unsigned int temp;
315
316     /* Activate the SS signal */
317     cfg_reg |= CPLD_SPI_CHIP_SELECT_NO;
318     writel(cfg_reg, CPLD_SPI_BASE + SPI_CTRL_REG_OFF);
319
320     /* Write the data */
321     writel(data, base + SPI_TX_REG_OFF);
322     writel(data1, base + SPI_TX_REG_OFF);
323
324     cfg_reg |= SPI_CTRL_REG_XCH_BIT;
325     writel(cfg_reg, base + SPI_CTRL_REG_OFF);
326
327     while ((((cfg_reg = readl(base + SPI_TEST_REG_OFF)) &
328               SPI_TEST_REG_RXCNT_MASK) >> SPI_TEST_REG_RXCNT_OFFSET) != 2) {
329     }
330
331     /* Deactivate the SS signal */
332     cfg_reg = readl(base + SPI_CTRL_REG_OFF);
333     cfg_reg &= ~SPI_CTRL_CS_MASK;
334     writel(cfg_reg, base + SPI_CTRL_REG_OFF);
335
336     /* Read from RX FIFO, second entry contains the data */
337     temp = readl(base + SPI_RX_REG_OFF);
338     temp = readl(base + SPI_RX_REG_OFF);
339     return ((temp >> 6) & 0xffff);
340 }
341
342 static void mxc_cpld_spi_init(void)
343 {
344     unsigned int ctrl;
345
346     ctrl = SPI_CTRL_REG_BIT_COUNT46 | CPLD_SPI_CTRL_MODE_MASTER | SPI_CTRL_EN;
347
348     spi_init(CPLD_SPI_BASE, 18000000,      // 54MHz data rate
349              ctrl);
350 }
351
352 RedBoot_init(mxc_cpld_spi_init, RedBoot_INIT_PRIO(102));
353
354 static void do_cpld(int argc, char *argv[]);
355
356 RedBoot_cmd("spi_cpld",
357             "Read/Write 16-bit internal CPLD register over CSPI",
358             "<reg num> [16-bit value to be written]",
359             do_cpld
360            );
361
362 static void do_cpld(int argc,char *argv[])
363 {
364     unsigned int reg, temp, val = 0, read = 1;
365
366     if (argc == 1) {
367         diag_printf("\tRead:  spi_cpld <reg num>\n");
368         diag_printf("\tWrite: spi_cpld <reg num> <value to be written>\n");
369         return;
370     }
371
372     if (!parse_num(*(&argv[1]), (unsigned long *)&reg, &argv[1], ":")) {
373         diag_printf("Error: Invalid parameter\n");
374         return;
375     }
376
377     if (argc == 3) {
378         if (!parse_num(*(&argv[2]), (unsigned long *)&val, &argv[2], ":")) {
379             diag_printf("Error: Invalid parameter\n");
380             return;
381         }
382         read = 0;
383     }
384
385     mxc_cpld_spi_init();
386     temp = cpld_reg(reg, val, read);
387
388     diag_printf("\tval: 0x%04x\n\n", temp);
389 }
390
391 /*!
392  * To read/write to a CPLD register.
393  *
394  * @param   reg         register number inside the CPLD
395  * @param   val         data to be written to the register; don't care for read
396  * @param   read        0 for write; 1 for read
397  *
398  * @return              the actual data in the CPLD register
399  */
400 unsigned int cpld_reg_xfer(unsigned int reg, unsigned int val, unsigned int read)
401 {
402     unsigned int local_val1, local_val2;
403
404     reg >>= 1;
405
406     local_val1 = (read << 13) | ((reg & 0x0001FFFF) >> 5) | 0x00001000;
407     if (read) {
408         //local_val1 = (read << 22) | (reg << 4) | 0x00200004;
409         //local_val2 = 0x1F;
410         local_val2 = ( ((reg & 0x0000001F) << 27) | 0x0200001f);
411
412     } else {
413         //local_val1 = (read << 22) | (reg << 4) | 0x00200007;
414         //local_val2 = ((val & 0xFFFF) << 6) | 0x00400027;
415         local_val2 = ( ((reg & 0x0000001F) << 27) | ((val & 0x0000FFFF) << 6) | 0x03C00027);
416
417     }
418
419     diag_printf1("reg=0x%x, val=0x%08x\n", reg, val);
420     return spi_cpld_xchg_single(local_val1, local_val2, CPLD_SPI_BASE);
421 }
422
423 /*!
424  * To read/write to a CPLD register. For write, it does another read for the
425  * actual register value.
426  *
427  * @param   reg         register number inside the CPLD
428  * @param   val         data to be written to the register; don't care for read
429  * @param   read        0 for write; 1 for read
430  *
431  * @return              the actual data in the CPLD register
432  */
433 unsigned int cpld_reg(unsigned int reg, unsigned int val, unsigned int read)
434 {
435     unsigned int temp;
436
437     if (reg > 0x20068 || read > 1 ) {
438         diag_printf("<reg num> = %x is invalid. Should be less then 0x20068\n", reg);
439         return 0;
440     }
441
442     temp = cpld_reg_xfer(reg, val, read);
443     diag_printf1("reg=0x%x, val=0x%08x\n", reg, val);
444
445     if (read == 0) {
446         temp = cpld_reg_xfer(reg, val, 1);
447     }
448
449     return temp;
450 }
451
452 #endif // CPLD_SPI_BASE