diff options
Diffstat (limited to 'arch/arm/cpu/armv7')
50 files changed, 1337 insertions, 4561 deletions
diff --git a/arch/arm/cpu/armv7/Makefile b/arch/arm/cpu/armv7/Makefile index 6b2addca11..4fdbee4bc0 100644 --- a/arch/arm/cpu/armv7/Makefile +++ b/arch/arm/cpu/armv7/Makefile @@ -32,8 +32,12 @@ COBJS += cache_v7.o COBJS += cpu.o COBJS += syslib.o +ifneq ($(CONFIG_AM33XX)$(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX)$(CONFIG_TEGRA20),) +SOBJS += lowlevel_init.o +endif + SRCS := $(START:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(COBJS)) +OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) START := $(addprefix $(obj),$(START)) all: $(obj).depend $(START) $(LIB) diff --git a/arch/arm/cpu/armv7/am33xx/board.c b/arch/arm/cpu/armv7/am33xx/board.c index 71309a7f47..b387ac27ec 100644 --- a/arch/arm/cpu/armv7/am33xx/board.c +++ b/arch/arm/cpu/armv7/am33xx/board.c @@ -17,15 +17,22 @@ */ #include <common.h> +#include <errno.h> #include <asm/arch/cpu.h> #include <asm/arch/hardware.h> #include <asm/arch/omap.h> #include <asm/arch/ddr_defs.h> #include <asm/arch/clock.h> +#include <asm/arch/gpio.h> #include <asm/arch/mmc_host_def.h> -#include <asm/arch/common_def.h> +#include <asm/arch/sys_proto.h> #include <asm/io.h> #include <asm/omap_common.h> +#include <asm/emif.h> +#include <asm/gpio.h> +#include <i2c.h> +#include <miiphy.h> +#include <cpsw.h> DECLARE_GLOBAL_DATA_PTR; @@ -33,6 +40,78 @@ struct wd_timer *wdtimer = (struct wd_timer *)WDT_BASE; struct gptimer *timer_base = (struct gptimer *)CONFIG_SYS_TIMERBASE; struct uart_sys *uart_base = (struct uart_sys *)DEFAULT_UART_BASE; +static const struct gpio_bank gpio_bank_am33xx[4] = { + { (void *)AM33XX_GPIO0_BASE, METHOD_GPIO_24XX }, + { (void *)AM33XX_GPIO1_BASE, METHOD_GPIO_24XX }, + { (void *)AM33XX_GPIO2_BASE, METHOD_GPIO_24XX }, + { (void *)AM33XX_GPIO3_BASE, METHOD_GPIO_24XX }, +}; + +const struct gpio_bank *const omap_gpio_bank = gpio_bank_am33xx; + +/* MII mode defines */ +#define MII_MODE_ENABLE 0x0 +#define RGMII_MODE_ENABLE 0xA + +/* GPIO that controls power to DDR on EVM-SK */ +#define GPIO_DDR_VTT_EN 7 + +static struct ctrl_dev *cdev = (struct ctrl_dev *)CTRL_DEVICE_BASE; + +static struct am335x_baseboard_id __attribute__((section (".data"))) header; + +static inline int board_is_bone(void) +{ + return !strncmp(header.name, "A335BONE", HDR_NAME_LEN); +} + +static inline int board_is_evm_sk(void) +{ + return !strncmp("A335X_SK", header.name, HDR_NAME_LEN); +} + +/* + * Read header information from EEPROM into global structure. + */ +static int read_eeprom(void) +{ + /* Check if baseboard eeprom is available */ + if (i2c_probe(CONFIG_SYS_I2C_EEPROM_ADDR)) { + puts("Could not probe the EEPROM; something fundamentally " + "wrong on the I2C bus.\n"); + return -ENODEV; + } + + /* read the eeprom using i2c */ + if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 2, (uchar *)&header, + sizeof(header))) { + puts("Could not read the EEPROM; something fundamentally" + " wrong on the I2C bus.\n"); + return -EIO; + } + + if (header.magic != 0xEE3355AA) { + /* + * read the eeprom using i2c again, + * but use only a 1 byte address + */ + if (i2c_read(CONFIG_SYS_I2C_EEPROM_ADDR, 0, 1, + (uchar *)&header, sizeof(header))) { + puts("Could not read the EEPROM; something " + "fundamentally wrong on the I2C bus.\n"); + return -EIO; + } + + if (header.magic != 0xEE3355AA) { + printf("Incorrect magic number (0x%x) in EEPROM\n", + header.magic); + return -EINVAL; + } + } + + return 0; +} + /* UART Defines */ #ifdef CONFIG_SPL_BUILD #define UART_RESET (0x1 << 1) @@ -57,6 +136,18 @@ static void init_timer(void) #endif /* + * Determine what type of DDR we have. + */ +static short inline board_memory_type(void) +{ + /* The following boards are known to use DDR3. */ + if (board_is_evm_sk()) + return EMIF_REG_SDRAM_TYPE_DDR3; + + return EMIF_REG_SDRAM_TYPE_DDR2; +} + +/* * early system init of muxing and clocks. */ void s_init(void) @@ -97,17 +188,36 @@ void s_init(void) preloader_console_init(); - config_ddr(); -#endif + /* Initalize the board header */ + enable_i2c0_pin_mux(); + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + if (read_eeprom() < 0) + puts("Could not get board ID.\n"); + + enable_board_pin_mux(&header); + if (board_is_evm_sk()) { + /* + * EVM SK 1.2A and later use gpio0_7 to enable DDR3. + * This is safe enough to do on older revs. + */ + gpio_request(GPIO_DDR_VTT_EN, "ddr_vtt_en"); + gpio_direction_output(GPIO_DDR_VTT_EN, 1); + } - /* Enable MMC0 */ - enable_mmc0_pin_mux(); + config_ddr(board_memory_type()); +#endif } #if defined(CONFIG_OMAP_HSMMC) && !defined(CONFIG_SPL_BUILD) int board_mmc_init(bd_t *bis) { - return omap_mmc_init(0, 0, 0); + int ret; + + ret = omap_mmc_init(0, 0, 0); + if (ret) + return ret; + + return omap_mmc_init(1, 0, 0); } #endif @@ -116,3 +226,93 @@ void setup_clocks_for_console(void) /* Not yet implemented */ return; } + +/* + * Basic board specific setup. Pinmux has been handled already. + */ +int board_init(void) +{ + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); + if (read_eeprom() < 0) + puts("Could not get board ID.\n"); + + gd->bd->bi_boot_params = PHYS_DRAM_1 + 0x100; + + return 0; +} + +#ifdef CONFIG_DRIVER_TI_CPSW +static void cpsw_control(int enabled) +{ + /* VTP can be added here */ + + return; +} + +static struct cpsw_slave_data cpsw_slaves[] = { + { + .slave_reg_ofs = 0x208, + .sliver_reg_ofs = 0xd80, + .phy_id = 0, + }, + { + .slave_reg_ofs = 0x308, + .sliver_reg_ofs = 0xdc0, + .phy_id = 1, + }, +}; + +static struct cpsw_platform_data cpsw_data = { + .mdio_base = AM335X_CPSW_MDIO_BASE, + .cpsw_base = AM335X_CPSW_BASE, + .mdio_div = 0xff, + .channels = 8, + .cpdma_reg_ofs = 0x800, + .slaves = 1, + .slave_data = cpsw_slaves, + .ale_reg_ofs = 0xd00, + .ale_entries = 1024, + .host_port_reg_ofs = 0x108, + .hw_stats_reg_ofs = 0x900, + .mac_control = (1 << 5), + .control = cpsw_control, + .host_port_num = 0, + .version = CPSW_CTRL_VERSION_2, +}; + +int board_eth_init(bd_t *bis) +{ + uint8_t mac_addr[6]; + uint32_t mac_hi, mac_lo; + + if (!eth_getenv_enetaddr("ethaddr", mac_addr)) { + debug("<ethaddr> not set. Reading from E-fuse\n"); + /* try reading mac address from efuse */ + mac_lo = readl(&cdev->macid0l); + mac_hi = readl(&cdev->macid0h); + mac_addr[0] = mac_hi & 0xFF; + mac_addr[1] = (mac_hi & 0xFF00) >> 8; + mac_addr[2] = (mac_hi & 0xFF0000) >> 16; + mac_addr[3] = (mac_hi & 0xFF000000) >> 24; + mac_addr[4] = mac_lo & 0xFF; + mac_addr[5] = (mac_lo & 0xFF00) >> 8; + + if (is_valid_ether_addr(mac_addr)) + eth_setenv_enetaddr("ethaddr", mac_addr); + else + return -1; + } + + if (board_is_bone()) { + writel(MII_MODE_ENABLE, &cdev->miisel); + cpsw_slaves[0].phy_if = cpsw_slaves[1].phy_if = + PHY_INTERFACE_MODE_MII; + } else { + writel(RGMII_MODE_ENABLE, &cdev->miisel); + cpsw_slaves[0].phy_if = cpsw_slaves[1].phy_if = + PHY_INTERFACE_MODE_RGMII; + } + + return cpsw_register(&cpsw_data); +} +#endif diff --git a/arch/arm/cpu/armv7/am33xx/clock.c b/arch/arm/cpu/armv7/am33xx/clock.c index bbb9c1353f..2b19506a34 100644 --- a/arch/arm/cpu/armv7/am33xx/clock.c +++ b/arch/arm/cpu/armv7/am33xx/clock.c @@ -24,6 +24,7 @@ #define PRCM_MOD_EN 0x2 #define PRCM_FORCE_WAKEUP 0x2 +#define PRCM_FUNCTL 0x0 #define PRCM_EMIF_CLK_ACTIVITY BIT(2) #define PRCM_L3_GCLK_ACTIVITY BIT(4) @@ -38,7 +39,7 @@ #define CLK_MODE_SEL 0x7 #define CLK_MODE_MASK 0xfffffff8 #define CLK_DIV_SEL 0xFFFFFFE0 - +#define CPGMAC0_IDLE 0x30000 const struct cm_perpll *cmper = (struct cm_perpll *)CM_PER; const struct cm_wkuppll *cmwkup = (struct cm_wkuppll *)CM_WKUP; @@ -70,6 +71,10 @@ static void enable_interface_clocks(void) writel(PRCM_MOD_EN, &cmper->l4hsclkctrl); while (readl(&cmper->l4hsclkctrl) != PRCM_MOD_EN) ; + + writel(PRCM_MOD_EN, &cmwkup->wkgpio0clkctrl); + while (readl(&cmwkup->wkgpio0clkctrl) != PRCM_MOD_EN) + ; } /* @@ -118,6 +123,36 @@ static void enable_per_clocks(void) writel(PRCM_MOD_EN, &cmwkup->wkup_i2c0ctrl); while (readl(&cmwkup->wkup_i2c0ctrl) != PRCM_MOD_EN) ; + + /* gpio1 module */ + writel(PRCM_MOD_EN, &cmper->gpio1clkctrl); + while (readl(&cmper->gpio1clkctrl) != PRCM_MOD_EN) + ; + + /* gpio2 module */ + writel(PRCM_MOD_EN, &cmper->gpio2clkctrl); + while (readl(&cmper->gpio2clkctrl) != PRCM_MOD_EN) + ; + + /* gpio3 module */ + writel(PRCM_MOD_EN, &cmper->gpio3clkctrl); + while (readl(&cmper->gpio3clkctrl) != PRCM_MOD_EN) + ; + + /* i2c1 */ + writel(PRCM_MOD_EN, &cmper->i2c1clkctrl); + while (readl(&cmper->i2c1clkctrl) != PRCM_MOD_EN) + ; + + /* Ethernet */ + writel(PRCM_MOD_EN, &cmper->cpgmac0clkctrl); + while ((readl(&cmper->cpgmac0clkctrl) & CPGMAC0_IDLE) != PRCM_FUNCTL) + ; + + /* spi0 */ + writel(PRCM_MOD_EN, &cmper->spi0clkctrl); + while (readl(&cmper->spi0clkctrl) != PRCM_MOD_EN) + ; } static void mpu_pll_config(void) @@ -216,7 +251,7 @@ static void per_pll_config(void) ; } -static void ddr_pll_config(void) +void ddr_pll_config(unsigned int ddrpll_m) { u32 clkmode, clksel, div_m2; @@ -234,7 +269,7 @@ static void ddr_pll_config(void) ; clksel = clksel & (~CLK_SEL_MASK); - clksel = clksel | ((DDRPLL_M << CLK_SEL_SHIFT) | DDRPLL_N); + clksel = clksel | ((ddrpll_m << CLK_SEL_SHIFT) | DDRPLL_N); writel(clksel, &cmwkup->clkseldpllddr); div_m2 = div_m2 & CLK_DIV_SEL; @@ -255,11 +290,6 @@ void enable_emif_clocks(void) writel(PRCM_MOD_EN, &cmper->emiffwclkctrl); /* Enable EMIF0 Clock */ writel(PRCM_MOD_EN, &cmper->emifclkctrl); - /* Poll for emif_gclk & L3_G clock are active */ - while ((readl(&cmper->l3clkstctrl) & (PRCM_EMIF_CLK_ACTIVITY | - PRCM_L3_GCLK_ACTIVITY)) != (PRCM_EMIF_CLK_ACTIVITY | - PRCM_L3_GCLK_ACTIVITY)) - ; /* Poll if module is functional */ while ((readl(&cmper->emifclkctrl)) != PRCM_MOD_EN) ; @@ -273,7 +303,6 @@ void pll_init() mpu_pll_config(); core_pll_config(); per_pll_config(); - ddr_pll_config(); /* Enable the required interconnect clocks */ enable_interface_clocks(); diff --git a/arch/arm/cpu/armv7/am33xx/ddr.c b/arch/arm/cpu/armv7/am33xx/ddr.c index ed982c11e8..fd9fc4a720 100644 --- a/arch/arm/cpu/armv7/am33xx/ddr.c +++ b/arch/arm/cpu/armv7/am33xx/ddr.c @@ -17,13 +17,15 @@ http://www.ti.com/ #include <asm/arch/cpu.h> #include <asm/arch/ddr_defs.h> +#include <asm/arch/sys_proto.h> #include <asm/io.h> +#include <asm/emif.h> /** * Base address for EMIF instances */ -static struct emif_regs *emif_reg = { - (struct emif_regs *)EMIF4_0_CFG_BASE}; +static struct emif_reg_struct *emif_reg = { + (struct emif_reg_struct *)EMIF4_0_CFG_BASE}; /** * Base address for DDR instance @@ -39,109 +41,79 @@ static struct ddr_cmdtctrl *ioctrl_reg = { (struct ddr_cmdtctrl *)DDR_CONTROL_BASE_ADDR}; /** - * As a convention, all functions here return 0 on success - * -1 on failure. - */ - -/** * Configure SDRAM */ -int config_sdram(struct sdram_config *cfg) +void config_sdram(const struct emif_regs *regs) { - writel(cfg->sdrcr, &emif_reg->sdrcr); - writel(cfg->sdrcr2, &emif_reg->sdrcr2); - writel(cfg->refresh, &emif_reg->sdrrcr); - writel(cfg->refresh_sh, &emif_reg->sdrrcsr); - - return 0; + writel(regs->ref_ctrl, &emif_reg->emif_sdram_ref_ctrl); + writel(regs->ref_ctrl, &emif_reg->emif_sdram_ref_ctrl_shdw); + if (regs->zq_config){ + writel(regs->zq_config, &emif_reg->emif_zq_config); + writel(regs->sdram_config, &cstat->secure_emif_sdram_config); + } + writel(regs->sdram_config, &emif_reg->emif_sdram_config); } /** * Set SDRAM timings */ -int set_sdram_timings(struct sdram_timing *t) +void set_sdram_timings(const struct emif_regs *regs) { - writel(t->time1, &emif_reg->sdrtim1); - writel(t->time1_sh, &emif_reg->sdrtim1sr); - writel(t->time2, &emif_reg->sdrtim2); - writel(t->time2_sh, &emif_reg->sdrtim2sr); - writel(t->time3, &emif_reg->sdrtim3); - writel(t->time3_sh, &emif_reg->sdrtim3sr); - - return 0; + writel(regs->sdram_tim1, &emif_reg->emif_sdram_tim_1); + writel(regs->sdram_tim1, &emif_reg->emif_sdram_tim_1_shdw); + writel(regs->sdram_tim2, &emif_reg->emif_sdram_tim_2); + writel(regs->sdram_tim2, &emif_reg->emif_sdram_tim_2_shdw); + writel(regs->sdram_tim3, &emif_reg->emif_sdram_tim_3); + writel(regs->sdram_tim3, &emif_reg->emif_sdram_tim_3_shdw); } /** * Configure DDR PHY */ -int config_ddr_phy(struct ddr_phy_control *p) +void config_ddr_phy(const struct emif_regs *regs) { - writel(p->reg, &emif_reg->ddrphycr); - writel(p->reg_sh, &emif_reg->ddrphycsr); - - return 0; + writel(regs->emif_ddr_phy_ctlr_1, &emif_reg->emif_ddr_phy_ctrl_1); + writel(regs->emif_ddr_phy_ctlr_1, &emif_reg->emif_ddr_phy_ctrl_1_shdw); } /** * Configure DDR CMD control registers */ -int config_cmd_ctrl(struct cmd_control *cmd) +void config_cmd_ctrl(const struct cmd_control *cmd) { writel(cmd->cmd0csratio, &ddr_reg[0]->cm0csratio); - writel(cmd->cmd0csforce, &ddr_reg[0]->cm0csforce); - writel(cmd->cmd0csdelay, &ddr_reg[0]->cm0csdelay); writel(cmd->cmd0dldiff, &ddr_reg[0]->cm0dldiff); writel(cmd->cmd0iclkout, &ddr_reg[0]->cm0iclkout); writel(cmd->cmd1csratio, &ddr_reg[0]->cm1csratio); - writel(cmd->cmd1csforce, &ddr_reg[0]->cm1csforce); - writel(cmd->cmd1csdelay, &ddr_reg[0]->cm1csdelay); writel(cmd->cmd1dldiff, &ddr_reg[0]->cm1dldiff); writel(cmd->cmd1iclkout, &ddr_reg[0]->cm1iclkout); writel(cmd->cmd2csratio, &ddr_reg[0]->cm2csratio); - writel(cmd->cmd2csforce, &ddr_reg[0]->cm2csforce); - writel(cmd->cmd2csdelay, &ddr_reg[0]->cm2csdelay); writel(cmd->cmd2dldiff, &ddr_reg[0]->cm2dldiff); writel(cmd->cmd2iclkout, &ddr_reg[0]->cm2iclkout); - - return 0; } /** * Configure DDR DATA registers */ -int config_ddr_data(int macrono, struct ddr_data *data) +void config_ddr_data(int macrono, const struct ddr_data *data) { writel(data->datardsratio0, &ddr_reg[macrono]->dt0rdsratio0); - writel(data->datardsratio1, &ddr_reg[macrono]->dt0rdsratio1); - writel(data->datawdsratio0, &ddr_reg[macrono]->dt0wdsratio0); - writel(data->datawdsratio1, &ddr_reg[macrono]->dt0wdsratio1); - writel(data->datawiratio0, &ddr_reg[macrono]->dt0wiratio0); - writel(data->datawiratio1, &ddr_reg[macrono]->dt0wiratio1); writel(data->datagiratio0, &ddr_reg[macrono]->dt0giratio0); - writel(data->datagiratio1, &ddr_reg[macrono]->dt0giratio1); - writel(data->datafwsratio0, &ddr_reg[macrono]->dt0fwsratio0); - writel(data->datafwsratio1, &ddr_reg[macrono]->dt0fwsratio1); - writel(data->datawrsratio0, &ddr_reg[macrono]->dt0wrsratio0); - writel(data->datawrsratio1, &ddr_reg[macrono]->dt0wrsratio1); - + writel(data->datauserank0delay, &ddr_reg[macrono]->dt0rdelays0); writel(data->datadldiff0, &ddr_reg[macrono]->dt0dldiff0); - - return 0; } -int config_io_ctrl(struct ddr_ioctrl *ioctrl) +void config_io_ctrl(unsigned long val) { - writel(ioctrl->cmd1ctl, &ioctrl_reg->cm0ioctl); - writel(ioctrl->cmd2ctl, &ioctrl_reg->cm1ioctl); - writel(ioctrl->cmd3ctl, &ioctrl_reg->cm2ioctl); - writel(ioctrl->data1ctl, &ioctrl_reg->dt0ioctl); - writel(ioctrl->data2ctl, &ioctrl_reg->dt1ioctl); - - return 0; + writel(val, &ioctrl_reg->cm0ioctl); + writel(val, &ioctrl_reg->cm1ioctl); + writel(val, &ioctrl_reg->cm2ioctl); + writel(val, &ioctrl_reg->dt0ioctl); + writel(val, &ioctrl_reg->dt1ioctl); } diff --git a/arch/arm/cpu/armv7/am33xx/emif4.c b/arch/arm/cpu/armv7/am33xx/emif4.c index 2f4164df82..b2d7c0d956 100644 --- a/arch/arm/cpu/armv7/am33xx/emif4.c +++ b/arch/arm/cpu/armv7/am33xx/emif4.c @@ -21,15 +21,12 @@ #include <asm/arch/ddr_defs.h> #include <asm/arch/hardware.h> #include <asm/arch/clock.h> +#include <asm/arch/sys_proto.h> #include <asm/io.h> +#include <asm/emif.h> DECLARE_GLOBAL_DATA_PTR; -struct ddr_regs *ddrregs = (struct ddr_regs *)DDR_PHY_BASE_ADDR; -struct vtp_reg *vtpreg = (struct vtp_reg *)VTP0_CTRL_ADDR; -struct ddr_ctrl *ddrctrl = (struct ddr_ctrl *)DDR_CTRL_ADDR; - - int dram_init(void) { /* dram_init must store complete ramsize in gd->ram_size */ @@ -47,58 +44,80 @@ void dram_init_banksize(void) #ifdef CONFIG_SPL_BUILD -static void data_macro_config(int dataMacroNum) -{ - struct ddr_data data; - - data.datardsratio0 = ((DDR2_RD_DQS<<30)|(DDR2_RD_DQS<<20) - |(DDR2_RD_DQS<<10)|(DDR2_RD_DQS<<0)); - data.datardsratio1 = DDR2_RD_DQS>>2; - data.datawdsratio0 = ((DDR2_WR_DQS<<30)|(DDR2_WR_DQS<<20) - |(DDR2_WR_DQS<<10)|(DDR2_WR_DQS<<0)); - data.datawdsratio1 = DDR2_WR_DQS>>2; - data.datawiratio0 = ((DDR2_PHY_WRLVL<<30)|(DDR2_PHY_WRLVL<<20) - |(DDR2_PHY_WRLVL<<10)|(DDR2_PHY_WRLVL<<0)); - data.datawiratio1 = DDR2_PHY_WRLVL>>2; - data.datagiratio0 = ((DDR2_PHY_GATELVL<<30)|(DDR2_PHY_GATELVL<<20) - |(DDR2_PHY_GATELVL<<10)|(DDR2_PHY_GATELVL<<0)); - data.datagiratio1 = DDR2_PHY_GATELVL>>2; - data.datafwsratio0 = ((DDR2_PHY_FIFO_WE<<30)|(DDR2_PHY_FIFO_WE<<20) - |(DDR2_PHY_FIFO_WE<<10)|(DDR2_PHY_FIFO_WE<<0)); - data.datafwsratio1 = DDR2_PHY_FIFO_WE>>2; - data.datawrsratio0 = ((DDR2_PHY_WR_DATA<<30)|(DDR2_PHY_WR_DATA<<20) - |(DDR2_PHY_WR_DATA<<10)|(DDR2_PHY_WR_DATA<<0)); - data.datawrsratio1 = DDR2_PHY_WR_DATA>>2; - data.datadldiff0 = PHY_DLL_LOCK_DIFF; - - config_ddr_data(dataMacroNum, &data); -} - -static void cmd_macro_config(void) -{ - struct cmd_control cmd; - - cmd.cmd0csratio = DDR2_RATIO; - cmd.cmd0csforce = CMD_FORCE; - cmd.cmd0csdelay = CMD_DELAY; - cmd.cmd0dldiff = DDR2_DLL_LOCK_DIFF; - cmd.cmd0iclkout = DDR2_INVERT_CLKOUT; - - cmd.cmd1csratio = DDR2_RATIO; - cmd.cmd1csforce = CMD_FORCE; - cmd.cmd1csdelay = CMD_DELAY; - cmd.cmd1dldiff = DDR2_DLL_LOCK_DIFF; - cmd.cmd1iclkout = DDR2_INVERT_CLKOUT; - - cmd.cmd2csratio = DDR2_RATIO; - cmd.cmd2csforce = CMD_FORCE; - cmd.cmd2csdelay = CMD_DELAY; - cmd.cmd2dldiff = DDR2_DLL_LOCK_DIFF; - cmd.cmd2iclkout = DDR2_INVERT_CLKOUT; - - config_cmd_ctrl(&cmd); - -} +static struct vtp_reg *vtpreg = (struct vtp_reg *)VTP0_CTRL_ADDR; +static struct ddr_ctrl *ddrctrl = (struct ddr_ctrl *)DDR_CTRL_ADDR; + +static const struct ddr_data ddr2_data = { + .datardsratio0 = ((DDR2_RD_DQS<<30)|(DDR2_RD_DQS<<20) + |(DDR2_RD_DQS<<10)|(DDR2_RD_DQS<<0)), + .datawdsratio0 = ((DDR2_WR_DQS<<30)|(DDR2_WR_DQS<<20) + |(DDR2_WR_DQS<<10)|(DDR2_WR_DQS<<0)), + .datawiratio0 = ((DDR2_PHY_WRLVL<<30)|(DDR2_PHY_WRLVL<<20) + |(DDR2_PHY_WRLVL<<10)|(DDR2_PHY_WRLVL<<0)), + .datagiratio0 = ((DDR2_PHY_GATELVL<<30)|(DDR2_PHY_GATELVL<<20) + |(DDR2_PHY_GATELVL<<10)|(DDR2_PHY_GATELVL<<0)), + .datafwsratio0 = ((DDR2_PHY_FIFO_WE<<30)|(DDR2_PHY_FIFO_WE<<20) + |(DDR2_PHY_FIFO_WE<<10)|(DDR2_PHY_FIFO_WE<<0)), + .datawrsratio0 = ((DDR2_PHY_WR_DATA<<30)|(DDR2_PHY_WR_DATA<<20) + |(DDR2_PHY_WR_DATA<<10)|(DDR2_PHY_WR_DATA<<0)), + .datauserank0delay = DDR2_PHY_RANK0_DELAY, + .datadldiff0 = PHY_DLL_LOCK_DIFF, +}; + +static const struct cmd_control ddr2_cmd_ctrl_data = { + .cmd0csratio = DDR2_RATIO, + .cmd0dldiff = DDR2_DLL_LOCK_DIFF, + .cmd0iclkout = DDR2_INVERT_CLKOUT, + + .cmd1csratio = DDR2_RATIO, + .cmd1dldiff = DDR2_DLL_LOCK_DIFF, + .cmd1iclkout = DDR2_INVERT_CLKOUT, + + .cmd2csratio = DDR2_RATIO, + .cmd2dldiff = DDR2_DLL_LOCK_DIFF, + .cmd2iclkout = DDR2_INVERT_CLKOUT, +}; + +static const struct emif_regs ddr2_emif_reg_data = { + .sdram_config = DDR2_EMIF_SDCFG, + .ref_ctrl = DDR2_EMIF_SDREF, + .sdram_tim1 = DDR2_EMIF_TIM1, + .sdram_tim2 = DDR2_EMIF_TIM2, + .sdram_tim3 = DDR2_EMIF_TIM3, + .emif_ddr_phy_ctlr_1 = DDR2_EMIF_READ_LATENCY, +}; + +static const struct ddr_data ddr3_data = { + .datardsratio0 = DDR3_RD_DQS, + .datawdsratio0 = DDR3_WR_DQS, + .datafwsratio0 = DDR3_PHY_FIFO_WE, + .datawrsratio0 = DDR3_PHY_WR_DATA, + .datadldiff0 = PHY_DLL_LOCK_DIFF, +}; + +static const struct cmd_control ddr3_cmd_ctrl_data = { + .cmd0csratio = DDR3_RATIO, + .cmd0dldiff = DDR3_DLL_LOCK_DIFF, + .cmd0iclkout = DDR3_INVERT_CLKOUT, + + .cmd1csratio = DDR3_RATIO, + .cmd1dldiff = DDR3_DLL_LOCK_DIFF, + .cmd1iclkout = DDR3_INVERT_CLKOUT, + + .cmd2csratio = DDR3_RATIO, + .cmd2dldiff = DDR3_DLL_LOCK_DIFF, + .cmd2iclkout = DDR3_INVERT_CLKOUT, +}; + +static struct emif_regs ddr3_emif_reg_data = { + .sdram_config = DDR3_EMIF_SDCFG, + .ref_ctrl = DDR3_EMIF_SDREF, + .sdram_tim1 = DDR3_EMIF_TIM1, + .sdram_tim2 = DDR3_EMIF_TIM2, + .sdram_tim3 = DDR3_EMIF_TIM3, + .zq_config = DDR3_ZQ_CFG, + .emif_ddr_phy_ctlr_1 = DDR3_EMIF_READ_LATENCY, +}; static void config_vtp(void) { @@ -115,87 +134,46 @@ static void config_vtp(void) ; } -static void config_emif_ddr2(void) -{ - int i; - int ret; - struct sdram_config cfg; - struct sdram_timing tmg; - struct ddr_phy_control phyc; - - /*Program EMIF0 CFG Registers*/ - phyc.reg = EMIF_READ_LATENCY; - phyc.reg_sh = EMIF_READ_LATENCY; - phyc.reg2 = EMIF_READ_LATENCY; - - tmg.time1 = EMIF_TIM1; - tmg.time1_sh = EMIF_TIM1; - tmg.time2 = EMIF_TIM2; - tmg.time2_sh = EMIF_TIM2; - tmg.time3 = EMIF_TIM3; - tmg.time3_sh = EMIF_TIM3; - - cfg.sdrcr = EMIF_SDCFG; - cfg.sdrcr2 = EMIF_SDCFG; - cfg.refresh = 0x00004650; - cfg.refresh_sh = 0x00004650; - - /* Program EMIF instance */ - ret = config_ddr_phy(&phyc); - if (ret < 0) - printf("Couldn't configure phyc\n"); - - ret = config_sdram(&cfg); - if (ret < 0) - printf("Couldn't configure SDRAM\n"); - - ret = set_sdram_timings(&tmg); - if (ret < 0) - printf("Couldn't configure timings\n"); - - /* Delay */ - for (i = 0; i < 5000; i++) - ; - - cfg.refresh = EMIF_SDREF; - cfg.refresh_sh = EMIF_SDREF; - cfg.sdrcr = EMIF_SDCFG; - cfg.sdrcr2 = EMIF_SDCFG; - - ret = config_sdram(&cfg); - if (ret < 0) - printf("Couldn't configure SDRAM\n"); -} - -void config_ddr(void) +void config_ddr(short ddr_type) { - int data_macro_0 = 0; - int data_macro_1 = 1; - struct ddr_ioctrl ioctrl; + int ddr_pll, ioctrl_val; + const struct emif_regs *emif_regs; + const struct ddr_data *ddr_data; + const struct cmd_control *cmd_ctrl_data; + + if (ddr_type == EMIF_REG_SDRAM_TYPE_DDR2) { + ddr_pll = 266; + cmd_ctrl_data = &ddr2_cmd_ctrl_data; + ddr_data = &ddr2_data; + ioctrl_val = DDR2_IOCTRL_VALUE; + emif_regs = &ddr2_emif_reg_data; + } else if (ddr_type == EMIF_REG_SDRAM_TYPE_DDR3) { + ddr_pll = 303; + cmd_ctrl_data = &ddr3_cmd_ctrl_data; + ddr_data = &ddr3_data; + ioctrl_val = DDR3_IOCTRL_VALUE; + emif_regs = &ddr3_emif_reg_data; + } else { + puts("Unknown memory type"); + hang(); + } enable_emif_clocks(); - + ddr_pll_config(ddr_pll); config_vtp(); + config_cmd_ctrl(cmd_ctrl_data); - cmd_macro_config(); - - data_macro_config(data_macro_0); - data_macro_config(data_macro_1); + config_ddr_data(0, ddr_data); + config_ddr_data(1, ddr_data); - writel(PHY_RANK0_DELAY, &ddrregs->dt0rdelays0); - writel(PHY_RANK0_DELAY, &ddrregs->dt1rdelays0); + config_io_ctrl(ioctrl_val); - ioctrl.cmd1ctl = DDR_IOCTRL_VALUE; - ioctrl.cmd2ctl = DDR_IOCTRL_VALUE; - ioctrl.cmd3ctl = DDR_IOCTRL_VALUE; - ioctrl.data1ctl = DDR_IOCTRL_VALUE; - ioctrl.data2ctl = DDR_IOCTRL_VALUE; + /* Set CKE to be controlled by EMIF/DDR PHY */ + writel(DDR_CKE_CTRL_NORMAL, &ddrctrl->ddrckectrl); - config_io_ctrl(&ioctrl); - - writel(readl(&ddrctrl->ddrioctrl) & 0xefffffff, &ddrctrl->ddrioctrl); - writel(readl(&ddrctrl->ddrckectrl) | 0x00000001, &ddrctrl->ddrckectrl); - - config_emif_ddr2(); + /* Program EMIF instance */ + config_ddr_phy(emif_regs); + set_sdram_timings(emif_regs); + config_sdram(emif_regs); } #endif diff --git a/arch/arm/cpu/armv7/config.mk b/arch/arm/cpu/armv7/config.mk index 560c084dc9..5407cb68a8 100644 --- a/arch/arm/cpu/armv7/config.mk +++ b/arch/arm/cpu/armv7/config.mk @@ -26,8 +26,6 @@ PLATFORM_RELFLAGS += -fno-common -ffixed-r8 -msoft-float # supported by more tool-chains PF_CPPFLAGS_ARMV7 := $(call cc-option, -march=armv7-a, -march=armv5) PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_ARMV7) -PF_CPPFLAGS_NO_UNALIGNED := $(call cc-option, -mno-unaligned-access,) -PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_NO_UNALIGNED) # ========================================================================= # diff --git a/arch/arm/cpu/armv7/cpu.c b/arch/arm/cpu/armv7/cpu.c index c6fa8ef136..39a80237cd 100644 --- a/arch/arm/cpu/armv7/cpu.c +++ b/arch/arm/cpu/armv7/cpu.c @@ -36,13 +36,9 @@ #include <asm/system.h> #include <asm/cache.h> #include <asm/armv7.h> +#include <linux/compiler.h> -void save_boot_params_default(u32 r0, u32 r1, u32 r2, u32 r3) -{ -} - -void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) - __attribute__((weak, alias("save_boot_params_default"))); +void __weak cpu_cache_initialization(void){} int cleanup_before_linux(void) { @@ -81,5 +77,10 @@ int cleanup_before_linux(void) */ invalidate_dcache_all(); + /* + * Some CPU need more cache attention before starting the kernel. + */ + cpu_cache_initialization(); + return 0; } diff --git a/arch/arm/cpu/armv7/exynos/clock.c b/arch/arm/cpu/armv7/exynos/clock.c index f7829b2cc7..4f3b451be9 100644 --- a/arch/arm/cpu/armv7/exynos/clock.c +++ b/arch/arm/cpu/armv7/exynos/clock.c @@ -98,7 +98,7 @@ static unsigned long exynos5_get_pll_clk(int pllreg) struct exynos5_clock *clk = (struct exynos5_clock *)samsung_get_base_clock(); unsigned long r, m, p, s, k = 0, mask, fout; - unsigned int freq; + unsigned int freq, pll_div2_sel, fout_sel; switch (pllreg) { case APLL: @@ -115,6 +115,9 @@ static unsigned long exynos5_get_pll_clk(int pllreg) r = readl(&clk->vpll_con0); k = readl(&clk->vpll_con1); break; + case BPLL: + r = readl(&clk->bpll_con0); + break; default: printf("Unsupported PLL (%d)\n", pllreg); return 0; @@ -125,8 +128,9 @@ static unsigned long exynos5_get_pll_clk(int pllreg) * MPLL_CON: MIDV [25:16] * EPLL_CON: MIDV [24:16] * VPLL_CON: MIDV [24:16] + * BPLL_CON: MIDV [25:16] */ - if (pllreg == APLL || pllreg == MPLL) + if (pllreg == APLL || pllreg == MPLL || pllreg == BPLL) mask = 0x3ff; else mask = 0x1ff; @@ -155,6 +159,29 @@ static unsigned long exynos5_get_pll_clk(int pllreg) fout = m * (freq / (p * (1 << (s - 1)))); } + /* According to the user manual, in EVT1 MPLL and BPLL always gives + * 1.6GHz clock, so divide by 2 to get 800MHz MPLL clock.*/ + if (pllreg == MPLL || pllreg == BPLL) { + pll_div2_sel = readl(&clk->pll_div2_sel); + + switch (pllreg) { + case MPLL: + fout_sel = (pll_div2_sel >> MPLL_FOUT_SEL_SHIFT) + & MPLL_FOUT_SEL_MASK; + break; + case BPLL: + fout_sel = (pll_div2_sel >> BPLL_FOUT_SEL_SHIFT) + & BPLL_FOUT_SEL_MASK; + break; + default: + fout_sel = -1; + break; + } + + if (fout_sel == 0) + fout /= 2; + } + return fout; } @@ -456,6 +483,48 @@ static unsigned long exynos4_get_lcd_clk(void) return pclk; } +/* get_lcd_clk: return lcd clock frequency */ +static unsigned long exynos5_get_lcd_clk(void) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + unsigned long pclk, sclk; + unsigned int sel; + unsigned int ratio; + + /* + * CLK_SRC_LCD0 + * FIMD0_SEL [3:0] + */ + sel = readl(&clk->src_disp1_0); + sel = sel & 0xf; + + /* + * 0x6: SCLK_MPLL + * 0x7: SCLK_EPLL + * 0x8: SCLK_VPLL + */ + if (sel == 0x6) + sclk = get_pll_clk(MPLL); + else if (sel == 0x7) + sclk = get_pll_clk(EPLL); + else if (sel == 0x8) + sclk = get_pll_clk(VPLL); + else + return 0; + + /* + * CLK_DIV_LCD0 + * FIMD0_RATIO [3:0] + */ + ratio = readl(&clk->div_disp1_0); + ratio = ratio & 0xf; + + pclk = sclk / (ratio + 1); + + return pclk; +} + void exynos4_set_lcd_clk(void) { struct exynos4_clock *clk = @@ -518,6 +587,68 @@ void exynos4_set_lcd_clk(void) writel(cfg, &clk->div_lcd0); } +void exynos5_set_lcd_clk(void) +{ + struct exynos5_clock *clk = + (struct exynos5_clock *)samsung_get_base_clock(); + unsigned int cfg = 0; + + /* + * CLK_GATE_BLOCK + * CLK_CAM [0] + * CLK_TV [1] + * CLK_MFC [2] + * CLK_G3D [3] + * CLK_LCD0 [4] + * CLK_LCD1 [5] + * CLK_GPS [7] + */ + cfg = readl(&clk->gate_block); + cfg |= 1 << 4; + writel(cfg, &clk->gate_block); + + /* + * CLK_SRC_LCD0 + * FIMD0_SEL [3:0] + * MDNIE0_SEL [7:4] + * MDNIE_PWM0_SEL [8:11] + * MIPI0_SEL [12:15] + * set lcd0 src clock 0x6: SCLK_MPLL + */ + cfg = readl(&clk->src_disp1_0); + cfg &= ~(0xf); + cfg |= 0x8; + writel(cfg, &clk->src_disp1_0); + + /* + * CLK_GATE_IP_LCD0 + * CLK_FIMD0 [0] + * CLK_MIE0 [1] + * CLK_MDNIE0 [2] + * CLK_DSIM0 [3] + * CLK_SMMUFIMD0 [4] + * CLK_PPMULCD0 [5] + * Gating all clocks for FIMD0 + */ + cfg = readl(&clk->gate_ip_disp1); + cfg |= 1 << 0; + writel(cfg, &clk->gate_ip_disp1); + + /* + * CLK_DIV_LCD0 + * FIMD0_RATIO [3:0] + * MDNIE0_RATIO [7:4] + * MDNIE_PWM0_RATIO [11:8] + * MDNIE_PWM_PRE_RATIO [15:12] + * MIPI0_RATIO [19:16] + * MIPI0_PRE_RATIO [23:20] + * set fimd ratio + */ + cfg &= ~(0xf); + cfg |= 0x0; + writel(cfg, &clk->div_disp1_0); +} + void exynos4_set_mipi_clk(void) { struct exynos4_clock *clk = @@ -656,13 +787,15 @@ unsigned long get_lcd_clk(void) if (cpu_is_exynos4()) return exynos4_get_lcd_clk(); else - return 0; + return exynos5_get_lcd_clk(); } void set_lcd_clk(void) { if (cpu_is_exynos4()) exynos4_set_lcd_clk(); + else + exynos5_set_lcd_clk(); } void set_mipi_clk(void) diff --git a/arch/arm/cpu/armv7/exynos/pinmux.c b/arch/arm/cpu/armv7/exynos/pinmux.c index d28f05557f..7776add9db 100644 --- a/arch/arm/cpu/armv7/exynos/pinmux.c +++ b/arch/arm/cpu/armv7/exynos/pinmux.c @@ -40,8 +40,8 @@ static void exynos5_uart_config(int peripheral) count = 4; break; case PERIPH_ID_UART1: - bank = &gpio1->a0; - start = 4; + bank = &gpio1->d0; + start = 0; count = 4; break; case PERIPH_ID_UART2: @@ -66,23 +66,27 @@ static int exynos5_mmc_config(int peripheral, int flags) struct exynos5_gpio_part1 *gpio1 = (struct exynos5_gpio_part1 *) samsung_get_base_gpio_part1(); struct s5p_gpio_bank *bank, *bank_ext; - int i; + int i, start = 0, gpio_func = 0; switch (peripheral) { case PERIPH_ID_SDMMC0: bank = &gpio1->c0; bank_ext = &gpio1->c1; + start = 0; + gpio_func = GPIO_FUNC(0x2); break; case PERIPH_ID_SDMMC1: - bank = &gpio1->c1; + bank = &gpio1->c2; bank_ext = NULL; break; case PERIPH_ID_SDMMC2: - bank = &gpio1->c2; - bank_ext = &gpio1->c3; + bank = &gpio1->c3; + bank_ext = &gpio1->c4; + start = 3; + gpio_func = GPIO_FUNC(0x3); break; case PERIPH_ID_SDMMC3: - bank = &gpio1->c3; + bank = &gpio1->c4; bank_ext = NULL; break; } @@ -92,8 +96,8 @@ static int exynos5_mmc_config(int peripheral, int flags) return -1; } if (flags & PINMUX_FLAG_8BIT_MODE) { - for (i = 3; i <= 6; i++) { - s5p_gpio_cfg_pin(bank_ext, i, GPIO_FUNC(0x3)); + for (i = start; i <= (start + 3); i++) { + s5p_gpio_cfg_pin(bank_ext, i, gpio_func); s5p_gpio_set_pull(bank_ext, i, GPIO_PULL_UP); s5p_gpio_set_drv(bank_ext, i, GPIO_DRV_4X); } diff --git a/arch/arm/cpu/armv7/exynos/power.c b/arch/arm/cpu/armv7/exynos/power.c index 4116781a36..d4bce6d4dd 100644 --- a/arch/arm/cpu/armv7/exynos/power.c +++ b/arch/arm/cpu/armv7/exynos/power.c @@ -74,3 +74,24 @@ void set_usbhost_phy_ctrl(unsigned int enable) if (cpu_is_exynos5()) exynos5_set_usbhost_phy_ctrl(enable); } + +static void exynos5_dp_phy_control(unsigned int enable) +{ + unsigned int cfg; + struct exynos5_power *power = + (struct exynos5_power *)samsung_get_base_power(); + + cfg = readl(&power->dptx_phy_control); + if (enable) + cfg |= EXYNOS_DP_PHY_ENABLE; + else + cfg &= ~EXYNOS_DP_PHY_ENABLE; + + writel(cfg, &power->dptx_phy_control); +} + +void set_dp_phy_ctrl(unsigned int enable) +{ + if (cpu_is_exynos5()) + exynos5_dp_phy_control(enable); +} diff --git a/arch/arm/cpu/armv7/exynos/soc.c b/arch/arm/cpu/armv7/exynos/soc.c index dcfcec22dc..ab65b8d3a8 100644 --- a/arch/arm/cpu/armv7/exynos/soc.c +++ b/arch/arm/cpu/armv7/exynos/soc.c @@ -28,3 +28,11 @@ void reset_cpu(ulong addr) { writel(0x1, samsung_get_base_swreset()); } + +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} +#endif diff --git a/arch/arm/cpu/armv7/exynos/system.c b/arch/arm/cpu/armv7/exynos/system.c index 4426611d1b..8424c57e95 100644 --- a/arch/arm/cpu/armv7/exynos/system.c +++ b/arch/arm/cpu/armv7/exynos/system.c @@ -62,8 +62,26 @@ static void exynos4_set_system_display(void) writel(cfg, &sysreg->display_ctrl); } +static void exynos5_set_system_display(void) +{ + struct exynos5_sysreg *sysreg = + (struct exynos5_sysreg *)samsung_get_base_sysreg(); + unsigned int cfg = 0; + + /* + * system register path set + * 0: MIE/MDNIE + * 1: FIMD Bypass + */ + cfg = readl(&sysreg->disp1blk_cfg); + cfg |= (1 << 15); + writel(cfg, &sysreg->disp1blk_cfg); +} + void set_system_display_ctrl(void) { if (cpu_is_exynos4()) exynos4_set_system_display(); + else + exynos5_set_system_display(); } diff --git a/arch/arm/cpu/armv7/highbank/Makefile b/arch/arm/cpu/armv7/highbank/Makefile index 917c3a36ba..76faeb0fe1 100644 --- a/arch/arm/cpu/armv7/highbank/Makefile +++ b/arch/arm/cpu/armv7/highbank/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(SOC).o -COBJS := timer.o bootcount.o +COBJS := timer.o SOBJS := SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/arch/arm/cpu/armv7/highbank/bootcount.c b/arch/arm/cpu/armv7/highbank/bootcount.c deleted file mode 100644 index 9ca06567a8..0000000000 --- a/arch/arm/cpu/armv7/highbank/bootcount.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2011 Calxeda, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <common.h> -#include <asm/io.h> - -#ifdef CONFIG_BOOTCOUNT_LIMIT -void bootcount_store(ulong a) -{ - writel((BOOTCOUNT_MAGIC & 0xffff0000) | a, CONFIG_SYS_BOOTCOUNT_ADDR); -} - -ulong bootcount_load(void) -{ - u32 tmp = readl(CONFIG_SYS_BOOTCOUNT_ADDR); - - if ((tmp & 0xffff0000) != (BOOTCOUNT_MAGIC & 0xffff0000)) - return 0; - else - return tmp & 0x0000ffff; -} -#endif diff --git a/arch/arm/cpu/armv7/imx-common/Makefile b/arch/arm/cpu/armv7/imx-common/Makefile index bf36be5767..16fba8da93 100644 --- a/arch/arm/cpu/armv7/imx-common/Makefile +++ b/arch/arm/cpu/armv7/imx-common/Makefile @@ -29,6 +29,7 @@ LIB = $(obj)libimx-common.o COBJS-y = iomux-v3.o timer.o cpu.o speed.o COBJS-$(CONFIG_I2C_MXC) += i2c.o +COBJS-$(CONFIG_CMD_BMODE) += cmd_bmode.o COBJS := $(sort $(COBJS-y)) SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/arch/arm/cpu/armv7/imx-common/cmd_bmode.c b/arch/arm/cpu/armv7/imx-common/cmd_bmode.c new file mode 100644 index 0000000000..02fe72ed7f --- /dev/null +++ b/arch/arm/cpu/armv7/imx-common/cmd_bmode.c @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2012 Boundary Devices Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <common.h> +#include <asm/errno.h> +#include <asm/io.h> +#include <asm/imx-common/boot_mode.h> +#include <malloc.h> + +static const struct boot_mode *modes[2]; + +static const struct boot_mode *search_modes(char *arg) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(modes); i++) { + const struct boot_mode *p = modes[i]; + if (p) { + while (p->name) { + if (!strcmp(p->name, arg)) + return p; + p++; + } + } + } + return NULL; +} + +static int create_usage(char *dest) +{ + int i; + int size = 0; + + for (i = 0; i < ARRAY_SIZE(modes); i++) { + const struct boot_mode *p = modes[i]; + if (p) { + while (p->name) { + int len = strlen(p->name); + if (dest) { + memcpy(dest, p->name, len); + dest += len; + *dest++ = '|'; + } + size += len + 1; + p++; + } + } + } + if (dest) + memcpy(dest - 1, " [noreset]", 11); /* include trailing 0 */ + size += 10; + return size; +} + +static int do_boot_mode(cmd_tbl_t *cmdtp, int flag, int argc, + char * const argv[]) +{ + const struct boot_mode *p; + int reset_requested = 1; + + if (argc < 2) + return CMD_RET_USAGE; + p = search_modes(argv[1]); + if (!p) + return CMD_RET_USAGE; + if (argc == 3) { + if (strcmp(argv[2], "noreset")) + return CMD_RET_USAGE; + reset_requested = 0; + } + + boot_mode_apply(p->cfg_val); + if (reset_requested && p->cfg_val) + do_reset(NULL, 0, 0, NULL); + return 0; +} + +U_BOOT_CMD( + bmode, 3, 0, do_boot_mode, + NULL, + ""); + +void add_board_boot_modes(const struct boot_mode *p) +{ + int size; + char *dest; + + if (__u_boot_cmd_bmode.usage) { + free(__u_boot_cmd_bmode.usage); + __u_boot_cmd_bmode.usage = NULL; + } + + modes[0] = p; + modes[1] = soc_boot_modes; + size = create_usage(NULL); + dest = malloc(size); + if (dest) { + create_usage(dest); + __u_boot_cmd_bmode.usage = dest; + } +} diff --git a/arch/arm/cpu/armv7/imx-common/cpu.c b/arch/arm/cpu/armv7/imx-common/cpu.c index b3195dd6fb..fa1d468041 100644 --- a/arch/arm/cpu/armv7/imx-common/cpu.c +++ b/arch/arm/cpu/armv7/imx-common/cpu.c @@ -66,7 +66,7 @@ char *get_reset_cause(void) #if defined(CONFIG_DISPLAY_CPUINFO) -static char *get_imx_type(u32 imxtype) +static const char *get_imx_type(u32 imxtype) { switch (imxtype) { case 0x63: @@ -80,7 +80,7 @@ static char *get_imx_type(u32 imxtype) case 0x53: return "53"; default: - return "unknown"; + return "??"; } } @@ -111,18 +111,16 @@ int cpu_eth_init(bd_t *bis) return rc; } +#ifdef CONFIG_FSL_ESDHC /* * Initializes on-chip MMC controllers. * to override, implement board_mmc_init() */ int cpu_mmc_init(bd_t *bis) { -#ifdef CONFIG_FSL_ESDHC return fsl_esdhc_mmc_init(bis); -#else - return 0; -#endif } +#endif void reset_cpu(ulong addr) { diff --git a/arch/arm/cpu/armv7/imx-common/timer.c b/arch/arm/cpu/armv7/imx-common/timer.c index 1645ff83f4..e2725e1a64 100644 --- a/arch/arm/cpu/armv7/imx-common/timer.c +++ b/arch/arm/cpu/armv7/imx-common/timer.c @@ -61,7 +61,7 @@ static inline unsigned long long tick_to_time(unsigned long long tick) static inline unsigned long long us_to_tick(unsigned long long usec) { - usec *= CLK_32KHZ; + usec = usec * CLK_32KHZ + 999999; do_div(usec, 1000000); return usec; diff --git a/arch/arm/cpu/armv7/tegra2/lowlevel_init.S b/arch/arm/cpu/armv7/lowlevel_init.S index d117f23a62..0d45528e99 100644 --- a/arch/arm/cpu/armv7/tegra2/lowlevel_init.S +++ b/arch/arm/cpu/armv7/lowlevel_init.S @@ -1,8 +1,12 @@ /* - * SoC-specific setup info + * A lowlevel_init function that sets up the stack to call a C function to + * perform further init. * - * (C) Copyright 2010,2011 - * NVIDIA Corporation <www.nvidia.com> + * (C) Copyright 2010 + * Texas Instruments, <www.ti.com> + * + * Author : + * Aneesh V <aneesh@ti.com> * * See file CREDITS for list of people who contributed to this * project. @@ -14,7 +18,7 @@ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License @@ -23,20 +27,25 @@ * MA 02111-1307 USA */ +#include <asm-offsets.h> #include <config.h> -#include <version.h> #include <linux/linkage.h> - .align 5 -ENTRY(reset_cpu) - ldr r1, rstctl @ get addr for global reset - @ reg - ldr r3, [r1] - orr r3, r3, #0x10 - str r3, [r1] @ force reset - mov r0, r0 -_loop_forever: - b _loop_forever -rstctl: - .word PRM_RSTCTRL -ENDPROC(reset_cpu) +ENTRY(lowlevel_init) + /* + * Setup a temporary stack + */ + ldr sp, =CONFIG_SYS_INIT_SP_ADDR + bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ + + /* + * Save the old lr(passed in ip) and the current lr to stack + */ + push {ip, lr} + + /* + * go setup pll, mux, memory + */ + bl s_init + pop {ip, pc} +ENDPROC(lowlevel_init) diff --git a/arch/arm/cpu/armv7/mx5/lowlevel_init.S b/arch/arm/cpu/armv7/mx5/lowlevel_init.S index 683a7b53af..a40b84feeb 100644 --- a/arch/arm/cpu/armv7/mx5/lowlevel_init.S +++ b/arch/arm/cpu/armv7/mx5/lowlevel_init.S @@ -36,9 +36,9 @@ /* reconfigure L2 cache aux control reg */ mov r0, #0xC0 /* tag RAM */ add r0, r0, #0x4 /* data RAM */ - orr r0, r0, #(1 << 24) /* disable write allocate delay */ - orr r0, r0, #(1 << 23) /* disable write allocate combine */ - orr r0, r0, #(1 << 22) /* disable write allocate */ + orr r0, r0, #1 << 24 /* disable write allocate delay */ + orr r0, r0, #1 << 23 /* disable write allocate combine */ + orr r0, r0, #1 << 22 /* disable write allocate */ #if defined(CONFIG_MX51) ldr r1, =0x0 @@ -46,7 +46,7 @@ cmp r3, #0x10 /* disable write combine for TO 2 and lower revs */ - orrls r0, r0, #(1 << 25) + orrls r0, r0, #1 << 25 #endif mcr 15, 1, r0, c9, c0, 2 @@ -247,9 +247,9 @@ movhi r1, #0 #else mov r1, #0 - #endif str r1, [r0, #CLKCTL_CACRR] + /* Switch ARM back to PLL 1 */ mov r1, #0 str r1, [r0, #CLKCTL_CCSR] @@ -288,9 +288,9 @@ /* Switch peripheral to PLL2 */ ldr r0, =CCM_BASE_ADDR ldr r1, =0x00808145 - orr r1, r1, #(2 << 10) - orr r1, r1, #(0 << 16) - orr r1, r1, #(1 << 19) + orr r1, r1, #2 << 10 + orr r1, r1, #0 << 16 + orr r1, r1, #1 << 19 str r1, [r0, #CLKCTL_CBCDR] ldr r1, =0x00016154 @@ -331,10 +331,10 @@ ENTRY(lowlevel_init) #if defined(CONFIG_MX51) ldr r0, =GPIO1_BASE_ADDR ldr r1, [r0, #0x0] - orr r1, r1, #(1 << 23) + orr r1, r1, #1 << 23 str r1, [r0, #0x0] ldr r1, [r0, #0x4] - orr r1, r1, #(1 << 23) + orr r1, r1, #1 << 23 str r1, [r0, #0x4] #endif @@ -351,16 +351,16 @@ ENTRY(lowlevel_init) ENDPROC(lowlevel_init) /* Board level setting value */ -W_DP_OP_864: .word DP_OP_864 -W_DP_MFD_864: .word DP_MFD_864 -W_DP_MFN_864: .word DP_MFN_864 -W_DP_MFN_800_DIT: .word DP_MFN_800_DIT -W_DP_OP_800: .word DP_OP_800 -W_DP_MFD_800: .word DP_MFD_800 -W_DP_MFN_800: .word DP_MFN_800 -W_DP_OP_665: .word DP_OP_665 -W_DP_MFD_665: .word DP_MFD_665 -W_DP_MFN_665: .word DP_MFN_665 -W_DP_OP_216: .word DP_OP_216 -W_DP_MFD_216: .word DP_MFD_216 -W_DP_MFN_216: .word DP_MFN_216 +W_DP_OP_864: .word DP_OP_864 +W_DP_MFD_864: .word DP_MFD_864 +W_DP_MFN_864: .word DP_MFN_864 +W_DP_MFN_800_DIT: .word DP_MFN_800_DIT +W_DP_OP_800: .word DP_OP_800 +W_DP_MFD_800: .word DP_MFD_800 +W_DP_MFN_800: .word DP_MFN_800 +W_DP_OP_665: .word DP_OP_665 +W_DP_MFD_665: .word DP_MFD_665 +W_DP_MFN_665: .word DP_MFN_665 +W_DP_OP_216: .word DP_OP_216 +W_DP_MFD_216: .word DP_MFD_216 +W_DP_MFN_216: .word DP_MFN_216 diff --git a/arch/arm/cpu/armv7/mx5/soc.c b/arch/arm/cpu/armv7/mx5/soc.c index 3f5a4f726c..263658aa4b 100644 --- a/arch/arm/cpu/armv7/mx5/soc.c +++ b/arch/arm/cpu/armv7/mx5/soc.c @@ -30,6 +30,7 @@ #include <asm/errno.h> #include <asm/io.h> +#include <asm/imx-common/boot_mode.h> #if !(defined(CONFIG_MX51) || defined(CONFIG_MX53)) #error "CPU_TYPE not defined" @@ -71,6 +72,14 @@ u32 get_cpu_rev(void) return system_rev; } +#ifndef CONFIG_SYS_DCACHE_OFF +void enable_caches(void) +{ + /* Enable D-cache. I-cache is already enabled in start.S */ + dcache_enable(); +} +#endif + #if defined(CONFIG_FEC_MXC) void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) { @@ -115,3 +124,33 @@ void set_chipselect_size(int const cs_size) writel(reg, &iomuxc_regs->gpr1); } + +#ifdef CONFIG_MX53 +void boot_mode_apply(unsigned cfg_val) +{ + writel(cfg_val, &((struct srtc_regs *)SRTC_BASE_ADDR)->lpgr); +} +/* + * cfg_val will be used for + * Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0] + * + * If bit 28 of LPGR is set upon watchdog reset, + * bits[25:0] of LPGR will move to SBMR. + */ +const struct boot_mode soc_boot_modes[] = { + {"normal", MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)}, + /* usb or serial download */ + {"usb", MAKE_CFGVAL(0x00, 0x00, 0x00, 0x13)}, + {"sata", MAKE_CFGVAL(0x28, 0x00, 0x00, 0x12)}, + {"escpi1:0", MAKE_CFGVAL(0x38, 0x20, 0x00, 0x12)}, + {"escpi1:1", MAKE_CFGVAL(0x38, 0x20, 0x04, 0x12)}, + {"escpi1:2", MAKE_CFGVAL(0x38, 0x20, 0x08, 0x12)}, + {"escpi1:3", MAKE_CFGVAL(0x38, 0x20, 0x0c, 0x12)}, + /* 4 bit bus width */ + {"esdhc1", MAKE_CFGVAL(0x40, 0x20, 0x00, 0x12)}, + {"esdhc2", MAKE_CFGVAL(0x40, 0x20, 0x08, 0x12)}, + {"esdhc3", MAKE_CFGVAL(0x40, 0x20, 0x10, 0x12)}, + {"esdhc4", MAKE_CFGVAL(0x40, 0x20, 0x18, 0x12)}, + {NULL, 0}, +}; +#endif diff --git a/arch/arm/cpu/armv7/mx6/soc.c b/arch/arm/cpu/armv7/mx6/soc.c index 84b458c7eb..7380ffe46c 100644 --- a/arch/arm/cpu/armv7/mx6/soc.c +++ b/arch/arm/cpu/armv7/mx6/soc.c @@ -29,6 +29,7 @@ #include <asm/arch/imx-regs.h> #include <asm/arch/clock.h> #include <asm/arch/sys_proto.h> +#include <asm/imx-common/boot_mode.h> u32 get_cpu_rev(void) { @@ -141,3 +142,38 @@ void imx_get_mac_from_fuse(int dev_id, unsigned char *mac) } #endif + +void boot_mode_apply(unsigned cfg_val) +{ + unsigned reg; + struct src_regs *psrc = (struct src_regs *)SRC_BASE_ADDR; + writel(cfg_val, &psrc->gpr9); + reg = readl(&psrc->gpr10); + if (cfg_val) + reg |= 1 << 28; + else + reg &= ~(1 << 28); + writel(reg, &psrc->gpr10); +} +/* + * cfg_val will be used for + * Boot_cfg4[7:0]:Boot_cfg3[7:0]:Boot_cfg2[7:0]:Boot_cfg1[7:0] + * After reset, if GPR10[28] is 1, ROM will copy GPR9[25:0] + * to SBMR1, which will determine the boot device. + */ +const struct boot_mode soc_boot_modes[] = { + {"normal", MAKE_CFGVAL(0x00, 0x00, 0x00, 0x00)}, + /* reserved value should start rom usb */ + {"usb", MAKE_CFGVAL(0x01, 0x00, 0x00, 0x00)}, + {"sata", MAKE_CFGVAL(0x20, 0x00, 0x00, 0x00)}, + {"escpi1:0", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x08)}, + {"escpi1:1", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x18)}, + {"escpi1:2", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x28)}, + {"escpi1:3", MAKE_CFGVAL(0x30, 0x00, 0x00, 0x38)}, + /* 4 bit bus width */ + {"esdhc1", MAKE_CFGVAL(0x40, 0x20, 0x00, 0x00)}, + {"esdhc2", MAKE_CFGVAL(0x40, 0x28, 0x00, 0x00)}, + {"esdhc3", MAKE_CFGVAL(0x40, 0x30, 0x00, 0x00)}, + {"esdhc4", MAKE_CFGVAL(0x40, 0x38, 0x00, 0x00)}, + {NULL, 0}, +}; diff --git a/arch/arm/cpu/armv7/omap-common/Makefile b/arch/arm/cpu/armv7/omap-common/Makefile index 2a6625f1c4..d37b22d98a 100644 --- a/arch/arm/cpu/armv7/omap-common/Makefile +++ b/arch/arm/cpu/armv7/omap-common/Makefile @@ -29,9 +29,6 @@ SOBJS := reset.o COBJS := timer.o COBJS += utils.o -ifdef CONFIG_OMAP -COBJS += gpio.o -endif ifneq ($(CONFIG_OMAP44XX)$(CONFIG_OMAP54XX),) COBJS += hwinit-common.o diff --git a/arch/arm/cpu/armv7/omap-common/gpio.c b/arch/arm/cpu/armv7/omap-common/gpio.c deleted file mode 100644 index fc89f2a42b..0000000000 --- a/arch/arm/cpu/armv7/omap-common/gpio.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (c) 2009 Wind River Systems, Inc. - * Tom Rix <Tom.Rix@windriver.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - * - * This work is derived from the linux 2.6.27 kernel source - * To fetch, use the kernel repository - * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git - * Use the v2.6.27 tag. - * - * Below is the original's header including its copyright - * - * linux/arch/arm/plat-omap/gpio.c - * - * Support functions for OMAP GPIO - * - * Copyright (C) 2003-2005 Nokia Corporation - * Written by Juha Yrjölä <juha.yrjola@nokia.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <common.h> -#include <asm/gpio.h> -#include <asm/io.h> -#include <asm/errno.h> - -#define OMAP_GPIO_DIR_OUT 0 -#define OMAP_GPIO_DIR_IN 1 - -static inline const struct gpio_bank *get_gpio_bank(int gpio) -{ - return &omap_gpio_bank[gpio >> 5]; -} - -static inline int get_gpio_index(int gpio) -{ - return gpio & 0x1f; -} - -static inline int gpio_valid(int gpio) -{ - if (gpio < 0) - return -1; - if (gpio < 192) - return 0; - return -1; -} - -static int check_gpio(int gpio) -{ - if (gpio_valid(gpio) < 0) { - printf("ERROR : check_gpio: invalid GPIO %d\n", gpio); - return -1; - } - return 0; -} - -static void _set_gpio_direction(const struct gpio_bank *bank, int gpio, - int is_input) -{ - void *reg = bank->base; - u32 l; - - switch (bank->method) { - case METHOD_GPIO_24XX: - reg += OMAP_GPIO_OE; - break; - default: - return; - } - l = __raw_readl(reg); - if (is_input) - l |= 1 << gpio; - else - l &= ~(1 << gpio); - __raw_writel(l, reg); -} - -/** - * Get the direction of the GPIO by reading the GPIO_OE register - * corresponding to the specified bank. - */ -static int _get_gpio_direction(const struct gpio_bank *bank, int gpio) -{ - void *reg = bank->base; - u32 v; - - switch (bank->method) { - case METHOD_GPIO_24XX: - reg += OMAP_GPIO_OE; - break; - default: - return -1; - } - - v = __raw_readl(reg); - - if (v & (1 << gpio)) - return OMAP_GPIO_DIR_IN; - else - return OMAP_GPIO_DIR_OUT; -} - -static void _set_gpio_dataout(const struct gpio_bank *bank, int gpio, - int enable) -{ - void *reg = bank->base; - u32 l = 0; - - switch (bank->method) { - case METHOD_GPIO_24XX: - if (enable) - reg += OMAP_GPIO_SETDATAOUT; - else - reg += OMAP_GPIO_CLEARDATAOUT; - l = 1 << gpio; - break; - default: - printf("omap3-gpio unknown bank method %s %d\n", - __FILE__, __LINE__); - return; - } - __raw_writel(l, reg); -} - -/** - * Set value of the specified gpio - */ -int gpio_set_value(unsigned gpio, int value) -{ - const struct gpio_bank *bank; - - if (check_gpio(gpio) < 0) - return -1; - bank = get_gpio_bank(gpio); - _set_gpio_dataout(bank, get_gpio_index(gpio), value); - - return 0; -} - -/** - * Get value of the specified gpio - */ -int gpio_get_value(unsigned gpio) -{ - const struct gpio_bank *bank; - void *reg; - int input; - - if (check_gpio(gpio) < 0) - return -1; - bank = get_gpio_bank(gpio); - reg = bank->base; - switch (bank->method) { - case METHOD_GPIO_24XX: - input = _get_gpio_direction(bank, get_gpio_index(gpio)); - switch (input) { - case OMAP_GPIO_DIR_IN: - reg += OMAP_GPIO_DATAIN; - break; - case OMAP_GPIO_DIR_OUT: - reg += OMAP_GPIO_DATAOUT; - break; - default: - return -1; - } - break; - default: - return -1; - } - return (__raw_readl(reg) - & (1 << get_gpio_index(gpio))) != 0; -} - -/** - * Set gpio direction as input - */ -int gpio_direction_input(unsigned gpio) -{ - const struct gpio_bank *bank; - - if (check_gpio(gpio) < 0) - return -1; - - bank = get_gpio_bank(gpio); - _set_gpio_direction(bank, get_gpio_index(gpio), 1); - - return 0; -} - -/** - * Set gpio direction as output - */ -int gpio_direction_output(unsigned gpio, int value) -{ - const struct gpio_bank *bank; - - if (check_gpio(gpio) < 0) - return -1; - - bank = get_gpio_bank(gpio); - _set_gpio_dataout(bank, get_gpio_index(gpio), value); - _set_gpio_direction(bank, get_gpio_index(gpio), 0); - - return 0; -} - -/** - * Request a gpio before using it. - * - * NOTE: Argument 'label' is unused. - */ -int gpio_request(unsigned gpio, const char *label) -{ - if (check_gpio(gpio) < 0) - return -1; - - return 0; -} - -/** - * Reset and free the gpio after using it. - */ -int gpio_free(unsigned gpio) -{ - return 0; -} diff --git a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S index ccc6bb6b85..1ece073630 100644 --- a/arch/arm/cpu/armv7/omap-common/lowlevel_init.S +++ b/arch/arm/cpu/armv7/omap-common/lowlevel_init.S @@ -78,24 +78,6 @@ ENTRY(save_boot_params) bx lr ENDPROC(save_boot_params) -ENTRY(lowlevel_init) - /* - * Setup a temporary stack - */ - ldr sp, =LOW_LEVEL_SRAM_STACK - - /* - * Save the old lr(passed in ip) and the current lr to stack - */ - push {ip, lr} - - /* - * go setup pll, mux, memory - */ - bl s_init - pop {ip, pc} -ENDPROC(lowlevel_init) - ENTRY(set_pl310_ctrl_reg) PUSH {r4-r11, lr} @ save registers - ROM code may pollute @ our registers diff --git a/arch/arm/cpu/armv7/s5p-common/pwm.c b/arch/arm/cpu/armv7/s5p-common/pwm.c index 58d279e003..44d7bc360e 100644 --- a/arch/arm/cpu/armv7/s5p-common/pwm.c +++ b/arch/arm/cpu/armv7/s5p-common/pwm.c @@ -170,7 +170,7 @@ int pwm_init(int pwm_id, int div, int invert) timer_rate_hz = get_pwm_clk() / ((prescaler + 1) * (div + 1)); - timer_rate_hz = timer_rate_hz / 100; + timer_rate_hz = timer_rate_hz / CONFIG_SYS_HZ; /* set count value */ offset = pwm_id * 3; diff --git a/arch/arm/cpu/armv7/s5p-common/timer.c b/arch/arm/cpu/armv7/s5p-common/timer.c index 359c21f5e0..bb0e795e66 100644 --- a/arch/arm/cpu/armv7/s5p-common/timer.c +++ b/arch/arm/cpu/armv7/s5p-common/timer.c @@ -31,6 +31,8 @@ DECLARE_GLOBAL_DATA_PTR; +unsigned long get_current_tick(void); + /* macro to read the 16 bit timer */ static inline struct s5p_timer *s5p_get_base_timer(void) { @@ -44,6 +46,8 @@ int timer_init(void) pwm_config(4, 0, 0); pwm_enable(4); + reset_timer_masked(); + return 0; } @@ -72,16 +76,16 @@ void __udelay(unsigned long usec) * 3. finish normalize. */ tmo = usec / 1000; - tmo *= (CONFIG_SYS_HZ * count_value / 10); + tmo *= (CONFIG_SYS_HZ * count_value); tmo /= 1000; } else { /* else small number, don't kill it prior to HZ multiply */ - tmo = usec * CONFIG_SYS_HZ * count_value / 10; + tmo = usec * CONFIG_SYS_HZ * count_value; tmo /= (1000 * 1000); } /* get current timestamp */ - tmp = get_timer(0); + tmp = get_current_tick(); /* if setting this fordward will roll time stamp */ /* reset "advancing" timestamp to 0, set lastinc value */ @@ -92,7 +96,7 @@ void __udelay(unsigned long usec) tmo += tmp; /* loop till event */ - while (get_timer_masked() < tmo) + while (get_current_tick() < tmo) ; /* nop */ } @@ -108,6 +112,14 @@ void reset_timer_masked(void) unsigned long get_timer_masked(void) { struct s5p_timer *const timer = s5p_get_base_timer(); + unsigned long count_value = readl(&timer->tcntb4); + + return get_current_tick() / count_value; +} + +unsigned long get_current_tick(void) +{ + struct s5p_timer *const timer = s5p_get_base_timer(); unsigned long now = readl(&timer->tcnto4); unsigned long count_value = readl(&timer->tcntb4); diff --git a/arch/arm/cpu/armv7/start.S b/arch/arm/cpu/armv7/start.S index aee27fdc4d..32658eb7a5 100644 --- a/arch/arm/cpu/armv7/start.S +++ b/arch/arm/cpu/armv7/start.S @@ -133,7 +133,6 @@ reset: orr r0, r0, #0xd3 msr cpsr,r0 -#if !defined(CONFIG_TEGRA2) /* * Setup vector: * (OMAP4 spl TEXT_BASE is not 32 byte aligned. @@ -149,7 +148,6 @@ reset: ldr r0, =_start mcr p15, 0, r0, c12, c0, 0 @Set VBAR #endif -#endif /* !Tegra2 */ /* the mask ROM code should have PLL and others stable */ #ifndef CONFIG_SKIP_LOWLEVEL_INIT @@ -282,14 +280,14 @@ jump_2_ram: /* * Move vector table */ -#if !defined(CONFIG_TEGRA2) +#if !defined(CONFIG_TEGRA20) #if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD)) /* Set vector address in CP15 VBAR register */ ldr r0, =_start add r0, r0, r9 mcr p15, 0, r0, c12, c0, 0 @Set VBAR #endif -#endif /* !Tegra2 */ +#endif /* !Tegra20 */ ldr r0, _board_init_r_ofs adr r1, _start @@ -307,6 +305,20 @@ ENDPROC(relocate_code) /************************************************************************* * + * void save_boot_params(u32 r0, u32 r1, u32 r2, u32 r3) + * __attribute__((weak)); + * + * Stack pointer is not yet initialized at this moment + * Don't save anything to stack even if compiled with -O0 + * + *************************************************************************/ +ENTRY(save_boot_params) + bx lr @ back to my caller +ENDPROC(save_boot_params) + .weak save_boot_params + +/************************************************************************* + * * cpu_init_cp15 * * Setup CP15 registers (cache, MMU, TLBs). The I-cache is turned on unless diff --git a/arch/arm/cpu/armv7/tegra2/ap20.c b/arch/arm/cpu/armv7/tegra2/ap20.c deleted file mode 100644 index 1aad3879ee..0000000000 --- a/arch/arm/cpu/armv7/tegra2/ap20.c +++ /dev/null @@ -1,388 +0,0 @@ -/* -* (C) Copyright 2010-2011 -* NVIDIA Corporation <www.nvidia.com> -* -* See file CREDITS for list of people who contributed to this -* project. -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License as -* published by the Free Software Foundation; either version 2 of -* the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, -* MA 02111-1307 USA -*/ - -#include <asm/io.h> -#include <asm/arch/tegra2.h> -#include <asm/arch/ap20.h> -#include <asm/arch/clk_rst.h> -#include <asm/arch/clock.h> -#include <asm/arch/fuse.h> -#include <asm/arch/gp_padctrl.h> -#include <asm/arch/pmc.h> -#include <asm/arch/pinmux.h> -#include <asm/arch/scu.h> -#include <asm/arch/warmboot.h> -#include <common.h> - -int tegra_get_chip_type(void) -{ - struct apb_misc_gp_ctlr *gp; - struct fuse_regs *fuse = (struct fuse_regs *)TEGRA2_FUSE_BASE; - uint tegra_sku_id, rev; - - /* - * This is undocumented, Chip ID is bits 15:8 of the register - * APB_MISC + 0x804, and has value 0x20 for Tegra20, 0x30 for - * Tegra30 - */ - gp = (struct apb_misc_gp_ctlr *)TEGRA2_APB_MISC_GP_BASE; - rev = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> HIDREV_CHIPID_SHIFT; - - tegra_sku_id = readl(&fuse->sku_info) & 0xff; - - switch (rev) { - case CHIPID_TEGRA2: - switch (tegra_sku_id) { - case SKU_ID_T20: - return TEGRA_SOC_T20; - case SKU_ID_T25SE: - case SKU_ID_AP25: - case SKU_ID_T25: - case SKU_ID_AP25E: - case SKU_ID_T25E: - return TEGRA_SOC_T25; - } - break; - } - /* unknown sku id */ - return TEGRA_SOC_UNKNOWN; -} - -/* Returns 1 if the current CPU executing is a Cortex-A9, else 0 */ -static int ap20_cpu_is_cortexa9(void) -{ - u32 id = readb(NV_PA_PG_UP_BASE + PG_UP_TAG_0); - return id == (PG_UP_TAG_0_PID_CPU & 0xff); -} - -void init_pllx(void) -{ - struct clk_rst_ctlr *clkrst = - (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; - struct clk_pll_simple *pll = - &clkrst->crc_pll_simple[CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE]; - u32 reg; - - /* If PLLX is already enabled, just return */ - if (readl(&pll->pll_base) & PLL_ENABLE_MASK) - return; - - /* Set PLLX_MISC */ - writel(1 << PLL_CPCON_SHIFT, &pll->pll_misc); - - /* Use 12MHz clock here */ - reg = PLL_BYPASS_MASK | (12 << PLL_DIVM_SHIFT); - reg |= 1000 << PLL_DIVN_SHIFT; - writel(reg, &pll->pll_base); - - reg |= PLL_ENABLE_MASK; - writel(reg, &pll->pll_base); - - reg &= ~PLL_BYPASS_MASK; - writel(reg, &pll->pll_base); -} - -static void enable_cpu_clock(int enable) -{ - struct clk_rst_ctlr *clkrst = (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; - u32 clk; - - /* - * NOTE: - * Regardless of whether the request is to enable or disable the CPU - * clock, every processor in the CPU complex except the master (CPU 0) - * will have it's clock stopped because the AVP only talks to the - * master. The AVP does not know (nor does it need to know) that there - * are multiple processors in the CPU complex. - */ - - if (enable) { - /* Initialize PLLX */ - init_pllx(); - - /* Wait until all clocks are stable */ - udelay(PLL_STABILIZATION_DELAY); - - writel(CCLK_BURST_POLICY, &clkrst->crc_cclk_brst_pol); - writel(SUPER_CCLK_DIVIDER, &clkrst->crc_super_cclk_div); - } - - /* - * Read the register containing the individual CPU clock enables and - * always stop the clock to CPU 1. - */ - clk = readl(&clkrst->crc_clk_cpu_cmplx); - clk |= 1 << CPU1_CLK_STP_SHIFT; - - /* Stop/Unstop the CPU clock */ - clk &= ~CPU0_CLK_STP_MASK; - clk |= !enable << CPU0_CLK_STP_SHIFT; - writel(clk, &clkrst->crc_clk_cpu_cmplx); - - clock_enable(PERIPH_ID_CPU); -} - -static int is_cpu_powered(void) -{ - struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; - - return (readl(&pmc->pmc_pwrgate_status) & CPU_PWRED) ? 1 : 0; -} - -static void remove_cpu_io_clamps(void) -{ - struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; - u32 reg; - - /* Remove the clamps on the CPU I/O signals */ - reg = readl(&pmc->pmc_remove_clamping); - reg |= CPU_CLMP; - writel(reg, &pmc->pmc_remove_clamping); - - /* Give I/O signals time to stabilize */ - udelay(IO_STABILIZATION_DELAY); -} - -static void powerup_cpu(void) -{ - struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; - u32 reg; - int timeout = IO_STABILIZATION_DELAY; - - if (!is_cpu_powered()) { - /* Toggle the CPU power state (OFF -> ON) */ - reg = readl(&pmc->pmc_pwrgate_toggle); - reg &= PARTID_CP; - reg |= START_CP; - writel(reg, &pmc->pmc_pwrgate_toggle); - - /* Wait for the power to come up */ - while (!is_cpu_powered()) { - if (timeout-- == 0) - printf("CPU failed to power up!\n"); - else - udelay(10); - } - - /* - * Remove the I/O clamps from CPU power partition. - * Recommended only on a Warm boot, if the CPU partition gets - * power gated. Shouldn't cause any harm when called after a - * cold boot according to HW, probably just redundant. - */ - remove_cpu_io_clamps(); - } -} - -static void enable_cpu_power_rail(void) -{ - struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; - u32 reg; - - reg = readl(&pmc->pmc_cntrl); - reg |= CPUPWRREQ_OE; - writel(reg, &pmc->pmc_cntrl); - - /* - * The TI PMU65861C needs a 3.75ms delay between enabling - * the power rail and enabling the CPU clock. This delay - * between SM1EN and SM1 is for switching time + the ramp - * up of the voltage to the CPU (VDD_CPU from PMU). - */ - udelay(3750); -} - -static void reset_A9_cpu(int reset) -{ - /* - * NOTE: Regardless of whether the request is to hold the CPU in reset - * or take it out of reset, every processor in the CPU complex - * except the master (CPU 0) will be held in reset because the - * AVP only talks to the master. The AVP does not know that there - * are multiple processors in the CPU complex. - */ - - /* Hold CPU 1 in reset, and CPU 0 if asked */ - reset_cmplx_set_enable(1, crc_rst_cpu | crc_rst_de | crc_rst_debug, 1); - reset_cmplx_set_enable(0, crc_rst_cpu | crc_rst_de | crc_rst_debug, - reset); - - /* Enable/Disable master CPU reset */ - reset_set_enable(PERIPH_ID_CPU, reset); -} - -static void clock_enable_coresight(int enable) -{ - u32 rst, src; - - clock_set_enable(PERIPH_ID_CORESIGHT, enable); - reset_set_enable(PERIPH_ID_CORESIGHT, !enable); - - if (enable) { - /* - * Put CoreSight on PLLP_OUT0 (216 MHz) and divide it down by - * 1.5, giving an effective frequency of 144MHz. - * Set PLLP_OUT0 [bits31:30 = 00], and use a 7.1 divisor - * (bits 7:0), so 00000001b == 1.5 (n+1 + .5) - */ - src = CLK_DIVIDER(NVBL_PLLP_KHZ, 144000); - clock_ll_set_source_divisor(PERIPH_ID_CSI, 0, src); - - /* Unlock the CPU CoreSight interfaces */ - rst = 0xC5ACCE55; - writel(rst, CSITE_CPU_DBG0_LAR); - writel(rst, CSITE_CPU_DBG1_LAR); - } -} - -void start_cpu(u32 reset_vector) -{ - /* Enable VDD_CPU */ - enable_cpu_power_rail(); - - /* Hold the CPUs in reset */ - reset_A9_cpu(1); - - /* Disable the CPU clock */ - enable_cpu_clock(0); - - /* Enable CoreSight */ - clock_enable_coresight(1); - - /* - * Set the entry point for CPU execution from reset, - * if it's a non-zero value. - */ - if (reset_vector) - writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR); - - /* Enable the CPU clock */ - enable_cpu_clock(1); - - /* If the CPU doesn't already have power, power it up */ - powerup_cpu(); - - /* Take the CPU out of reset */ - reset_A9_cpu(0); -} - - -void halt_avp(void) -{ - for (;;) { - writel((HALT_COP_EVENT_JTAG | HALT_COP_EVENT_IRQ_1 \ - | HALT_COP_EVENT_FIQ_1 | (FLOW_MODE_STOP<<29)), - FLOW_CTLR_HALT_COP_EVENTS); - } -} - -void enable_scu(void) -{ - struct scu_ctlr *scu = (struct scu_ctlr *)NV_PA_ARM_PERIPHBASE; - u32 reg; - - /* If SCU already setup/enabled, return */ - if (readl(&scu->scu_ctrl) & SCU_CTRL_ENABLE) - return; - - /* Invalidate all ways for all processors */ - writel(0xFFFF, &scu->scu_inv_all); - - /* Enable SCU - bit 0 */ - reg = readl(&scu->scu_ctrl); - reg |= SCU_CTRL_ENABLE; - writel(reg, &scu->scu_ctrl); -} - -static u32 get_odmdata(void) -{ - /* - * ODMDATA is stored in the BCT in IRAM by the BootROM. - * The BCT start and size are stored in the BIT in IRAM. - * Read the data @ bct_start + (bct_size - 12). This works - * on T20 and T30 BCTs, which are locked down. If this changes - * in new chips (T114, etc.), we can revisit this algorithm. - */ - - u32 bct_start, odmdata; - - bct_start = readl(AP20_BASE_PA_SRAM + NVBOOTINFOTABLE_BCTPTR); - odmdata = readl(bct_start + BCT_ODMDATA_OFFSET); - - return odmdata; -} - -void init_pmc_scratch(void) -{ - struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; - u32 odmdata; - int i; - - /* SCRATCH0 is initialized by the boot ROM and shouldn't be cleared */ - for (i = 0; i < 23; i++) - writel(0, &pmc->pmc_scratch1+i); - - /* ODMDATA is for kernel use to determine RAM size, LP config, etc. */ - odmdata = get_odmdata(); - writel(odmdata, &pmc->pmc_scratch20); - -#ifdef CONFIG_TEGRA2_LP0 - /* save Sdram params to PMC 2, 4, and 24 for WB0 */ - warmboot_save_sdram_params(); -#endif -} - -void tegra2_start(void) -{ - struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; - - /* If we are the AVP, start up the first Cortex-A9 */ - if (!ap20_cpu_is_cortexa9()) { - /* enable JTAG */ - writel(0xC0, &pmt->pmt_cfg_ctl); - - /* - * If we are ARM7 - give it a different stack. We are about to - * start up the A9 which will want to use this one. - */ - asm volatile("mov sp, %0\n" - : : "r"(AVP_EARLY_BOOT_STACK_LIMIT)); - - start_cpu((u32)_start); - halt_avp(); - /* not reached */ - } - - /* Init PMC scratch memory */ - init_pmc_scratch(); - - enable_scu(); - - /* enable SMP mode and FW for CPU0, by writing to Auxiliary Ctl reg */ - asm volatile( - "mrc p15, 0, r0, c1, c0, 1\n" - "orr r0, r0, #0x41\n" - "mcr p15, 0, r0, c1, c0, 1\n"); - - /* FIXME: should have ap20's L2 disabled too? */ -} diff --git a/arch/arm/cpu/armv7/tegra2/board.c b/arch/arm/cpu/armv7/tegra2/board.c deleted file mode 100644 index 923678d063..0000000000 --- a/arch/arm/cpu/armv7/tegra2/board.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * (C) Copyright 2010,2011 - * NVIDIA Corporation <www.nvidia.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/io.h> -#include <asm/arch/ap20.h> -#include <asm/arch/clock.h> -#include <asm/arch/funcmux.h> -#include <asm/arch/pmc.h> -#include <asm/arch/sys_proto.h> -#include <asm/arch/tegra2.h> - -DECLARE_GLOBAL_DATA_PTR; - -enum { - /* UARTs which we can enable */ - UARTA = 1 << 0, - UARTB = 1 << 1, - UARTD = 1 << 3, - UART_COUNT = 4, -}; - -/* - * Boot ROM initializes the odmdata in APBDEV_PMC_SCRATCH20_0, - * so we are using this value to identify memory size. - */ - -unsigned int query_sdram_size(void) -{ - struct pmc_ctlr *const pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; - u32 reg; - - reg = readl(&pmc->pmc_scratch20); - debug("pmc->pmc_scratch20 (ODMData) = 0x%08x\n", reg); - - /* bits 31:28 in OdmData are used for RAM size */ - switch ((reg) >> 28) { - case 1: - return 0x10000000; /* 256 MB */ - case 2: - default: - return 0x20000000; /* 512 MB */ - case 3: - return 0x40000000; /* 1GB */ - } -} - -int dram_init(void) -{ - /* We do not initialise DRAM here. We just query the size */ - gd->ram_size = query_sdram_size(); - return 0; -} - -#ifdef CONFIG_DISPLAY_BOARDINFO -int checkboard(void) -{ - printf("Board: %s\n", sysinfo.board_string); - return 0; -} -#endif /* CONFIG_DISPLAY_BOARDINFO */ - -#ifdef CONFIG_ARCH_CPU_INIT -/* - * Note this function is executed by the ARM7TDMI AVP. It does not return - * in this case. It is also called once the A9 starts up, but does nothing in - * that case. - */ -int arch_cpu_init(void) -{ - /* Fire up the Cortex A9 */ - tegra2_start(); - - /* We didn't do this init in start.S, so do it now */ - cpu_init_cp15(); - - /* Initialize essential common plls */ - clock_early_init(); - - return 0; -} -#endif - -static int uart_configs[] = { -#if defined(CONFIG_TEGRA2_UARTA_UAA_UAB) - FUNCMUX_UART1_UAA_UAB, -#elif defined(CONFIG_TEGRA2_UARTA_GPU) - FUNCMUX_UART1_GPU, -#elif defined(CONFIG_TEGRA2_UARTA_SDIO1) - FUNCMUX_UART1_SDIO1, -#else - FUNCMUX_UART1_IRRX_IRTX, -#endif - FUNCMUX_UART2_IRDA, - -1, - FUNCMUX_UART4_GMC, - -1, -}; - -/** - * Set up the specified uarts - * - * @param uarts_ids Mask containing UARTs to init (UARTx) - */ -static void setup_uarts(int uart_ids) -{ - static enum periph_id id_for_uart[] = { - PERIPH_ID_UART1, - PERIPH_ID_UART2, - PERIPH_ID_UART3, - PERIPH_ID_UART4, - }; - size_t i; - - for (i = 0; i < UART_COUNT; i++) { - if (uart_ids & (1 << i)) { - enum periph_id id = id_for_uart[i]; - - funcmux_select(id, uart_configs[i]); - clock_ll_start_uart(id); - } - } -} - -void board_init_uart_f(void) -{ - int uart_ids = 0; /* bit mask of which UART ids to enable */ - -#ifdef CONFIG_TEGRA2_ENABLE_UARTA - uart_ids |= UARTA; -#endif -#ifdef CONFIG_TEGRA2_ENABLE_UARTB - uart_ids |= UARTB; -#endif -#ifdef CONFIG_TEGRA2_ENABLE_UARTD - uart_ids |= UARTD; -#endif - setup_uarts(uart_ids); -} - -#ifndef CONFIG_SYS_DCACHE_OFF -void enable_caches(void) -{ - /* Enable D-cache. I-cache is already enabled in start.S */ - dcache_enable(); -} -#endif diff --git a/arch/arm/cpu/armv7/tegra2/clock.c b/arch/arm/cpu/armv7/tegra2/clock.c deleted file mode 100644 index 602589cde0..0000000000 --- a/arch/arm/cpu/armv7/tegra2/clock.c +++ /dev/null @@ -1,1087 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -/* Tegra2 Clock control functions */ - -#include <asm/io.h> -#include <asm/arch/clk_rst.h> -#include <asm/arch/clock.h> -#include <asm/arch/timer.h> -#include <asm/arch/tegra2.h> -#include <common.h> -#include <div64.h> -#include <fdtdec.h> - -/* - * This is our record of the current clock rate of each clock. We don't - * fill all of these in since we are only really interested in clocks which - * we use as parents. - */ -static unsigned pll_rate[CLOCK_ID_COUNT]; - -/* - * The oscillator frequency is fixed to one of four set values. Based on this - * the other clocks are set up appropriately. - */ -static unsigned osc_freq[CLOCK_OSC_FREQ_COUNT] = { - 13000000, - 19200000, - 12000000, - 26000000, -}; - -/* - * Clock types that we can use as a source. The Tegra2 has muxes for the - * peripheral clocks, and in most cases there are four options for the clock - * source. This gives us a clock 'type' and exploits what commonality exists - * in the device. - * - * Letters are obvious, except for T which means CLK_M, and S which means the - * clock derived from 32KHz. Beware that CLK_M (also called OSC in the - * datasheet) and PLL_M are different things. The former is the basic - * clock supplied to the SOC from an external oscillator. The latter is the - * memory clock PLL. - * - * See definitions in clock_id in the header file. - */ -enum clock_type_id { - CLOCK_TYPE_AXPT, /* PLL_A, PLL_X, PLL_P, CLK_M */ - CLOCK_TYPE_MCPA, /* and so on */ - CLOCK_TYPE_MCPT, - CLOCK_TYPE_PCM, - CLOCK_TYPE_PCMT, - CLOCK_TYPE_PCMT16, /* CLOCK_TYPE_PCMT with 16-bit divider */ - CLOCK_TYPE_PCXTS, - CLOCK_TYPE_PDCT, - - CLOCK_TYPE_COUNT, - CLOCK_TYPE_NONE = -1, /* invalid clock type */ -}; - -/* return 1 if a peripheral ID is in range */ -#define clock_type_id_isvalid(id) ((id) >= 0 && \ - (id) < CLOCK_TYPE_COUNT) - -char pllp_valid = 1; /* PLLP is set up correctly */ - -enum { - CLOCK_MAX_MUX = 4 /* number of source options for each clock */ -}; - -/* - * Clock source mux for each clock type. This just converts our enum into - * a list of mux sources for use by the code. Note that CLOCK_TYPE_PCXTS - * is special as it has 5 sources. Since it also has a different number of - * bits in its register for the source, we just handle it with a special - * case in the code. - */ -#define CLK(x) CLOCK_ID_ ## x -static enum clock_id clock_source[CLOCK_TYPE_COUNT][CLOCK_MAX_MUX] = { - { CLK(AUDIO), CLK(XCPU), CLK(PERIPH), CLK(OSC) }, - { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(AUDIO) }, - { CLK(MEMORY), CLK(CGENERAL), CLK(PERIPH), CLK(OSC) }, - { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(NONE) }, - { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC) }, - { CLK(PERIPH), CLK(CGENERAL), CLK(MEMORY), CLK(OSC) }, - { CLK(PERIPH), CLK(CGENERAL), CLK(XCPU), CLK(OSC) }, - { CLK(PERIPH), CLK(DISPLAY), CLK(CGENERAL), CLK(OSC) }, -}; - -/* - * Clock peripheral IDs which sadly don't match up with PERIPH_ID. This is - * not in the header file since it is for purely internal use - we want - * callers to use the PERIPH_ID for all access to peripheral clocks to avoid - * confusion bewteen PERIPH_ID_... and PERIPHC_... - * - * We don't call this CLOCK_PERIPH_ID or PERIPH_CLOCK_ID as it would just be - * confusing. - * - * Note to SOC vendors: perhaps define a unified numbering for peripherals and - * use it for reset, clock enable, clock source/divider and even pinmuxing - * if you can. - */ -enum periphc_internal_id { - /* 0x00 */ - PERIPHC_I2S1, - PERIPHC_I2S2, - PERIPHC_SPDIF_OUT, - PERIPHC_SPDIF_IN, - PERIPHC_PWM, - PERIPHC_SPI1, - PERIPHC_SPI2, - PERIPHC_SPI3, - - /* 0x08 */ - PERIPHC_XIO, - PERIPHC_I2C1, - PERIPHC_DVC_I2C, - PERIPHC_TWC, - PERIPHC_0c, - PERIPHC_10, /* PERIPHC_SPI1, what is this really? */ - PERIPHC_DISP1, - PERIPHC_DISP2, - - /* 0x10 */ - PERIPHC_CVE, - PERIPHC_IDE0, - PERIPHC_VI, - PERIPHC_1c, - PERIPHC_SDMMC1, - PERIPHC_SDMMC2, - PERIPHC_G3D, - PERIPHC_G2D, - - /* 0x18 */ - PERIPHC_NDFLASH, - PERIPHC_SDMMC4, - PERIPHC_VFIR, - PERIPHC_EPP, - PERIPHC_MPE, - PERIPHC_MIPI, - PERIPHC_UART1, - PERIPHC_UART2, - - /* 0x20 */ - PERIPHC_HOST1X, - PERIPHC_21, - PERIPHC_TVO, - PERIPHC_HDMI, - PERIPHC_24, - PERIPHC_TVDAC, - PERIPHC_I2C2, - PERIPHC_EMC, - - /* 0x28 */ - PERIPHC_UART3, - PERIPHC_29, - PERIPHC_VI_SENSOR, - PERIPHC_2b, - PERIPHC_2c, - PERIPHC_SPI4, - PERIPHC_I2C3, - PERIPHC_SDMMC3, - - /* 0x30 */ - PERIPHC_UART4, - PERIPHC_UART5, - PERIPHC_VDE, - PERIPHC_OWR, - PERIPHC_NOR, - PERIPHC_CSITE, - - PERIPHC_COUNT, - - PERIPHC_NONE = -1, -}; - -/* return 1 if a periphc_internal_id is in range */ -#define periphc_internal_id_isvalid(id) ((id) >= 0 && \ - (id) < PERIPHC_COUNT) - -/* - * Clock type for each peripheral clock source. We put the name in each - * record just so it is easy to match things up - */ -#define TYPE(name, type) type -static enum clock_type_id clock_periph_type[PERIPHC_COUNT] = { - /* 0x00 */ - TYPE(PERIPHC_I2S1, CLOCK_TYPE_AXPT), - TYPE(PERIPHC_I2S2, CLOCK_TYPE_AXPT), - TYPE(PERIPHC_SPDIF_OUT, CLOCK_TYPE_AXPT), - TYPE(PERIPHC_SPDIF_IN, CLOCK_TYPE_PCM), - TYPE(PERIPHC_PWM, CLOCK_TYPE_PCXTS), - TYPE(PERIPHC_SPI1, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_SPI22, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_SPI3, CLOCK_TYPE_PCMT), - - /* 0x08 */ - TYPE(PERIPHC_XIO, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_I2C1, CLOCK_TYPE_PCMT16), - TYPE(PERIPHC_DVC_I2C, CLOCK_TYPE_PCMT16), - TYPE(PERIPHC_TWC, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), - TYPE(PERIPHC_SPI1, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_DISP1, CLOCK_TYPE_PDCT), - TYPE(PERIPHC_DISP2, CLOCK_TYPE_PDCT), - - /* 0x10 */ - TYPE(PERIPHC_CVE, CLOCK_TYPE_PDCT), - TYPE(PERIPHC_IDE0, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA), - TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), - TYPE(PERIPHC_SDMMC1, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_SDMMC2, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_G3D, CLOCK_TYPE_MCPA), - TYPE(PERIPHC_G2D, CLOCK_TYPE_MCPA), - - /* 0x18 */ - TYPE(PERIPHC_NDFLASH, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_SDMMC4, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_VFIR, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_EPP, CLOCK_TYPE_MCPA), - TYPE(PERIPHC_MPE, CLOCK_TYPE_MCPA), - TYPE(PERIPHC_MIPI, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_UART1, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_UART2, CLOCK_TYPE_PCMT), - - /* 0x20 */ - TYPE(PERIPHC_HOST1X, CLOCK_TYPE_MCPA), - TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), - TYPE(PERIPHC_TVO, CLOCK_TYPE_PDCT), - TYPE(PERIPHC_HDMI, CLOCK_TYPE_PDCT), - TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), - TYPE(PERIPHC_TVDAC, CLOCK_TYPE_PDCT), - TYPE(PERIPHC_I2C2, CLOCK_TYPE_PCMT16), - TYPE(PERIPHC_EMC, CLOCK_TYPE_MCPT), - - /* 0x28 */ - TYPE(PERIPHC_UART3, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), - TYPE(PERIPHC_VI, CLOCK_TYPE_MCPA), - TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), - TYPE(PERIPHC_NONE, CLOCK_TYPE_NONE), - TYPE(PERIPHC_SPI4, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_I2C3, CLOCK_TYPE_PCMT16), - TYPE(PERIPHC_SDMMC3, CLOCK_TYPE_PCMT), - - /* 0x30 */ - TYPE(PERIPHC_UART4, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_UART5, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_VDE, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_OWR, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_NOR, CLOCK_TYPE_PCMT), - TYPE(PERIPHC_CSITE, CLOCK_TYPE_PCMT), -}; - -/* - * This array translates a periph_id to a periphc_internal_id - * - * Not present/matched up: - * uint vi_sensor; _VI_SENSOR_0, 0x1A8 - * SPDIF - which is both 0x08 and 0x0c - * - */ -#define NONE(name) (-1) -#define OFFSET(name, value) PERIPHC_ ## name -static s8 periph_id_to_internal_id[PERIPH_ID_COUNT] = { - /* Low word: 31:0 */ - NONE(CPU), - NONE(RESERVED1), - NONE(RESERVED2), - NONE(AC97), - NONE(RTC), - NONE(TMR), - PERIPHC_UART1, - PERIPHC_UART2, /* and vfir 0x68 */ - - /* 0x08 */ - NONE(GPIO), - PERIPHC_SDMMC2, - NONE(SPDIF), /* 0x08 and 0x0c, unclear which to use */ - PERIPHC_I2S1, - PERIPHC_I2C1, - PERIPHC_NDFLASH, - PERIPHC_SDMMC1, - PERIPHC_SDMMC4, - - /* 0x10 */ - PERIPHC_TWC, - PERIPHC_PWM, - PERIPHC_I2S2, - PERIPHC_EPP, - PERIPHC_VI, - PERIPHC_G2D, - NONE(USBD), - NONE(ISP), - - /* 0x18 */ - PERIPHC_G3D, - PERIPHC_IDE0, - PERIPHC_DISP2, - PERIPHC_DISP1, - PERIPHC_HOST1X, - NONE(VCP), - NONE(RESERVED30), - NONE(CACHE2), - - /* Middle word: 63:32 */ - NONE(MEM), - NONE(AHBDMA), - NONE(APBDMA), - NONE(RESERVED35), - NONE(KBC), - NONE(STAT_MON), - NONE(PMC), - NONE(FUSE), - - /* 0x28 */ - NONE(KFUSE), - NONE(SBC1), /* SBC1, 0x34, is this SPI1? */ - PERIPHC_NOR, - PERIPHC_SPI1, - PERIPHC_SPI2, - PERIPHC_XIO, - PERIPHC_SPI3, - PERIPHC_DVC_I2C, - - /* 0x30 */ - NONE(DSI), - PERIPHC_TVO, /* also CVE 0x40 */ - PERIPHC_MIPI, - PERIPHC_HDMI, - PERIPHC_CSITE, - PERIPHC_TVDAC, - PERIPHC_I2C2, - PERIPHC_UART3, - - /* 0x38 */ - NONE(RESERVED56), - PERIPHC_EMC, - NONE(USB2), - NONE(USB3), - PERIPHC_MPE, - PERIPHC_VDE, - NONE(BSEA), - NONE(BSEV), - - /* Upper word 95:64 */ - NONE(SPEEDO), - PERIPHC_UART4, - PERIPHC_UART5, - PERIPHC_I2C3, - PERIPHC_SPI4, - PERIPHC_SDMMC3, - NONE(PCIE), - PERIPHC_OWR, - - /* 0x48 */ - NONE(AFI), - NONE(CORESIGHT), - NONE(RESERVED74), - NONE(AVPUCQ), - NONE(RESERVED76), - NONE(RESERVED77), - NONE(RESERVED78), - NONE(RESERVED79), - - /* 0x50 */ - NONE(RESERVED80), - NONE(RESERVED81), - NONE(RESERVED82), - NONE(RESERVED83), - NONE(IRAMA), - NONE(IRAMB), - NONE(IRAMC), - NONE(IRAMD), - - /* 0x58 */ - NONE(CRAM2), -}; - -/* - * Get the oscillator frequency, from the corresponding hardware configuration - * field. - */ -enum clock_osc_freq clock_get_osc_freq(void) -{ - struct clk_rst_ctlr *clkrst = - (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; - u32 reg; - - reg = readl(&clkrst->crc_osc_ctrl); - return (reg & OSC_FREQ_MASK) >> OSC_FREQ_SHIFT; -} - -int clock_get_osc_bypass(void) -{ - struct clk_rst_ctlr *clkrst = - (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; - u32 reg; - - reg = readl(&clkrst->crc_osc_ctrl); - return (reg & OSC_XOBP_MASK) >> OSC_XOBP_SHIFT; -} - -/* Returns a pointer to the registers of the given pll */ -static struct clk_pll *get_pll(enum clock_id clkid) -{ - struct clk_rst_ctlr *clkrst = - (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; - - assert(clock_id_is_pll(clkid)); - return &clkrst->crc_pll[clkid]; -} - -int clock_ll_read_pll(enum clock_id clkid, u32 *divm, u32 *divn, - u32 *divp, u32 *cpcon, u32 *lfcon) -{ - struct clk_pll *pll = get_pll(clkid); - u32 data; - - assert(clkid != CLOCK_ID_USB); - - /* Safety check, adds to code size but is small */ - if (!clock_id_is_pll(clkid) || clkid == CLOCK_ID_USB) - return -1; - data = readl(&pll->pll_base); - *divm = (data & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT; - *divn = (data & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT; - *divp = (data & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT; - data = readl(&pll->pll_misc); - *cpcon = (data & PLL_CPCON_MASK) >> PLL_CPCON_SHIFT; - *lfcon = (data & PLL_LFCON_MASK) >> PLL_LFCON_SHIFT; - - return 0; -} - -unsigned long clock_start_pll(enum clock_id clkid, u32 divm, u32 divn, - u32 divp, u32 cpcon, u32 lfcon) -{ - struct clk_pll *pll = get_pll(clkid); - u32 data; - - /* - * We cheat by treating all PLL (except PLLU) in the same fashion. - * This works only because: - * - same fields are always mapped at same offsets, except DCCON - * - DCCON is always 0, doesn't conflict - * - M,N, P of PLLP values are ignored for PLLP - */ - data = (cpcon << PLL_CPCON_SHIFT) | (lfcon << PLL_LFCON_SHIFT); - writel(data, &pll->pll_misc); - - data = (divm << PLL_DIVM_SHIFT) | (divn << PLL_DIVN_SHIFT) | - (0 << PLL_BYPASS_SHIFT) | (1 << PLL_ENABLE_SHIFT); - - if (clkid == CLOCK_ID_USB) - data |= divp << PLLU_VCO_FREQ_SHIFT; - else - data |= divp << PLL_DIVP_SHIFT; - writel(data, &pll->pll_base); - - /* calculate the stable time */ - return timer_get_us() + CLOCK_PLL_STABLE_DELAY_US; -} - -/* return 1 if a peripheral ID is in range and valid */ -static int clock_periph_id_isvalid(enum periph_id id) -{ - if (id < PERIPH_ID_FIRST || id >= PERIPH_ID_COUNT) - printf("Peripheral id %d out of range\n", id); - else { - switch (id) { - case PERIPH_ID_RESERVED1: - case PERIPH_ID_RESERVED2: - case PERIPH_ID_RESERVED30: - case PERIPH_ID_RESERVED35: - case PERIPH_ID_RESERVED56: - case PERIPH_ID_RESERVED74: - case PERIPH_ID_RESERVED76: - case PERIPH_ID_RESERVED77: - case PERIPH_ID_RESERVED78: - case PERIPH_ID_RESERVED79: - case PERIPH_ID_RESERVED80: - case PERIPH_ID_RESERVED81: - case PERIPH_ID_RESERVED82: - case PERIPH_ID_RESERVED83: - printf("Peripheral id %d is reserved\n", id); - break; - default: - return 1; - } - } - return 0; -} - -/* Returns a pointer to the clock source register for a peripheral */ -static u32 *get_periph_source_reg(enum periph_id periph_id) -{ - struct clk_rst_ctlr *clkrst = - (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; - enum periphc_internal_id internal_id; - - assert(clock_periph_id_isvalid(periph_id)); - internal_id = periph_id_to_internal_id[periph_id]; - assert(internal_id != -1); - return &clkrst->crc_clk_src[internal_id]; -} - -void clock_ll_set_source_divisor(enum periph_id periph_id, unsigned source, - unsigned divisor) -{ - u32 *reg = get_periph_source_reg(periph_id); - u32 value; - - value = readl(reg); - - value &= ~OUT_CLK_SOURCE_MASK; - value |= source << OUT_CLK_SOURCE_SHIFT; - - value &= ~OUT_CLK_DIVISOR_MASK; - value |= divisor << OUT_CLK_DIVISOR_SHIFT; - - writel(value, reg); -} - -void clock_ll_set_source(enum periph_id periph_id, unsigned source) -{ - u32 *reg = get_periph_source_reg(periph_id); - - clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK, - source << OUT_CLK_SOURCE_SHIFT); -} - -/** - * Given the parent's rate and the required rate for the children, this works - * out the peripheral clock divider to use, in 7.1 binary format. - * - * @param divider_bits number of divider bits (8 or 16) - * @param parent_rate clock rate of parent clock in Hz - * @param rate required clock rate for this clock - * @return divider which should be used - */ -static int clk_get_divider(unsigned divider_bits, unsigned long parent_rate, - unsigned long rate) -{ - u64 divider = parent_rate * 2; - unsigned max_divider = 1 << divider_bits; - - divider += rate - 1; - do_div(divider, rate); - - if ((s64)divider - 2 < 0) - return 0; - - if ((s64)divider - 2 >= max_divider) - return -1; - - return divider - 2; -} - -/** - * Given the parent's rate and the divider in 7.1 format, this works out the - * resulting peripheral clock rate. - * - * @param parent_rate clock rate of parent clock in Hz - * @param divider which should be used in 7.1 format - * @return effective clock rate of peripheral - */ -static unsigned long get_rate_from_divider(unsigned long parent_rate, - int divider) -{ - u64 rate; - - rate = (u64)parent_rate * 2; - do_div(rate, divider + 2); - return rate; -} - -unsigned long clock_get_periph_rate(enum periph_id periph_id, - enum clock_id parent) -{ - u32 *reg = get_periph_source_reg(periph_id); - - return get_rate_from_divider(pll_rate[parent], - (readl(reg) & OUT_CLK_DIVISOR_MASK) >> OUT_CLK_DIVISOR_SHIFT); -} - -/** - * Find the best available 7.1 format divisor given a parent clock rate and - * required child clock rate. This function assumes that a second-stage - * divisor is available which can divide by powers of 2 from 1 to 256. - * - * @param divider_bits number of divider bits (8 or 16) - * @param parent_rate clock rate of parent clock in Hz - * @param rate required clock rate for this clock - * @param extra_div value for the second-stage divisor (not set if this - * function returns -1. - * @return divider which should be used, or -1 if nothing is valid - * - */ -static int find_best_divider(unsigned divider_bits, unsigned long parent_rate, - unsigned long rate, int *extra_div) -{ - int shift; - int best_divider = -1; - int best_error = rate; - - /* try dividers from 1 to 256 and find closest match */ - for (shift = 0; shift <= 8 && best_error > 0; shift++) { - unsigned divided_parent = parent_rate >> shift; - int divider = clk_get_divider(divider_bits, divided_parent, - rate); - unsigned effective_rate = get_rate_from_divider(divided_parent, - divider); - int error = rate - effective_rate; - - /* Given a valid divider, look for the lowest error */ - if (divider != -1 && error < best_error) { - best_error = error; - *extra_div = 1 << shift; - best_divider = divider; - } - } - - /* return what we found - *extra_div will already be set */ - return best_divider; -} - -/** - * Given a peripheral ID and the required source clock, this returns which - * value should be programmed into the source mux for that peripheral. - * - * There is special code here to handle the one source type with 5 sources. - * - * @param periph_id peripheral to start - * @param source PLL id of required parent clock - * @param mux_bits Set to number of bits in mux register: 2 or 4 - * @param divider_bits Set to number of divider bits (8 or 16) - * @return mux value (0-4, or -1 if not found) - */ -static int get_periph_clock_source(enum periph_id periph_id, - enum clock_id parent, int *mux_bits, int *divider_bits) -{ - enum clock_type_id type; - enum periphc_internal_id internal_id; - int mux; - - assert(clock_periph_id_isvalid(periph_id)); - - internal_id = periph_id_to_internal_id[periph_id]; - assert(periphc_internal_id_isvalid(internal_id)); - - type = clock_periph_type[internal_id]; - assert(clock_type_id_isvalid(type)); - - /* - * Special cases here for the clock with a 4-bit source mux and I2C - * with its 16-bit divisor - */ - if (type == CLOCK_TYPE_PCXTS) - *mux_bits = 4; - else - *mux_bits = 2; - if (type == CLOCK_TYPE_PCMT16) - *divider_bits = 16; - else - *divider_bits = 8; - - for (mux = 0; mux < CLOCK_MAX_MUX; mux++) - if (clock_source[type][mux] == parent) - return mux; - - /* - * Not found: it might be looking for the 'S' in CLOCK_TYPE_PCXTS - * which is not in our table. If not, then they are asking for a - * source which this peripheral can't access through its mux. - */ - assert(type == CLOCK_TYPE_PCXTS); - assert(parent == CLOCK_ID_SFROM32KHZ); - if (type == CLOCK_TYPE_PCXTS && parent == CLOCK_ID_SFROM32KHZ) - return 4; /* mux value for this clock */ - - /* if we get here, either us or the caller has made a mistake */ - printf("Caller requested bad clock: periph=%d, parent=%d\n", periph_id, - parent); - return -1; -} - -/** - * Adjust peripheral PLL to use the given divider and source. - * - * @param periph_id peripheral to adjust - * @param source Source number (0-3 or 0-7) - * @param mux_bits Number of mux bits (2 or 4) - * @param divider Required divider in 7.1 or 15.1 format - * @return 0 if ok, -1 on error (requesting a parent clock which is not valid - * for this peripheral) - */ -static int adjust_periph_pll(enum periph_id periph_id, int source, - int mux_bits, unsigned divider) -{ - u32 *reg = get_periph_source_reg(periph_id); - - clrsetbits_le32(reg, OUT_CLK_DIVISOR_MASK, - divider << OUT_CLK_DIVISOR_SHIFT); - udelay(1); - - /* work out the source clock and set it */ - if (source < 0) - return -1; - if (mux_bits == 4) { - clrsetbits_le32(reg, OUT_CLK_SOURCE4_MASK, - source << OUT_CLK_SOURCE4_SHIFT); - } else { - clrsetbits_le32(reg, OUT_CLK_SOURCE_MASK, - source << OUT_CLK_SOURCE_SHIFT); - } - udelay(2); - return 0; -} - -unsigned clock_adjust_periph_pll_div(enum periph_id periph_id, - enum clock_id parent, unsigned rate, int *extra_div) -{ - unsigned effective_rate; - int mux_bits, divider_bits, source; - int divider; - - /* work out the source clock and set it */ - source = get_periph_clock_source(periph_id, parent, &mux_bits, - ÷r_bits); - - if (extra_div) - divider = find_best_divider(divider_bits, pll_rate[parent], - rate, extra_div); - else - divider = clk_get_divider(divider_bits, pll_rate[parent], - rate); - assert(divider >= 0); - if (adjust_periph_pll(periph_id, source, mux_bits, divider)) - return -1U; - debug("periph %d, rate=%d, reg=%p = %x\n", periph_id, rate, - get_periph_source_reg(periph_id), - readl(get_periph_source_reg(periph_id))); - - /* Check what we ended up with. This shouldn't matter though */ - effective_rate = clock_get_periph_rate(periph_id, parent); - if (extra_div) - effective_rate /= *extra_div; - if (rate != effective_rate) - debug("Requested clock rate %u not honored (got %u)\n", - rate, effective_rate); - return effective_rate; -} - -unsigned clock_start_periph_pll(enum periph_id periph_id, - enum clock_id parent, unsigned rate) -{ - unsigned effective_rate; - - reset_set_enable(periph_id, 1); - clock_enable(periph_id); - - effective_rate = clock_adjust_periph_pll_div(periph_id, parent, rate, - NULL); - - reset_set_enable(periph_id, 0); - return effective_rate; -} - -void clock_set_enable(enum periph_id periph_id, int enable) -{ - struct clk_rst_ctlr *clkrst = - (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; - u32 *clk = &clkrst->crc_clk_out_enb[PERIPH_REG(periph_id)]; - u32 reg; - - /* Enable/disable the clock to this peripheral */ - assert(clock_periph_id_isvalid(periph_id)); - reg = readl(clk); - if (enable) - reg |= PERIPH_MASK(periph_id); - else - reg &= ~PERIPH_MASK(periph_id); - writel(reg, clk); -} - -void clock_enable(enum periph_id clkid) -{ - clock_set_enable(clkid, 1); -} - -void clock_disable(enum periph_id clkid) -{ - clock_set_enable(clkid, 0); -} - -void reset_set_enable(enum periph_id periph_id, int enable) -{ - struct clk_rst_ctlr *clkrst = - (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; - u32 *reset = &clkrst->crc_rst_dev[PERIPH_REG(periph_id)]; - u32 reg; - - /* Enable/disable reset to the peripheral */ - assert(clock_periph_id_isvalid(periph_id)); - reg = readl(reset); - if (enable) - reg |= PERIPH_MASK(periph_id); - else - reg &= ~PERIPH_MASK(periph_id); - writel(reg, reset); -} - -void reset_periph(enum periph_id periph_id, int us_delay) -{ - /* Put peripheral into reset */ - reset_set_enable(periph_id, 1); - udelay(us_delay); - - /* Remove reset */ - reset_set_enable(periph_id, 0); - - udelay(us_delay); -} - -void reset_cmplx_set_enable(int cpu, int which, int reset) -{ - struct clk_rst_ctlr *clkrst = - (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; - u32 mask; - - /* Form the mask, which depends on the cpu chosen. Tegra2 has 2 */ - assert(cpu >= 0 && cpu < 2); - mask = which << cpu; - - /* either enable or disable those reset for that CPU */ - if (reset) - writel(mask, &clkrst->crc_cpu_cmplx_set); - else - writel(mask, &clkrst->crc_cpu_cmplx_clr); -} - -unsigned clock_get_rate(enum clock_id clkid) -{ - struct clk_pll *pll; - u32 base; - u32 divm; - u64 parent_rate; - u64 rate; - - parent_rate = osc_freq[clock_get_osc_freq()]; - if (clkid == CLOCK_ID_OSC) - return parent_rate; - - pll = get_pll(clkid); - base = readl(&pll->pll_base); - - /* Oh for bf_unpack()... */ - rate = parent_rate * ((base & PLL_DIVN_MASK) >> PLL_DIVN_SHIFT); - divm = (base & PLL_DIVM_MASK) >> PLL_DIVM_SHIFT; - if (clkid == CLOCK_ID_USB) - divm <<= (base & PLLU_VCO_FREQ_MASK) >> PLLU_VCO_FREQ_SHIFT; - else - divm <<= (base & PLL_DIVP_MASK) >> PLL_DIVP_SHIFT; - do_div(rate, divm); - return rate; -} - -/** - * Set the output frequency you want for each PLL clock. - * PLL output frequencies are programmed by setting their N, M and P values. - * The governing equations are: - * VCO = (Fi / m) * n, Fo = VCO / (2^p) - * where Fo is the output frequency from the PLL. - * Example: Set the output frequency to 216Mhz(Fo) with 12Mhz OSC(Fi) - * 216Mhz = ((12Mhz / m) * n) / (2^p) so n=432,m=12,p=1 - * Please see Tegra TRM section 5.3 to get the detail for PLL Programming - * - * @param n PLL feedback divider(DIVN) - * @param m PLL input divider(DIVN) - * @param p post divider(DIVP) - * @param cpcon base PLL charge pump(CPCON) - * @return 0 if ok, -1 on error (the requested PLL is incorrect and cannot - * be overriden), 1 if PLL is already correct - */ -static int clock_set_rate(enum clock_id clkid, u32 n, u32 m, u32 p, u32 cpcon) -{ - u32 base_reg; - u32 misc_reg; - struct clk_pll *pll; - - pll = get_pll(clkid); - - base_reg = readl(&pll->pll_base); - - /* Set BYPASS, m, n and p to PLL_BASE */ - base_reg &= ~PLL_DIVM_MASK; - base_reg |= m << PLL_DIVM_SHIFT; - - base_reg &= ~PLL_DIVN_MASK; - base_reg |= n << PLL_DIVN_SHIFT; - - base_reg &= ~PLL_DIVP_MASK; - base_reg |= p << PLL_DIVP_SHIFT; - - if (clkid == CLOCK_ID_PERIPH) { - /* - * If the PLL is already set up, check that it is correct - * and record this info for clock_verify() to check. - */ - if (base_reg & PLL_BASE_OVRRIDE_MASK) { - base_reg |= PLL_ENABLE_MASK; - if (base_reg != readl(&pll->pll_base)) - pllp_valid = 0; - return pllp_valid ? 1 : -1; - } - base_reg |= PLL_BASE_OVRRIDE_MASK; - } - - base_reg |= PLL_BYPASS_MASK; - writel(base_reg, &pll->pll_base); - - /* Set cpcon to PLL_MISC */ - misc_reg = readl(&pll->pll_misc); - misc_reg &= ~PLL_CPCON_MASK; - misc_reg |= cpcon << PLL_CPCON_SHIFT; - writel(misc_reg, &pll->pll_misc); - - /* Enable PLL */ - base_reg |= PLL_ENABLE_MASK; - writel(base_reg, &pll->pll_base); - - /* Disable BYPASS */ - base_reg &= ~PLL_BYPASS_MASK; - writel(base_reg, &pll->pll_base); - - return 0; -} - -void clock_ll_start_uart(enum periph_id periph_id) -{ - /* Assert UART reset and enable clock */ - reset_set_enable(periph_id, 1); - clock_enable(periph_id); - clock_ll_set_source(periph_id, 0); /* UARTx_CLK_SRC = 00, PLLP_OUT0 */ - - /* wait for 2us */ - udelay(2); - - /* De-assert reset to UART */ - reset_set_enable(periph_id, 0); -} - -#ifdef CONFIG_OF_CONTROL -/* - * Convert a device tree clock ID to our peripheral ID. They are mostly - * the same but we are very cautious so we check that a valid clock ID is - * provided. - * - * @param clk_id Clock ID according to tegra2 device tree binding - * @return peripheral ID, or PERIPH_ID_NONE if the clock ID is invalid - */ -static enum periph_id clk_id_to_periph_id(int clk_id) -{ - if (clk_id > 95) - return PERIPH_ID_NONE; - - switch (clk_id) { - case 1: - case 2: - case 7: - case 10: - case 20: - case 30: - case 35: - case 49: - case 56: - case 74: - case 76: - case 77: - case 78: - case 79: - case 80: - case 81: - case 82: - case 83: - case 91: - case 95: - return PERIPH_ID_NONE; - default: - return clk_id; - } -} - -int clock_decode_periph_id(const void *blob, int node) -{ - enum periph_id id; - u32 cell[2]; - int err; - - err = fdtdec_get_int_array(blob, node, "clocks", cell, - ARRAY_SIZE(cell)); - if (err) - return -1; - id = clk_id_to_periph_id(cell[1]); - assert(clock_periph_id_isvalid(id)); - return id; -} -#endif /* CONFIG_OF_CONTROL */ - -int clock_verify(void) -{ - struct clk_pll *pll = get_pll(CLOCK_ID_PERIPH); - u32 reg = readl(&pll->pll_base); - - if (!pllp_valid) { - printf("Warning: PLLP %x is not correct\n", reg); - return -1; - } - debug("PLLX %x is correct\n", reg); - return 0; -} - -void clock_early_init(void) -{ - /* - * PLLP output frequency set to 216MHz - * PLLC output frequency set to 600Mhz - * - * TODO: Can we calculate these values instead of hard-coding? - */ - switch (clock_get_osc_freq()) { - case CLOCK_OSC_FREQ_12_0: /* OSC is 12Mhz */ - clock_set_rate(CLOCK_ID_PERIPH, 432, 12, 1, 8); - clock_set_rate(CLOCK_ID_CGENERAL, 600, 12, 0, 8); - break; - - case CLOCK_OSC_FREQ_26_0: /* OSC is 26Mhz */ - clock_set_rate(CLOCK_ID_PERIPH, 432, 26, 1, 8); - clock_set_rate(CLOCK_ID_CGENERAL, 600, 26, 0, 8); - break; - - case CLOCK_OSC_FREQ_13_0: /* OSC is 13Mhz */ - clock_set_rate(CLOCK_ID_PERIPH, 432, 13, 1, 8); - clock_set_rate(CLOCK_ID_CGENERAL, 600, 13, 0, 8); - break; - case CLOCK_OSC_FREQ_19_2: - default: - /* - * These are not supported. It is too early to print a - * message and the UART likely won't work anyway due to the - * oscillator being wrong. - */ - break; - } -} - -void clock_init(void) -{ - pll_rate[CLOCK_ID_MEMORY] = clock_get_rate(CLOCK_ID_MEMORY); - pll_rate[CLOCK_ID_PERIPH] = clock_get_rate(CLOCK_ID_PERIPH); - pll_rate[CLOCK_ID_CGENERAL] = clock_get_rate(CLOCK_ID_CGENERAL); - pll_rate[CLOCK_ID_OSC] = clock_get_rate(CLOCK_ID_OSC); - pll_rate[CLOCK_ID_SFROM32KHZ] = 32768; - debug("Osc = %d\n", pll_rate[CLOCK_ID_OSC]); - debug("PLLM = %d\n", pll_rate[CLOCK_ID_MEMORY]); - debug("PLLP = %d\n", pll_rate[CLOCK_ID_PERIPH]); -} diff --git a/arch/arm/cpu/armv7/tegra2/crypto.c b/arch/arm/cpu/armv7/tegra2/crypto.c deleted file mode 100644 index 5f0b240e27..0000000000 --- a/arch/arm/cpu/armv7/tegra2/crypto.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * (C) Copyright 2010 - 2011 NVIDIA Corporation <www.nvidia.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/errno.h> -#include "crypto.h" -#include "aes.h" - -static u8 zero_key[16]; - -#define AES_CMAC_CONST_RB 0x87 /* from RFC 4493, Figure 2.2 */ - -enum security_op { - SECURITY_SIGN = 1 << 0, /* Sign the data */ - SECURITY_ENCRYPT = 1 << 1, /* Encrypt the data */ -}; - -static void debug_print_vector(char *name, u32 num_bytes, u8 *data) -{ - u32 i; - - debug("%s [%d] @0x%08x", name, num_bytes, (u32)data); - for (i = 0; i < num_bytes; i++) { - if (i % 16 == 0) - debug(" = "); - debug("%02x", data[i]); - if ((i+1) % 16 != 0) - debug(" "); - } - debug("\n"); -} - -/** - * Apply chain data to the destination using EOR - * - * Each array is of length AES_AES_KEY_LENGTH. - * - * \param cbc_chain_data Chain data - * \param src Source data - * \param dst Destination data, which is modified here - */ -static void apply_cbc_chain_data(u8 *cbc_chain_data, u8 *src, u8 *dst) -{ - int i; - - for (i = 0; i < 16; i++) - *dst++ = *src++ ^ *cbc_chain_data++; -} - -/** - * Encrypt some data with AES. - * - * \param key_schedule Expanded key to use - * \param src Source data to encrypt - * \param dst Destination buffer - * \param num_aes_blocks Number of AES blocks to encrypt - */ -static void encrypt_object(u8 *key_schedule, u8 *src, u8 *dst, - u32 num_aes_blocks) -{ - u8 tmp_data[AES_KEY_LENGTH]; - u8 *cbc_chain_data; - u32 i; - - cbc_chain_data = zero_key; /* Convenient array of 0's for IV */ - - for (i = 0; i < num_aes_blocks; i++) { - debug("encrypt_object: block %d of %d\n", i, num_aes_blocks); - debug_print_vector("AES Src", AES_KEY_LENGTH, src); - - /* Apply the chain data */ - apply_cbc_chain_data(cbc_chain_data, src, tmp_data); - debug_print_vector("AES Xor", AES_KEY_LENGTH, tmp_data); - - /* encrypt the AES block */ - aes_encrypt(tmp_data, key_schedule, dst); - debug_print_vector("AES Dst", AES_KEY_LENGTH, dst); - - /* Update pointers for next loop. */ - cbc_chain_data = dst; - src += AES_KEY_LENGTH; - dst += AES_KEY_LENGTH; - } -} - -/** - * Shift a vector left by one bit - * - * \param in Input vector - * \param out Output vector - * \param size Length of vector in bytes - */ -static void left_shift_vector(u8 *in, u8 *out, int size) -{ - int carry = 0; - int i; - - for (i = size - 1; i >= 0; i--) { - out[i] = (in[i] << 1) | carry; - carry = in[i] >> 7; /* get most significant bit */ - } -} - -/** - * Sign a block of data, putting the result into dst. - * - * \param key Input AES key, length AES_KEY_LENGTH - * \param key_schedule Expanded key to use - * \param src Source data of length 'num_aes_blocks' blocks - * \param dst Destination buffer, length AES_KEY_LENGTH - * \param num_aes_blocks Number of AES blocks to encrypt - */ -static void sign_object(u8 *key, u8 *key_schedule, u8 *src, u8 *dst, - u32 num_aes_blocks) -{ - u8 tmp_data[AES_KEY_LENGTH]; - u8 left[AES_KEY_LENGTH]; - u8 k1[AES_KEY_LENGTH]; - u8 *cbc_chain_data; - unsigned i; - - cbc_chain_data = zero_key; /* Convenient array of 0's for IV */ - - /* compute K1 constant needed by AES-CMAC calculation */ - for (i = 0; i < AES_KEY_LENGTH; i++) - tmp_data[i] = 0; - - encrypt_object(key_schedule, tmp_data, left, 1); - debug_print_vector("AES(key, nonce)", AES_KEY_LENGTH, left); - - left_shift_vector(left, k1, sizeof(left)); - debug_print_vector("L", AES_KEY_LENGTH, left); - - if ((left[0] >> 7) != 0) /* get MSB of L */ - k1[AES_KEY_LENGTH-1] ^= AES_CMAC_CONST_RB; - debug_print_vector("K1", AES_KEY_LENGTH, k1); - - /* compute the AES-CMAC value */ - for (i = 0; i < num_aes_blocks; i++) { - /* Apply the chain data */ - apply_cbc_chain_data(cbc_chain_data, src, tmp_data); - - /* for the final block, XOR K1 into the IV */ - if (i == num_aes_blocks - 1) - apply_cbc_chain_data(tmp_data, k1, tmp_data); - - /* encrypt the AES block */ - aes_encrypt(tmp_data, key_schedule, dst); - - debug("sign_obj: block %d of %d\n", i, num_aes_blocks); - debug_print_vector("AES-CMAC Src", AES_KEY_LENGTH, src); - debug_print_vector("AES-CMAC Xor", AES_KEY_LENGTH, tmp_data); - debug_print_vector("AES-CMAC Dst", AES_KEY_LENGTH, dst); - - /* Update pointers for next loop. */ - cbc_chain_data = dst; - src += AES_KEY_LENGTH; - } - - debug_print_vector("AES-CMAC Hash", AES_KEY_LENGTH, dst); -} - -/** - * Encrypt and sign a block of data (depending on security mode). - * - * \param key Input AES key, length AES_KEY_LENGTH - * \param oper Security operations mask to perform (enum security_op) - * \param src Source data - * \param length Size of source data - * \param sig_dst Destination address for signature, AES_KEY_LENGTH bytes - */ -static int encrypt_and_sign(u8 *key, enum security_op oper, u8 *src, - u32 length, u8 *sig_dst) -{ - u32 num_aes_blocks; - u8 key_schedule[AES_EXPAND_KEY_LENGTH]; - - debug("encrypt_and_sign: length = %d\n", length); - debug_print_vector("AES key", AES_KEY_LENGTH, key); - - /* - * The only need for a key is for signing/checksum purposes, so - * if not encrypting, expand a key of 0s. - */ - aes_expand_key(oper & SECURITY_ENCRYPT ? key : zero_key, key_schedule); - - num_aes_blocks = (length + AES_KEY_LENGTH - 1) / AES_KEY_LENGTH; - - if (oper & SECURITY_ENCRYPT) { - /* Perform this in place, resulting in src being encrypted. */ - debug("encrypt_and_sign: begin encryption\n"); - encrypt_object(key_schedule, src, src, num_aes_blocks); - debug("encrypt_and_sign: end encryption\n"); - } - - if (oper & SECURITY_SIGN) { - /* encrypt the data, overwriting the result in signature. */ - debug("encrypt_and_sign: begin signing\n"); - sign_object(key, key_schedule, src, sig_dst, num_aes_blocks); - debug("encrypt_and_sign: end signing\n"); - } - - return 0; -} - -int sign_data_block(u8 *source, unsigned length, u8 *signature) -{ - return encrypt_and_sign(zero_key, SECURITY_SIGN, source, - length, signature); -} diff --git a/arch/arm/cpu/armv7/tegra2/crypto.h b/arch/arm/cpu/armv7/tegra2/crypto.h deleted file mode 100644 index aff67e77b0..0000000000 --- a/arch/arm/cpu/armv7/tegra2/crypto.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * (C) Copyright 2010 - 2011 NVIDIA Corporation <www.nvidia.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef _CRYPTO_H_ -#define _CRYPTO_H_ - -/** - * Sign a block of data - * - * \param source Source data - * \param length Size of source data - * \param signature Destination address for signature, AES_KEY_LENGTH bytes - */ -int sign_data_block(u8 *source, unsigned length, u8 *signature); - -#endif /* #ifndef _CRYPTO_H_ */ diff --git a/arch/arm/cpu/armv7/tegra2/emc.c b/arch/arm/cpu/armv7/tegra2/emc.c deleted file mode 100644 index c0e5c565f1..0000000000 --- a/arch/arm/cpu/armv7/tegra2/emc.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <fdtdec.h> -#include <asm/io.h> -#include <asm/arch/ap20.h> -#include <asm/arch/apb_misc.h> -#include <asm/arch/clock.h> -#include <asm/arch/emc.h> -#include <asm/arch/tegra2.h> - -/* - * The EMC registers have shadow registers. When the EMC clock is updated - * in the clock controller, the shadow registers are copied to the active - * registers, allowing glitchless memory bus frequency changes. - * This function updates the shadow registers for a new clock frequency, - * and relies on the clock lock on the emc clock to avoid races between - * multiple frequency changes - */ - -/* - * This table defines the ordering of the registers provided to - * tegra_set_mmc() - * TODO: Convert to fdt version once available - */ -static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = { - 0x2c, /* RC */ - 0x30, /* RFC */ - 0x34, /* RAS */ - 0x38, /* RP */ - 0x3c, /* R2W */ - 0x40, /* W2R */ - 0x44, /* R2P */ - 0x48, /* W2P */ - 0x4c, /* RD_RCD */ - 0x50, /* WR_RCD */ - 0x54, /* RRD */ - 0x58, /* REXT */ - 0x5c, /* WDV */ - 0x60, /* QUSE */ - 0x64, /* QRST */ - 0x68, /* QSAFE */ - 0x6c, /* RDV */ - 0x70, /* REFRESH */ - 0x74, /* BURST_REFRESH_NUM */ - 0x78, /* PDEX2WR */ - 0x7c, /* PDEX2RD */ - 0x80, /* PCHG2PDEN */ - 0x84, /* ACT2PDEN */ - 0x88, /* AR2PDEN */ - 0x8c, /* RW2PDEN */ - 0x90, /* TXSR */ - 0x94, /* TCKE */ - 0x98, /* TFAW */ - 0x9c, /* TRPAB */ - 0xa0, /* TCLKSTABLE */ - 0xa4, /* TCLKSTOP */ - 0xa8, /* TREFBW */ - 0xac, /* QUSE_EXTRA */ - 0x114, /* FBIO_CFG6 */ - 0xb0, /* ODT_WRITE */ - 0xb4, /* ODT_READ */ - 0x104, /* FBIO_CFG5 */ - 0x2bc, /* CFG_DIG_DLL */ - 0x2c0, /* DLL_XFORM_DQS */ - 0x2c4, /* DLL_XFORM_QUSE */ - 0x2e0, /* ZCAL_REF_CNT */ - 0x2e4, /* ZCAL_WAIT_CNT */ - 0x2a8, /* AUTO_CAL_INTERVAL */ - 0x2d0, /* CFG_CLKTRIM_0 */ - 0x2d4, /* CFG_CLKTRIM_1 */ - 0x2d8, /* CFG_CLKTRIM_2 */ -}; - -struct emc_ctlr *emc_get_controller(const void *blob) -{ - fdt_addr_t addr; - int node; - - node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_EMC); - if (node > 0) { - addr = fdtdec_get_addr(blob, node, "reg"); - if (addr != FDT_ADDR_T_NONE) - return (struct emc_ctlr *)addr; - } - return NULL; -} - -/* Error codes we use */ -enum { - ERR_NO_EMC_NODE = -10, - ERR_NO_EMC_REG, - ERR_NO_FREQ, - ERR_FREQ_NOT_FOUND, - ERR_BAD_REGS, - ERR_NO_RAM_CODE, - ERR_RAM_CODE_NOT_FOUND, -}; - -/** - * Find EMC tables for the given ram code. - * - * The tegra EMC binding has two options, one using the ram code and one not. - * We detect which is in use by looking for the nvidia,use-ram-code property. - * If this is not present, then the EMC tables are directly below 'node', - * otherwise we select the correct emc-tables subnode based on the 'ram_code' - * value. - * - * @param blob Device tree blob - * @param node EMC node (nvidia,tegra20-emc compatible string) - * @param ram_code RAM code to select (0-3, or -1 if unknown) - * @return 0 if ok, otherwise a -ve ERR_ code (see enum above) - */ -static int find_emc_tables(const void *blob, int node, int ram_code) -{ - int need_ram_code; - int depth; - int offset; - - /* If we are using RAM codes, scan through the tables for our code */ - need_ram_code = fdtdec_get_bool(blob, node, "nvidia,use-ram-code"); - if (!need_ram_code) - return node; - if (ram_code == -1) { - debug("%s: RAM code required but not supplied\n", __func__); - return ERR_NO_RAM_CODE; - } - - offset = node; - depth = 0; - do { - /* - * Sadly there is no compatible string so we cannot use - * fdtdec_next_compatible_subnode(). - */ - offset = fdt_next_node(blob, offset, &depth); - if (depth <= 0) - break; - - /* Make sure this is a direct subnode */ - if (depth != 1) - continue; - if (strcmp("emc-tables", fdt_get_name(blob, offset, NULL))) - continue; - - if (fdtdec_get_int(blob, offset, "nvidia,ram-code", -1) - == ram_code) - return offset; - } while (1); - - debug("%s: Could not find tables for RAM code %d\n", __func__, - ram_code); - return ERR_RAM_CODE_NOT_FOUND; -} - -/** - * Decode the EMC node of the device tree, returning a pointer to the emc - * controller and the table to be used for the given rate. - * - * @param blob Device tree blob - * @param rate Clock speed of memory controller in Hz (=2x memory bus rate) - * @param emcp Returns address of EMC controller registers - * @param tablep Returns pointer to table to program into EMC. There are - * TEGRA_EMC_NUM_REGS entries, destined for offsets as per the - * emc_reg_addr array. - * @return 0 if ok, otherwise a -ve error code which will allow someone to - * figure out roughly what went wrong by looking at this code. - */ -static int decode_emc(const void *blob, unsigned rate, struct emc_ctlr **emcp, - const u32 **tablep) -{ - struct apb_misc_pp_ctlr *pp = - (struct apb_misc_pp_ctlr *)NV_PA_APB_MISC_BASE; - int ram_code; - int depth; - int node; - - ram_code = (readl(&pp->strapping_opt_a) & RAM_CODE_MASK) - >> RAM_CODE_SHIFT; - /* - * The EMC clock rate is twice the bus rate, and the bus rate is - * measured in kHz - */ - rate = rate / 2 / 1000; - - node = fdtdec_next_compatible(blob, 0, COMPAT_NVIDIA_TEGRA20_EMC); - if (node < 0) { - debug("%s: No EMC node found in FDT\n", __func__); - return ERR_NO_EMC_NODE; - } - *emcp = (struct emc_ctlr *)fdtdec_get_addr(blob, node, "reg"); - if (*emcp == (struct emc_ctlr *)FDT_ADDR_T_NONE) { - debug("%s: No EMC node reg property\n", __func__); - return ERR_NO_EMC_REG; - } - - /* Work out the parent node which contains our EMC tables */ - node = find_emc_tables(blob, node, ram_code & 3); - if (node < 0) - return node; - - depth = 0; - for (;;) { - int node_rate; - - node = fdtdec_next_compatible_subnode(blob, node, - COMPAT_NVIDIA_TEGRA20_EMC_TABLE, &depth); - if (node < 0) - break; - node_rate = fdtdec_get_int(blob, node, "clock-frequency", -1); - if (node_rate == -1) { - debug("%s: Missing clock-frequency\n", __func__); - return ERR_NO_FREQ; /* we expect this property */ - } - - if (node_rate == rate) - break; - } - if (node < 0) { - debug("%s: No node found for clock frequency %d\n", __func__, - rate); - return ERR_FREQ_NOT_FOUND; - } - - *tablep = fdtdec_locate_array(blob, node, "nvidia,emc-registers", - TEGRA_EMC_NUM_REGS); - if (!*tablep) { - debug("%s: node '%s' array missing / wrong size\n", __func__, - fdt_get_name(blob, node, NULL)); - return ERR_BAD_REGS; - } - - /* All seems well */ - return 0; -} - -int tegra_set_emc(const void *blob, unsigned rate) -{ - struct emc_ctlr *emc; - const u32 *table; - int err, i; - - err = decode_emc(blob, rate, &emc, &table); - if (err) { - debug("Warning: no valid EMC (%d), memory timings unset\n", - err); - return err; - } - - debug("%s: Table found, setting EMC values as follows:\n", __func__); - for (i = 0; i < TEGRA_EMC_NUM_REGS; i++) { - u32 value = fdt32_to_cpu(table[i]); - u32 addr = (uintptr_t)emc + emc_reg_addr[i]; - - debug(" %#x: %#x\n", addr, value); - writel(value, addr); - } - - /* trigger emc with new settings */ - clock_adjust_periph_pll_div(PERIPH_ID_EMC, CLOCK_ID_MEMORY, - clock_get_rate(CLOCK_ID_MEMORY), NULL); - debug("EMC clock set to %lu\n", - clock_get_periph_rate(PERIPH_ID_EMC, CLOCK_ID_MEMORY)); - - return 0; -} diff --git a/arch/arm/cpu/armv7/tegra2/funcmux.c b/arch/arm/cpu/armv7/tegra2/funcmux.c deleted file mode 100644 index 4a31a4cf0c..0000000000 --- a/arch/arm/cpu/armv7/tegra2/funcmux.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -/* Tegra2 high-level function multiplexing */ -#include <common.h> -#include <asm/arch/clock.h> -#include <asm/arch/funcmux.h> -#include <asm/arch/pinmux.h> - -int funcmux_select(enum periph_id id, int config) -{ - int bad_config = config != FUNCMUX_DEFAULT; - - switch (id) { - case PERIPH_ID_UART1: - switch (config) { - case FUNCMUX_UART1_IRRX_IRTX: - pinmux_set_func(PINGRP_IRRX, PMUX_FUNC_UARTA); - pinmux_set_func(PINGRP_IRTX, PMUX_FUNC_UARTA); - pinmux_tristate_disable(PINGRP_IRRX); - pinmux_tristate_disable(PINGRP_IRTX); - break; - case FUNCMUX_UART1_UAA_UAB: - pinmux_set_func(PINGRP_UAA, PMUX_FUNC_UARTA); - pinmux_set_func(PINGRP_UAB, PMUX_FUNC_UARTA); - pinmux_tristate_disable(PINGRP_UAA); - pinmux_tristate_disable(PINGRP_UAB); - bad_config = 0; - break; - case FUNCMUX_UART1_GPU: - pinmux_set_func(PINGRP_GPU, PMUX_FUNC_UARTA); - pinmux_tristate_disable(PINGRP_GPU); - bad_config = 0; - break; - case FUNCMUX_UART1_SDIO1: - pinmux_set_func(PINGRP_SDIO1, PMUX_FUNC_UARTA); - pinmux_tristate_disable(PINGRP_SDIO1); - bad_config = 0; - break; - } - if (!bad_config) { - /* - * Tegra appears to boot with function UARTA pre- - * selected on mux group SDB. If two mux groups are - * both set to the same function, it's unclear which - * group's pins drive the RX signals into the HW. - * For UARTA, SDB certainly overrides group IRTX in - * practice. To solve this, configure some alternative - * function on SDB to avoid the conflict. Also, tri- - * state the group to avoid driving any signal onto it - * until we know what's connected. - */ - pinmux_tristate_enable(PINGRP_SDB); - pinmux_set_func(PINGRP_SDB, PMUX_FUNC_SDIO3); - } - break; - - case PERIPH_ID_UART2: - if (config == FUNCMUX_UART2_IRDA) { - pinmux_set_func(PINGRP_UAD, PMUX_FUNC_IRDA); - pinmux_tristate_disable(PINGRP_UAD); - } - break; - - case PERIPH_ID_UART4: - if (config == FUNCMUX_UART4_GMC) { - pinmux_set_func(PINGRP_GMC, PMUX_FUNC_UARTD); - pinmux_tristate_disable(PINGRP_GMC); - } - break; - - case PERIPH_ID_DVC_I2C: - /* there is only one selection, pinmux_config is ignored */ - if (config == FUNCMUX_DVC_I2CP) { - pinmux_set_func(PINGRP_I2CP, PMUX_FUNC_I2C); - pinmux_tristate_disable(PINGRP_I2CP); - } - break; - - case PERIPH_ID_I2C1: - /* support pinmux_config of 0 for now, */ - if (config == FUNCMUX_I2C1_RM) { - pinmux_set_func(PINGRP_RM, PMUX_FUNC_I2C); - pinmux_tristate_disable(PINGRP_RM); - } - break; - case PERIPH_ID_I2C2: /* I2C2 */ - switch (config) { - case FUNCMUX_I2C2_DDC: /* DDC pin group, select I2C2 */ - pinmux_set_func(PINGRP_DDC, PMUX_FUNC_I2C2); - /* PTA to HDMI */ - pinmux_set_func(PINGRP_PTA, PMUX_FUNC_HDMI); - pinmux_tristate_disable(PINGRP_DDC); - break; - case FUNCMUX_I2C2_PTA: /* PTA pin group, select I2C2 */ - pinmux_set_func(PINGRP_PTA, PMUX_FUNC_I2C2); - /* set DDC_SEL to RSVDx (RSVD2 works for now) */ - pinmux_set_func(PINGRP_DDC, PMUX_FUNC_RSVD2); - pinmux_tristate_disable(PINGRP_PTA); - bad_config = 0; - break; - } - break; - case PERIPH_ID_I2C3: /* I2C3 */ - /* support pinmux_config of 0 for now */ - if (config == FUNCMUX_I2C3_DTF) { - pinmux_set_func(PINGRP_DTF, PMUX_FUNC_I2C3); - pinmux_tristate_disable(PINGRP_DTF); - } - break; - - case PERIPH_ID_SDMMC1: - if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) { - pinmux_set_func(PINGRP_SDIO1, PMUX_FUNC_SDIO1); - pinmux_tristate_disable(PINGRP_SDIO1); - } - break; - - case PERIPH_ID_SDMMC2: - if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) { - pinmux_set_func(PINGRP_DTA, PMUX_FUNC_SDIO2); - pinmux_set_func(PINGRP_DTD, PMUX_FUNC_SDIO2); - - pinmux_tristate_disable(PINGRP_DTA); - pinmux_tristate_disable(PINGRP_DTD); - } - break; - - case PERIPH_ID_SDMMC3: - switch (config) { - case FUNCMUX_SDMMC3_SDB_SLXA_8BIT: - pinmux_set_func(PINGRP_SLXA, PMUX_FUNC_SDIO3); - pinmux_set_func(PINGRP_SLXC, PMUX_FUNC_SDIO3); - pinmux_set_func(PINGRP_SLXD, PMUX_FUNC_SDIO3); - pinmux_set_func(PINGRP_SLXK, PMUX_FUNC_SDIO3); - - pinmux_tristate_disable(PINGRP_SLXA); - pinmux_tristate_disable(PINGRP_SLXC); - pinmux_tristate_disable(PINGRP_SLXD); - pinmux_tristate_disable(PINGRP_SLXK); - /* fall through */ - - case FUNCMUX_SDMMC3_SDB_4BIT: - pinmux_set_func(PINGRP_SDB, PMUX_FUNC_SDIO3); - pinmux_set_func(PINGRP_SDC, PMUX_FUNC_SDIO3); - pinmux_set_func(PINGRP_SDD, PMUX_FUNC_SDIO3); - - pinmux_tristate_disable(PINGRP_SDB); - pinmux_tristate_disable(PINGRP_SDC); - pinmux_tristate_disable(PINGRP_SDD); - bad_config = 0; - break; - } - break; - - case PERIPH_ID_SDMMC4: - switch (config) { - case FUNCMUX_SDMMC4_ATC_ATD_8BIT: - pinmux_set_func(PINGRP_ATC, PMUX_FUNC_SDIO4); - pinmux_set_func(PINGRP_ATD, PMUX_FUNC_SDIO4); - - pinmux_tristate_disable(PINGRP_ATC); - pinmux_tristate_disable(PINGRP_ATD); - break; - - case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT: - pinmux_set_func(PINGRP_GME, PMUX_FUNC_SDIO4); - pinmux_tristate_disable(PINGRP_GME); - /* fall through */ - - case FUNCMUX_SDMMC4_ATB_GMA_4_BIT: - pinmux_set_func(PINGRP_ATB, PMUX_FUNC_SDIO4); - pinmux_set_func(PINGRP_GMA, PMUX_FUNC_SDIO4); - - pinmux_tristate_disable(PINGRP_ATB); - pinmux_tristate_disable(PINGRP_GMA); - bad_config = 0; - break; - } - break; - - case PERIPH_ID_KBC: - if (config == FUNCMUX_DEFAULT) { - enum pmux_pingrp grp[] = {PINGRP_KBCA, PINGRP_KBCB, - PINGRP_KBCC, PINGRP_KBCD, PINGRP_KBCE, - PINGRP_KBCF}; - int i; - - for (i = 0; i < ARRAY_SIZE(grp); i++) { - pinmux_tristate_disable(grp[i]); - pinmux_set_func(grp[i], PMUX_FUNC_KBC); - pinmux_set_pullupdown(grp[i], PMUX_PULL_UP); - } - } - break; - - case PERIPH_ID_USB2: - if (config == FUNCMUX_USB2_ULPI) { - pinmux_set_func(PINGRP_UAA, PMUX_FUNC_ULPI); - pinmux_set_func(PINGRP_UAB, PMUX_FUNC_ULPI); - pinmux_set_func(PINGRP_UDA, PMUX_FUNC_ULPI); - - pinmux_tristate_disable(PINGRP_UAA); - pinmux_tristate_disable(PINGRP_UAB); - pinmux_tristate_disable(PINGRP_UDA); - } - break; - - case PERIPH_ID_SPI1: - if (config == FUNCMUX_SPI1_GMC_GMD) { - pinmux_set_func(PINGRP_GMC, PMUX_FUNC_SFLASH); - pinmux_set_func(PINGRP_GMD, PMUX_FUNC_SFLASH); - - pinmux_tristate_disable(PINGRP_GMC); - pinmux_tristate_disable(PINGRP_GMD); - } - break; - - default: - debug("%s: invalid periph_id %d", __func__, id); - return -1; - } - - if (bad_config) { - debug("%s: invalid config %d for periph_id %d", __func__, - config, id); - return -1; - } - - return 0; -} diff --git a/arch/arm/cpu/armv7/tegra2/pinmux.c b/arch/arm/cpu/armv7/tegra2/pinmux.c deleted file mode 100644 index b053f90608..0000000000 --- a/arch/arm/cpu/armv7/tegra2/pinmux.c +++ /dev/null @@ -1,572 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -/* Tegra2 pin multiplexing functions */ - -#include <asm/io.h> -#include <asm/arch/tegra2.h> -#include <asm/arch/pinmux.h> -#include <common.h> - - -/* - * This defines the order of the pin mux control bits in the registers. For - * some reason there is no correspendence between the tristate, pin mux and - * pullup/pulldown registers. - */ -enum pmux_ctlid { - /* 0: APB_MISC_PP_PIN_MUX_CTL_A_0 */ - MUXCTL_UAA, - MUXCTL_UAB, - MUXCTL_UAC, - MUXCTL_UAD, - MUXCTL_UDA, - MUXCTL_RESERVED5, - MUXCTL_ATE, - MUXCTL_RM, - - MUXCTL_ATB, - MUXCTL_RESERVED9, - MUXCTL_ATD, - MUXCTL_ATC, - MUXCTL_ATA, - MUXCTL_KBCF, - MUXCTL_KBCE, - MUXCTL_SDMMC1, - - /* 16: APB_MISC_PP_PIN_MUX_CTL_B_0 */ - MUXCTL_GMA, - MUXCTL_GMC, - MUXCTL_HDINT, - MUXCTL_SLXA, - MUXCTL_OWC, - MUXCTL_SLXC, - MUXCTL_SLXD, - MUXCTL_SLXK, - - MUXCTL_UCA, - MUXCTL_UCB, - MUXCTL_DTA, - MUXCTL_DTB, - MUXCTL_RESERVED28, - MUXCTL_DTC, - MUXCTL_DTD, - MUXCTL_DTE, - - /* 32: APB_MISC_PP_PIN_MUX_CTL_C_0 */ - MUXCTL_DDC, - MUXCTL_CDEV1, - MUXCTL_CDEV2, - MUXCTL_CSUS, - MUXCTL_I2CP, - MUXCTL_KBCA, - MUXCTL_KBCB, - MUXCTL_KBCC, - - MUXCTL_IRTX, - MUXCTL_IRRX, - MUXCTL_DAP1, - MUXCTL_DAP2, - MUXCTL_DAP3, - MUXCTL_DAP4, - MUXCTL_GMB, - MUXCTL_GMD, - - /* 48: APB_MISC_PP_PIN_MUX_CTL_D_0 */ - MUXCTL_GME, - MUXCTL_GPV, - MUXCTL_GPU, - MUXCTL_SPDO, - MUXCTL_SPDI, - MUXCTL_SDB, - MUXCTL_SDC, - MUXCTL_SDD, - - MUXCTL_SPIH, - MUXCTL_SPIG, - MUXCTL_SPIF, - MUXCTL_SPIE, - MUXCTL_SPID, - MUXCTL_SPIC, - MUXCTL_SPIB, - MUXCTL_SPIA, - - /* 64: APB_MISC_PP_PIN_MUX_CTL_E_0 */ - MUXCTL_LPW0, - MUXCTL_LPW1, - MUXCTL_LPW2, - MUXCTL_LSDI, - MUXCTL_LSDA, - MUXCTL_LSPI, - MUXCTL_LCSN, - MUXCTL_LDC, - - MUXCTL_LSCK, - MUXCTL_LSC0, - MUXCTL_LSC1, - MUXCTL_LHS, - MUXCTL_LVS, - MUXCTL_LM0, - MUXCTL_LM1, - MUXCTL_LVP0, - - /* 80: APB_MISC_PP_PIN_MUX_CTL_F_0 */ - MUXCTL_LD0, - MUXCTL_LD1, - MUXCTL_LD2, - MUXCTL_LD3, - MUXCTL_LD4, - MUXCTL_LD5, - MUXCTL_LD6, - MUXCTL_LD7, - - MUXCTL_LD8, - MUXCTL_LD9, - MUXCTL_LD10, - MUXCTL_LD11, - MUXCTL_LD12, - MUXCTL_LD13, - MUXCTL_LD14, - MUXCTL_LD15, - - /* 96: APB_MISC_PP_PIN_MUX_CTL_G_0 */ - MUXCTL_LD16, - MUXCTL_LD17, - MUXCTL_LHP1, - MUXCTL_LHP2, - MUXCTL_LVP1, - MUXCTL_LHP0, - MUXCTL_RESERVED102, - MUXCTL_LPP, - - MUXCTL_LDI, - MUXCTL_PMC, - MUXCTL_CRTP, - MUXCTL_PTA, - MUXCTL_RESERVED108, - MUXCTL_KBCD, - MUXCTL_GPU7, - MUXCTL_DTF, - - MUXCTL_NONE = -1, -}; - -/* - * And this defines the order of the pullup/pulldown controls which are again - * in a different order - */ -enum pmux_pullid { - /* 0: APB_MISC_PP_PULLUPDOWN_REG_A_0 */ - PUCTL_ATA, - PUCTL_ATB, - PUCTL_ATC, - PUCTL_ATD, - PUCTL_ATE, - PUCTL_DAP1, - PUCTL_DAP2, - PUCTL_DAP3, - - PUCTL_DAP4, - PUCTL_DTA, - PUCTL_DTB, - PUCTL_DTC, - PUCTL_DTD, - PUCTL_DTE, - PUCTL_DTF, - PUCTL_GPV, - - /* 16: APB_MISC_PP_PULLUPDOWN_REG_B_0 */ - PUCTL_RM, - PUCTL_I2CP, - PUCTL_PTA, - PUCTL_GPU7, - PUCTL_KBCA, - PUCTL_KBCB, - PUCTL_KBCC, - PUCTL_KBCD, - - PUCTL_SPDI, - PUCTL_SPDO, - PUCTL_GPSLXAU, - PUCTL_CRTP, - PUCTL_SLXC, - PUCTL_SLXD, - PUCTL_SLXK, - - /* 32: APB_MISC_PP_PULLUPDOWN_REG_C_0 */ - PUCTL_CDEV1, - PUCTL_CDEV2, - PUCTL_SPIA, - PUCTL_SPIB, - PUCTL_SPIC, - PUCTL_SPID, - PUCTL_SPIE, - PUCTL_SPIF, - - PUCTL_SPIG, - PUCTL_SPIH, - PUCTL_IRTX, - PUCTL_IRRX, - PUCTL_GME, - PUCTL_RESERVED45, - PUCTL_XM2D, - PUCTL_XM2C, - - /* 48: APB_MISC_PP_PULLUPDOWN_REG_D_0 */ - PUCTL_UAA, - PUCTL_UAB, - PUCTL_UAC, - PUCTL_UAD, - PUCTL_UCA, - PUCTL_UCB, - PUCTL_LD17, - PUCTL_LD19_18, - - PUCTL_LD21_20, - PUCTL_LD23_22, - PUCTL_LS, - PUCTL_LC, - PUCTL_CSUS, - PUCTL_DDRC, - PUCTL_SDC, - PUCTL_SDD, - - /* 64: APB_MISC_PP_PULLUPDOWN_REG_E_0 */ - PUCTL_KBCF, - PUCTL_KBCE, - PUCTL_PMCA, - PUCTL_PMCB, - PUCTL_PMCC, - PUCTL_PMCD, - PUCTL_PMCE, - PUCTL_CK32, - - PUCTL_UDA, - PUCTL_SDMMC1, - PUCTL_GMA, - PUCTL_GMB, - PUCTL_GMC, - PUCTL_GMD, - PUCTL_DDC, - PUCTL_OWC, - - PUCTL_NONE = -1 -}; - -struct tegra_pingroup_desc { - const char *name; - enum pmux_func funcs[4]; - enum pmux_func func_safe; - enum pmux_vddio vddio; - enum pmux_ctlid ctl_id; - enum pmux_pullid pull_id; -}; - - -/* Converts a pmux_pingrp number to a tristate register: 0=A, 1=B, 2=C, 3=D */ -#define TRISTATE_REG(pmux_pingrp) ((pmux_pingrp) >> 5) - -/* Mask value for a tristate (within TRISTATE_REG(id)) */ -#define TRISTATE_MASK(pmux_pingrp) (1 << ((pmux_pingrp) & 0x1f)) - -/* Converts a PUCTL id to a pull register: 0=A, 1=B...4=E */ -#define PULL_REG(pmux_pullid) ((pmux_pullid) >> 4) - -/* Converts a PUCTL id to a shift position */ -#define PULL_SHIFT(pmux_pullid) ((pmux_pullid << 1) & 0x1f) - -/* Converts a MUXCTL id to a ctl register: 0=A, 1=B...6=G */ -#define MUXCTL_REG(pmux_ctlid) ((pmux_ctlid) >> 4) - -/* Converts a MUXCTL id to a shift position */ -#define MUXCTL_SHIFT(pmux_ctlid) ((pmux_ctlid << 1) & 0x1f) - -/* Convenient macro for defining pin group properties */ -#define PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe, mux, pupd) \ - { \ - .vddio = PMUX_VDDIO_ ## vdd, \ - .funcs = { \ - PMUX_FUNC_ ## f0, \ - PMUX_FUNC_ ## f1, \ - PMUX_FUNC_ ## f2, \ - PMUX_FUNC_ ## f3, \ - }, \ - .func_safe = PMUX_FUNC_ ## f_safe, \ - .ctl_id = mux, \ - .pull_id = pupd \ - } - -/* A normal pin group where the mux name and pull-up name match */ -#define PIN(pg_name, vdd, f0, f1, f2, f3, f_safe) \ - PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe, \ - MUXCTL_ ## pg_name, PUCTL_ ## pg_name) - -/* A pin group where the pull-up name doesn't have a 1-1 mapping */ -#define PINP(pg_name, vdd, f0, f1, f2, f3, f_safe, pupd) \ - PINALL(pg_name, vdd, f0, f1, f2, f3, f_safe, \ - MUXCTL_ ## pg_name, PUCTL_ ## pupd) - -/* A pin group number which is not used */ -#define PIN_RESERVED \ - PIN(NONE, NONE, NONE, NONE, NONE, NONE, NONE) - -const struct tegra_pingroup_desc tegra_soc_pingroups[PINGRP_COUNT] = { - PIN(ATA, NAND, IDE, NAND, GMI, RSVD, IDE), - PIN(ATB, NAND, IDE, NAND, GMI, SDIO4, IDE), - PIN(ATC, NAND, IDE, NAND, GMI, SDIO4, IDE), - PIN(ATD, NAND, IDE, NAND, GMI, SDIO4, IDE), - PIN(CDEV1, AUDIO, OSC, PLLA_OUT, PLLM_OUT1, AUDIO_SYNC, OSC), - PIN(CDEV2, AUDIO, OSC, AHB_CLK, APB_CLK, PLLP_OUT4, OSC), - PIN(CSUS, VI, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK, - PLLC_OUT1), - PIN(DAP1, AUDIO, DAP1, RSVD, GMI, SDIO2, DAP1), - - PIN(DAP2, AUDIO, DAP2, TWC, RSVD, GMI, DAP2), - PIN(DAP3, BB, DAP3, RSVD, RSVD, RSVD, DAP3), - PIN(DAP4, UART, DAP4, RSVD, GMI, RSVD, DAP4), - PIN(DTA, VI, RSVD, SDIO2, VI, RSVD, RSVD4), - PIN(DTB, VI, RSVD, RSVD, VI, SPI1, RSVD1), - PIN(DTC, VI, RSVD, RSVD, VI, RSVD, RSVD1), - PIN(DTD, VI, RSVD, SDIO2, VI, RSVD, RSVD1), - PIN(DTE, VI, RSVD, RSVD, VI, SPI1, RSVD1), - - PINP(GPU, UART, PWM, UARTA, GMI, RSVD, RSVD4, - GPSLXAU), - PIN(GPV, SD, PCIE, RSVD, RSVD, RSVD, PCIE), - PIN(I2CP, SYS, I2C, RSVD, RSVD, RSVD, RSVD4), - PIN(IRTX, UART, UARTA, UARTB, GMI, SPI4, UARTB), - PIN(IRRX, UART, UARTA, UARTB, GMI, SPI4, UARTB), - PIN(KBCB, SYS, KBC, NAND, SDIO2, MIO, KBC), - PIN(KBCA, SYS, KBC, NAND, SDIO2, EMC_TEST0_DLL, KBC), - PINP(PMC, SYS, PWR_ON, PWR_INTR, RSVD, RSVD, PWR_ON, NONE), - - PIN(PTA, NAND, I2C2, HDMI, GMI, RSVD, RSVD4), - PIN(RM, UART, I2C, RSVD, RSVD, RSVD, RSVD4), - PIN(KBCE, SYS, KBC, NAND, OWR, RSVD, KBC), - PIN(KBCF, SYS, KBC, NAND, TRACE, MIO, KBC), - PIN(GMA, NAND, UARTE, SPI3, GMI, SDIO4, SPI3), - PIN(GMC, NAND, UARTD, SPI4, GMI, SFLASH, SPI4), - PIN(SDMMC1, BB, SDIO1, RSVD, UARTE, UARTA, RSVD2), - PIN(OWC, SYS, OWR, RSVD, RSVD, RSVD, OWR), - - PIN(GME, NAND, RSVD, DAP5, GMI, SDIO4, GMI), - PIN(SDC, SD, PWM, TWC, SDIO3, SPI3, TWC), - PIN(SDD, SD, UARTA, PWM, SDIO3, SPI3, PWM), - PIN_RESERVED, - PINP(SLXA, SD, PCIE, SPI4, SDIO3, SPI2, PCIE, CRTP), - PIN(SLXC, SD, SPDIF, SPI4, SDIO3, SPI2, SPI4), - PIN(SLXD, SD, SPDIF, SPI4, SDIO3, SPI2, SPI4), - PIN(SLXK, SD, PCIE, SPI4, SDIO3, SPI2, PCIE), - - PIN(SPDI, AUDIO, SPDIF, RSVD, I2C, SDIO2, RSVD2), - PIN(SPDO, AUDIO, SPDIF, RSVD, I2C, SDIO2, RSVD2), - PIN(SPIA, AUDIO, SPI1, SPI2, SPI3, GMI, GMI), - PIN(SPIB, AUDIO, SPI1, SPI2, SPI3, GMI, GMI), - PIN(SPIC, AUDIO, SPI1, SPI2, SPI3, GMI, GMI), - PIN(SPID, AUDIO, SPI2, SPI1, SPI2_ALT, GMI, GMI), - PIN(SPIE, AUDIO, SPI2, SPI1, SPI2_ALT, GMI, GMI), - PIN(SPIF, AUDIO, SPI3, SPI1, SPI2, RSVD, RSVD4), - - PIN(SPIG, AUDIO, SPI3, SPI2, SPI2_ALT, I2C, SPI2_ALT), - PIN(SPIH, AUDIO, SPI3, SPI2, SPI2_ALT, I2C, SPI2_ALT), - PIN(UAA, BB, SPI3, MIPI_HS, UARTA, ULPI, MIPI_HS), - PIN(UAB, BB, SPI2, MIPI_HS, UARTA, ULPI, MIPI_HS), - PIN(UAC, BB, OWR, RSVD, RSVD, RSVD, RSVD4), - PIN(UAD, UART, IRDA, SPDIF, UARTA, SPI4, SPDIF), - PIN(UCA, UART, UARTC, RSVD, GMI, RSVD, RSVD4), - PIN(UCB, UART, UARTC, PWM, GMI, RSVD, RSVD4), - - PIN_RESERVED, - PIN(ATE, NAND, IDE, NAND, GMI, RSVD, IDE), - PIN(KBCC, SYS, KBC, NAND, TRACE, EMC_TEST1_DLL, KBC), - PIN_RESERVED, - PIN_RESERVED, - PIN(GMB, NAND, IDE, NAND, GMI, GMI_INT, GMI), - PIN(GMD, NAND, RSVD, NAND, GMI, SFLASH, GMI), - PIN(DDC, LCD, I2C2, RSVD, RSVD, RSVD, RSVD4), - - /* 64 */ - PINP(LD0, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - PINP(LD1, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - PINP(LD2, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - PINP(LD3, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - PINP(LD4, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - PINP(LD5, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - PINP(LD6, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - PINP(LD7, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - - PINP(LD8, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - PINP(LD9, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - PINP(LD10, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - PINP(LD11, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - PINP(LD12, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - PINP(LD13, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - PINP(LD14, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - PINP(LD15, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - - PINP(LD16, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LD17), - PINP(LD17, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD17), - PINP(LHP0, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD21_20), - PINP(LHP1, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD19_18), - PINP(LHP2, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD19_18), - PINP(LVP0, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LC), - PINP(LVP1, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD21_20), - PINP(HDINT, LCD, HDMI, RSVD, RSVD, RSVD, HDMI , LC), - - PINP(LM0, LCD, DISPA, DISPB, SPI3, RSVD, RSVD4, LC), - PINP(LM1, LCD, DISPA, DISPB, RSVD, CRT, RSVD3, LC), - PINP(LVS, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LC), - PINP(LSC0, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LC), - PINP(LSC1, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS), - PINP(LSCK, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS), - PINP(LDC, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LS), - PINP(LCSN, LCD, DISPA, DISPB, SPI3, RSVD, RSVD4, LS), - - /* 96 */ - PINP(LSPI, LCD, DISPA, DISPB, XIO, HDMI, DISPA, LC), - PINP(LSDA, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS), - PINP(LSDI, LCD, DISPA, DISPB, SPI3, RSVD, DISPA, LS), - PINP(LPW0, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS), - PINP(LPW1, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LS), - PINP(LPW2, LCD, DISPA, DISPB, SPI3, HDMI, DISPA, LS), - PINP(LDI, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD23_22), - PINP(LHS, LCD, DISPA, DISPB, XIO, RSVD, RSVD4, LC), - - PINP(LPP, LCD, DISPA, DISPB, RSVD, RSVD, RSVD4, LD23_22), - PIN_RESERVED, - PIN(KBCD, SYS, KBC, NAND, SDIO2, MIO, KBC), - PIN(GPU7, SYS, RTCK, RSVD, RSVD, RSVD, RTCK), - PIN(DTF, VI, I2C3, RSVD, VI, RSVD, RSVD4), - PIN(UDA, BB, SPI1, RSVD, UARTD, ULPI, RSVD2), - PIN(CRTP, LCD, CRT, RSVD, RSVD, RSVD, RSVD), - PINP(SDB, SD, UARTA, PWM, SDIO3, SPI2, PWM, NONE), - - /* these pin groups only have pullup and pull down control */ - PINALL(CK32, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, - PUCTL_NONE), - PINALL(DDRC, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, - PUCTL_NONE), - PINALL(PMCA, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, - PUCTL_NONE), - PINALL(PMCB, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, - PUCTL_NONE), - PINALL(PMCC, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, - PUCTL_NONE), - PINALL(PMCD, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, - PUCTL_NONE), - PINALL(PMCE, SYS, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, - PUCTL_NONE), - PINALL(XM2C, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, - PUCTL_NONE), - PINALL(XM2D, DDR, RSVD, RSVD, RSVD, RSVD, RSVD, MUXCTL_NONE, - PUCTL_NONE), -}; - -void pinmux_set_tristate(enum pmux_pingrp pin, int enable) -{ - struct pmux_tri_ctlr *pmt = - (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; - u32 *tri = &pmt->pmt_tri[TRISTATE_REG(pin)]; - u32 reg; - - reg = readl(tri); - if (enable) - reg |= TRISTATE_MASK(pin); - else - reg &= ~TRISTATE_MASK(pin); - writel(reg, tri); -} - -void pinmux_tristate_enable(enum pmux_pingrp pin) -{ - pinmux_set_tristate(pin, 1); -} - -void pinmux_tristate_disable(enum pmux_pingrp pin) -{ - pinmux_set_tristate(pin, 0); -} - -void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd) -{ - struct pmux_tri_ctlr *pmt = - (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; - enum pmux_pullid pull_id = tegra_soc_pingroups[pin].pull_id; - u32 *pull = &pmt->pmt_pull[PULL_REG(pull_id)]; - u32 mask_bit; - u32 reg; - mask_bit = PULL_SHIFT(pull_id); - - reg = readl(pull); - reg &= ~(0x3 << mask_bit); - reg |= pupd << mask_bit; - writel(reg, pull); -} - -void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func) -{ - struct pmux_tri_ctlr *pmt = - (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; - enum pmux_ctlid mux_id = tegra_soc_pingroups[pin].ctl_id; - u32 *muxctl = &pmt->pmt_ctl[MUXCTL_REG(mux_id)]; - u32 mask_bit; - int i, mux = -1; - u32 reg; - - assert(pmux_func_isvalid(func)); - - /* Handle special values */ - if (func >= PMUX_FUNC_RSVD1) { - mux = (func - PMUX_FUNC_RSVD1) & 0x3; - } else { - /* Search for the appropriate function */ - for (i = 0; i < 4; i++) { - if (tegra_soc_pingroups[pin].funcs[i] == func) { - mux = i; - break; - } - } - } - assert(mux != -1); - - mask_bit = MUXCTL_SHIFT(mux_id); - reg = readl(muxctl); - reg &= ~(0x3 << mask_bit); - reg |= mux << mask_bit; - writel(reg, muxctl); -} - -void pinmux_config_pingroup(struct pingroup_config *config) -{ - enum pmux_pingrp pin = config->pingroup; - - pinmux_set_func(pin, config->func); - pinmux_set_pullupdown(pin, config->pull); - pinmux_set_tristate(pin, config->tristate); -} - -void pinmux_config_table(struct pingroup_config *config, int len) -{ - int i; - - for (i = 0; i < len; i++) - pinmux_config_pingroup(&config[i]); -} diff --git a/arch/arm/cpu/armv7/tegra2/pmu.c b/arch/arm/cpu/armv7/tegra2/pmu.c deleted file mode 100644 index 46738023ff..0000000000 --- a/arch/arm/cpu/armv7/tegra2/pmu.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * (C) Copyright 2010,2011 NVIDIA Corporation <www.nvidia.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <tps6586x.h> -#include <asm/io.h> -#include <asm/arch/ap20.h> -#include <asm/arch/tegra2.h> -#include <asm/arch/tegra_i2c.h> -#include <asm/arch/sys_proto.h> - -#define VDD_CORE_NOMINAL_T25 0x17 /* 1.3v */ -#define VDD_CPU_NOMINAL_T25 0x10 /* 1.125v */ - -#define VDD_CORE_NOMINAL_T20 0x16 /* 1.275v */ -#define VDD_CPU_NOMINAL_T20 0x0f /* 1.1v */ - -#define VDD_RELATION 0x02 /* 50mv */ -#define VDD_TRANSITION_STEP 0x06 /* 150mv */ -#define VDD_TRANSITION_RATE 0x06 /* 3.52mv/us */ - -int pmu_set_nominal(void) -{ - int core, cpu, bus; - - /* by default, the table has been filled with T25 settings */ - switch (tegra_get_chip_type()) { - case TEGRA_SOC_T20: - core = VDD_CORE_NOMINAL_T20; - cpu = VDD_CPU_NOMINAL_T20; - break; - case TEGRA_SOC_T25: - core = VDD_CORE_NOMINAL_T25; - cpu = VDD_CPU_NOMINAL_T25; - break; - default: - debug("%s: Unknown chip type\n", __func__); - return -1; - } - - bus = tegra_i2c_get_dvc_bus_num(); - if (bus == -1) { - debug("%s: Cannot find DVC I2C bus\n", __func__); - return -1; - } - tps6586x_init(bus); - tps6586x_set_pwm_mode(TPS6586X_PWM_SM1); - return tps6586x_adjust_sm0_sm1(core, cpu, VDD_TRANSITION_STEP, - VDD_TRANSITION_RATE, VDD_RELATION); -} diff --git a/arch/arm/cpu/armv7/tegra2/sys_info.c b/arch/arm/cpu/armv7/tegra2/sys_info.c deleted file mode 100644 index 6d11dc16bf..0000000000 --- a/arch/arm/cpu/armv7/tegra2/sys_info.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * (C) Copyright 2010,2011 - * NVIDIA Corporation <www.nvidia.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> - -#ifdef CONFIG_DISPLAY_CPUINFO -/* Print CPU information */ -int print_cpuinfo(void) -{ - puts("TEGRA2\n"); - - /* TBD: Add printf of major/minor rev info, stepping, etc. */ - return 0; -} -#endif /* CONFIG_DISPLAY_CPUINFO */ diff --git a/arch/arm/cpu/armv7/tegra2/timer.c b/arch/arm/cpu/armv7/tegra2/timer.c deleted file mode 100644 index b12b12cc30..0000000000 --- a/arch/arm/cpu/armv7/tegra2/timer.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * (C) Copyright 2010,2011 - * NVIDIA Corporation <www.nvidia.com> - * - * (C) Copyright 2008 - * Texas Instruments - * - * Richard Woodruff <r-woodruff2@ti.com> - * Syed Moahmmed Khasim <khasim@ti.com> - * - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Marius Groeger <mgroeger@sysgo.de> - * Alex Zuepke <azu@sysgo.de> - * - * (C) Copyright 2002 - * Gary Jennejohn, DENX Software Engineering, <garyj@denx.de> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/io.h> -#include <asm/arch/tegra2.h> -#include <asm/arch/timer.h> - -DECLARE_GLOBAL_DATA_PTR; - -/* counter runs at 1MHz */ -#define TIMER_CLK 1000000 -#define TIMER_LOAD_VAL 0xffffffff - -/* timer without interrupts */ -ulong get_timer(ulong base) -{ - return get_timer_masked() - base; -} - -/* delay x useconds */ -void __udelay(unsigned long usec) -{ - long tmo = usec * (TIMER_CLK / 1000) / 1000; - unsigned long now, last = timer_get_us(); - - while (tmo > 0) { - now = timer_get_us(); - if (last > now) /* count up timer overflow */ - tmo -= TIMER_LOAD_VAL - last + now; - else - tmo -= now - last; - last = now; - } -} - -ulong get_timer_masked(void) -{ - ulong now; - - /* current tick value */ - now = timer_get_us() / (TIMER_CLK / CONFIG_SYS_HZ); - - if (now >= gd->lastinc) /* normal mode (non roll) */ - /* move stamp forward with absolute diff ticks */ - gd->tbl += (now - gd->lastinc); - else /* we have rollover of incrementer */ - gd->tbl += ((TIMER_LOAD_VAL / (TIMER_CLK / CONFIG_SYS_HZ)) - - gd->lastinc) + now; - gd->lastinc = now; - return gd->tbl; -} - -/* - * This function is derived from PowerPC code (read timebase as long long). - * On ARM it just returns the timer value. - */ -unsigned long long get_ticks(void) -{ - return get_timer(0); -} - -/* - * This function is derived from PowerPC code (timebase clock frequency). - * On ARM it returns the number of timer ticks per second. - */ -ulong get_tbclk(void) -{ - return CONFIG_SYS_HZ; -} - -unsigned long timer_get_us(void) -{ - struct timerus *timer_base = (struct timerus *)NV_PA_TMRUS_BASE; - - return readl(&timer_base->cntr_1us); -} diff --git a/arch/arm/cpu/armv7/tegra2/warmboot.c b/arch/arm/cpu/armv7/tegra2/warmboot.c deleted file mode 100644 index 25d896888a..0000000000 --- a/arch/arm/cpu/armv7/tegra2/warmboot.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * (C) Copyright 2010 - 2011 - * NVIDIA Corporation <www.nvidia.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/io.h> -#include <asm/errno.h> -#include <asm/arch/ap20.h> -#include <asm/arch/clk_rst.h> -#include <asm/arch/clock.h> -#include <asm/arch/pmc.h> -#include <asm/arch/pinmux.h> -#include <asm/arch/tegra2.h> -#include <asm/arch/fuse.h> -#include <asm/arch/emc.h> -#include <asm/arch/gp_padctrl.h> -#include <asm/arch/warmboot.h> -#include <asm/arch/sdram_param.h> - -DECLARE_GLOBAL_DATA_PTR; - -#ifndef CONFIG_TEGRA_CLOCK_SCALING -#error "You must enable CONFIG_TEGRA_CLOCK_SCALING to use CONFIG_TEGRA2_LP0" -#endif - -/* - * This is the place in SRAM where the SDRAM parameters are stored. There - * are 4 blocks, one for each RAM code - */ -#define SDRAM_PARAMS_BASE (AP20_BASE_PA_SRAM + 0x188) - -/* TODO: If we later add support for the Misc GP controller, refactor this */ -union xm2cfga_reg { - struct { - u32 reserved0:2; - u32 hsm_en:1; - u32 reserved1:2; - u32 preemp_en:1; - u32 vref_en:1; - u32 reserved2:5; - u32 cal_drvdn:5; - u32 reserved3:3; - u32 cal_drvup:5; - u32 reserved4:3; - u32 cal_drvdn_slwr:2; - u32 cal_drvup_slwf:2; - }; - u32 word; -}; - -union xm2cfgd_reg { - struct { - u32 reserved0:2; - u32 hsm_en:1; - u32 schmt_en:1; - u32 lpmd:2; - u32 vref_en:1; - u32 reserved1:5; - u32 cal_drvdn:5; - u32 reserved2:3; - u32 cal_drvup:5; - u32 reserved3:3; - u32 cal_drvdn_slwr:2; - u32 cal_drvup_slwf:2; - }; - u32 word; -}; - -/* - * TODO: This register is not documented in the TRM yet. We could move this - * into the EMC and give it a proper interface, but not while it is - * undocumented. - */ -union fbio_spare_reg { - struct { - u32 reserved:24; - u32 cfg_wb0:8; - }; - u32 word; -}; - -/* We pack the resume information into these unions for later */ -union scratch2_reg { - struct { - u32 pllm_base_divm:5; - u32 pllm_base_divn:10; - u32 pllm_base_divp:3; - u32 pllm_misc_lfcon:4; - u32 pllm_misc_cpcon:4; - u32 gp_xm2cfga_padctrl_preemp:1; - u32 gp_xm2cfgd_padctrl_schmt:1; - u32 osc_ctrl_xobp:1; - u32 memory_type:3; - }; - u32 word; -}; - -union scratch4_reg { - struct { - u32 emc_clock_divider:8; - u32 pllm_stable_time:8; - u32 pllx_stable_time:8; - u32 emc_fbio_spare_cfg_wb0:8; - }; - u32 word; -}; - -union scratch24_reg { - struct { - u32 emc_auto_cal_wait:8; - u32 emc_pin_program_wait:8; - u32 warmboot_wait:8; - u32 reserved:8; - }; - u32 word; -}; - -int warmboot_save_sdram_params(void) -{ - u32 ram_code; - struct sdram_params sdram; - struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; - struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; - struct apb_misc_gp_ctlr *gp = - (struct apb_misc_gp_ctlr *)TEGRA2_APB_MISC_GP_BASE; - struct emc_ctlr *emc = emc_get_controller(gd->fdt_blob); - union scratch2_reg scratch2; - union scratch4_reg scratch4; - union scratch24_reg scratch24; - union xm2cfga_reg xm2cfga; - union xm2cfgd_reg xm2cfgd; - union fbio_spare_reg fbio_spare; - - /* get ram code that is used as index to array sdram_params in BCT */ - ram_code = (readl(&pmt->pmt_strap_opt_a) >> - STRAP_OPT_A_RAM_CODE_SHIFT) & 3; - memcpy(&sdram, - (char *)((struct sdram_params *)SDRAM_PARAMS_BASE + ram_code), - sizeof(sdram)); - - xm2cfga.word = readl(&gp->xm2cfga); - xm2cfgd.word = readl(&gp->xm2cfgd); - - scratch2.word = 0; - scratch2.osc_ctrl_xobp = clock_get_osc_bypass(); - - /* Get the memory PLL settings */ - { - u32 divm, divn, divp, cpcon, lfcon; - - if (clock_ll_read_pll(CLOCK_ID_MEMORY, &divm, &divn, &divp, - &cpcon, &lfcon)) - return -1; - scratch2.pllm_base_divm = divm; - scratch2.pllm_base_divn = divn; - scratch2.pllm_base_divp = divp; - scratch2.pllm_misc_cpcon = cpcon; - scratch2.pllm_misc_lfcon = lfcon; - } - - scratch2.gp_xm2cfga_padctrl_preemp = xm2cfga.preemp_en; - scratch2.gp_xm2cfgd_padctrl_schmt = xm2cfgd.schmt_en; - scratch2.memory_type = sdram.memory_type; - writel(scratch2.word, &pmc->pmc_scratch2); - - /* collect data from various sources for pmc_scratch4 */ - fbio_spare.word = readl(&emc->fbio_spare); - scratch4.word = 0; - scratch4.emc_fbio_spare_cfg_wb0 = fbio_spare.cfg_wb0; - scratch4.emc_clock_divider = sdram.emc_clock_divider; - scratch4.pllm_stable_time = -1; - scratch4.pllx_stable_time = -1; - writel(scratch4.word, &pmc->pmc_scratch4); - - /* collect various data from sdram for pmc_scratch24 */ - scratch24.word = 0; - scratch24.emc_pin_program_wait = sdram.emc_pin_program_wait; - scratch24.emc_auto_cal_wait = sdram.emc_auto_cal_wait; - scratch24.warmboot_wait = sdram.warm_boot_wait; - writel(scratch24.word, &pmc->pmc_scratch24); - - return 0; -} - -static u32 get_major_version(void) -{ - u32 major_id; - struct apb_misc_gp_ctlr *gp = - (struct apb_misc_gp_ctlr *)TEGRA2_APB_MISC_GP_BASE; - - major_id = (readl(&gp->hidrev) & HIDREV_MAJORPREV_MASK) >> - HIDREV_MAJORPREV_SHIFT; - return major_id; -} - -static int is_production_mode_fuse_set(struct fuse_regs *fuse) -{ - return readl(&fuse->production_mode); -} - -static int is_odm_production_mode_fuse_set(struct fuse_regs *fuse) -{ - return readl(&fuse->security_mode); -} - -static int is_failure_analysis_mode(struct fuse_regs *fuse) -{ - return readl(&fuse->fa); -} - -static int ap20_is_odm_production_mode(void) -{ - struct fuse_regs *fuse = (struct fuse_regs *)TEGRA2_FUSE_BASE; - - if (!is_failure_analysis_mode(fuse) && - is_odm_production_mode_fuse_set(fuse)) - return 1; - else - return 0; -} - -static int ap20_is_production_mode(void) -{ - struct fuse_regs *fuse = (struct fuse_regs *)TEGRA2_FUSE_BASE; - - if (get_major_version() == 0) - return 1; - - if (!is_failure_analysis_mode(fuse) && - is_production_mode_fuse_set(fuse) && - !is_odm_production_mode_fuse_set(fuse)) - return 1; - else - return 0; -} - -static enum fuse_operating_mode fuse_get_operation_mode(void) -{ - u32 chip_id; - struct apb_misc_gp_ctlr *gp = - (struct apb_misc_gp_ctlr *)TEGRA2_APB_MISC_GP_BASE; - - chip_id = (readl(&gp->hidrev) & HIDREV_CHIPID_MASK) >> - HIDREV_CHIPID_SHIFT; - if (chip_id == CHIPID_TEGRA2) { - if (ap20_is_odm_production_mode()) { - printf("!! odm_production_mode is not supported !!\n"); - return MODE_UNDEFINED; - } else - if (ap20_is_production_mode()) - return MODE_PRODUCTION; - else - return MODE_UNDEFINED; - } - return MODE_UNDEFINED; -} - -static void determine_crypto_options(int *is_encrypted, int *is_signed, - int *use_zero_key) -{ - switch (fuse_get_operation_mode()) { - case MODE_PRODUCTION: - *is_encrypted = 0; - *is_signed = 1; - *use_zero_key = 1; - break; - case MODE_UNDEFINED: - default: - *is_encrypted = 0; - *is_signed = 0; - *use_zero_key = 0; - break; - } -} - -static int sign_wb_code(u32 start, u32 length, int use_zero_key) -{ - int err; - u8 *source; /* Pointer to source */ - u8 *hash; - - /* Calculate AES block parameters. */ - source = (u8 *)(start + offsetof(struct wb_header, random_aes_block)); - length -= offsetof(struct wb_header, random_aes_block); - hash = (u8 *)(start + offsetof(struct wb_header, hash)); - err = sign_data_block(source, length, hash); - - return err; -} - -int warmboot_prepare_code(u32 seg_address, u32 seg_length) -{ - int err = 0; - u32 length; /* length of the signed/encrypt code */ - struct wb_header *dst_header; /* Pointer to dest WB header */ - int is_encrypted; /* Segment is encrypted */ - int is_signed; /* Segment is signed */ - int use_zero_key; /* Use key of all zeros */ - - /* Determine crypto options. */ - determine_crypto_options(&is_encrypted, &is_signed, &use_zero_key); - - /* Get the actual code limits. */ - length = roundup(((u32)wb_end - (u32)wb_start), 16); - - /* - * The region specified by seg_address must be in SDRAM and must be - * nonzero in length. - */ - if (seg_length == 0 || seg_address < NV_PA_SDRAM_BASE || - seg_address + seg_length >= NV_PA_SDRAM_BASE + gd->ram_size) { - err = -EFAULT; - goto fail; - } - - /* Things must be 16-byte aligned. */ - if ((seg_length & 0xF) || (seg_address & 0xF)) { - err = -EINVAL; - goto fail; - } - - /* Will the code fit? (destination includes wb_header + wb code) */ - if (seg_length < (length + sizeof(struct wb_header))) { - err = -EINVAL; - goto fail; - } - - dst_header = (struct wb_header *)seg_address; - memset((char *)dst_header, 0, sizeof(struct wb_header)); - - /* Populate the random_aes_block as requested. */ - { - u32 *aes_block = (u32 *)&(dst_header->random_aes_block); - u32 *end = (u32 *)(((u32)aes_block) + - sizeof(dst_header->random_aes_block)); - - do { - *aes_block++ = 0; - } while (aes_block < end); - } - - /* Populate the header. */ - dst_header->length_insecure = length + sizeof(struct wb_header); - dst_header->length_secure = length + sizeof(struct wb_header); - dst_header->destination = AP20_WB_RUN_ADDRESS; - dst_header->entry_point = AP20_WB_RUN_ADDRESS; - dst_header->code_length = length; - - if (is_encrypted) { - printf("!!!! Encryption is not supported !!!!\n"); - dst_header->length_insecure = 0; - err = -EACCES; - goto fail; - } else - /* copy the wb code directly following dst_header. */ - memcpy((char *)(dst_header+1), (char *)wb_start, length); - - if (is_signed) - err = sign_wb_code(seg_address, dst_header->length_insecure, - use_zero_key); - -fail: - if (err) - printf("Warning: warmboot code copy failed (error=%d)\n", err); - - return err; -} diff --git a/arch/arm/cpu/armv7/tegra2/warmboot_avp.c b/arch/arm/cpu/armv7/tegra2/warmboot_avp.c deleted file mode 100644 index 70bcd8e5f3..0000000000 --- a/arch/arm/cpu/armv7/tegra2/warmboot_avp.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * (C) Copyright 2010 - 2011 - * NVIDIA Corporation <www.nvidia.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#include <common.h> -#include <asm/io.h> -#include <asm/arch/ap20.h> -#include <asm/arch/clk_rst.h> -#include <asm/arch/clock.h> -#include <asm/arch/flow.h> -#include <asm/arch/pinmux.h> -#include <asm/arch/pmc.h> -#include <asm/arch/tegra2.h> -#include <asm/arch/warmboot.h> -#include "warmboot_avp.h" - -#define DEBUG_RESET_CORESIGHT - -void wb_start(void) -{ - struct pmux_tri_ctlr *pmt = (struct pmux_tri_ctlr *)NV_PA_APB_MISC_BASE; - struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; - struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE; - struct clk_rst_ctlr *clkrst = - (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE; - union osc_ctrl_reg osc_ctrl; - union pllx_base_reg pllx_base; - union pllx_misc_reg pllx_misc; - union scratch3_reg scratch3; - u32 reg; - - /* enable JTAG & TBE */ - writel(CONFIG_CTL_TBE | CONFIG_CTL_JTAG, &pmt->pmt_cfg_ctl); - - /* Are we running where we're supposed to be? */ - asm volatile ( - "adr %0, wb_start;" /* reg: wb_start address */ - : "=r"(reg) /* output */ - /* no input, no clobber list */ - ); - - if (reg != AP20_WB_RUN_ADDRESS) - goto do_reset; - - /* Are we running with AVP? */ - if (readl(NV_PA_PG_UP_BASE + PG_UP_TAG_0) != PG_UP_TAG_AVP) - goto do_reset; - -#ifdef DEBUG_RESET_CORESIGHT - /* Assert CoreSight reset */ - reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_U]); - reg |= SWR_CSITE_RST; - writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_U]); -#endif - - /* TODO: Set the drive strength - maybe make this a board parameter? */ - osc_ctrl.word = readl(&clkrst->crc_osc_ctrl); - osc_ctrl.xofs = 4; - osc_ctrl.xoe = 1; - writel(osc_ctrl.word, &clkrst->crc_osc_ctrl); - - /* Power up the CPU complex if necessary */ - if (!(readl(&pmc->pmc_pwrgate_status) & PWRGATE_STATUS_CPU)) { - reg = PWRGATE_TOGGLE_PARTID_CPU | PWRGATE_TOGGLE_START; - writel(reg, &pmc->pmc_pwrgate_toggle); - while (!(readl(&pmc->pmc_pwrgate_status) & PWRGATE_STATUS_CPU)) - ; - } - - /* Remove the I/O clamps from the CPU power partition. */ - reg = readl(&pmc->pmc_remove_clamping); - reg |= CPU_CLMP; - writel(reg, &pmc->pmc_remove_clamping); - - reg = EVENT_ZERO_VAL_20 | EVENT_MSEC | EVENT_MODE_STOP; - writel(reg, &flow->halt_cop_events); - - /* Assert CPU complex reset */ - reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]); - reg |= CPU_RST; - writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]); - - /* Hold both CPUs in reset */ - reg = CPU_CMPLX_CPURESET0 | CPU_CMPLX_CPURESET1 | CPU_CMPLX_DERESET0 | - CPU_CMPLX_DERESET1 | CPU_CMPLX_DBGRESET0 | CPU_CMPLX_DBGRESET1; - writel(reg, &clkrst->crc_cpu_cmplx_set); - - /* Halt CPU1 at the flow controller for uni-processor configurations */ - writel(EVENT_MODE_STOP, &flow->halt_cpu1_events); - - /* - * Set the CPU reset vector. SCRATCH41 contains the physical - * address of the CPU-side restoration code. - */ - reg = readl(&pmc->pmc_scratch41); - writel(reg, EXCEP_VECTOR_CPU_RESET_VECTOR); - - /* Select CPU complex clock source */ - writel(CCLK_PLLP_BURST_POLICY, &clkrst->crc_cclk_brst_pol); - - /* Start the CPU0 clock and stop the CPU1 clock */ - reg = CPU_CMPLX_CPU_BRIDGE_CLKDIV_4 | CPU_CMPLX_CPU0_CLK_STP_RUN | - CPU_CMPLX_CPU1_CLK_STP_STOP; - writel(reg, &clkrst->crc_clk_cpu_cmplx); - - /* Enable the CPU complex clock */ - reg = readl(&clkrst->crc_clk_out_enb[TEGRA_DEV_L]); - reg |= CLK_ENB_CPU; - writel(reg, &clkrst->crc_clk_out_enb[TEGRA_DEV_L]); - - /* Make sure the resets were held for at least 2 microseconds */ - reg = readl(TIMER_USEC_CNTR); - while (readl(TIMER_USEC_CNTR) <= (reg + 2)) - ; - -#ifdef DEBUG_RESET_CORESIGHT - /* - * De-assert CoreSight reset. - * NOTE: We're leaving the CoreSight clock on the oscillator for - * now. It will be restored to its original clock source - * when the CPU-side restoration code runs. - */ - reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_U]); - reg &= ~SWR_CSITE_RST; - writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_U]); -#endif - - /* Unlock the CPU CoreSight interfaces */ - reg = 0xC5ACCE55; - writel(reg, CSITE_CPU_DBG0_LAR); - writel(reg, CSITE_CPU_DBG1_LAR); - - /* - * Sample the microsecond timestamp again. This is the time we must - * use when returning from LP0 for PLL stabilization delays. - */ - reg = readl(TIMER_USEC_CNTR); - writel(reg, &pmc->pmc_scratch1); - - pllx_base.word = 0; - pllx_misc.word = 0; - scratch3.word = readl(&pmc->pmc_scratch3); - - /* Get the OSC. For 19.2 MHz, use 19 to make the calculations easier */ - reg = (readl(TIMER_USEC_CFG) & USEC_CFG_DIVISOR_MASK) + 1; - - /* - * According to the TRM, for 19.2MHz OSC, the USEC_DIVISOR is 0x5f, and - * USEC_DIVIDEND is 0x04. So, if USEC_DIVISOR > 26, OSC is 19.2 MHz. - * - * reg is used to calculate the pllx freq, which is used to determine if - * to set dccon or not. - */ - if (reg > 26) - reg = 19; - - /* PLLX_BASE.PLLX_DIVM */ - if (scratch3.pllx_base_divm == reg) - reg = 0; - else - reg = 1; - - /* PLLX_BASE.PLLX_DIVN */ - pllx_base.divn = scratch3.pllx_base_divn; - reg = scratch3.pllx_base_divn << reg; - - /* PLLX_BASE.PLLX_DIVP */ - pllx_base.divp = scratch3.pllx_base_divp; - reg = reg >> scratch3.pllx_base_divp; - - pllx_base.bypass = 1; - - /* PLLX_MISC_DCCON must be set for pllx frequency > 600 MHz. */ - if (reg > 600) - pllx_misc.dccon = 1; - - /* PLLX_MISC_LFCON */ - pllx_misc.lfcon = scratch3.pllx_misc_lfcon; - - /* PLLX_MISC_CPCON */ - pllx_misc.cpcon = scratch3.pllx_misc_cpcon; - - writel(pllx_misc.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_misc); - writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); - - pllx_base.enable = 1; - writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); - pllx_base.bypass = 0; - writel(pllx_base.word, &clkrst->crc_pll_simple[SIMPLE_PLLX].pll_base); - - writel(0, flow->halt_cpu_events); - - reg = CPU_CMPLX_CPURESET0 | CPU_CMPLX_DBGRESET0 | CPU_CMPLX_DERESET0; - writel(reg, &clkrst->crc_cpu_cmplx_clr); - - reg = PLLM_OUT1_RSTN_RESET_DISABLE | PLLM_OUT1_CLKEN_ENABLE | - PLLM_OUT1_RATIO_VAL_8; - writel(reg, &clkrst->crc_pll[CLOCK_ID_MEMORY].pll_out); - - reg = SCLK_SWAKE_FIQ_SRC_PLLM_OUT1 | SCLK_SWAKE_IRQ_SRC_PLLM_OUT1 | - SCLK_SWAKE_RUN_SRC_PLLM_OUT1 | SCLK_SWAKE_IDLE_SRC_PLLM_OUT1 | - SCLK_SYS_STATE_IDLE; - writel(reg, &clkrst->crc_sclk_brst_pol); - - /* avp_resume: no return after the write */ - reg = readl(&clkrst->crc_rst_dev[TEGRA_DEV_L]); - reg &= ~CPU_RST; - writel(reg, &clkrst->crc_rst_dev[TEGRA_DEV_L]); - - /* avp_halt: */ -avp_halt: - reg = EVENT_MODE_STOP | EVENT_JTAG; - writel(reg, flow->halt_cop_events); - goto avp_halt; - -do_reset: - /* - * Execution comes here if something goes wrong. The chip is reset and - * a cold boot is performed. - */ - writel(SWR_TRIG_SYS_RST, &clkrst->crc_rst_dev[TEGRA_DEV_L]); - goto do_reset; -} - -/* - * wb_end() is a dummy function, and must be directly following wb_start(), - * and is used to calculate the size of wb_start(). - */ -void wb_end(void) -{ -} diff --git a/arch/arm/cpu/armv7/tegra2/warmboot_avp.h b/arch/arm/cpu/armv7/tegra2/warmboot_avp.h deleted file mode 100644 index 4b71c07843..0000000000 --- a/arch/arm/cpu/armv7/tegra2/warmboot_avp.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * (C) Copyright 2010, 2011 - * NVIDIA Corporation <www.nvidia.com> - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ - -#ifndef _WARMBOOT_AVP_H_ -#define _WARMBOOT_AVP_H_ - -#define TEGRA_DEV_L 0 -#define TEGRA_DEV_H 1 -#define TEGRA_DEV_U 2 - -#define SIMPLE_PLLX (CLOCK_ID_XCPU - CLOCK_ID_FIRST_SIMPLE) -#define SIMPLE_PLLE (CLOCK_ID_EPCI - CLOCK_ID_FIRST_SIMPLE) - -#define TIMER_USEC_CNTR (NV_PA_TMRUS_BASE + 0) -#define TIMER_USEC_CFG (NV_PA_TMRUS_BASE + 4) - -#define USEC_CFG_DIVISOR_MASK 0xffff - -#define CONFIG_CTL_TBE (1 << 7) -#define CONFIG_CTL_JTAG (1 << 6) - -#define CPU_RST (1 << 0) -#define CLK_ENB_CPU (1 << 0) -#define SWR_TRIG_SYS_RST (1 << 2) -#define SWR_CSITE_RST (1 << 9) - -#define PWRGATE_STATUS_CPU (1 << 0) -#define PWRGATE_TOGGLE_PARTID_CPU (0 << 0) -#define PWRGATE_TOGGLE_START (1 << 8) - -#define CPU_CMPLX_CPU_BRIDGE_CLKDIV_4 (3 << 0) -#define CPU_CMPLX_CPU0_CLK_STP_STOP (1 << 8) -#define CPU_CMPLX_CPU0_CLK_STP_RUN (0 << 8) -#define CPU_CMPLX_CPU1_CLK_STP_STOP (1 << 9) -#define CPU_CMPLX_CPU1_CLK_STP_RUN (0 << 9) - -#define CPU_CMPLX_CPURESET0 (1 << 0) -#define CPU_CMPLX_CPURESET1 (1 << 1) -#define CPU_CMPLX_DERESET0 (1 << 4) -#define CPU_CMPLX_DERESET1 (1 << 5) -#define CPU_CMPLX_DBGRESET0 (1 << 12) -#define CPU_CMPLX_DBGRESET1 (1 << 13) - -#define PLLM_OUT1_RSTN_RESET_DISABLE (1 << 0) -#define PLLM_OUT1_CLKEN_ENABLE (1 << 1) -#define PLLM_OUT1_RATIO_VAL_8 (8 << 8) - -#define SCLK_SYS_STATE_IDLE (1 << 28) -#define SCLK_SWAKE_FIQ_SRC_PLLM_OUT1 (7 << 12) -#define SCLK_SWAKE_IRQ_SRC_PLLM_OUT1 (7 << 8) -#define SCLK_SWAKE_RUN_SRC_PLLM_OUT1 (7 << 4) -#define SCLK_SWAKE_IDLE_SRC_PLLM_OUT1 (7 << 0) - -#define EVENT_ZERO_VAL_20 (20 << 0) -#define EVENT_MSEC (1 << 24) -#define EVENT_JTAG (1 << 28) -#define EVENT_MODE_STOP (2 << 29) - -#define CCLK_PLLP_BURST_POLICY 0x20004444 - -#endif diff --git a/arch/arm/cpu/armv7/tegra2/Makefile b/arch/arm/cpu/armv7/tegra20/Makefile index 80da4536d3..5f4035d79c 100644 --- a/arch/arm/cpu/armv7/tegra2/Makefile +++ b/arch/arm/cpu/armv7/tegra20/Makefile @@ -23,27 +23,16 @@ # MA 02111-1307 USA # -# The AVP is ARMv4T architecture so we must use special compiler -# flags for any startup files it might use. -CFLAGS_arch/arm/cpu/armv7/tegra2/ap20.o += -march=armv4t -CFLAGS_arch/arm/cpu/armv7/tegra2/clock.o += -march=armv4t -CFLAGS_arch/arm/cpu/armv7/tegra2/warmboot_avp.o += -march=armv4t - include $(TOPDIR)/config.mk LIB = $(obj)lib$(SOC).o -SOBJS := lowlevel_init.o -COBJS-y := ap20.o board.o clock.o funcmux.o pinmux.o sys_info.o timer.o -COBJS-$(CONFIG_TEGRA_CLOCK_SCALING) += emc.o -COBJS-$(CONFIG_TEGRA_PMU) += pmu.o COBJS-$(CONFIG_USB_EHCI_TEGRA) += usb.o -COBJS-$(CONFIG_TEGRA2_LP0) += crypto.o warmboot.o warmboot_avp.o COBJS-$(CONFIG_CMD_ENTERRCM) += cmd_enterrcm.o COBJS := $(COBJS-y) -SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) -OBJS := $(addprefix $(obj),$(COBJS) $(SOBJS)) +SRCS := $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) all: $(obj).depend $(LIB) diff --git a/arch/arm/cpu/armv7/tegra2/cmd_enterrcm.c b/arch/arm/cpu/armv7/tegra20/cmd_enterrcm.c index 2fcd107df5..75cadb03ec 100644 --- a/arch/arm/cpu/armv7/tegra2/cmd_enterrcm.c +++ b/arch/arm/cpu/armv7/tegra20/cmd_enterrcm.c @@ -40,13 +40,13 @@ */ #include <common.h> -#include <asm/arch/tegra2.h> +#include <asm/arch/tegra20.h> #include <asm/arch/pmc.h> static int do_enterrcm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA2_PMC_BASE; + struct pmc_ctlr *pmc = (struct pmc_ctlr *)TEGRA20_PMC_BASE; puts("Entering RCM...\n"); udelay(50000); diff --git a/arch/arm/cpu/armv7/tegra2/config.mk b/arch/arm/cpu/armv7/tegra20/config.mk index 4dd8cb8442..6432e754e8 100644 --- a/arch/arm/cpu/armv7/tegra2/config.mk +++ b/arch/arm/cpu/armv7/tegra20/config.mk @@ -23,16 +23,4 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, # MA 02111-1307 USA # - -# Tegra has an ARMv4T CPU which runs board_init_f(), so we must build these -# files with compatible flags -ifdef CONFIG_TEGRA2 -CFLAGS_arch/arm/lib/board.o += -march=armv4t -CFLAGS_arch/arm/lib/memset.o += -march=armv4t -CFLAGS_lib/string.o += -march=armv4t -CFLAGS_common/cmd_nvedit.o += -march=armv4t -endif - -USE_PRIVATE_LIBGCC = yes - CONFIG_ARCH_DEVICE_TREE := tegra20 diff --git a/arch/arm/cpu/armv7/tegra2/usb.c b/arch/arm/cpu/armv7/tegra20/usb.c index 5f2b243750..178bb130c2 100644 --- a/arch/arm/cpu/armv7/tegra2/usb.c +++ b/arch/arm/cpu/armv7/tegra20/usb.c @@ -24,7 +24,7 @@ #include <common.h> #include <asm/io.h> #include <asm-generic/gpio.h> -#include <asm/arch/tegra2.h> +#include <asm/arch/tegra20.h> #include <asm/arch/clk_rst.h> #include <asm/arch/clock.h> #include <asm/arch/gpio.h> diff --git a/arch/arm/cpu/armv7/u8500/Makefile b/arch/arm/cpu/armv7/u8500/Makefile index 270aa40c88..ce8af96038 100644 --- a/arch/arm/cpu/armv7/u8500/Makefile +++ b/arch/arm/cpu/armv7/u8500/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(SOC).o -COBJS = timer.o clock.o +COBJS = timer.o clock.o prcmu.o cpu.o SOBJS = lowlevel.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/arch/arm/cpu/armv7/u8500/clock.c b/arch/arm/cpu/armv7/u8500/clock.c index 9e3b87394d..fcfd61a1f4 100644 --- a/arch/arm/cpu/armv7/u8500/clock.c +++ b/arch/arm/cpu/armv7/u8500/clock.c @@ -54,3 +54,37 @@ void u8500_clock_enable(int periph, int cluster, int kern) if (cluster != -1) writel(1 << cluster, &clkrst->pcken); } + +void db8500_clocks_init(void) +{ + /* + * Enable all clocks. This is u-boot, we can enable it all. There is no + * powersave in u-boot. + */ + + u8500_clock_enable(1, 9, -1); /* GPIO0 */ + u8500_clock_enable(2, 11, -1);/* GPIO1 */ + u8500_clock_enable(3, 8, -1); /* GPIO2 */ + u8500_clock_enable(5, 1, -1); /* GPIO3 */ + u8500_clock_enable(3, 6, 6); /* UART2 */ + u8500_clock_enable(3, 3, 3); /* I2C0 */ + u8500_clock_enable(1, 5, 5); /* SDI0 */ + u8500_clock_enable(2, 4, 2); /* SDI4 */ + u8500_clock_enable(6, 6, -1); /* MTU0 */ + u8500_clock_enable(3, 4, 4); /* SDI2 */ + + /* + * Enabling clocks for all devices which are AMBA devices in the + * kernel. Otherwise they will not get probe()'d because the + * peripheral ID register will not be powered. + */ + + /* XXX: some of these differ between ED/V1 */ + + u8500_clock_enable(1, 1, 1); /* UART1 */ + u8500_clock_enable(1, 0, 0); /* UART0 */ + u8500_clock_enable(3, 2, 2); /* SSP1 */ + u8500_clock_enable(3, 1, 1); /* SSP0 */ + u8500_clock_enable(2, 8, -1); /* SPI0 */ + u8500_clock_enable(2, 5, 3); /* MSP2 */ +} diff --git a/arch/arm/cpu/armv7/u8500/cpu.c b/arch/arm/cpu/armv7/u8500/cpu.c new file mode 100644 index 0000000000..6f95c30673 --- /dev/null +++ b/arch/arm/cpu/armv7/u8500/cpu.c @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2012 Linaro Limited + * Mathieu Poirier <mathieu.poirier@linaro.org> + * + * Based on original code from Joakim Axelsson at ST-Ericsson + * (C) Copyright 2010 ST-Ericsson + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/prcmu.h> +#include <asm/arch/clock.h> +#include <asm/arch/hardware.h> + +#include <asm/arch/hardware.h> + +#define CPUID_DB8500V1 0x411fc091 +#define CPUID_DB8500V2 0x412fc091 +#define ASICID_DB8500V11 0x008500A1 + +#define CACHE_CONTR_BASE 0xA0412000 +/* Cache controller register offsets + * as found in ARM's technical reference manual + */ +#define CACHE_INVAL_BY_WAY (CACHE_CONTR_BASE + 0x77C) +#define CACHE_LOCKDOWN_BY_D (CACHE_CONTR_BASE + 0X900) +#define CACHE_LOCKDOWN_BY_I (CACHE_CONTR_BASE + 0X904) + +static unsigned int read_asicid(void); + +static inline unsigned int read_cpuid(void) +{ + unsigned int val; + + /* Main ID register (MIDR) */ + asm("mrc p15, 0, %0, c0, c0, 0" + : "=r" (val) + : + : "cc"); + + return val; +} + +static int cpu_is_u8500v11(void) +{ + return read_asicid() == ASICID_DB8500V11; +} + +static int cpu_is_u8500v2(void) +{ + return read_cpuid() == CPUID_DB8500V2; +} + +static unsigned int read_asicid(void) +{ + unsigned int *address; + + if (cpu_is_u8500v2()) + address = (void *) U8500_ASIC_ID_LOC_V2; + else + address = (void *) U8500_ASIC_ID_LOC_ED_V1; + + return readl(address); +} + +void cpu_cache_initialization(void) +{ + unsigned int value; + /* invalidate all cache entries */ + writel(0xFFFF, CACHE_INVAL_BY_WAY); + + /* ways are set to '0' when they are totally + * cleaned and invalidated + */ + do { + value = readl(CACHE_INVAL_BY_WAY); + } while (value & 0xFF); + + /* Invalidate register 9 D and I lockdown */ + writel(0xFF, CACHE_LOCKDOWN_BY_D); + writel(0xFF, CACHE_LOCKDOWN_BY_I); +} + +#ifdef CONFIG_ARCH_CPU_INIT +/* + * SOC specific cpu init + */ +int arch_cpu_init(void) +{ + db8500_prcmu_init(); + db8500_clocks_init(); + + return 0; +} +#endif /* CONFIG_ARCH_CPU_INIT */ + +#ifdef CONFIG_MMC + +int u8500_mmc_power_init(void) +{ + int ret; + int enable, voltage; + int ab8500_revision; + + if (!cpu_is_u8500v11() && !cpu_is_u8500v2()) + return 0; + + /* Get AB8500 revision */ + ret = ab8500_read(AB8500_MISC, AB8500_REV_REG); + if (ret < 0) + goto out; + + ab8500_revision = ret; + + /* + * On v1.1 HREF boards (HREF+), Vaux3 needs to be enabled for the SD + * card to work. This is done by enabling the regulators in the AB8500 + * via PRCMU I2C transactions. + * + * This code is derived from the handling of AB8500_LDO_VAUX3 in + * ab8500_ldo_enable() and ab8500_ldo_disable() in Linux. + * + * Turn off and delay is required to have it work across soft reboots. + */ + + /* Turn off (read-modify-write) */ + ret = ab8500_read(AB8500_REGU_CTRL2, + AB8500_REGU_VRF1VAUX3_REGU_REG); + if (ret < 0) + goto out; + + enable = ret; + + /* Turn off */ + ret = ab8500_write(AB8500_REGU_CTRL2, + AB8500_REGU_VRF1VAUX3_REGU_REG, + enable & ~LDO_VAUX3_ENABLE_MASK); + if (ret < 0) + goto out; + + udelay(10 * 1000); + + /* Set the voltage to 2.91 V or 2.9 V without overriding VRF1 value */ + ret = ab8500_read(AB8500_REGU_CTRL2, + AB8500_REGU_VRF1VAUX3_SEL_REG); + if (ret < 0) + goto out; + + voltage = ret; + + if (ab8500_revision < 0x20) { + voltage &= ~LDO_VAUX3_SEL_MASK; + voltage |= LDO_VAUX3_SEL_2V9; + } else { + voltage &= ~LDO_VAUX3_V2_SEL_MASK; + voltage |= LDO_VAUX3_V2_SEL_2V91; + } + + ret = ab8500_write(AB8500_REGU_CTRL2, + AB8500_REGU_VRF1VAUX3_SEL_REG, voltage); + if (ret < 0) + goto out; + + /* Turn on the supply */ + enable &= ~LDO_VAUX3_ENABLE_MASK; + enable |= LDO_VAUX3_ENABLE_VAL; + + ret = ab8500_write(AB8500_REGU_CTRL2, + AB8500_REGU_VRF1VAUX3_REGU_REG, enable); + +out: + return ret; +} +#endif /* CONFIG_MMC */ diff --git a/arch/arm/cpu/armv7/u8500/prcmu.c b/arch/arm/cpu/armv7/u8500/prcmu.c new file mode 100644 index 0000000000..934428fb89 --- /dev/null +++ b/arch/arm/cpu/armv7/u8500/prcmu.c @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2009 ST-Ericsson SA + * + * Adapted from the Linux version: + * Author: Kumar Sanghvi <kumar.sanghvi@stericsson.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + */ + +/* + * NOTE: This currently does not support the I2C workaround access method. + */ + +#include <common.h> +#include <config.h> +#include <asm/io.h> +#include <asm/arch/hardware.h> +#include <asm/types.h> +#include <asm/io.h> +#include <asm/errno.h> +#include <asm/arch/prcmu.h> + +/* CPU mailbox registers */ +#define PRCMU_I2C_WRITE(slave) \ + (((slave) << 1) | I2CWRITE | (1 << 6)) +#define PRCMU_I2C_READ(slave) \ + (((slave) << 1) | I2CREAD | (1 << 6)) + +#define I2C_MBOX_BIT (1 << 5) + +static int prcmu_is_ready(void) +{ + int ready = readb(PRCM_XP70_CUR_PWR_STATE) == AP_EXECUTE; + if (!ready) + printf("PRCMU firmware not ready\n"); + return ready; +} + +static int wait_for_i2c_mbx_rdy(void) +{ + int timeout = 10000; + + if (readl(PRCM_ARM_IT1_VAL) & I2C_MBOX_BIT) { + printf("prcmu: warning i2c mailbox was not acked\n"); + /* clear mailbox 5 ack irq */ + writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR); + } + + /* check any already on-going transaction */ + while ((readl(PRCM_MBOX_CPU_VAL) & I2C_MBOX_BIT) && timeout) + timeout--; + + if (timeout == 0) + return -1; + + return 0; +} + +static int wait_for_i2c_req_done(void) +{ + int timeout = 10000; + + /* Set an interrupt to XP70 */ + writel(I2C_MBOX_BIT, PRCM_MBOX_CPU_SET); + + /* wait for mailbox 5 (i2c) ack */ + while (!(readl(PRCM_ARM_IT1_VAL) & I2C_MBOX_BIT) && timeout) + timeout--; + + if (timeout == 0) + return -1; + + return 0; +} + +/** + * prcmu_i2c_read - PRCMU - 4500 communication using PRCMU I2C + * @reg: - db8500 register bank to be accessed + * @slave: - db8500 register to be accessed + * Returns: ACK_MB5 value containing the status + */ +int prcmu_i2c_read(u8 reg, u16 slave) +{ + uint8_t i2c_status; + uint8_t i2c_val; + int ret; + + if (!prcmu_is_ready()) + return -1; + + debug("\nprcmu_4500_i2c_read:bank=%x;reg=%x;\n", + reg, slave); + + ret = wait_for_i2c_mbx_rdy(); + if (ret) { + printf("prcmu_i2c_read: mailbox became not ready\n"); + return ret; + } + + /* prepare the data for mailbox 5 */ + writeb(PRCMU_I2C_READ(reg), PRCM_REQ_MB5_I2COPTYPE_REG); + writeb((1 << 3) | 0x0, PRCM_REQ_MB5_BIT_FIELDS); + writeb(slave, PRCM_REQ_MB5_I2CSLAVE); + writeb(0, PRCM_REQ_MB5_I2CVAL); + + ret = wait_for_i2c_req_done(); + if (ret) { + printf("prcmu_i2c_read: mailbox request timed out\n"); + return ret; + } + + /* retrieve values */ + debug("ack-mb5:transfer status = %x\n", + readb(PRCM_ACK_MB5_STATUS)); + debug("ack-mb5:reg bank = %x\n", readb(PRCM_ACK_MB5) >> 1); + debug("ack-mb5:slave_add = %x\n", + readb(PRCM_ACK_MB5_SLAVE)); + debug("ack-mb5:reg_val = %d\n", readb(PRCM_ACK_MB5_VAL)); + + i2c_status = readb(PRCM_ACK_MB5_STATUS); + i2c_val = readb(PRCM_ACK_MB5_VAL); + /* clear mailbox 5 ack irq */ + writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR); + + if (i2c_status == I2C_RD_OK) + return i2c_val; + + printf("prcmu_i2c_read:read return status= %d\n", i2c_status); + return -1; +} + +/** + * prcmu_i2c_write - PRCMU-db8500 communication using PRCMU I2C + * @reg: - db8500 register bank to be accessed + * @slave: - db800 register to be written to + * @reg_data: - the data to write + * Returns: ACK_MB5 value containing the status + */ +int prcmu_i2c_write(u8 reg, u16 slave, u8 reg_data) +{ + uint8_t i2c_status; + int ret; + + if (!prcmu_is_ready()) + return -1; + + debug("\nprcmu_4500_i2c_write:bank=%x;reg=%x;\n", + reg, slave); + + ret = wait_for_i2c_mbx_rdy(); + if (ret) { + printf("prcmu_i2c_write: mailbox became not ready\n"); + return ret; + } + + /* prepare the data for mailbox 5 */ + writeb(PRCMU_I2C_WRITE(reg), PRCM_REQ_MB5_I2COPTYPE_REG); + writeb((1 << 3) | 0x0, PRCM_REQ_MB5_BIT_FIELDS); + writeb(slave, PRCM_REQ_MB5_I2CSLAVE); + writeb(reg_data, PRCM_REQ_MB5_I2CVAL); + + ret = wait_for_i2c_req_done(); + if (ret) { + printf("prcmu_i2c_write: mailbox request timed out\n"); + return ret; + } + + /* retrieve values */ + debug("ack-mb5:transfer status = %x\n", + readb(PRCM_ACK_MB5_STATUS)); + debug("ack-mb5:reg bank = %x\n", readb(PRCM_ACK_MB5) >> 1); + debug("ack-mb5:slave_add = %x\n", + readb(PRCM_ACK_MB5_SLAVE)); + debug("ack-mb5:reg_val = %d\n", readb(PRCM_ACK_MB5_VAL)); + + i2c_status = readb(PRCM_ACK_MB5_STATUS); + debug("\ni2c_status = %x\n", i2c_status); + /* clear mailbox 5 ack irq */ + writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR); + + if (i2c_status == I2C_WR_OK) + return 0; + + printf("%s: i2c_status : 0x%x\n", __func__, i2c_status); + return -1; +} + +void u8500_prcmu_enable(u32 *reg) +{ + writel(readl(reg) | (1 << 8), reg); +} + +void db8500_prcmu_init(void) +{ + /* Enable timers */ + writel(1 << 17, PRCM_TCR); + + u8500_prcmu_enable((u32 *)PRCM_PER1CLK_MGT_REG); + u8500_prcmu_enable((u32 *)PRCM_PER2CLK_MGT_REG); + u8500_prcmu_enable((u32 *)PRCM_PER3CLK_MGT_REG); + /* PER4CLK does not exist */ + u8500_prcmu_enable((u32 *)PRCM_PER5CLK_MGT_REG); + u8500_prcmu_enable((u32 *)PRCM_PER6CLK_MGT_REG); + /* Only exists in ED but is always ok to write to */ + u8500_prcmu_enable((u32 *)PRCM_PER7CLK_MGT_REG); + + u8500_prcmu_enable((u32 *)PRCM_UARTCLK_MGT_REG); + u8500_prcmu_enable((u32 *)PRCM_I2CCLK_MGT_REG); + + u8500_prcmu_enable((u32 *)PRCM_SDMMCCLK_MGT_REG); + + /* Clean up the mailbox interrupts after pre-u-boot code. */ + writel(I2C_MBOX_BIT, PRCM_ARM_IT1_CLEAR); +} |