]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/spi/imx_spi_cpld.c
Unified codebase for TX28, TX48, TX51, TX53
[karo-tx-uboot.git] / drivers / spi / imx_spi_cpld.c
1 /*
2  * (C) Copyright 2009 Freescale Semiconductor, Inc.
3  *
4  * See file CREDITS for list of people who contributed to this
5  * project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307 USA
21  */
22
23 #include <config.h>
24 #include <common.h>
25 #include <spi.h>
26 #include <asm/errno.h>
27 #include <linux/types.h>
28
29 #include <imx_spi.h>
30 #include <asm/arch/imx_spi_cpld.h>
31
32 static struct spi_slave *cpld_slave;
33
34 void cpld_reg_write(u32 offset, u32 val)
35 {
36         cpld_reg_xfer(offset, val, 0);
37         cpld_reg_xfer(offset + 0x2, (val >> 16), 0);
38 }
39
40 u32 cpld_reg_read(u32 offset)
41 {
42         return cpld_reg_xfer(offset, 0x0, 1) | \
43                 (cpld_reg_xfer(offset + 0x2, 0x0, 1) << 16);
44 }
45
46 /*!
47  * To read/write to a CPLD register.
48  *
49  * @param   reg         register number inside the CPLD
50  * @param   val         data to be written to the register; don't care for read
51  * @param   read        0 for write; 1 for read
52  *
53  * @return              the actual data in the CPLD register
54  */
55 unsigned int cpld_reg_xfer(unsigned int reg, unsigned int val,
56                            unsigned int read)
57 {
58         unsigned int local_val1, local_val2;
59         unsigned int g_tx_buf[2], g_rx_buf[2];
60
61         reg >>= 1;
62
63         local_val1 = (read << 13) | ((reg & 0x0001FFFF) >> 5) | 0x00001000;
64         if (read)
65                 local_val2 = (((reg & 0x0000001F) << 27) | 0x0200001f);
66         else
67                 local_val2 =
68                     (((reg & 0x0000001F) << 27) | ((val & 0x0000FFFF) << 6) |
69                      0x03C00027);
70
71         *g_tx_buf = local_val1;
72         *(g_tx_buf + 1) = local_val2;
73
74         if (read) {
75                 if (spi_xfer(cpld_slave, 46, (u8 *) g_tx_buf, (u8 *) g_rx_buf,
76                              SPI_XFER_BEGIN | SPI_XFER_END)) {
77                         return -1;
78                 }
79         } else {
80                 if (spi_xfer(cpld_slave, 46, (u8 *) g_tx_buf, (u8 *) g_rx_buf,
81                              SPI_XFER_BEGIN)) {
82                         return -1;
83                 }
84         }
85         return ((*(g_rx_buf + 1)) >> 6) & 0xffff;
86 }
87
88 struct spi_slave *spi_cpld_probe()
89 {
90         u32 reg;
91         cpld_slave = spi_setup_slave(0, 0, 25000000, 0);
92
93         udelay(1000);
94
95         /* Reset interrupt status reg */
96         cpld_reg_write(PBC_INT_REST, 0x1F);
97         cpld_reg_write(PBC_INT_REST, 0);
98         cpld_reg_write(PBC_INT_MASK, 0xFFFF);
99         /* Reset the XUART and Ethernet controllers */
100         reg = cpld_reg_read(PBC_SW_RESET);
101         reg |= 0x9;
102         cpld_reg_write(PBC_SW_RESET, reg);
103         reg &= ~0x9;
104         cpld_reg_write(PBC_SW_RESET, reg);
105
106         return cpld_slave;
107 }
108
109 void mxc_cpld_spi_init(void)
110 {
111         spi_cpld_probe();
112 }
113
114 void spi_cpld_free(struct spi_slave *slave)
115 {
116         if (slave)
117                 spi_free_slave(slave);
118 }