diff options
Diffstat (limited to 'roms/u-boot/arch/arm/mach-omap2/omap5/hwinit.c')
-rw-r--r-- | roms/u-boot/arch/arm/mach-omap2/omap5/hwinit.c | 510 |
1 files changed, 510 insertions, 0 deletions
diff --git a/roms/u-boot/arch/arm/mach-omap2/omap5/hwinit.c b/roms/u-boot/arch/arm/mach-omap2/omap5/hwinit.c new file mode 100644 index 000000000..edab9a929 --- /dev/null +++ b/roms/u-boot/arch/arm/mach-omap2/omap5/hwinit.c @@ -0,0 +1,510 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * + * Functions for omap5 based boards. + * + * (C) Copyright 2011 + * Texas Instruments, <www.ti.com> + * + * Author : + * Aneesh V <aneesh@ti.com> + * Steve Sakoman <steve@sakoman.com> + * Sricharan <r.sricharan@ti.com> + */ +#include <common.h> +#include <cpu_func.h> +#include <palmas.h> +#include <asm/armv7.h> +#include <asm/arch/cpu.h> +#include <asm/arch/sys_proto.h> +#include <asm/arch/clock.h> +#include <linux/delay.h> +#include <linux/sizes.h> +#include <asm/utils.h> +#include <asm/arch/gpio.h> +#include <asm/emif.h> +#include <asm/omap_common.h> + +u32 *const omap_si_rev = (u32 *)OMAP_SRAM_SCRATCH_OMAP_REV; + +#if !CONFIG_IS_ENABLED(DM_GPIO) +static struct gpio_bank gpio_bank_54xx[8] = { + { (void *)OMAP54XX_GPIO1_BASE }, + { (void *)OMAP54XX_GPIO2_BASE }, + { (void *)OMAP54XX_GPIO3_BASE }, + { (void *)OMAP54XX_GPIO4_BASE }, + { (void *)OMAP54XX_GPIO5_BASE }, + { (void *)OMAP54XX_GPIO6_BASE }, + { (void *)OMAP54XX_GPIO7_BASE }, + { (void *)OMAP54XX_GPIO8_BASE }, +}; + +const struct gpio_bank *const omap_gpio_bank = gpio_bank_54xx; +#endif + +void do_set_mux32(u32 base, struct pad_conf_entry const *array, int size) +{ + int i; + struct pad_conf_entry *pad = (struct pad_conf_entry *)array; + + for (i = 0; i < size; i++, pad++) + writel(pad->val, base + pad->offset); +} + +#ifdef CONFIG_SPL_BUILD +/* LPDDR2 specific IO settings */ +static void io_settings_lpddr2(void) +{ + const struct ctrl_ioregs *ioregs; + + get_ioregs(&ioregs); + writel(ioregs->ctrl_ddrch, (*ctrl)->control_ddrch1_0); + writel(ioregs->ctrl_ddrch, (*ctrl)->control_ddrch1_1); + writel(ioregs->ctrl_ddrch, (*ctrl)->control_ddrch2_0); + writel(ioregs->ctrl_ddrch, (*ctrl)->control_ddrch2_1); + writel(ioregs->ctrl_lpddr2ch, (*ctrl)->control_lpddr2ch1_0); + writel(ioregs->ctrl_lpddr2ch, (*ctrl)->control_lpddr2ch1_1); + writel(ioregs->ctrl_ddrio_0, (*ctrl)->control_ddrio_0); + writel(ioregs->ctrl_ddrio_1, (*ctrl)->control_ddrio_1); + writel(ioregs->ctrl_ddrio_2, (*ctrl)->control_ddrio_2); +} + +/* DDR3 specific IO settings */ +static void io_settings_ddr3(void) +{ + u32 io_settings = 0; + const struct ctrl_ioregs *ioregs; + + get_ioregs(&ioregs); + writel(ioregs->ctrl_ddr3ch, (*ctrl)->control_ddr3ch1_0); + writel(ioregs->ctrl_ddrch, (*ctrl)->control_ddrch1_0); + writel(ioregs->ctrl_ddrch, (*ctrl)->control_ddrch1_1); + + writel(ioregs->ctrl_ddr3ch, (*ctrl)->control_ddr3ch2_0); + writel(ioregs->ctrl_ddrch, (*ctrl)->control_ddrch2_0); + writel(ioregs->ctrl_ddrch, (*ctrl)->control_ddrch2_1); + + writel(ioregs->ctrl_ddrio_0, (*ctrl)->control_ddrio_0); + writel(ioregs->ctrl_ddrio_1, (*ctrl)->control_ddrio_1); + + if (!is_dra7xx()) { + writel(ioregs->ctrl_ddrio_2, (*ctrl)->control_ddrio_2); + writel(ioregs->ctrl_lpddr2ch, (*ctrl)->control_lpddr2ch1_1); + } + + /* omap5432 does not use lpddr2 */ + writel(ioregs->ctrl_lpddr2ch, (*ctrl)->control_lpddr2ch1_0); + + writel(ioregs->ctrl_emif_sdram_config_ext, + (*ctrl)->control_emif1_sdram_config_ext); + if (!is_dra72x()) + writel(ioregs->ctrl_emif_sdram_config_ext, + (*ctrl)->control_emif2_sdram_config_ext); + + if (is_omap54xx()) { + /* Disable DLL select */ + io_settings = (readl((*ctrl)->control_port_emif1_sdram_config) + & 0xFFEFFFFF); + writel(io_settings, + (*ctrl)->control_port_emif1_sdram_config); + + io_settings = (readl((*ctrl)->control_port_emif2_sdram_config) + & 0xFFEFFFFF); + writel(io_settings, + (*ctrl)->control_port_emif2_sdram_config); + } else { + writel(ioregs->ctrl_ddr_ctrl_ext_0, + (*ctrl)->control_ddr_control_ext_0); + } +} + +/* + * Some tuning of IOs for optimal power and performance + */ +void do_io_settings(void) +{ + u32 io_settings = 0, mask = 0; + struct emif_reg_struct *emif = (struct emif_reg_struct *)EMIF1_BASE; + + /* Impedance settings EMMC, C2C 1,2, hsi2 */ + mask = (ds_mask << 2) | (ds_mask << 8) | + (ds_mask << 16) | (ds_mask << 18); + io_settings = readl((*ctrl)->control_smart1io_padconf_0) & + (~mask); + io_settings |= (ds_60_ohm << 8) | (ds_45_ohm << 16) | + (ds_45_ohm << 18) | (ds_60_ohm << 2); + writel(io_settings, (*ctrl)->control_smart1io_padconf_0); + + /* Impedance settings Mcspi2 */ + mask = (ds_mask << 30); + io_settings = readl((*ctrl)->control_smart1io_padconf_1) & + (~mask); + io_settings |= (ds_60_ohm << 30); + writel(io_settings, (*ctrl)->control_smart1io_padconf_1); + + /* Impedance settings C2C 3,4 */ + mask = (ds_mask << 14) | (ds_mask << 16); + io_settings = readl((*ctrl)->control_smart1io_padconf_2) & + (~mask); + io_settings |= (ds_45_ohm << 14) | (ds_45_ohm << 16); + writel(io_settings, (*ctrl)->control_smart1io_padconf_2); + + /* Slew rate settings EMMC, C2C 1,2 */ + mask = (sc_mask << 8) | (sc_mask << 16) | (sc_mask << 18); + io_settings = readl((*ctrl)->control_smart2io_padconf_0) & + (~mask); + io_settings |= (sc_fast << 8) | (sc_na << 16) | (sc_na << 18); + writel(io_settings, (*ctrl)->control_smart2io_padconf_0); + + /* Slew rate settings hsi2, Mcspi2 */ + mask = (sc_mask << 24) | (sc_mask << 28); + io_settings = readl((*ctrl)->control_smart2io_padconf_1) & + (~mask); + io_settings |= (sc_fast << 28) | (sc_fast << 24); + writel(io_settings, (*ctrl)->control_smart2io_padconf_1); + + /* Slew rate settings C2C 3,4 */ + mask = (sc_mask << 16) | (sc_mask << 18); + io_settings = readl((*ctrl)->control_smart2io_padconf_2) & + (~mask); + io_settings |= (sc_na << 16) | (sc_na << 18); + writel(io_settings, (*ctrl)->control_smart2io_padconf_2); + + /* impedance and slew rate settings for usb */ + mask = (usb_i_mask << 29) | (usb_i_mask << 26) | (usb_i_mask << 23) | + (usb_i_mask << 20) | (usb_i_mask << 17) | (usb_i_mask << 14); + io_settings = readl((*ctrl)->control_smart3io_padconf_1) & + (~mask); + io_settings |= (ds_60_ohm << 29) | (ds_60_ohm << 26) | + (ds_60_ohm << 23) | (sc_fast << 20) | + (sc_fast << 17) | (sc_fast << 14); + writel(io_settings, (*ctrl)->control_smart3io_padconf_1); + + if (emif_sdram_type(emif->emif_sdram_config) == EMIF_SDRAM_TYPE_LPDDR2) + io_settings_lpddr2(); + else + io_settings_ddr3(); +} + +static const struct srcomp_params srcomp_parameters[NUM_SYS_CLKS] = { + {0x45, 0x1}, /* 12 MHz */ + {-1, -1}, /* 13 MHz */ + {0x63, 0x2}, /* 16.8 MHz */ + {0x57, 0x2}, /* 19.2 MHz */ + {0x20, 0x1}, /* 26 MHz */ + {-1, -1}, /* 27 MHz */ + {0x41, 0x3} /* 38.4 MHz */ +}; + +void srcomp_enable(void) +{ + u32 srcomp_value, mul_factor, div_factor, clk_val, i; + u32 sysclk_ind = get_sys_clk_index(); + u32 omap_rev = omap_revision(); + + if (!is_omap54xx()) + return; + + mul_factor = srcomp_parameters[sysclk_ind].multiply_factor; + div_factor = srcomp_parameters[sysclk_ind].divide_factor; + + for (i = 0; i < 4; i++) { + srcomp_value = readl((*ctrl)->control_srcomp_north_side + i*4); + srcomp_value &= + ~(MULTIPLY_FACTOR_XS_MASK | DIVIDE_FACTOR_XS_MASK); + srcomp_value |= (mul_factor << MULTIPLY_FACTOR_XS_SHIFT) | + (div_factor << DIVIDE_FACTOR_XS_SHIFT); + writel(srcomp_value, (*ctrl)->control_srcomp_north_side + i*4); + } + + if ((omap_rev == OMAP5430_ES1_0) || (omap_rev == OMAP5432_ES1_0)) { + clk_val = readl((*prcm)->cm_coreaon_io_srcomp_clkctrl); + clk_val |= OPTFCLKEN_SRCOMP_FCLK_MASK; + writel(clk_val, (*prcm)->cm_coreaon_io_srcomp_clkctrl); + + for (i = 0; i < 4; i++) { + srcomp_value = + readl((*ctrl)->control_srcomp_north_side + i*4); + srcomp_value &= ~PWRDWN_XS_MASK; + writel(srcomp_value, + (*ctrl)->control_srcomp_north_side + i*4); + + while (((readl((*ctrl)->control_srcomp_north_side + i*4) + & SRCODE_READ_XS_MASK) >> + SRCODE_READ_XS_SHIFT) == 0) + ; + + srcomp_value = + readl((*ctrl)->control_srcomp_north_side + i*4); + srcomp_value &= ~OVERRIDE_XS_MASK; + writel(srcomp_value, + (*ctrl)->control_srcomp_north_side + i*4); + } + } else { + srcomp_value = readl((*ctrl)->control_srcomp_east_side_wkup); + srcomp_value &= ~(MULTIPLY_FACTOR_XS_MASK | + DIVIDE_FACTOR_XS_MASK); + srcomp_value |= (mul_factor << MULTIPLY_FACTOR_XS_SHIFT) | + (div_factor << DIVIDE_FACTOR_XS_SHIFT); + writel(srcomp_value, (*ctrl)->control_srcomp_east_side_wkup); + + for (i = 0; i < 4; i++) { + srcomp_value = + readl((*ctrl)->control_srcomp_north_side + i*4); + srcomp_value |= SRCODE_OVERRIDE_SEL_XS_MASK; + writel(srcomp_value, + (*ctrl)->control_srcomp_north_side + i*4); + + srcomp_value = + readl((*ctrl)->control_srcomp_north_side + i*4); + srcomp_value &= ~OVERRIDE_XS_MASK; + writel(srcomp_value, + (*ctrl)->control_srcomp_north_side + i*4); + } + + srcomp_value = + readl((*ctrl)->control_srcomp_east_side_wkup); + srcomp_value |= SRCODE_OVERRIDE_SEL_XS_MASK; + writel(srcomp_value, (*ctrl)->control_srcomp_east_side_wkup); + + srcomp_value = + readl((*ctrl)->control_srcomp_east_side_wkup); + srcomp_value &= ~OVERRIDE_XS_MASK; + writel(srcomp_value, (*ctrl)->control_srcomp_east_side_wkup); + + clk_val = readl((*prcm)->cm_coreaon_io_srcomp_clkctrl); + clk_val |= OPTFCLKEN_SRCOMP_FCLK_MASK; + writel(clk_val, (*prcm)->cm_coreaon_io_srcomp_clkctrl); + + clk_val = readl((*prcm)->cm_wkupaon_io_srcomp_clkctrl); + clk_val |= OPTFCLKEN_SRCOMP_FCLK_MASK; + writel(clk_val, (*prcm)->cm_wkupaon_io_srcomp_clkctrl); + + for (i = 0; i < 4; i++) { + while (((readl((*ctrl)->control_srcomp_north_side + i*4) + & SRCODE_READ_XS_MASK) >> + SRCODE_READ_XS_SHIFT) == 0) + ; + + srcomp_value = + readl((*ctrl)->control_srcomp_north_side + i*4); + srcomp_value &= ~SRCODE_OVERRIDE_SEL_XS_MASK; + writel(srcomp_value, + (*ctrl)->control_srcomp_north_side + i*4); + } + + while (((readl((*ctrl)->control_srcomp_east_side_wkup) & + SRCODE_READ_XS_MASK) >> SRCODE_READ_XS_SHIFT) == 0) + ; + + srcomp_value = + readl((*ctrl)->control_srcomp_east_side_wkup); + srcomp_value &= ~SRCODE_OVERRIDE_SEL_XS_MASK; + writel(srcomp_value, (*ctrl)->control_srcomp_east_side_wkup); + } +} +#endif + +void config_data_eye_leveling_samples(u32 emif_base) +{ + const struct ctrl_ioregs *ioregs; + + get_ioregs(&ioregs); + + /*EMIF_SDRAM_CONFIG_EXT-Read data eye leveling no of samples =4*/ + if (emif_base == EMIF1_BASE) + writel(ioregs->ctrl_emif_sdram_config_ext_final, + (*ctrl)->control_emif1_sdram_config_ext); + else if (emif_base == EMIF2_BASE) + writel(ioregs->ctrl_emif_sdram_config_ext_final, + (*ctrl)->control_emif2_sdram_config_ext); +} + +void init_cpu_configuration(void) +{ + u32 l2actlr; + + asm volatile("mrc p15, 1, %0, c15, c0, 0" : "=r"(l2actlr)); + /* + * L2ACTLR: Ensure to enable the following: + * 3: Disable clean/evict push to external + * 4: Disable WriteUnique and WriteLineUnique transactions from master + * 8: Disable DVM/CMO message broadcast + */ + l2actlr |= 0x118; + omap_smc1(OMAP5_SERVICE_L2ACTLR_SET, l2actlr); +} + +void init_omap_revision(void) +{ + /* + * For some of the ES2/ES1 boards ID_CODE is not reliable: + * Also, ES1 and ES2 have different ARM revisions + * So use ARM revision for identification + */ + unsigned int rev = cortex_rev(); + + switch (readl(CONTROL_ID_CODE)) { + case OMAP5430_CONTROL_ID_CODE_ES1_0: + *omap_si_rev = OMAP5430_ES1_0; + if (rev == MIDR_CORTEX_A15_R2P2) + *omap_si_rev = OMAP5430_ES2_0; + break; + case OMAP5432_CONTROL_ID_CODE_ES1_0: + *omap_si_rev = OMAP5432_ES1_0; + if (rev == MIDR_CORTEX_A15_R2P2) + *omap_si_rev = OMAP5432_ES2_0; + break; + case OMAP5430_CONTROL_ID_CODE_ES2_0: + *omap_si_rev = OMAP5430_ES2_0; + break; + case OMAP5432_CONTROL_ID_CODE_ES2_0: + *omap_si_rev = OMAP5432_ES2_0; + break; + case DRA762_CONTROL_ID_CODE_ES1_0: + *omap_si_rev = DRA762_ES1_0; + break; + case DRA752_CONTROL_ID_CODE_ES1_0: + *omap_si_rev = DRA752_ES1_0; + break; + case DRA752_CONTROL_ID_CODE_ES1_1: + *omap_si_rev = DRA752_ES1_1; + break; + case DRA752_CONTROL_ID_CODE_ES2_0: + *omap_si_rev = DRA752_ES2_0; + break; + case DRA722_CONTROL_ID_CODE_ES1_0: + *omap_si_rev = DRA722_ES1_0; + break; + case DRA722_CONTROL_ID_CODE_ES2_0: + *omap_si_rev = DRA722_ES2_0; + break; + case DRA722_CONTROL_ID_CODE_ES2_1: + *omap_si_rev = DRA722_ES2_1; + break; + default: + *omap_si_rev = OMAP5430_SILICON_ID_INVALID; + } + init_cpu_configuration(); +} + +void init_package_revision(void) +{ + unsigned int die_id[4] = { 0 }; + u8 package; + + omap_die_id(die_id); + package = (die_id[2] >> 16) & 0x3; + + if (is_dra76x()) { + switch (package) { + case DRA762_ABZ_PACKAGE: + *omap_si_rev = DRA762_ABZ_ES1_0; + break; + case DRA762_ACD_PACKAGE: + default: + *omap_si_rev = DRA762_ACD_ES1_0; + break; + } + } +} + +void omap_die_id(unsigned int *die_id) +{ + die_id[0] = readl((*ctrl)->control_std_fuse_die_id_0); + die_id[1] = readl((*ctrl)->control_std_fuse_die_id_1); + die_id[2] = readl((*ctrl)->control_std_fuse_die_id_2); + die_id[3] = readl((*ctrl)->control_std_fuse_die_id_3); +} + +void reset_cpu(void) +{ + u32 omap_rev = omap_revision(); + + /* + * WARM reset is not functional in case of OMAP5430 ES1.0 soc. + * So use cold reset in case instead. + */ + if (omap_rev == OMAP5430_ES1_0) + writel(PRM_RSTCTRL_RESET << 0x1, (*prcm)->prm_rstctrl); + else + writel(PRM_RSTCTRL_RESET, (*prcm)->prm_rstctrl); +} + +u32 warm_reset(void) +{ + return readl((*prcm)->prm_rstst) & PRM_RSTST_WARM_RESET_MASK; +} + +void setup_warmreset_time(void) +{ + u32 rst_time, rst_val; + + /* + * MAX value for PRM_RSTTIME[9:0]RSTTIME1 stored is 0x3ff. + * 0x3ff is in the no of FUNC_32K_CLK cycles. Converting cycles + * into microsec and passing the value. + */ + rst_time = usec_to_32k(CONFIG_OMAP_PLATFORM_RESET_TIME_MAX_USEC) + << RSTTIME1_SHIFT; + + if (rst_time > RSTTIME1_MASK) + rst_time = RSTTIME1_MASK; + + rst_val = readl((*prcm)->prm_rsttime) & ~RSTTIME1_MASK; + rst_val |= rst_time; + writel(rst_val, (*prcm)->prm_rsttime); +} + +void v7_arch_cp15_set_l2aux_ctrl(u32 l2auxctrl, u32 cpu_midr, + u32 cpu_rev_comb, u32 cpu_variant, + u32 cpu_rev) +{ + omap_smc1(OMAP5_SERVICE_L2ACTLR_SET, l2auxctrl); +} + +void v7_arch_cp15_set_acr(u32 acr, u32 cpu_midr, u32 cpu_rev_comb, + u32 cpu_variant, u32 cpu_rev) +{ + +#ifdef CONFIG_ARM_ERRATA_801819 + /* + * DRA72x processors are uniprocessors and DONOT have + * ACP (Accelerator Coherency Port) hooked to ACE (AXI Coherency + * Extensions) Hence the erratum workaround is not applicable for + * DRA72x processors. + */ + if (is_dra72x()) + acr &= ~((0x3 << 23) | (0x3 << 25)); +#endif + omap_smc1(OMAP5_SERVICE_ACR_SET, acr); +} + +#if defined(CONFIG_PALMAS_POWER) +__weak void board_mmc_poweron_ldo(uint voltage) +{ + palmas_mmc1_poweron_ldo(LDO1_VOLTAGE, LDO1_CTRL, voltage); +} + +void vmmc_pbias_config(uint voltage) +{ + u32 value = 0; + + value = readl((*ctrl)->control_pbias); + value &= ~SDCARD_PWRDNZ; + writel(value, (*ctrl)->control_pbias); + udelay(10); /* wait 10 us */ + value &= ~SDCARD_BIAS_PWRDNZ; + writel(value, (*ctrl)->control_pbias); + + board_mmc_poweron_ldo(voltage); + + value = readl((*ctrl)->control_pbias); + value |= SDCARD_BIAS_PWRDNZ; + writel(value, (*ctrl)->control_pbias); + udelay(150); /* wait 150 us */ + value |= SDCARD_PWRDNZ; + writel(value, (*ctrl)->control_pbias); + udelay(150); /* wait 150 us */ +} +#endif |