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>
8 #include <cyg/hal/fsl_board.h>
9 #include <cyg/io/imx_spi.h>
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.
15 int imx_spi_init_v2_3 (struct imx_spi_dev *dev)
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;
22 diag_printf("Error: desired clock is 0\n");
28 reg_ctrl = readl(dev->base + 0x8);
30 writel(0, dev->base + 0x8);
31 writel(reg_ctrl | 0x1, dev->base + 0x8);
33 // control register setup
34 if (clk_src > dev->freq) {
35 pre_div = clk_src / dev->freq;
37 post_div = pre_div / 16;
41 for (i = 0; i < 16; i++) {
42 if ((1 << i) >= post_div)
46 diag_printf("Error: no divider can meet the freq: %d\n",
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
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));
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;
83 // clear interrupt reg
84 writel(0, dev->base + 0x10);
85 writel(3 << 6, dev->base + 0x18);
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.
95 * Note: If one wants to change the SPI parameters such as clock, the
96 * imx_spi_init_xxx() needs to be called again.
98 static void spi_start_v2_3(struct imx_spi_dev *dev,
99 struct spi_v2_3_reg *reg, int len)
101 if (reg->ctrl_reg == 0) {
102 diag_printf("Error: spi(base=0x%x) has not been initialized yet\n",
108 reg->ctrl_reg = (reg->ctrl_reg & ~0xFFF00000) | ((len * 8 - 1) << 20);
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));
117 * Stop the SPI module that the slave device is connected to.
119 static void spi_stop_v2_3(struct imx_spi_dev *dev)
121 writel(0, dev->base + 0x8);
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.
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)
137 int val = SPI_RETRY_TIMES;
140 int len, ret_val = 0;
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);
148 spi_start_v2_3(dev, dev->reg, burst_bytes);
150 // move data to the tx fifo
151 for (p_buf = (unsigned int *)tx_buf, len = burst_bytes; len > 0;
153 writel(*p_buf, dev->base + 0x4);
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);
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);
168 writel(3 << 6, dev->base + 0x18);
170 diag_printf("Error: re-tried %d times without response. Give up\n", SPI_RETRY_TIMES);
175 // move data in the rx buf
176 for (p_buf = (unsigned int *)rx_buf, len = burst_bytes; len > 0;
178 *p_buf = readl(dev->base + 0x0);
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;
190 static void show_pmic_info(void)
192 volatile unsigned int rev_id;
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) {
232 diag_printf("unknown");
238 RedBoot_init(show_pmic_info, RedBoot_INIT_PRIO(100));
240 static void do_pmic(int argc, char *argv[]);
242 "Read/Write internal PMIC register",
243 "<reg num> [value to be written]",
247 static void do_pmic(int argc, char *argv[])
249 unsigned int reg, temp, val = 0, write = 0;
252 diag_printf("\tRead: pmic <reg num>\n");
253 diag_printf("\tWrite: pmic <reg num> <value to be written>\n");
257 if (!parse_num(*(&argv[1]), (unsigned long *)®, &argv[1], ":")) {
258 diag_printf("Error: Invalid parameter\n");
263 if (!parse_num(*(&argv[2]), (unsigned long *)&val, &argv[2], ":")) {
264 diag_printf("Error: Invalid parameter\n");
270 spi_pmic_init(&imx_spi_pmic);
271 temp = pmic_reg(reg, val, write);
273 diag_printf("\tval: 0x%08x\n\n", temp);
276 static unsigned int pmic_tx, pmic_rx;
278 * To read/write to a PMIC register. For write, it does another read for the
279 * actual register value.
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
285 * @return the actual data in the PMIC register
287 unsigned int pmic_reg(unsigned int reg, unsigned int val, unsigned int write)
289 if (reg > 63 || write > 1 ) {
290 diag_printf("<reg num> = %d is invalide. Should be less then 63\n", reg);
293 pmic_tx = (write << 31) | (reg << 25) | (val & 0x00FFFFFF);
294 diag_printf1("reg=0x%x, val=0x%08x\n", reg, pmic_tx);
296 spi_pmic_xfer(&imx_spi_pmic, (unsigned char *)&pmic_tx,
297 (unsigned char *)&pmic_rx, 4);
300 pmic_tx &= ~(1 << 31);
301 spi_pmic_xfer(&imx_spi_pmic, (unsigned char *)&pmic_tx,
302 (unsigned char *)&pmic_rx, 4);
307 #endif // PMIC_SPI_BASE
311 unsigned int spi_cpld_xchg_single(unsigned int data, unsigned int data1, unsigned int base)
313 volatile unsigned int cfg_reg = readl(base + SPI_CTRL_REG_OFF);
316 /* Activate the SS signal */
317 cfg_reg |= CPLD_SPI_CHIP_SELECT_NO;
318 writel(cfg_reg, CPLD_SPI_BASE + SPI_CTRL_REG_OFF);
321 writel(data, base + SPI_TX_REG_OFF);
322 writel(data1, base + SPI_TX_REG_OFF);
324 cfg_reg |= SPI_CTRL_REG_XCH_BIT;
325 writel(cfg_reg, base + SPI_CTRL_REG_OFF);
327 while ((((cfg_reg = readl(base + SPI_TEST_REG_OFF)) &
328 SPI_TEST_REG_RXCNT_MASK) >> SPI_TEST_REG_RXCNT_OFFSET) != 2) {
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);
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);
342 static void mxc_cpld_spi_init(void)
346 ctrl = SPI_CTRL_REG_BIT_COUNT46 | CPLD_SPI_CTRL_MODE_MASTER | SPI_CTRL_EN;
348 spi_init(CPLD_SPI_BASE, 18000000, // 54MHz data rate
352 RedBoot_init(mxc_cpld_spi_init, RedBoot_INIT_PRIO(102));
354 static void do_cpld(int argc, char *argv[]);
356 RedBoot_cmd("spi_cpld",
357 "Read/Write 16-bit internal CPLD register over CSPI",
358 "<reg num> [16-bit value to be written]",
362 static void do_cpld(int argc,char *argv[])
364 unsigned int reg, temp, val = 0, read = 1;
367 diag_printf("\tRead: spi_cpld <reg num>\n");
368 diag_printf("\tWrite: spi_cpld <reg num> <value to be written>\n");
372 if (!parse_num(*(&argv[1]), (unsigned long *)®, &argv[1], ":")) {
373 diag_printf("Error: Invalid parameter\n");
378 if (!parse_num(*(&argv[2]), (unsigned long *)&val, &argv[2], ":")) {
379 diag_printf("Error: Invalid parameter\n");
386 temp = cpld_reg(reg, val, read);
388 diag_printf("\tval: 0x%04x\n\n", temp);
392 * To read/write to a CPLD register.
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
398 * @return the actual data in the CPLD register
400 unsigned int cpld_reg_xfer(unsigned int reg, unsigned int val, unsigned int read)
402 unsigned int local_val1, local_val2;
406 local_val1 = (read << 13) | ((reg & 0x0001FFFF) >> 5) | 0x00001000;
408 //local_val1 = (read << 22) | (reg << 4) | 0x00200004;
410 local_val2 = ( ((reg & 0x0000001F) << 27) | 0x0200001f);
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);
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);
424 * To read/write to a CPLD register. For write, it does another read for the
425 * actual register value.
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
431 * @return the actual data in the CPLD register
433 unsigned int cpld_reg(unsigned int reg, unsigned int val, unsigned int read)
437 if (reg > 0x20068 || read > 1 ) {
438 diag_printf("<reg num> = %x is invalid. Should be less then 0x20068\n", reg);
442 temp = cpld_reg_xfer(reg, val, read);
443 diag_printf1("reg=0x%x, val=0x%08x\n", reg, val);
446 temp = cpld_reg_xfer(reg, val, 1);
452 #endif // CPLD_SPI_BASE