mirror of
https://github.com/brain-hackers/u-boot-brain
synced 2024-09-07 05:13:21 +09:00
![Paul Kocialkowski](/assets/img/avatar_default.png)
This introduces OMAP3 support for the common omap boot code, as well as a major cleanup of the common omap boot code. First, the omap_boot_parameters structure becomes platform-specific, since its definition differs a bit across omap platforms. The offsets are removed as well since it is U-Boot's coding style to use structures for mapping such kind of data (in the sense that it is similar to registers). It is correct to assume that romcode structure encoding is the same as U-Boot, given the description of these structures in the TRMs. The original address provided by the bootrom is passed to the U-Boot binary instead of a duplicate of the structure stored in global data. This allows to have only the relevant (boot device and mode) information stored in global data. It is also expected that the address where the bootrom stores that information is not overridden by the U-Boot SPL or U-Boot. The save_omap_boot_params is expected to handle all special cases where the data provided by the bootrom cannot be used as-is, so that spl_boot_device and spl_boot_mode only return the data from global data. All of this is only relevant when the U-Boot SPL is used. In cases it is not, save_boot_params should fallback to its weak (or board-specific) definition. save_omap_boot_params should not be called in that context either. Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
260 lines
5.7 KiB
C
260 lines
5.7 KiB
C
/*
|
|
* Board functions for Compulab CM-T54 board
|
|
*
|
|
* Copyright (C) 2014, Compulab Ltd - http://compulab.co.il/
|
|
*
|
|
* Author: Dmitry Lifshitz <lifshitz@compulab.co.il>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <fdt_support.h>
|
|
#include <usb.h>
|
|
#include <mmc.h>
|
|
#include <palmas.h>
|
|
#include <spl.h>
|
|
|
|
#include <asm/gpio.h>
|
|
#include <asm/arch/sys_proto.h>
|
|
#include <asm/arch/mmc_host_def.h>
|
|
#include <asm/arch/clock.h>
|
|
#include <asm/arch/ehci.h>
|
|
#include <asm/ehci-omap.h>
|
|
|
|
#include "../common/eeprom.h"
|
|
|
|
#define DIE_ID_REG_BASE (OMAP54XX_L4_CORE_BASE + 0x2000)
|
|
#define DIE_ID_REG_OFFSET 0x200
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
#if !defined(CONFIG_SPL_BUILD)
|
|
inline void set_muxconf_regs_essential(void){};
|
|
#endif
|
|
|
|
const struct omap_sysinfo sysinfo = {
|
|
"Board: CM-T54\n"
|
|
};
|
|
|
|
/*
|
|
* Routine: board_init
|
|
* Description: hardware init.
|
|
*/
|
|
int board_init(void)
|
|
{
|
|
gd->bd->bi_boot_params = (CONFIG_SYS_SDRAM_BASE + 0x100);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Routine: cm_t54_palmas_regulator_set
|
|
* Description: select voltage and turn on/off Palmas PMIC regulator.
|
|
*/
|
|
static int cm_t54_palmas_regulator_set(u8 vreg, u8 vval, u8 creg, u8 cval)
|
|
{
|
|
int err;
|
|
|
|
/* Setup voltage */
|
|
err = palmas_i2c_write_u8(TWL603X_CHIP_P1, vreg, vval);
|
|
if (err) {
|
|
printf("cm_t54: could not set regulator 0x%02x voltage : %d\n",
|
|
vreg, err);
|
|
return err;
|
|
}
|
|
|
|
/* Turn on/off regulator */
|
|
err = palmas_i2c_write_u8(TWL603X_CHIP_P1, creg, cval);
|
|
if (err) {
|
|
printf("cm_t54: could not turn on/off regulator 0x%02x : %d\n",
|
|
creg, err);
|
|
return err;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Routine: mmc_get_env_part
|
|
* Description: setup environment storage device partition.
|
|
*/
|
|
#ifdef CONFIG_SYS_MMC_ENV_PART
|
|
uint mmc_get_env_part(struct mmc *mmc)
|
|
{
|
|
u32 bootmode = gd->arch.omap_boot_mode;
|
|
uint bootpart = CONFIG_SYS_MMC_ENV_PART;
|
|
|
|
/*
|
|
* If booted from eMMC boot partition then force eMMC
|
|
* FIRST boot partition to be env storage
|
|
*/
|
|
if (bootmode == BOOT_DEVICE_MMC2)
|
|
bootpart = 1;
|
|
|
|
return bootpart;
|
|
}
|
|
#endif
|
|
|
|
#if defined(CONFIG_GENERIC_MMC) && !defined(CONFIG_SPL_BUILD)
|
|
#define SB_T54_CD_GPIO 228
|
|
#define SB_T54_WP_GPIO 229
|
|
|
|
int board_mmc_init(bd_t *bis)
|
|
{
|
|
int ret0, ret1;
|
|
|
|
ret0 = omap_mmc_init(0, 0, 0, SB_T54_CD_GPIO, SB_T54_WP_GPIO);
|
|
if (ret0)
|
|
printf("cm_t54: failed to initialize mmc0\n");
|
|
|
|
ret1 = omap_mmc_init(1, 0, 0, -1, -1);
|
|
if (ret1)
|
|
printf("cm_t54: failed to initialize mmc1\n");
|
|
|
|
if (ret0 && ret1)
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_USB_HOST_ETHER
|
|
|
|
int ft_board_setup(void *blob, bd_t *bd)
|
|
{
|
|
uint8_t enetaddr[6];
|
|
|
|
/* MAC addr */
|
|
if (eth_getenv_enetaddr("usbethaddr", enetaddr)) {
|
|
fdt_find_and_setprop(blob, "/smsc95xx@0", "mac-address",
|
|
enetaddr, 6, 1);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void generate_mac_addr(uint8_t *enetaddr)
|
|
{
|
|
int reg;
|
|
|
|
reg = DIE_ID_REG_BASE + DIE_ID_REG_OFFSET;
|
|
|
|
/*
|
|
* create a fake MAC address from the processor ID code.
|
|
* first byte is 0x02 to signify locally administered.
|
|
*/
|
|
enetaddr[0] = 0x02;
|
|
enetaddr[1] = readl(reg + 0x10) & 0xff;
|
|
enetaddr[2] = readl(reg + 0xC) & 0xff;
|
|
enetaddr[3] = readl(reg + 0x8) & 0xff;
|
|
enetaddr[4] = readl(reg) & 0xff;
|
|
enetaddr[5] = (readl(reg) >> 8) & 0xff;
|
|
}
|
|
|
|
/*
|
|
* Routine: handle_mac_address
|
|
* Description: prepare MAC address for on-board Ethernet.
|
|
*/
|
|
static int handle_mac_address(void)
|
|
{
|
|
uint8_t enetaddr[6];
|
|
int ret;
|
|
|
|
ret = eth_getenv_enetaddr("usbethaddr", enetaddr);
|
|
if (ret)
|
|
return 0;
|
|
|
|
ret = cl_eeprom_read_mac_addr(enetaddr, CONFIG_SYS_I2C_EEPROM_BUS);
|
|
if (ret || !is_valid_ethaddr(enetaddr))
|
|
generate_mac_addr(enetaddr);
|
|
|
|
if (!is_valid_ethaddr(enetaddr))
|
|
return -1;
|
|
|
|
return eth_setenv_enetaddr("usbethaddr", enetaddr);
|
|
}
|
|
|
|
int board_eth_init(bd_t *bis)
|
|
{
|
|
return handle_mac_address();
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_USB_EHCI
|
|
static struct omap_usbhs_board_data usbhs_bdata = {
|
|
.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
|
|
.port_mode[1] = OMAP_EHCI_PORT_MODE_HSIC,
|
|
.port_mode[2] = OMAP_EHCI_PORT_MODE_HSIC,
|
|
};
|
|
|
|
static void setup_host_clocks(bool enable)
|
|
{
|
|
int usbhost_clk = OPTFCLKEN_HSIC60M_P3_CLK |
|
|
OPTFCLKEN_HSIC480M_P3_CLK |
|
|
OPTFCLKEN_HSIC60M_P2_CLK |
|
|
OPTFCLKEN_HSIC480M_P2_CLK |
|
|
OPTFCLKEN_UTMI_P3_CLK |
|
|
OPTFCLKEN_UTMI_P2_CLK;
|
|
|
|
int usbtll_clk = OPTFCLKEN_USB_CH1_CLK_ENABLE |
|
|
OPTFCLKEN_USB_CH2_CLK_ENABLE;
|
|
|
|
int usbhub_clk = CKOBUFFER_CLK_ENABLE_MASK;
|
|
|
|
if (enable) {
|
|
/* Enable port 2 and 3 clocks*/
|
|
setbits_le32((*prcm)->cm_l3init_hsusbhost_clkctrl, usbhost_clk);
|
|
/* Enable port 2 and 3 usb host ports tll clocks*/
|
|
setbits_le32((*prcm)->cm_l3init_hsusbtll_clkctrl, usbtll_clk);
|
|
/* Request FREF_XTAL_CLK clock for HSIC USB Hub */
|
|
setbits_le32((*ctrl)->control_ckobuffer, usbhub_clk);
|
|
} else {
|
|
clrbits_le32((*ctrl)->control_ckobuffer, usbhub_clk);
|
|
clrbits_le32((*prcm)->cm_l3init_hsusbtll_clkctrl, usbtll_clk);
|
|
clrbits_le32((*prcm)->cm_l3init_hsusbhost_clkctrl, usbhost_clk);
|
|
}
|
|
}
|
|
|
|
int ehci_hcd_init(int index, enum usb_init_type init,
|
|
struct ehci_hccr **hccr, struct ehci_hcor **hcor)
|
|
{
|
|
int ret;
|
|
|
|
/* VCC_3V3_ETH */
|
|
cm_t54_palmas_regulator_set(SMPS9_VOLTAGE, SMPS_VOLT_3V3, SMPS9_CTRL,
|
|
SMPS_MODE_SLP_AUTO | SMPS_MODE_ACT_AUTO);
|
|
|
|
setup_host_clocks(true);
|
|
|
|
ret = omap_ehci_hcd_init(index, &usbhs_bdata, hccr, hcor);
|
|
if (ret < 0)
|
|
printf("cm_t54: Failed to initialize ehci : %d\n", ret);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int ehci_hcd_stop(void)
|
|
{
|
|
int ret = omap_ehci_hcd_stop();
|
|
|
|
setup_host_clocks(false);
|
|
|
|
cm_t54_palmas_regulator_set(SMPS9_VOLTAGE, SMPS_VOLT_OFF,
|
|
SMPS9_CTRL, SMPS_MODE_SLP_AUTO);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void usb_hub_reset_devices(int port)
|
|
{
|
|
/* The LAN9730 needs to be reset after the port power has been set. */
|
|
if (port == 3) {
|
|
gpio_direction_output(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, 0);
|
|
udelay(10);
|
|
gpio_direction_output(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, 1);
|
|
}
|
|
}
|
|
#endif
|
|
|