]>
Commit | Line | Data |
---|---|---|
076446f1 DL |
1 | /* |
2 | * Board functions for Compulab CM-T54 board | |
3 | * | |
4 | * Copyright (C) 2014, Compulab Ltd - http://compulab.co.il/ | |
5 | * | |
6 | * Author: Dmitry Lifshitz <[email protected]> | |
7 | * | |
8 | * SPDX-License-Identifier: GPL-2.0+ | |
9 | */ | |
10 | ||
11 | #include <common.h> | |
a9375f33 | 12 | #include <fdt_support.h> |
076446f1 DL |
13 | #include <usb.h> |
14 | #include <mmc.h> | |
15 | #include <palmas.h> | |
1c8c36f5 | 16 | #include <spl.h> |
076446f1 DL |
17 | |
18 | #include <asm/gpio.h> | |
19 | #include <asm/arch/sys_proto.h> | |
20 | #include <asm/arch/mmc_host_def.h> | |
21 | #include <asm/arch/clock.h> | |
22 | #include <asm/arch/ehci.h> | |
23 | #include <asm/ehci-omap.h> | |
24 | ||
a9375f33 DL |
25 | #include "../common/eeprom.h" |
26 | ||
076446f1 DL |
27 | #define DIE_ID_REG_BASE (OMAP54XX_L4_CORE_BASE + 0x2000) |
28 | #define DIE_ID_REG_OFFSET 0x200 | |
29 | ||
30 | DECLARE_GLOBAL_DATA_PTR; | |
31 | ||
32 | #if !defined(CONFIG_SPL_BUILD) | |
3ef56e61 | 33 | inline void set_muxconf_regs(void){}; |
076446f1 DL |
34 | #endif |
35 | ||
36 | const struct omap_sysinfo sysinfo = { | |
37 | "Board: CM-T54\n" | |
38 | }; | |
39 | ||
40 | /* | |
41 | * Routine: board_init | |
42 | * Description: hardware init. | |
43 | */ | |
44 | int board_init(void) | |
45 | { | |
91c9885e | 46 | gd->bd->bi_boot_params = (CONFIG_SYS_SDRAM_BASE + 0x100); |
076446f1 DL |
47 | |
48 | return 0; | |
49 | } | |
50 | ||
51 | /* | |
52 | * Routine: cm_t54_palmas_regulator_set | |
53 | * Description: select voltage and turn on/off Palmas PMIC regulator. | |
54 | */ | |
55 | static int cm_t54_palmas_regulator_set(u8 vreg, u8 vval, u8 creg, u8 cval) | |
56 | { | |
57 | int err; | |
58 | ||
59 | /* Setup voltage */ | |
60 | err = palmas_i2c_write_u8(TWL603X_CHIP_P1, vreg, vval); | |
61 | if (err) { | |
62 | printf("cm_t54: could not set regulator 0x%02x voltage : %d\n", | |
63 | vreg, err); | |
64 | return err; | |
65 | } | |
66 | ||
67 | /* Turn on/off regulator */ | |
68 | err = palmas_i2c_write_u8(TWL603X_CHIP_P1, creg, cval); | |
69 | if (err) { | |
70 | printf("cm_t54: could not turn on/off regulator 0x%02x : %d\n", | |
71 | creg, err); | |
72 | return err; | |
73 | } | |
74 | ||
75 | return 0; | |
76 | } | |
77 | ||
1c8c36f5 DL |
78 | /* |
79 | * Routine: mmc_get_env_part | |
80 | * Description: setup environment storage device partition. | |
81 | */ | |
82 | #ifdef CONFIG_SYS_MMC_ENV_PART | |
83 | uint mmc_get_env_part(struct mmc *mmc) | |
84 | { | |
60c7c30a | 85 | u32 bootmode = gd->arch.omap_boot_mode; |
1c8c36f5 DL |
86 | uint bootpart = CONFIG_SYS_MMC_ENV_PART; |
87 | ||
88 | /* | |
89 | * If booted from eMMC boot partition then force eMMC | |
90 | * FIRST boot partition to be env storage | |
91 | */ | |
e1c9895c | 92 | if (bootmode == BOOT_DEVICE_MMC2) |
1c8c36f5 DL |
93 | bootpart = 1; |
94 | ||
95 | return bootpart; | |
96 | } | |
97 | #endif | |
98 | ||
4aa2ba3a | 99 | #if defined(CONFIG_MMC) |
076446f1 DL |
100 | #define SB_T54_CD_GPIO 228 |
101 | #define SB_T54_WP_GPIO 229 | |
102 | ||
076446f1 DL |
103 | int board_mmc_init(bd_t *bis) |
104 | { | |
105 | int ret0, ret1; | |
106 | ||
0b03a931 | 107 | ret0 = omap_mmc_init(0, 0, 0, SB_T54_CD_GPIO, SB_T54_WP_GPIO); |
076446f1 DL |
108 | if (ret0) |
109 | printf("cm_t54: failed to initialize mmc0\n"); | |
110 | ||
111 | ret1 = omap_mmc_init(1, 0, 0, -1, -1); | |
112 | if (ret1) | |
113 | printf("cm_t54: failed to initialize mmc1\n"); | |
114 | ||
115 | if (ret0 && ret1) | |
116 | return -1; | |
117 | ||
118 | return 0; | |
119 | } | |
120 | #endif | |
121 | ||
a9375f33 DL |
122 | #ifdef CONFIG_USB_HOST_ETHER |
123 | ||
e895a4b0 | 124 | int ft_board_setup(void *blob, bd_t *bd) |
a9375f33 DL |
125 | { |
126 | uint8_t enetaddr[6]; | |
127 | ||
128 | /* MAC addr */ | |
35affd7a | 129 | if (eth_env_get_enetaddr("usbethaddr", enetaddr)) { |
a9375f33 DL |
130 | fdt_find_and_setprop(blob, "/smsc95xx@0", "mac-address", |
131 | enetaddr, 6, 1); | |
132 | } | |
e895a4b0 SG |
133 | |
134 | return 0; | |
a9375f33 DL |
135 | } |
136 | ||
137 | static void generate_mac_addr(uint8_t *enetaddr) | |
138 | { | |
139 | int reg; | |
140 | ||
141 | reg = DIE_ID_REG_BASE + DIE_ID_REG_OFFSET; | |
142 | ||
143 | /* | |
144 | * create a fake MAC address from the processor ID code. | |
145 | * first byte is 0x02 to signify locally administered. | |
146 | */ | |
147 | enetaddr[0] = 0x02; | |
148 | enetaddr[1] = readl(reg + 0x10) & 0xff; | |
149 | enetaddr[2] = readl(reg + 0xC) & 0xff; | |
150 | enetaddr[3] = readl(reg + 0x8) & 0xff; | |
151 | enetaddr[4] = readl(reg) & 0xff; | |
152 | enetaddr[5] = (readl(reg) >> 8) & 0xff; | |
153 | } | |
154 | ||
155 | /* | |
156 | * Routine: handle_mac_address | |
157 | * Description: prepare MAC address for on-board Ethernet. | |
158 | */ | |
159 | static int handle_mac_address(void) | |
160 | { | |
161 | uint8_t enetaddr[6]; | |
162 | int ret; | |
163 | ||
35affd7a | 164 | ret = eth_env_get_enetaddr("usbethaddr", enetaddr); |
a9375f33 DL |
165 | if (ret) |
166 | return 0; | |
167 | ||
e7a2447b | 168 | ret = cl_eeprom_read_mac_addr(enetaddr, CONFIG_SYS_I2C_EEPROM_BUS); |
0adb5b76 | 169 | if (ret || !is_valid_ethaddr(enetaddr)) |
a9375f33 DL |
170 | generate_mac_addr(enetaddr); |
171 | ||
0adb5b76 | 172 | if (!is_valid_ethaddr(enetaddr)) |
a9375f33 DL |
173 | return -1; |
174 | ||
fd1e959e | 175 | return eth_env_set_enetaddr("usbethaddr", enetaddr); |
a9375f33 DL |
176 | } |
177 | ||
178 | int board_eth_init(bd_t *bis) | |
179 | { | |
180 | return handle_mac_address(); | |
181 | } | |
182 | #endif | |
183 | ||
8850c5d5 | 184 | #ifdef CONFIG_USB_EHCI_HCD |
076446f1 DL |
185 | static struct omap_usbhs_board_data usbhs_bdata = { |
186 | .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED, | |
187 | .port_mode[1] = OMAP_EHCI_PORT_MODE_HSIC, | |
188 | .port_mode[2] = OMAP_EHCI_PORT_MODE_HSIC, | |
189 | }; | |
190 | ||
191 | static void setup_host_clocks(bool enable) | |
192 | { | |
193 | int usbhost_clk = OPTFCLKEN_HSIC60M_P3_CLK | | |
194 | OPTFCLKEN_HSIC480M_P3_CLK | | |
195 | OPTFCLKEN_HSIC60M_P2_CLK | | |
196 | OPTFCLKEN_HSIC480M_P2_CLK | | |
197 | OPTFCLKEN_UTMI_P3_CLK | | |
198 | OPTFCLKEN_UTMI_P2_CLK; | |
199 | ||
200 | int usbtll_clk = OPTFCLKEN_USB_CH1_CLK_ENABLE | | |
201 | OPTFCLKEN_USB_CH2_CLK_ENABLE; | |
202 | ||
203 | int usbhub_clk = CKOBUFFER_CLK_ENABLE_MASK; | |
204 | ||
205 | if (enable) { | |
206 | /* Enable port 2 and 3 clocks*/ | |
207 | setbits_le32((*prcm)->cm_l3init_hsusbhost_clkctrl, usbhost_clk); | |
208 | /* Enable port 2 and 3 usb host ports tll clocks*/ | |
209 | setbits_le32((*prcm)->cm_l3init_hsusbtll_clkctrl, usbtll_clk); | |
210 | /* Request FREF_XTAL_CLK clock for HSIC USB Hub */ | |
211 | setbits_le32((*ctrl)->control_ckobuffer, usbhub_clk); | |
212 | } else { | |
213 | clrbits_le32((*ctrl)->control_ckobuffer, usbhub_clk); | |
214 | clrbits_le32((*prcm)->cm_l3init_hsusbtll_clkctrl, usbtll_clk); | |
215 | clrbits_le32((*prcm)->cm_l3init_hsusbhost_clkctrl, usbhost_clk); | |
216 | } | |
217 | } | |
218 | ||
219 | int ehci_hcd_init(int index, enum usb_init_type init, | |
220 | struct ehci_hccr **hccr, struct ehci_hcor **hcor) | |
221 | { | |
222 | int ret; | |
223 | ||
224 | /* VCC_3V3_ETH */ | |
225 | cm_t54_palmas_regulator_set(SMPS9_VOLTAGE, SMPS_VOLT_3V3, SMPS9_CTRL, | |
226 | SMPS_MODE_SLP_AUTO | SMPS_MODE_ACT_AUTO); | |
227 | ||
228 | setup_host_clocks(true); | |
229 | ||
230 | ret = omap_ehci_hcd_init(index, &usbhs_bdata, hccr, hcor); | |
231 | if (ret < 0) | |
232 | printf("cm_t54: Failed to initialize ehci : %d\n", ret); | |
233 | ||
234 | return ret; | |
235 | } | |
236 | ||
237 | int ehci_hcd_stop(void) | |
238 | { | |
239 | int ret = omap_ehci_hcd_stop(); | |
240 | ||
241 | setup_host_clocks(false); | |
242 | ||
243 | cm_t54_palmas_regulator_set(SMPS9_VOLTAGE, SMPS_VOLT_OFF, | |
244 | SMPS9_CTRL, SMPS_MODE_SLP_AUTO); | |
245 | ||
246 | return ret; | |
247 | } | |
248 | ||
249 | void usb_hub_reset_devices(int port) | |
250 | { | |
251 | /* The LAN9730 needs to be reset after the port power has been set. */ | |
252 | if (port == 3) { | |
253 | gpio_direction_output(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, 0); | |
254 | udelay(10); | |
255 | gpio_direction_output(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, 1); | |
256 | } | |
257 | } | |
258 | #endif | |
259 |