1076446f1SDmitry Lifshitz /*
2076446f1SDmitry Lifshitz * Board functions for Compulab CM-T54 board
3076446f1SDmitry Lifshitz *
4076446f1SDmitry Lifshitz * Copyright (C) 2014, Compulab Ltd - http://compulab.co.il/
5076446f1SDmitry Lifshitz *
6076446f1SDmitry Lifshitz * Author: Dmitry Lifshitz <lifshitz@compulab.co.il>
7076446f1SDmitry Lifshitz *
8076446f1SDmitry Lifshitz * SPDX-License-Identifier: GPL-2.0+
9076446f1SDmitry Lifshitz */
10076446f1SDmitry Lifshitz
11076446f1SDmitry Lifshitz #include <common.h>
12a9375f33SDmitry Lifshitz #include <fdt_support.h>
13076446f1SDmitry Lifshitz #include <usb.h>
14076446f1SDmitry Lifshitz #include <mmc.h>
15076446f1SDmitry Lifshitz #include <palmas.h>
161c8c36f5SDmitry Lifshitz #include <spl.h>
17076446f1SDmitry Lifshitz
18076446f1SDmitry Lifshitz #include <asm/gpio.h>
19076446f1SDmitry Lifshitz #include <asm/arch/sys_proto.h>
20076446f1SDmitry Lifshitz #include <asm/arch/mmc_host_def.h>
21076446f1SDmitry Lifshitz #include <asm/arch/clock.h>
22076446f1SDmitry Lifshitz #include <asm/arch/ehci.h>
23076446f1SDmitry Lifshitz #include <asm/ehci-omap.h>
24076446f1SDmitry Lifshitz
25a9375f33SDmitry Lifshitz #include "../common/eeprom.h"
26a9375f33SDmitry Lifshitz
27076446f1SDmitry Lifshitz #define DIE_ID_REG_BASE (OMAP54XX_L4_CORE_BASE + 0x2000)
28076446f1SDmitry Lifshitz #define DIE_ID_REG_OFFSET 0x200
29076446f1SDmitry Lifshitz
30076446f1SDmitry Lifshitz DECLARE_GLOBAL_DATA_PTR;
31076446f1SDmitry Lifshitz
32076446f1SDmitry Lifshitz #if !defined(CONFIG_SPL_BUILD)
set_muxconf_regs(void)333ef56e61SPaul Kocialkowski inline void set_muxconf_regs(void){};
34076446f1SDmitry Lifshitz #endif
35076446f1SDmitry Lifshitz
36076446f1SDmitry Lifshitz const struct omap_sysinfo sysinfo = {
37076446f1SDmitry Lifshitz "Board: CM-T54\n"
38076446f1SDmitry Lifshitz };
39076446f1SDmitry Lifshitz
40076446f1SDmitry Lifshitz /*
41076446f1SDmitry Lifshitz * Routine: board_init
42076446f1SDmitry Lifshitz * Description: hardware init.
43076446f1SDmitry Lifshitz */
board_init(void)44076446f1SDmitry Lifshitz int board_init(void)
45076446f1SDmitry Lifshitz {
4691c9885eSDmitry Lifshitz gd->bd->bi_boot_params = (CONFIG_SYS_SDRAM_BASE + 0x100);
47076446f1SDmitry Lifshitz
48076446f1SDmitry Lifshitz return 0;
49076446f1SDmitry Lifshitz }
50076446f1SDmitry Lifshitz
51076446f1SDmitry Lifshitz /*
52076446f1SDmitry Lifshitz * Routine: cm_t54_palmas_regulator_set
53076446f1SDmitry Lifshitz * Description: select voltage and turn on/off Palmas PMIC regulator.
54076446f1SDmitry Lifshitz */
cm_t54_palmas_regulator_set(u8 vreg,u8 vval,u8 creg,u8 cval)55076446f1SDmitry Lifshitz static int cm_t54_palmas_regulator_set(u8 vreg, u8 vval, u8 creg, u8 cval)
56076446f1SDmitry Lifshitz {
57076446f1SDmitry Lifshitz int err;
58076446f1SDmitry Lifshitz
59076446f1SDmitry Lifshitz /* Setup voltage */
60076446f1SDmitry Lifshitz err = palmas_i2c_write_u8(TWL603X_CHIP_P1, vreg, vval);
61076446f1SDmitry Lifshitz if (err) {
62076446f1SDmitry Lifshitz printf("cm_t54: could not set regulator 0x%02x voltage : %d\n",
63076446f1SDmitry Lifshitz vreg, err);
64076446f1SDmitry Lifshitz return err;
65076446f1SDmitry Lifshitz }
66076446f1SDmitry Lifshitz
67076446f1SDmitry Lifshitz /* Turn on/off regulator */
68076446f1SDmitry Lifshitz err = palmas_i2c_write_u8(TWL603X_CHIP_P1, creg, cval);
69076446f1SDmitry Lifshitz if (err) {
70076446f1SDmitry Lifshitz printf("cm_t54: could not turn on/off regulator 0x%02x : %d\n",
71076446f1SDmitry Lifshitz creg, err);
72076446f1SDmitry Lifshitz return err;
73076446f1SDmitry Lifshitz }
74076446f1SDmitry Lifshitz
75076446f1SDmitry Lifshitz return 0;
76076446f1SDmitry Lifshitz }
77076446f1SDmitry Lifshitz
781c8c36f5SDmitry Lifshitz /*
791c8c36f5SDmitry Lifshitz * Routine: mmc_get_env_part
801c8c36f5SDmitry Lifshitz * Description: setup environment storage device partition.
811c8c36f5SDmitry Lifshitz */
821c8c36f5SDmitry Lifshitz #ifdef CONFIG_SYS_MMC_ENV_PART
mmc_get_env_part(struct mmc * mmc)831c8c36f5SDmitry Lifshitz uint mmc_get_env_part(struct mmc *mmc)
841c8c36f5SDmitry Lifshitz {
8560c7c30aSPaul Kocialkowski u32 bootmode = gd->arch.omap_boot_mode;
861c8c36f5SDmitry Lifshitz uint bootpart = CONFIG_SYS_MMC_ENV_PART;
871c8c36f5SDmitry Lifshitz
881c8c36f5SDmitry Lifshitz /*
891c8c36f5SDmitry Lifshitz * If booted from eMMC boot partition then force eMMC
901c8c36f5SDmitry Lifshitz * FIRST boot partition to be env storage
911c8c36f5SDmitry Lifshitz */
92e1c9895cSDmitry Lifshitz if (bootmode == BOOT_DEVICE_MMC2)
931c8c36f5SDmitry Lifshitz bootpart = 1;
941c8c36f5SDmitry Lifshitz
951c8c36f5SDmitry Lifshitz return bootpart;
961c8c36f5SDmitry Lifshitz }
971c8c36f5SDmitry Lifshitz #endif
981c8c36f5SDmitry Lifshitz
994aa2ba3aSMasahiro Yamada #if defined(CONFIG_MMC)
100076446f1SDmitry Lifshitz #define SB_T54_CD_GPIO 228
101076446f1SDmitry Lifshitz #define SB_T54_WP_GPIO 229
102076446f1SDmitry Lifshitz
board_mmc_init(bd_t * bis)103076446f1SDmitry Lifshitz int board_mmc_init(bd_t *bis)
104076446f1SDmitry Lifshitz {
105076446f1SDmitry Lifshitz int ret0, ret1;
106076446f1SDmitry Lifshitz
1070b03a931SIgor Grinberg ret0 = omap_mmc_init(0, 0, 0, SB_T54_CD_GPIO, SB_T54_WP_GPIO);
108076446f1SDmitry Lifshitz if (ret0)
109076446f1SDmitry Lifshitz printf("cm_t54: failed to initialize mmc0\n");
110076446f1SDmitry Lifshitz
111076446f1SDmitry Lifshitz ret1 = omap_mmc_init(1, 0, 0, -1, -1);
112076446f1SDmitry Lifshitz if (ret1)
113076446f1SDmitry Lifshitz printf("cm_t54: failed to initialize mmc1\n");
114076446f1SDmitry Lifshitz
115076446f1SDmitry Lifshitz if (ret0 && ret1)
116076446f1SDmitry Lifshitz return -1;
117076446f1SDmitry Lifshitz
118076446f1SDmitry Lifshitz return 0;
119076446f1SDmitry Lifshitz }
120076446f1SDmitry Lifshitz #endif
121076446f1SDmitry Lifshitz
122a9375f33SDmitry Lifshitz #ifdef CONFIG_USB_HOST_ETHER
123a9375f33SDmitry Lifshitz
ft_board_setup(void * blob,bd_t * bd)124e895a4b0SSimon Glass int ft_board_setup(void *blob, bd_t *bd)
125a9375f33SDmitry Lifshitz {
126a9375f33SDmitry Lifshitz uint8_t enetaddr[6];
127a9375f33SDmitry Lifshitz
128a9375f33SDmitry Lifshitz /* MAC addr */
12935affd7aSSimon Glass if (eth_env_get_enetaddr("usbethaddr", enetaddr)) {
130a9375f33SDmitry Lifshitz fdt_find_and_setprop(blob, "/smsc95xx@0", "mac-address",
131a9375f33SDmitry Lifshitz enetaddr, 6, 1);
132a9375f33SDmitry Lifshitz }
133e895a4b0SSimon Glass
134e895a4b0SSimon Glass return 0;
135a9375f33SDmitry Lifshitz }
136a9375f33SDmitry Lifshitz
generate_mac_addr(uint8_t * enetaddr)137a9375f33SDmitry Lifshitz static void generate_mac_addr(uint8_t *enetaddr)
138a9375f33SDmitry Lifshitz {
139a9375f33SDmitry Lifshitz int reg;
140a9375f33SDmitry Lifshitz
141a9375f33SDmitry Lifshitz reg = DIE_ID_REG_BASE + DIE_ID_REG_OFFSET;
142a9375f33SDmitry Lifshitz
143a9375f33SDmitry Lifshitz /*
144a9375f33SDmitry Lifshitz * create a fake MAC address from the processor ID code.
145a9375f33SDmitry Lifshitz * first byte is 0x02 to signify locally administered.
146a9375f33SDmitry Lifshitz */
147a9375f33SDmitry Lifshitz enetaddr[0] = 0x02;
148a9375f33SDmitry Lifshitz enetaddr[1] = readl(reg + 0x10) & 0xff;
149a9375f33SDmitry Lifshitz enetaddr[2] = readl(reg + 0xC) & 0xff;
150a9375f33SDmitry Lifshitz enetaddr[3] = readl(reg + 0x8) & 0xff;
151a9375f33SDmitry Lifshitz enetaddr[4] = readl(reg) & 0xff;
152a9375f33SDmitry Lifshitz enetaddr[5] = (readl(reg) >> 8) & 0xff;
153a9375f33SDmitry Lifshitz }
154a9375f33SDmitry Lifshitz
155a9375f33SDmitry Lifshitz /*
156a9375f33SDmitry Lifshitz * Routine: handle_mac_address
157a9375f33SDmitry Lifshitz * Description: prepare MAC address for on-board Ethernet.
158a9375f33SDmitry Lifshitz */
handle_mac_address(void)159a9375f33SDmitry Lifshitz static int handle_mac_address(void)
160a9375f33SDmitry Lifshitz {
161a9375f33SDmitry Lifshitz uint8_t enetaddr[6];
162a9375f33SDmitry Lifshitz int ret;
163a9375f33SDmitry Lifshitz
16435affd7aSSimon Glass ret = eth_env_get_enetaddr("usbethaddr", enetaddr);
165a9375f33SDmitry Lifshitz if (ret)
166a9375f33SDmitry Lifshitz return 0;
167a9375f33SDmitry Lifshitz
168e7a2447bSNikita Kiryanov ret = cl_eeprom_read_mac_addr(enetaddr, CONFIG_SYS_I2C_EEPROM_BUS);
1690adb5b76SJoe Hershberger if (ret || !is_valid_ethaddr(enetaddr))
170a9375f33SDmitry Lifshitz generate_mac_addr(enetaddr);
171a9375f33SDmitry Lifshitz
1720adb5b76SJoe Hershberger if (!is_valid_ethaddr(enetaddr))
173a9375f33SDmitry Lifshitz return -1;
174a9375f33SDmitry Lifshitz
175fd1e959eSSimon Glass return eth_env_set_enetaddr("usbethaddr", enetaddr);
176a9375f33SDmitry Lifshitz }
177a9375f33SDmitry Lifshitz
board_eth_init(bd_t * bis)178a9375f33SDmitry Lifshitz int board_eth_init(bd_t *bis)
179a9375f33SDmitry Lifshitz {
180a9375f33SDmitry Lifshitz return handle_mac_address();
181a9375f33SDmitry Lifshitz }
182a9375f33SDmitry Lifshitz #endif
183a9375f33SDmitry Lifshitz
1848850c5d5STom Rini #ifdef CONFIG_USB_EHCI_HCD
185076446f1SDmitry Lifshitz static struct omap_usbhs_board_data usbhs_bdata = {
186076446f1SDmitry Lifshitz .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
187076446f1SDmitry Lifshitz .port_mode[1] = OMAP_EHCI_PORT_MODE_HSIC,
188076446f1SDmitry Lifshitz .port_mode[2] = OMAP_EHCI_PORT_MODE_HSIC,
189076446f1SDmitry Lifshitz };
190076446f1SDmitry Lifshitz
setup_host_clocks(bool enable)191076446f1SDmitry Lifshitz static void setup_host_clocks(bool enable)
192076446f1SDmitry Lifshitz {
193076446f1SDmitry Lifshitz int usbhost_clk = OPTFCLKEN_HSIC60M_P3_CLK |
194076446f1SDmitry Lifshitz OPTFCLKEN_HSIC480M_P3_CLK |
195076446f1SDmitry Lifshitz OPTFCLKEN_HSIC60M_P2_CLK |
196076446f1SDmitry Lifshitz OPTFCLKEN_HSIC480M_P2_CLK |
197076446f1SDmitry Lifshitz OPTFCLKEN_UTMI_P3_CLK |
198076446f1SDmitry Lifshitz OPTFCLKEN_UTMI_P2_CLK;
199076446f1SDmitry Lifshitz
200076446f1SDmitry Lifshitz int usbtll_clk = OPTFCLKEN_USB_CH1_CLK_ENABLE |
201076446f1SDmitry Lifshitz OPTFCLKEN_USB_CH2_CLK_ENABLE;
202076446f1SDmitry Lifshitz
203076446f1SDmitry Lifshitz int usbhub_clk = CKOBUFFER_CLK_ENABLE_MASK;
204076446f1SDmitry Lifshitz
205076446f1SDmitry Lifshitz if (enable) {
206076446f1SDmitry Lifshitz /* Enable port 2 and 3 clocks*/
207076446f1SDmitry Lifshitz setbits_le32((*prcm)->cm_l3init_hsusbhost_clkctrl, usbhost_clk);
208076446f1SDmitry Lifshitz /* Enable port 2 and 3 usb host ports tll clocks*/
209076446f1SDmitry Lifshitz setbits_le32((*prcm)->cm_l3init_hsusbtll_clkctrl, usbtll_clk);
210076446f1SDmitry Lifshitz /* Request FREF_XTAL_CLK clock for HSIC USB Hub */
211076446f1SDmitry Lifshitz setbits_le32((*ctrl)->control_ckobuffer, usbhub_clk);
212076446f1SDmitry Lifshitz } else {
213076446f1SDmitry Lifshitz clrbits_le32((*ctrl)->control_ckobuffer, usbhub_clk);
214076446f1SDmitry Lifshitz clrbits_le32((*prcm)->cm_l3init_hsusbtll_clkctrl, usbtll_clk);
215076446f1SDmitry Lifshitz clrbits_le32((*prcm)->cm_l3init_hsusbhost_clkctrl, usbhost_clk);
216076446f1SDmitry Lifshitz }
217076446f1SDmitry Lifshitz }
218076446f1SDmitry Lifshitz
ehci_hcd_init(int index,enum usb_init_type init,struct ehci_hccr ** hccr,struct ehci_hcor ** hcor)219076446f1SDmitry Lifshitz int ehci_hcd_init(int index, enum usb_init_type init,
220076446f1SDmitry Lifshitz struct ehci_hccr **hccr, struct ehci_hcor **hcor)
221076446f1SDmitry Lifshitz {
222076446f1SDmitry Lifshitz int ret;
223076446f1SDmitry Lifshitz
224076446f1SDmitry Lifshitz /* VCC_3V3_ETH */
225076446f1SDmitry Lifshitz cm_t54_palmas_regulator_set(SMPS9_VOLTAGE, SMPS_VOLT_3V3, SMPS9_CTRL,
226076446f1SDmitry Lifshitz SMPS_MODE_SLP_AUTO | SMPS_MODE_ACT_AUTO);
227076446f1SDmitry Lifshitz
228076446f1SDmitry Lifshitz setup_host_clocks(true);
229076446f1SDmitry Lifshitz
230076446f1SDmitry Lifshitz ret = omap_ehci_hcd_init(index, &usbhs_bdata, hccr, hcor);
231076446f1SDmitry Lifshitz if (ret < 0)
232076446f1SDmitry Lifshitz printf("cm_t54: Failed to initialize ehci : %d\n", ret);
233076446f1SDmitry Lifshitz
234076446f1SDmitry Lifshitz return ret;
235076446f1SDmitry Lifshitz }
236076446f1SDmitry Lifshitz
ehci_hcd_stop(void)237076446f1SDmitry Lifshitz int ehci_hcd_stop(void)
238076446f1SDmitry Lifshitz {
239076446f1SDmitry Lifshitz int ret = omap_ehci_hcd_stop();
240076446f1SDmitry Lifshitz
241076446f1SDmitry Lifshitz setup_host_clocks(false);
242076446f1SDmitry Lifshitz
243076446f1SDmitry Lifshitz cm_t54_palmas_regulator_set(SMPS9_VOLTAGE, SMPS_VOLT_OFF,
244076446f1SDmitry Lifshitz SMPS9_CTRL, SMPS_MODE_SLP_AUTO);
245076446f1SDmitry Lifshitz
246076446f1SDmitry Lifshitz return ret;
247076446f1SDmitry Lifshitz }
248076446f1SDmitry Lifshitz
usb_hub_reset_devices(struct usb_hub_device * hub,int port)249*3f6e9bd9SPhilipp Tomsich void usb_hub_reset_devices(struct usb_hub_device *hub, int port)
250076446f1SDmitry Lifshitz {
251076446f1SDmitry Lifshitz /* The LAN9730 needs to be reset after the port power has been set. */
252076446f1SDmitry Lifshitz if (port == 3) {
253076446f1SDmitry Lifshitz gpio_direction_output(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, 0);
254076446f1SDmitry Lifshitz udelay(10);
255076446f1SDmitry Lifshitz gpio_direction_output(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, 1);
256076446f1SDmitry Lifshitz }
257076446f1SDmitry Lifshitz }
258076446f1SDmitry Lifshitz #endif
259076446f1SDmitry Lifshitz
260