]>
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 <lifshitz@compulab.co.il> | |
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) | |
33 | inline void set_muxconf_regs_essential(void){}; | |
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 | { | |
85 | u32 bootmode = gd->arch.omap_boot_params.omap_bootmode; | |
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 | ||
076446f1 DL |
99 | #if defined(CONFIG_GENERIC_MMC) && !defined(CONFIG_SPL_BUILD) |
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 | ||
124 | void ft_board_setup(void *blob, bd_t *bd) | |
125 | { | |
126 | uint8_t enetaddr[6]; | |
127 | ||
128 | /* MAC addr */ | |
129 | if (eth_getenv_enetaddr("usbethaddr", enetaddr)) { | |
130 | fdt_find_and_setprop(blob, "/smsc95xx@0", "mac-address", | |
131 | enetaddr, 6, 1); | |
132 | } | |
133 | } | |
134 | ||
135 | static void generate_mac_addr(uint8_t *enetaddr) | |
136 | { | |
137 | int reg; | |
138 | ||
139 | reg = DIE_ID_REG_BASE + DIE_ID_REG_OFFSET; | |
140 | ||
141 | /* | |
142 | * create a fake MAC address from the processor ID code. | |
143 | * first byte is 0x02 to signify locally administered. | |
144 | */ | |
145 | enetaddr[0] = 0x02; | |
146 | enetaddr[1] = readl(reg + 0x10) & 0xff; | |
147 | enetaddr[2] = readl(reg + 0xC) & 0xff; | |
148 | enetaddr[3] = readl(reg + 0x8) & 0xff; | |
149 | enetaddr[4] = readl(reg) & 0xff; | |
150 | enetaddr[5] = (readl(reg) >> 8) & 0xff; | |
151 | } | |
152 | ||
153 | /* | |
154 | * Routine: handle_mac_address | |
155 | * Description: prepare MAC address for on-board Ethernet. | |
156 | */ | |
157 | static int handle_mac_address(void) | |
158 | { | |
159 | uint8_t enetaddr[6]; | |
160 | int ret; | |
161 | ||
162 | ret = eth_getenv_enetaddr("usbethaddr", enetaddr); | |
163 | if (ret) | |
164 | return 0; | |
165 | ||
166 | ret = cl_eeprom_read_mac_addr(enetaddr); | |
91c9885e | 167 | if (ret || !is_valid_ether_addr(enetaddr)) |
a9375f33 DL |
168 | generate_mac_addr(enetaddr); |
169 | ||
170 | if (!is_valid_ether_addr(enetaddr)) | |
171 | return -1; | |
172 | ||
173 | return eth_setenv_enetaddr("usbethaddr", enetaddr); | |
174 | } | |
175 | ||
176 | int board_eth_init(bd_t *bis) | |
177 | { | |
178 | return handle_mac_address(); | |
179 | } | |
180 | #endif | |
181 | ||
076446f1 DL |
182 | #ifdef CONFIG_USB_EHCI |
183 | static struct omap_usbhs_board_data usbhs_bdata = { | |
184 | .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED, | |
185 | .port_mode[1] = OMAP_EHCI_PORT_MODE_HSIC, | |
186 | .port_mode[2] = OMAP_EHCI_PORT_MODE_HSIC, | |
187 | }; | |
188 | ||
189 | static void setup_host_clocks(bool enable) | |
190 | { | |
191 | int usbhost_clk = OPTFCLKEN_HSIC60M_P3_CLK | | |
192 | OPTFCLKEN_HSIC480M_P3_CLK | | |
193 | OPTFCLKEN_HSIC60M_P2_CLK | | |
194 | OPTFCLKEN_HSIC480M_P2_CLK | | |
195 | OPTFCLKEN_UTMI_P3_CLK | | |
196 | OPTFCLKEN_UTMI_P2_CLK; | |
197 | ||
198 | int usbtll_clk = OPTFCLKEN_USB_CH1_CLK_ENABLE | | |
199 | OPTFCLKEN_USB_CH2_CLK_ENABLE; | |
200 | ||
201 | int usbhub_clk = CKOBUFFER_CLK_ENABLE_MASK; | |
202 | ||
203 | if (enable) { | |
204 | /* Enable port 2 and 3 clocks*/ | |
205 | setbits_le32((*prcm)->cm_l3init_hsusbhost_clkctrl, usbhost_clk); | |
206 | /* Enable port 2 and 3 usb host ports tll clocks*/ | |
207 | setbits_le32((*prcm)->cm_l3init_hsusbtll_clkctrl, usbtll_clk); | |
208 | /* Request FREF_XTAL_CLK clock for HSIC USB Hub */ | |
209 | setbits_le32((*ctrl)->control_ckobuffer, usbhub_clk); | |
210 | } else { | |
211 | clrbits_le32((*ctrl)->control_ckobuffer, usbhub_clk); | |
212 | clrbits_le32((*prcm)->cm_l3init_hsusbtll_clkctrl, usbtll_clk); | |
213 | clrbits_le32((*prcm)->cm_l3init_hsusbhost_clkctrl, usbhost_clk); | |
214 | } | |
215 | } | |
216 | ||
217 | int ehci_hcd_init(int index, enum usb_init_type init, | |
218 | struct ehci_hccr **hccr, struct ehci_hcor **hcor) | |
219 | { | |
220 | int ret; | |
221 | ||
222 | /* VCC_3V3_ETH */ | |
223 | cm_t54_palmas_regulator_set(SMPS9_VOLTAGE, SMPS_VOLT_3V3, SMPS9_CTRL, | |
224 | SMPS_MODE_SLP_AUTO | SMPS_MODE_ACT_AUTO); | |
225 | ||
226 | setup_host_clocks(true); | |
227 | ||
228 | ret = omap_ehci_hcd_init(index, &usbhs_bdata, hccr, hcor); | |
229 | if (ret < 0) | |
230 | printf("cm_t54: Failed to initialize ehci : %d\n", ret); | |
231 | ||
232 | return ret; | |
233 | } | |
234 | ||
235 | int ehci_hcd_stop(void) | |
236 | { | |
237 | int ret = omap_ehci_hcd_stop(); | |
238 | ||
239 | setup_host_clocks(false); | |
240 | ||
241 | cm_t54_palmas_regulator_set(SMPS9_VOLTAGE, SMPS_VOLT_OFF, | |
242 | SMPS9_CTRL, SMPS_MODE_SLP_AUTO); | |
243 | ||
244 | return ret; | |
245 | } | |
246 | ||
247 | void usb_hub_reset_devices(int port) | |
248 | { | |
249 | /* The LAN9730 needs to be reset after the port power has been set. */ | |
250 | if (port == 3) { | |
251 | gpio_direction_output(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, 0); | |
252 | udelay(10); | |
253 | gpio_direction_output(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, 1); | |
254 | } | |
255 | } | |
256 | #endif | |
257 |