]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/karo/tx28/tx28.c
Update TX28 support and add support for TX28S AKA TX28-4130
[karo-tx-uboot.git] / board / karo / tx28 / tx28.c
1 /*
2  * Copyright (C) 2011 Lothar Waßmann <LW@KARO-electronics.de>
3  * based on: board/freesclae/mx28_evk.c (C) 2010 Freescale Semiconductor, Inc.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <errno.h>
26 #include <asm/io.h>
27 #include <asm/gpio.h>
28 #include <asm/arch/iomux-mx28.h>
29 #include <asm/arch/clock.h>
30 #include <asm/arch/imx-regs.h>
31 #include <asm/arch/regs-pinctrl.h>
32 #include <asm/arch/regs-clkctrl.h>
33 #include <asm/arch/regs-ocotp.h>
34 #include <asm/arch/sys_proto.h>
35
36 #include <mmc.h>
37 #include <netdev.h>
38 #include <imx_ssp_mmc.h>
39
40 DECLARE_GLOBAL_DATA_PTR;
41
42 /*
43  * Functions
44  */
45 int board_early_init_f(void)
46 {
47         /* IO0 clock at 480MHz */
48         mx28_set_ioclk(MXC_IOCLK0, 480000);
49         /* IO1 clock at 480MHz */
50         mx28_set_ioclk(MXC_IOCLK1, 480000);
51
52         /* SSP0 clock at 96MHz */
53         mx28_set_sspclk(MXC_SSPCLK0, 96000, 0);
54         /* SSP2 clock at 96MHz */
55         mx28_set_sspclk(MXC_SSPCLK2, 96000, 0);
56
57         return 0;
58 }
59
60 void coloured_LED_init(void)
61 {
62         /* Switch LED off */
63         gpio_set_value(MX28_PAD_ENET0_RXD3__GPIO_4_10, 0);
64 }
65
66 int board_init(void)
67 {
68         /* Address of boot parameters */
69         gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x1000;
70         return 0;
71 }
72
73 int dram_init(void)
74 {
75         return mx28_dram_init();
76 }
77
78 #ifdef  CONFIG_CMD_MMC
79 int board_mmc_init(bd_t *bis)
80 {
81         return mxsmmc_initialize(bis, 0, NULL);
82 }
83 #endif /* CONFIG_CMD_MMC */
84
85 #ifdef CONFIG_FEC_MXC
86 #ifdef CONFIG_GET_FEC_MAC_ADDR_FROM_IIM
87
88 #ifdef CONFIG_FEC_MXC_MULTI
89 #define FEC_MAX_IDX                     1
90 #else
91 #define FEC_MAX_IDX                     0
92 #endif
93
94 static int fec_get_mac_addr(int index)
95 {
96         u32 val1, val2;
97         int timeout = 1000;
98         struct mx28_ocotp_regs *ocotp_regs =
99                 (struct mx28_ocotp_regs *)MXS_OCOTP_BASE;
100         u32 *cust = &ocotp_regs->hw_ocotp_cust0;
101         char mac[6 * 3];
102         char env_name[] = "eth.addr";
103
104         if (index < 0 || index > FEC_MAX_IDX)
105                 return -EINVAL;
106
107         /* set this bit to open the OTP banks for reading */
108         writel(OCOTP_CTRL_RD_BANK_OPEN,
109                 &ocotp_regs->hw_ocotp_ctrl_set);
110
111         /* wait until OTP contents are readable */
112         while (OCOTP_CTRL_BUSY & readl(&ocotp_regs->hw_ocotp_ctrl)) {
113                 if (timeout-- < 0)
114                         return -ETIMEDOUT;
115                 udelay(100);
116         }
117
118         val1 = readl(&cust[index * 8]);
119         val2 = readl(&cust[index * 8 + 4]);
120         if ((val1 | val2) == 0)
121                 return 0;
122         snprintf(mac, sizeof(mac), "%02x:%02x:%02x:%02x:%02x:%02x",
123                 (val1 >> 24) & 0xFF, (val1 >> 16) & 0xFF,
124                 (val1 >> 8) & 0xFF, (val1 >> 0) & 0xFF,
125                 (val2 >> 24) & 0xFF, (val2 >> 16) & 0xFF);
126         if (index == 0)
127                 snprintf(env_name, sizeof(env_name), "ethaddr");
128         else
129                 snprintf(env_name, sizeof(env_name), "eth%daddr", index);
130
131         setenv(env_name, mac);
132         return 0;
133 }
134 #endif /* CONFIG_GET_FEC_MAC_ADDR_FROM_IIM */
135
136 static iomux_cfg_t tx28_fec_pads[] = {
137         MX28_PAD_ENET0_RX_EN__ENET0_RX_EN,
138         MX28_PAD_ENET0_RXD0__ENET0_RXD0,
139         MX28_PAD_ENET0_RXD1__ENET0_RXD1,
140 };
141
142 int board_eth_init(bd_t *bis)
143 {
144         int ret;
145
146         /* Reset the external phy */
147         gpio_direction_output(MX28_PAD_ENET0_RX_CLK__GPIO_4_13, 0);
148
149         /* Power on the external phy */
150         gpio_direction_output(MX28_PAD_PWM4__GPIO_3_29, 1);
151
152         /* Pull strap pins to high */
153         gpio_direction_output(MX28_PAD_ENET0_RX_EN__GPIO_4_2, 1);
154         gpio_direction_output(MX28_PAD_ENET0_RXD0__GPIO_4_3, 1);
155         gpio_direction_output(MX28_PAD_ENET0_RXD1__GPIO_4_4, 1);
156         gpio_direction_input(MX28_PAD_ENET0_TX_CLK__GPIO_4_5);
157
158         udelay(25000);
159         gpio_set_value(MX28_PAD_ENET0_RX_CLK__GPIO_4_13, 1);
160         udelay(100);
161
162         mxs_iomux_setup_multiple_pads(tx28_fec_pads, ARRAY_SIZE(tx28_fec_pads));
163
164         ret = cpu_eth_init(bis);
165         if (ret) {
166                 printf("cpu_eth_init() failed: %d\n", ret);
167                 return ret;
168         }
169
170         ret = fec_get_mac_addr(0);
171         if (ret < 0) {
172                 printf("Failed to read FEC0 MAC address from OCOTP\n");
173                 return ret;
174         }
175 #ifdef CONFIG_FEC_MXC_MULTI
176         if (getenv("ethaddr")) {
177                 ret = fecmxc_initialize_multi(bis, 0, 0, MXS_ENET0_BASE);
178                 if (ret) {
179                         printf("FEC MXS: Unable to init FEC0\n");
180                         return ret;
181                 }
182         }
183
184         ret = fec_get_mac_addr(1);
185         if (ret < 0) {
186                 printf("Failed to read FEC1 MAC address from OCOTP\n");
187                 return ret;
188         }
189         if (getenv("eth1addr")) {
190                 ret = fecmxc_initialize_multi(bis, 1, 1, MXS_ENET1_BASE);
191                 if (ret) {
192                         printf("FEC MXS: Unable to init FEC1\n");
193                         return ret;
194                 }
195         }
196         return 0;
197 #else
198         if (getenv("ethaddr")) {
199                 ret = fecmxc_initialize(bis);
200         }
201         return ret;
202 #endif
203 }
204 #endif /* CONFIG_FEC_MXC */
205
206 enum {
207         LED_STATE_INIT = -1,
208         LED_STATE_OFF,
209         LED_STATE_ON,
210 };
211
212 void show_activity(int arg)
213 {
214         static int led_state = LED_STATE_INIT;
215         static ulong last;
216
217         if (led_state == LED_STATE_INIT) {
218                 last = get_timer(0);
219                 gpio_set_value(MX28_PAD_ENET0_RXD3__GPIO_4_10, 1);
220                 led_state = LED_STATE_ON;
221         } else {
222                 if (get_timer(last) > CONFIG_SYS_HZ) {
223                         last = get_timer(0);
224                         if (led_state == LED_STATE_ON) {
225                                 gpio_set_value(MX28_PAD_ENET0_RXD3__GPIO_4_10, 0);
226                         } else {
227                                 gpio_set_value(MX28_PAD_ENET0_RXD3__GPIO_4_10, 1);
228                         }
229                         led_state = 1 - led_state;
230                 }
231         }
232 }