From 9c2ca2d1d367d6fe616d0b2f2fb4abac04d9069e Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Wed, 28 Apr 2010 13:09:22 +0530 Subject: HREF+ SD support On HREF+, SD card power supply is controlled by the Vaux3 regulator. In order to enable the power supply, port the AB8500 PRCMU I2C read/write code from Linux to U-Boot, and then write the appropriate registers via those functions. Signed-off-by: Rabin Vincent Change-Id: I470f3da694e6ea0e3e0e16571c3048066f0a4309 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/388 Reviewed-by: Michael BRANDT Reviewed-by: Jonas ABERG Tested-by: Jonas ABERG --- board/st/u8500/Makefile | 2 +- board/st/u8500/prcmu-fw-defs_v1.h | 586 ++++++++++++++++++++++++++++++++++++++ board/st/u8500/prcmu-fw.h | 173 +++++++++++ board/st/u8500/prcmu.c | 161 +++++++++++ board/st/u8500/u8500.c | 72 ++++- 5 files changed, 991 insertions(+), 3 deletions(-) create mode 100644 board/st/u8500/prcmu-fw-defs_v1.h create mode 100644 board/st/u8500/prcmu-fw.h create mode 100644 board/st/u8500/prcmu.c (limited to 'board') diff --git a/board/st/u8500/Makefile b/board/st/u8500/Makefile index 1dcc9e1a3..0042c3353 100644 --- a/board/st/u8500/Makefile +++ b/board/st/u8500/Makefile @@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk CFLAGS += -D__RELEASE -D__STN_8500 LIB = $(obj)lib$(BOARD).a -COBJS := u8500.o flash.o gpio.o u8500_i2c.o mmc.o mmc_utils.o init_mmc.o emmc.o clock.o +COBJS := u8500.o flash.o gpio.o u8500_i2c.o mmc.o mmc_utils.o init_mmc.o emmc.o clock.o prcmu.o SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/board/st/u8500/prcmu-fw-defs_v1.h b/board/st/u8500/prcmu-fw-defs_v1.h new file mode 100644 index 000000000..046f89e21 --- /dev/null +++ b/board/st/u8500/prcmu-fw-defs_v1.h @@ -0,0 +1,586 @@ +/* + * Copyright (c) 2009 ST-Ericsson SA + * + * 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. + * + * Copied from the Linux version: + * Author: Kumar Sanghvi + */ + +#ifndef __MACH_PRCMU_FW_DEFS_V1_H +#define __MACH_PRCMU_FW_DEFS_V1_H + +/** + * enum state_t - ON/OFF state definition + * @OFF: State is ON + * @ON: State is OFF + * + */ +enum state_t { + OFF = 0x0, + ON = 0x1, +}; + +/** + * enum ret_state_t - general purpose On/Off/Retention states + * + */ +enum ret_state_t { + OFFST = 0, + ONST = 1, + RETST = 2 +}; + + +/** + * enum clk_arm_t - ARM Cortex A9 clock schemes + * @A9_OFF: + * @A9_BOOT: + * @A9_OPPT1: + * @A9_OPPT2: + * @A9_EXTCLK: + */ +enum clk_arm_t { + A9_OFF, + A9_BOOT, + A9_OPPT1, + A9_OPPT2, + A9_EXTCLK +}; + +/** + * enum clk_gen_t - GEN#0/GEN#1 clock schemes + * @GEN_OFF: + * @GEN_BOOT: + * @GEN_OPPT1: + */ +enum clk_gen_t { + GEN_OFF, + GEN_BOOT, + GEN_OPPT1, +}; + +/* some information between arm and xp70 */ + +/** + * enum romcode_write_t - Romcode message written by A9 AND read by XP70 + * @RDY_2_DS: Value set when ApDeepSleep state can be executed by XP70 + * @RDY_2_XP70_RST: Value set when 0x0F has been successfully polled by the + * romcode. The xp70 will go into self-reset + */ +enum romcode_write_t { + RDY_2_DS = 0x09, + RDY_2_XP70_RST = 0x10 +}; + +/** + * enum romcode_read_t - Romcode message written by XP70 and read by A9 + * @INIT: Init value when romcode field is not used + * @FS_2_DS: Value set when power state is going from ApExecute to + * ApDeepSleep + * @END_DS: Value set when ApDeepSleep power state is reached coming from + * ApExecute state + * @DS_TO_FS: Value set when power state is going from ApDeepSleep to + * ApExecute + * @END_FS: Value set when ApExecute power state is reached coming from + * ApDeepSleep state + * @SWR: Value set when power state is going to ApReset + * @END_SWR: Value set when the xp70 finished executing ApReset actions and + * waits for romcode acknowledgment to go to self-reset + */ +enum romcode_read_t { + INIT = 0x00, + FS_2_DS = 0x0A, + END_DS = 0x0B, + DS_TO_FS = 0x0C, + END_FS = 0x0D, + SWR = 0x0E, + END_SWR = 0x0F +}; + + +/** + * enum pingpong_t + * @PING: value is 0 + * @PONG: value is 1 + * + * implementation issue: the values are chosen the way that + * we can change from ping to pong (resp. pong to ping) by + * simply using the 'not' operator in C, e.g. toggling operation: + * t_PingPong p = ping; p = ~p; + */ +enum pingpong_t { + PING = 0x00, + PONG = 0xFF +}; + +/** + * enum wkup_reason_fdst_t + * @EVTWR: event has been read by ARM + * @EVTST: event has been sent by PRCMU FW + * @EVTRD: event has been written by PRCMU FW + */ +enum wkup_reason_fdst_t { + /* WRF has been written but neither sent nor read by the arm */ + EVTWR = 1, + /* WRF has been written and sent, but not yet read by the arm */ + EVTST = 2, + /* WRF has been written, sent and read by the arm */ + EVTRD = 0 +}; /* Wake-up reason Field State */ + + + +/** + * enum ap_pwrst_t - current power states defined in PRCMU firmware + * @NO_PWRST: Current power state init + * @AP_BOOT: Current power state is apBoot + * @AP_EXECUTE: Current power state is apExecute + * @AP_DEEP_SLEEP: Current power state is apDeepSleep + * @AP_SLEEP: Current power state is apSleep + * @AP_IDLE: Current power state is apIdle + * @AP_RESET: Current power state is apReset + */ +enum ap_pwrst_t { + NO_PWRST = 0x00, + AP_BOOT = 0x01, + AP_EXECUTE = 0x02, + AP_DEEP_SLEEP = 0x03, + AP_SLEEP = 0x04, + AP_IDLE = 0x05, + AP_RESET = 0x06 +}; + +/** + * enum ap_pwrst_trans_t - Transition states defined in PRCMU firmware + * @NO_TRANSITION: No power state transition + * @APEXECUTE_TO_APSLEEP: Power state transition from ApExecute to ApSleep + * @APIDLE_TO_APSLEEP: Power state transition from ApIdle to ApSleep + * @APBOOT_TO_APEXECUTE: Power state transition from ApBoot to ApExecute + * @APEXECUTE_TO_APDEEPSLEEP: Power state transition from ApExecute to + * ApDeepSleep + * @APEXECUTE_TO_APIDLE: Power state transition from ApExecute to ApIdle + */ +enum ap_pwrst_trans_t { + NO_TRANSITION = 0x00, + APEXECUTE_TO_APSLEEP = 0x01, + APIDLE_TO_APSLEEP = 0x02, + APBOOT_TO_APEXECUTE = 0x03, + APEXECUTE_TO_APDEEPSLEEP = 0x04, + APEXECUTE_TO_APIDLE = 0x05 +}; + +/** + * enum ddr_pwrst_t - DDR power states definition + * @DDR_PWR_STATE_UNCHANGED: SDRAM and DDR controller state is unchanged + * @DDR_PWR_STATE_ON: + * @DDR_PWR_STATE_OFFLOWLAT: + * @DDR_PWR_STATE_OFFHIGHLAT: + */ +enum ddr_pwrst_t { + DDR_PWR_STATE_UNCHANGED = 0x00, + DDR_PWR_STATE_ON = 0x01, + DDR_PWR_STATE_OFFLOWLAT = 0x02, + DDR_PWR_STATE_OFFHIGHLAT = 0x03 +}; + +/** + * enum arm_opp_t - ARM OPP states definition + * @ARM_NO_CHANGE: The ARM operating point is unchanged + * @ARM_100_OPP: The new ARM operating point is arm100opp + * @ARM_50_OPP: The new ARM operating point is arm100opp + * @ARM_EXTCLK: The new ARM operating point is armExtClk + */ +enum arm_opp_t { + ARM_NO_CHANGE = 0x00, + ARM_100_OPP = 0x02, + ARM_50_OPP = 0x03, + ARM_EXTCLK = 0x07 +}; + +/** + * enum ape_opp_t - APE OPP states definition + * @APE_NO_CHANGE: The APE operating point is unchanged + * @APE_100_OPP: The new APE operating point is ape100opp + */ +enum ape_opp_t { + APE_NO_CHANGE = 0x00, + APE_100_OPP = 0x02, + APE_50_OPP = 0x03 +}; + +/** + * enum hw_accst_t - State definition for hardware accelerator + * @HW_NO_CHANGE: The hardware accelerator state must remain unchanged + * @HW_OFF: The hardware accelerator must be switched off + * @HW_OFF_RAMRET: The hardware accelerator must be switched off with its + * internal RAM in retention + * @HW_ON: The hwa hadware accelerator hwa must be switched on + */ +enum hw_accst_t { + HW_NO_CHANGE = 0x00, + HW_OFF = 0x01, + HW_OFF_RAMRET = 0x02, + HW_ON = 0x03 +}; + +/** + * enum mbox_2_arm_stat_t - Status messages definition for mbox_arm + * @BOOT_TO_EXECUTEOK: The apBoot to apExecute state transition has been + * completed + * @DEEPSLEEPOK: The apExecute to apDeepSleep state transition has been + * completed + * @SLEEPOK: The apExecute to apSleep state transition has been completed + * @IDLEOK: The apExecute to apIdle state transition has been completed + * @SOFTRESETOK: The A9 watchdog/ SoftReset state has been completed + * @SOFTRESETGO : The A9 watchdog/SoftReset state is on going + * @BOOT_TO_EXECUTE: The apBoot to apExecute state transition is on going + * @EXECUTE_TO_DEEPSLEEP: The apExecute to apDeepSleep state transition is on + * going + * @DEEPSLEEP_TO_EXECUTE: The apDeepSleep to apExecute state transition is on + * going + * @DEEPSLEEP_TO_EXECUTEOK: The apDeepSleep to apExecute state transition has + * been completed + * @EXECUTE_TO_SLEEP: The apExecute to apSleep state transition is on going + * @SLEEP_TO_EXECUTE: The apSleep to apExecute state transition is on going + * @SLEEP_TO_EXECUTEOK: The apSleep to apExecute state transition has been + * completed + * @EXECUTE_TO_IDLE: The apExecute to apIdle state transition is on going + * @IDLE_TO_EXECUTE: The apIdle to apExecute state transition is on going + * @IDLE_TO_EXECUTEOK: The apIdle to apExecute state transition has been + * completed + * @INIT_STATUS: Status init + */ +enum ap_pwrsttr_status_t { + BOOT_TO_EXECUTEOK = 0xFF, + DEEPSLEEPOK = 0xFE, + SLEEPOK = 0xFD, + IDLEOK = 0xFC, + SOFTRESETOK = 0xFB, + SOFTRESETGO = 0xFA, + BOOT_TO_EXECUTE = 0xF9, + EXECUTE_TO_DEEPSLEEP = 0xF8, + DEEPSLEEP_TO_EXECUTE = 0xF7, + DEEPSLEEP_TO_EXECUTEOK = 0xF6, + EXECUTE_TO_SLEEP = 0xF5, + SLEEP_TO_EXECUTE = 0xF4, + SLEEP_TO_EXECUTEOK = 0xF3, + EXECUTE_TO_IDLE = 0xF2, + IDLE_TO_EXECUTE = 0xF1, + IDLE_TO_EXECUTEOK = 0xF0, + RDYTODS_RETURNTOEXE = 0xEF, + NORDYTODS_RETURNTOEXE = 0xEE, + EXETOSLEEP_RETURNTOEXE = 0xED, + EXETOIDLE_RETURNTOEXE = 0xEC, + INIT_STATUS = 0xEB, + + /*error messages */ + INITERROR = 0x00, + PLLARMLOCKP_ER = 0x01, + PLLDDRLOCKP_ER = 0x02, + PLLSOCLOCKP_ER = 0x03, + PLLSOCK1LOCKP_ER = 0x04, + ARMWFI_ER = 0x05, + SYSCLKOK_ER = 0x06, + I2C_NACK_DATA_ER = 0x07, + BOOT_ER = 0x08, + I2C_STATUS_ALWAYS_1 = 0x0A, + I2C_NACK_REG_ADDR_ER = 0x0B, + I2C_NACK_DATA0123_ER = 0x1B, + I2C_NACK_ADDR_ER = 0x1F, + CURAPPWRSTISNOT_BOOT = 0x20, + CURAPPWRSTISNOT_EXECUTE = 0x21, + CURAPPWRSTISNOT_SLEEPMODE = 0x22, + CURAPPWRSTISNOT_CORRECTFORIT10 = 0x23, + FIFO4500WUISNOT_WUPEVENT = 0x24, + PLL32KLOCKP_ER = 0x29, + DDRDEEPSLEEPOK_ER = 0x2A, + ROMCODEREADY_ER = 0x50, + WUPBEFOREDS = 0x51, + DDRCONFIG_ER = 0x52, + WUPBEFORESLEEP = 0x53, + WUPBEFOREIDLE = 0x54 +}; /* earlier called as mbox_2_arm_stat_t */ + + +/** + * enum dvfs_stat_t - DVFS status messages definition + * @DVFS_GO: A state transition DVFS is on going + * @DVFS_ARM100OPPOK: The state transition DVFS has been completed for 100OPP + * @DVFS_ARM50OPPOK: The state transition DVFS has been completed for 50OPP + * @DVFS_ARMEXTCLKOK: The state transition DVFS has been completed for EXTCLK + * @DVFS_NOCHGTCLKOK: The state transition DVFS has been completed for + * NOCHGCLK + * @DVFS_INITSTATUS: Value init + */ +enum dvfs_stat_t { + DVFS_GO = 0xFF, + DVFS_ARM100OPPOK = 0xFE, + DVFS_ARM50OPPOK = 0xFD, + DVFS_ARMEXTCLKOK = 0xFC, + DVFS_NOCHGTCLKOK = 0xFB, + DVFS_INITSTATUS = 0x00 +}; + +/** + * enum mbox_2_arm_hwacc_pwr_stat_t - Hardware Accelarator status message + * @HWACC_PWRST_GO: A state transition on hardware accelerator is on going + * @HWACC_PWRST_OK: The state transition on hardware accelerator has been + * completed + * @HWACC_PWRSTATUS_INIT: Value init + */ +enum mbox_2_arm_hwacc_pwr_stat_t { + HWACC_PWRST_GO = 0xFF, + HWACC_PWRST_OK = 0xFE, + HWACC_PWRSTATUS_INIT = 0x00 +}; + +/** + * enum sva_mmdsp_stat_t - SVA MMDSP status messages + * @SVA_MMDSP_GO: SVAMMDSP interrupt has happened + * @SVA_MMDSP_INIT: Status init + */ +enum sva_mmdsp_stat_t { + SVA_MMDSP_GO = 0xFF, + SVA_MMDSP_INIT = 0x00 +}; + +/** + * enum sia_mmdsp_stat_t - SIA MMDSP status messages + * @SIA_MMDSP_GO: SIAMMDSP interrupt has happened + * @SIA_MMDSP_INIT: Status init + */ +enum sia_mmdsp_stat_t { + SIA_MMDSP_GO = 0xFF, + SIA_MMDSP_INIT = 0x00 +}; + +/** + * enum intr_wakeup_t - Configure STW4500 FIFO interrupt as wake-up + * @NTR_NOT_AS_WAKEUP: The 4500 fifo interrupt is not configured as a + * wake-up event + * @INTR_AS_WAKEUP: The 4500 fifo interrupt is configured as a wake-up event + */ +enum intr_wakeup_t { + INTR_NOT_AS_WAKEUP = 0x0, + INTR_AS_WAKEUP = 0x1 +}; + +/** + * enum mbox_to_arm_err_t - Error messages definition + * @INIT_ERR: Init value + * @PLLARMLOCKP_ERR: PLLARM has not been correctly locked in given time + * @PLLDDRLOCKP_ERR: PLLDDR has not been correctly locked in the given time + * @PLLSOC0LOCKP_ERR: PLLSOC0 has not been correctly locked in the given time + * @PLLSOC1LOCKP_ERR: PLLSOC1 has not been correctly locked in the given time + * @ARMWFI_ERR: The ARM WFI has not been correctly executed in the given time + * @SYSCLKOK_ERR: The SYSCLK is not available in the given time + * @BOOT_ERR: Romcode has not validated the XP70 self reset in the given time + * @ROMCODESAVECONTEXT: The Romcode didn.t correctly save it secure context + * @VARMHIGHSPEEDVALTO_ERR: The ARM high speed supply value transfered + * through I2C has not been correctly executed in the given time + * @VARMHIGHSPEEDACCESS_ERR: The command value of VarmHighSpeedVal transfered + * through I2C has not been correctly executed in the given time + * @VARMLOWSPEEDVALTO_ERR:The ARM low speed supply value transfered through + * I2C has not been correctly executed in the given time + * @VARMLOWSPEEDACCESS_ERR: The command value of VarmLowSpeedVal transfered + * through I2C has not been correctly executed in the given time + * @VARMRETENTIONVALTO_ERR: The ARM retention supply value transfered through + * I2C has not been correctly executed in the given time + * @VARMRETENTIONACCESS_ERR: The command value of VarmRetentionVal transfered + * through I2C has not been correctly executed in the given time + * @VAPEHIGHSPEEDVALTO_ERR: The APE highspeed supply value transfered through + * I2C has not been correctly executed in the given time + * @VSAFEHPVALTO_ERR: The SAFE high power supply value transfered through I2C + * has not been correctly executed in the given time + * @VMODSEL1VALTO_ERR: The MODEM sel1 supply value transfered through I2C has + * not been correctly executed in the given time + * @VMODSEL2VALTO_ERR: The MODEM sel2 supply value transfered through I2C has + * not been correctly executed in the given time + * @VARMOFFACCESS_ERR: The command value of Varm ON/OFF transfered through + * I2C has not been correctly executed in the given time + * @VAPEOFFACCESS_ERR: The command value of Vape ON/OFF transfered through + * I2C has not been correctly executed in the given time + * @VARMRETACCES_ERR: The command value of Varm retention ON/OFF transfered + * through I2C has not been correctly executed in the given time + * @CURAPPWRSTISNOTBOOT:Generated when Arm want to do power state transition + * ApBoot to ApExecute but the power current state is not Apboot + * @CURAPPWRSTISNOTEXECUTE: Generated when Arm want to do power state + * transition from ApExecute to others power state but the + * power current state is not ApExecute + * @CURAPPWRSTISNOTSLEEPMODE: Generated when wake up events are transmitted + * but the power current state is not ApDeepSleep/ApSleep/ApIdle + * @CURAPPWRSTISNOTCORRECTDBG: Generated when wake up events are transmitted + * but the power current state is not correct + * @ARMREGU1VALTO_ERR:The ArmRegu1 value transferred through I2C has not + * been correctly executed in the given time + * @ARMREGU2VALTO_ERR: The ArmRegu2 value transferred through I2C has not + * been correctly executed in the given time + * @VAPEREGUVALTO_ERR: The VApeRegu value transfered through I2C has not + * been correctly executed in the given time + * @VSMPS3REGUVALTO_ERR: The VSmps3Regu value transfered through I2C has not + * been correctly executed in the given time + * @VMODREGUVALTO_ERR: The VModemRegu value transfered through I2C has not + * been correctly executed in the given time + */ +enum mbox_to_arm_err_t { + INIT_ERR = 0x00, + PLLARMLOCKP_ERR = 0x01, + PLLDDRLOCKP_ERR = 0x02, + PLLSOC0LOCKP_ERR = 0x03, + PLLSOC1LOCKP_ERR = 0x04, + ARMWFI_ERR = 0x05, + SYSCLKOK_ERR = 0x06, + BOOT_ERR = 0x07, + ROMCODESAVECONTEXT = 0x08, + VARMHIGHSPEEDVALTO_ERR = 0x10, + VARMHIGHSPEEDACCESS_ERR = 0x11, + VARMLOWSPEEDVALTO_ERR = 0x12, + VARMLOWSPEEDACCESS_ERR = 0x13, + VARMRETENTIONVALTO_ERR = 0x14, + VARMRETENTIONACCESS_ERR = 0x15, + VAPEHIGHSPEEDVALTO_ERR = 0x16, + VSAFEHPVALTO_ERR = 0x17, + VMODSEL1VALTO_ERR = 0x18, + VMODSEL2VALTO_ERR = 0x19, + VARMOFFACCESS_ERR = 0x1A, + VAPEOFFACCESS_ERR = 0x1B, + VARMRETACCES_ERR = 0x1C, + CURAPPWRSTISNOTBOOT = 0x20, + CURAPPWRSTISNOTEXECUTE = 0x21, + CURAPPWRSTISNOTSLEEPMODE = 0x22, + CURAPPWRSTISNOTCORRECTDBG = 0x23, + ARMREGU1VALTO_ERR = 0x24, + ARMREGU2VALTO_ERR = 0x25, + VAPEREGUVALTO_ERR = 0x26, + VSMPS3REGUVALTO_ERR = 0x27, + VMODREGUVALTO_ERR = 0x28 +}; + +enum hw_acc_t { + SVAMMDSP = 0, + SVAPIPE = 1, + SIAMMDSP = 2, + SIAPIPE = 3, + SGA = 4, + B2R2MCDE = 5, + ESRAM1 = 6, + ESRAM2 = 7, + ESRAM3 = 8, + ESRAM4 = 9 +}; + +enum reqmb0_header_t { + PWRSTTRH = 0, + WKUPCFG_EXEH = 1, + WKUP_EXEH = 2, + RDWKUPACKH = 3, + WKUPCFG_SLEEPH = 4, + WKUP_SLEEPH = 5, +}; + +enum cs_pwrmgt_t { + PWRDNCS0 = 0, + WKUPCS0 = 1, + PWRDNCS1 = 2, + WKUPCS1 = 3 +}; + +enum reqmb2_header_t { + DPS_H = 0, + HW_ACCT_AUTO_PWR_H = 1, +}; + + +/* Defs related to autonomous power management */ + +/** + * enum sia_sva_pwr_policy_t - Power policy + * @NO_CHGT: No change + * @DSPOFF_HWPOFF: + * @DSPOFFRAMRET_HWPOFF: + * @DSPCLKOFF_HWPOFF: + * @DSPCLKOFF_HWPCLKOFF: + * + */ +enum sia_sva_pwr_policy_t { + NO_CHGT = 0x0, + DSPOFF_HWPOFF = 0x1, + DSPOFFRAMRET_HWPOFF = 0x2, + DSPCLKOFF_HWPOFF = 0x3, + DSPCLKOFF_HWPCLKOFF = 0x4, +}; + +/** + * enum auto_enable_t - Auto Power enable + * @AUTO_OFF: + * @AUTO_ON: + * + */ +enum auto_enable_t { + AUTO_OFF = 0x0, + AUTO_ON = 0x1, +}; + + +/** + * enum reqmb4_header_t -Header type for mail box 4 + * @MEMSTH: The ARM can set what are the expected memory states depending on + * the AP power states. + * @PARTIALREFRESHH: ARM has to update MR16 & MR17 of SDRAM register, for + * partial-refresh of SDRAM, via this mailbox + * @AUTOREFRESHH: Enable to change cycle count before enabling automatic + * DDR self-refresh + * @CSPWRDNH: Enables to lock/unlock one of SDRAM memory cut in self-refresh + * In V2,this service will enable to put CS in pwrdn + * @SYSCLKH: Enables to switch SYSCLK ON/OFF on the AP side + * @USBWKUPH: Used to enable USB wakeup event of PRCMU + */ +enum reqmb4_header_t { + MEM_ST_H = 0, + PARTIAL_S_REFRESH_H = 1, + AUTO_REFRESH_H = 2, + CS_PWRDN_H = 3, + SYSCLK_H = 5, + AUTO_PWR_H = 6, + USB_WKUP_H = 7 +}; + +enum ack_mb4_status_t { + ACKMB4_INIT = 0, + SYSCLKON_OK = 1, + DDRON_OK = 2 +}; + +enum I2C_op_t { + I2CWRITE = 0, + I2CREAD = 1 +}; + +enum ack_mb5_status_t { + ACKMB5_INIT = 0x00, + I2C_WR_OK = 0x01, + I2C_RD_OK = 0x02, + SYSCLK_OK = 0x03, + I2C_TIMEOUT = 0x11, + SYSCLK_ER = 0x12, + /*Error Status resent by PRCM_HWI2C_SR*/ + I2CWR_NACK_DATA_ER = 0x07, + I2CWR_NACK_REG_ADDR_ER = 0x0B, + I2CRDWR_NACK_DATA0123_ER = 0x1B, + I2CWR_NACK_ADDR_ER = 0x1F, + I2CRD_NACK_ADDR_INIT_ER = 0x0F, + I2CRD_NACK_REG_ADDR_INIT_ER = 0x13, + I2CRD_NACK_ADDR_ER = 0x17 +}; + +enum ack_mb7_status_t { + MOD_SW_RESET_REQ = 0x03, + CA_SLEEP_REQ = 0x02, + HOST_PORT_ACK = 0x01, + ACKMB7_INIT = 0x00 +}; + +#endif /* __MACH_PRCMU_FW_DEFS_V1_H */ diff --git a/board/st/u8500/prcmu-fw.h b/board/st/u8500/prcmu-fw.h new file mode 100644 index 000000000..0e4362629 --- /dev/null +++ b/board/st/u8500/prcmu-fw.h @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2009 ST-Ericsson SA + * + * 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. + * + * Copied from the Linux version: + * Author: Kumar Sanghvi + */ + +#ifndef __MACH_PRCMU_FW_V1_H +#define __MACH_PRCMU_FW_V1_H + +#include "prcmu-fw-defs_v1.h" + +#define _PRCMU_TCDM_BASE U8500_PRCMU_TCDM_BASE +#define PRCM_BOOT_STATUS (_PRCMU_TCDM_BASE + 0xFFF) +#define PRCM_ROMCODE_A2P (_PRCMU_TCDM_BASE + 0xFFE) +#define PRCM_ROMCODE_P2A (_PRCMU_TCDM_BASE + 0xFFD) +#define PRCM_XP70_CUR_PWR_STATE (_PRCMU_TCDM_BASE + 0xFFC) /* 4 BYTES */ + + +#define _PRCM_MBOX_HEADER (_PRCMU_TCDM_BASE + 0xFE8)/*16 bytes*/ +#define PRCM_MBOX_HEADER_REQ_MB0 (_PRCM_MBOX_HEADER + 0x0) +#define PRCM_MBOX_HEADER_REQ_MB1 (_PRCM_MBOX_HEADER + 0x1) +#define PRCM_MBOX_HEADER_REQ_MB2 (_PRCM_MBOX_HEADER + 0x2) +#define PRCM_MBOX_HEADER_REQ_MB3 (_PRCM_MBOX_HEADER + 0x3) +#define PRCM_MBOX_HEADER_REQ_MB4 (_PRCM_MBOX_HEADER + 0x4) +#define PRCM_MBOX_HEADER_REQ_MB5 (_PRCM_MBOX_HEADER + 0x5) +#define PRCM_MBOX_HEADER_REQ_MB6 (_PRCM_MBOX_HEADER + 0x6) +#define PRCM_MBOX_HEADER_REQ_MB7 (_PRCM_MBOX_HEADER + 0x7) +#define PRCM_MBOX_HEADER_ACK_MB0 (_PRCM_MBOX_HEADER + 0x8) +#define PRCM_MBOX_HEADER_ACK_MB1 (_PRCM_MBOX_HEADER + 0x9) +#define PRCM_MBOX_HEADER_ACK_MB2 (_PRCM_MBOX_HEADER + 0xA) +#define PRCM_MBOX_HEADER_ACK_MB3 (_PRCM_MBOX_HEADER + 0xB) +#define PRCM_MBOX_HEADER_ACK_MB4 (_PRCM_MBOX_HEADER + 0xC) +#define PRCM_MBOX_HEADER_ACK_MB5 (_PRCM_MBOX_HEADER + 0xD) +#define PRCM_MBOX_HEADER_ACK_MB6 (_PRCM_MBOX_HEADER + 0xE) +#define PRCM_MBOX_HEADER_ACK_MB7 (_PRCM_MBOX_HEADER + 0xF) + +/*Req Mailboxes */ +#define PRCM_REQ_MB0 (_PRCMU_TCDM_BASE + 0xFDC) /* 12 bytes */ +#define PRCM_REQ_MB1 (_PRCMU_TCDM_BASE + 0xFD0) /* 12 bytes */ +#define PRCM_REQ_MB2 (_PRCMU_TCDM_BASE + 0xFC0) /* 16 bytes */ +#define PRCM_REQ_MB3 (_PRCMU_TCDM_BASE + 0xE4C) /* 372 bytes */ +#define PRCM_REQ_MB4 (_PRCMU_TCDM_BASE + 0xE48) /* 4 bytes */ +#define PRCM_REQ_MB5 (_PRCMU_TCDM_BASE + 0xE44) /* 4 bytes */ +#define PRCM_REQ_MB6 (_PRCMU_TCDM_BASE + 0xE40) /* 4 bytes */ +#define PRCM_REQ_MB7 (_PRCMU_TCDM_BASE + 0xE3C) /* 4 bytes */ + +/*Ack Mailboxes */ +#define PRCM_ACK_MB0 (_PRCMU_TCDM_BASE + 0xE08) /* 52 bytes */ +#define PRCM_ACK_MB1 (_PRCMU_TCDM_BASE + 0xE04) /* 4 bytes */ +#define PRCM_ACK_MB2 (_PRCMU_TCDM_BASE + 0xE00) /* 4 bytes */ +#define PRCM_ACK_MB3 (_PRCMU_TCDM_BASE + 0xDFC) /* 4 bytes */ +#define PRCM_ACK_MB4 (_PRCMU_TCDM_BASE + 0xDF8) /* 4 bytes */ +#define PRCM_ACK_MB5 (_PRCMU_TCDM_BASE + 0xDF4) /* 4 bytes */ +#define PRCM_ACK_MB6 (_PRCMU_TCDM_BASE + 0xDF0) /* 4 bytes */ +#define PRCM_ACK_MB7 (_PRCMU_TCDM_BASE + 0xDEC) /* 4 bytes */ + +/* Mailbox 0 REQs */ +#define PRCM_REQ_MB0_PWRSTTRH (PRCM_REQ_MB0 + 0x0) +#define PRCM_REQ_MB0_PWRSTTRH_APPWRST (PRCM_REQ_MB0 + 0x0) +#define PRCM_REQ_MB0_PWRSTTRH_APPLLST (PRCM_REQ_MB0 + 0x1) +#define PRCM_REQ_MB0_PWRSTTRH_ULPCLKST (PRCM_REQ_MB0 + 0x2) +#define PRCM_REQ_MB0_PWRSTTRH_BYTEFILL (PRCM_REQ_MB0 + 0x3) +#define PRCM_REQ_MB0_WKUP_8500 (PRCM_REQ_MB0 + 0x4) +#define PRCM_REQ_MB0_WKUP_4500 (PRCM_REQ_MB0 + 0x8) + + +/* Mailbox 0 ACKs */ +#define PRCM_ACK_MB0_AP_PWRST_STATUS (PRCM_ACK_MB0 + 0x0) +#define PRCM_ACK_MB0_PINGPONG_RDP (PRCM_ACK_MB0 + 0x1) +#define PRCM_ACK_MB0_PINGPONG_WKUP_RST_0 (PRCM_ACK_MB0 + 0x2) +#define PRCM_ACK_MB0_PINGPONG_WKUP_RST_1 (PRCM_ACK_MB0 + 0x3) +#define PRCM_ACK_MB0_WK0_EVENT_8500 (_PRCMU_TCDM_BASE + 0xE0C) +#define PRCM_ACK_MB0_WK0_EVENT_4500 (_PRCMU_TCDM_BASE + 0xE10) +#define PRCM_ACK_MB0_WK1_EVENT_8500 (_PRCMU_TCDM_BASE + 0xE24) +#define PRCM_ACK_MB0_WK1_EVENT_4500 (_PRCMU_TCDM_BASE + 0xE28) +#define PRCM_ACK_MB0_EVENT_4500_NUMBERS 20 + + +/* Mailbox 1 Requests */ +#define PRCM_REQ_MB1_ARMOPP (PRCM_REQ_MB1 + 0x0) +#define PRCM_REQ_MB1_APEOPP (PRCM_REQ_MB1 + 0x1) +#define PRCM_REQ_MB1_BOOSTOPP (PRCM_REQ_MB1 + 0x2) + +/* Mailbox 1 ACKs */ +#define PRCM_ACK_MB1_CURR_ARMOPP (PRCM_ACK_MB1 + 0x0) +#define PRCM_ACK_MB1_CURR_APEOPP (PRCM_ACK_MB1 + 0x1) +#define PRCM_ACK_MB1_CURR_BOOSTOPP (PRCM_ACK_MB1 + 0x2) +#define PRCM_ACK_MB1_CURR_DVFS_STATUS (PRCM_ACK_MB1 + 0x3) + +/* Mailbox 2 REQs */ +#define PRCM_REQ_MB2_DPS_SVAMMDSP (PRCM_REQ_MB2 + 0x0) +#define PRCM_REQ_MB2_DPS_SVAPIPE (PRCM_REQ_MB2 + 0x1) +#define PRCM_REQ_MB2_DPS_SIAMMDSP (PRCM_REQ_MB2 + 0x2) +#define PRCM_REQ_MB2_DPS_SIAPIPE (PRCM_REQ_MB2 + 0x3) +#define PRCM_REQ_MB2_DPS_SGA (PRCM_REQ_MB2 + 0x4) +#define PRCM_REQ_MB2_DPS_B2R2MCDE (PRCM_REQ_MB2 + 0x5) +#define PRCM_REQ_MB2_DPS_ESRAM12 (PRCM_REQ_MB2 + 0x6) +#define PRCM_REQ_MB2_DPS_ESRAM34 (PRCM_REQ_MB2 + 0x7) +#define PRCM_REQ_MB2_AUTOPWR_APSLEEP (PRCM_REQ_MB2 + 0x8) +#define PRCM_REQ_MB2_AUTOPWR_APSLEEP_SIA_PWRON_ENABLE (PRCM_REQ_MB2 + 0x9) +#define PRCM_REQ_MB2_AUTOPWR_APSLEEP_SVA_PWRON_ENABLE (PRCM_REQ_MB2 + 0xA) +#define PRCM_REQ_MB2_AUTOPWR_APSLEEP_AUTO_PWRON_ENABLE (PRCM_REQ_MB2 + 0xB) +#define PRCM_REQ_MB2_AUTOPWR_APIDLE (PRCM_REQ_MB2 + 0xC) +#define PRCM_REQ_MB2_AUTOPWR_APIDLE_SIA_PWRON_ENABLE (PRCM_REQ_MB2 + 0xD) +#define PRCM_REQ_MB2_AUTOPWR_APIDLE_SVA_PWRON_ENABLE (PRCM_REQ_MB2 + 0xE) +#define PRCM_REQ_MB2_AUTOPWR_APIDLE_AUTO_PWRON_ENABLE (PRCM_REQ_MB2 + 0xF) + +/* Mailbox 2 ACKs */ +#define PRCM_ACK_MB2_DPS_STATUS (PRCM_ACK_MB2 + 0x0) + +/* Mailbox 5 Requests */ +#define PRCM_REQ_MB5_I2COPTYPE_REG (PRCM_REQ_MB5 + 0x0) +#define PRCM_REQ_MB5_BIT_FIELDS (PRCM_REQ_MB5 + 0x1) +#define PRCM_REQ_MB5_I2CSLAVE (PRCM_REQ_MB5 + 0x2) +#define PRCM_REQ_MB5_I2CVAL (PRCM_REQ_MB5 + 0x3) + +/* Mailbox 5 ACKs */ +#define PRCM_ACK_MB5_STATUS (PRCM_ACK_MB5 + 0x1) +#define PRCM_ACK_MB5_SLAVE (PRCM_ACK_MB5 + 0x2) +#define PRCM_ACK_MB5_VAL (PRCM_ACK_MB5 + 0x3) + +#define LOW_POWER_WAKEUP 1 +#define EXE_WAKEUP 0 + +/* FIXME : Need to Cleanup Code */ + +#define PRCM_SVAMMDSPSTATUS PRCM_REQ_MB6 +#define PRCM_SIAMMDSPSTATUS PRCM_REQ_MB7 + + +#define PRCM_XP70_TRIG_IT10 (1 << 0) +#define PRCM_XP70_TRIG_IT11 (1 << 1) +#define PRCM_XP70_TRIG_IT12 (1 << 2) +#define PRCM_XP70_TRIG_IT14 (1 << 4) +#define PRCM_XP70_TRIG_IT17 (1 << 5) + +enum mailbox_t { + REQ_MB0 = 0, /* Uses XP70_IT_EVENT_10 */ + REQ_MB1 = 1, /* Uses XP70_IT_EVENT_11 */ + REQ_MB2 = 2, /* Uses XP70_IT_EVENT_12 */ + REQ_MB5 = 5, /* Uses XP70_IT_EVENT_17 */ +}; + +/* Union declaration */ + + + +/* ARM to XP70 mailbox definition */ +union req_mb0_t { + struct { + enum ap_pwrst_trans_t ap_pwrst_trans:8; + enum intr_wakeup_t fifo_4500wu:8; + enum ddr_pwrst_t ddr_pwrst:8; + unsigned int unused:8; + } req_field; + unsigned int complete_field; +}; + +/* mailbox definition for ARM/APE operation */ +union req_mb1_t { + struct { + enum arm_opp_t arm_opp:8; + enum ape_opp_t ape_opp:8; + } req_field; + unsigned short complete_field; +}; + +#endif /* __MACH_PRCMU_FW_V1_H */ diff --git a/board/st/u8500/prcmu.c b/board/st/u8500/prcmu.c new file mode 100644 index 000000000..43e4cbef5 --- /dev/null +++ b/board/st/u8500/prcmu.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2009 ST-Ericsson SA + * + * 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. + * + * Adapted from the Linux version: + * Author: Kumar Sanghvi + */ + +/* + * NOTE: This currently does not support the I2C workaround access method. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "prcmu-fw.h" + +#define DEBUG 0 +#define dbg_printk(format, arg...) \ + if (DEBUG) \ + printf("prcmu: " format, ##arg) \ + +#define PRCMU_BASE U8500_PRCMU_BASE + +/* CPU mailbox registers */ +#define PRCM_MBOX_CPU_VAL (PRCMU_BASE + 0x0fc) +#define PRCM_MBOX_CPU_SET (PRCMU_BASE + 0x100) +#define PRCM_MBOX_CPU_CLR (PRCMU_BASE + 0x104) + +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_req_complete(enum mailbox_t num) +{ + int timeout = 1000; + + /* checking any already on-going transaction */ + while ((readl(PRCM_MBOX_CPU_VAL) & (1 << num)) && timeout--) + ; + + timeout = 1000; + + /* Set an interrupt to XP70 */ + writel(1 << num, PRCM_MBOX_CPU_SET); + + while ((readl(PRCM_MBOX_CPU_VAL) & (1 << num)) && timeout--) + ; + + if (!timeout) { + printf("PRCMU operation timed out\n"); + 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; + + if (!prcmu_is_ready()) + return -1; + + dbg_printk("\nprcmu_4500_i2c_read:bank=%x;reg=%x;\n", + reg, slave); + + /* prepare the data for mailbox 5 */ + writeb((reg << 1) | I2CREAD, 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); + + _wait_for_req_complete(REQ_MB5); + + /* retrieve values */ + dbg_printk("ack-mb5:transfer status = %x\n", + readb(PRCM_ACK_MB5_STATUS)); + dbg_printk("ack-mb5:reg bank = %x\n", readb(PRCM_ACK_MB5) >> 1); + dbg_printk("ack-mb5:slave_add = %x\n", + readb(PRCM_ACK_MB5_SLAVE)); + dbg_printk("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); + + if (i2c_status == I2C_RD_OK) + return i2c_val; + else { + + 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; + + if (!prcmu_is_ready()) + return -1; + + dbg_printk("\nprcmu_4500_i2c_write:bank=%x;reg=%x;\n", + reg, slave); + + /* prepare the data for mailbox 5 */ + writeb((reg << 1) | I2CWRITE, 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); + + dbg_printk("\ncpu_is_u8500v11\n"); + _wait_for_req_complete(REQ_MB5); + + /* retrieve values */ + dbg_printk("ack-mb5:transfer status = %x\n", + readb(PRCM_ACK_MB5_STATUS)); + dbg_printk("ack-mb5:reg bank = %x\n", readb(PRCM_ACK_MB5) >> 1); + dbg_printk("ack-mb5:slave_add = %x\n", + readb(PRCM_ACK_MB5_SLAVE)); + dbg_printk("ack-mb5:reg_val = %d\n", readb(PRCM_ACK_MB5_VAL)); + + i2c_status = readb(PRCM_ACK_MB5_STATUS); + dbg_printk("\ni2c_status = %x\n", i2c_status); + if (i2c_status == I2C_WR_OK) + return 0; + else { + printf("ape-i2c: i2c_status : 0x%x\n", i2c_status); + return -1; + } +} diff --git a/board/st/u8500/u8500.c b/board/st/u8500/u8500.c index cf6b70bdc..02df1ed53 100644 --- a/board/st/u8500/u8500.c +++ b/board/st/u8500/u8500.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "gpio.h" #include "common.h" @@ -126,13 +127,22 @@ void show_boot_progress(int progress) } #endif -int u8500_is_earlydrop(void) +static unsigned int read_asicid(void) { unsigned int *address = (void *)U8500_BOOTROM_BASE + U8500_BOOTROM_ASIC_ID_OFFSET; + return readl(address); +} +int u8500_is_earlydrop(void) +{ /* 0x01 for ED, 0xA0 for v1 */ - return (readl(address) & 0xff) == 0x01; + return (read_asicid() & 0xff) == 0x01; +} + +int cpu_is_u8500v11(void) +{ + return read_asicid() == 0x008500A1; } /* @@ -190,6 +200,62 @@ unsigned int addr_vall_arr[] = { }; #ifdef BOARD_LATE_INIT +#ifdef CONFIG_MMC + +#define LDO_VAUX3_MASK 0x3 +#define LDO_VAUX3_ENABLE 0x1 +#define VAUX3_VOLTAGE_2_9V 0xd + +static int hrefplus_mmc_power_init(void) +{ + int ret; + int val; + + if (!cpu_is_u8500v11()) + return 0; + + /* + * 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. + */ + + ret = ab8500_read(AB8500_REGU_CTRL2, AB8500_REGU_VRF1VAUX3_REGU_REG); + if (ret < 0) + goto out; + + val = ret; + + /* Turn off */ + ret = ab8500_write(AB8500_REGU_CTRL2, AB8500_REGU_VRF1VAUX3_REGU_REG, + val & ~LDO_VAUX3_MASK); + if (ret < 0) + goto out; + + udelay(10 * 1000); + + /* Set the voltage to 2.9V */ + ret = ab8500_write(AB8500_REGU_CTRL2, + AB8500_REGU_VRF1VAUX3_SEL_REG, VAUX3_VOLTAGE_2_9V); + if (ret < 0) + goto out; + + val = val & ~LDO_VAUX3_MASK; + val = val | LDO_VAUX3_ENABLE; + + /* Turn on the supply */ + ret = ab8500_write(AB8500_REGU_CTRL2, + AB8500_REGU_VRF1VAUX3_REGU_REG, val); + +out: + return ret; +} +#endif /* * called after all initialisation were done, but before the generic * mmc_initialize(). @@ -219,6 +285,8 @@ int board_late_init(void) setenv("board_id", "1"); } #ifdef CONFIG_MMC + hrefplus_mmc_power_init(); + /* * config extended GPIO pins for level shifter and * SDMMC_ENABLE -- cgit v1.2.3