| /* |
| * Copyright (C) 2015 Broadcom Corporation |
| * |
| * 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; version 2 of the License. |
| * |
| * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <arch/io.h> |
| #include <delay.h> |
| #include <console/console.h> |
| #include <soc/tz.h> |
| #include <soc/hw_init.h> |
| |
| /***************************************************************************** |
| * TrustZone |
| *****************************************************************************/ |
| #define IHOST_SCU_SECURE_ACCESS 0x19020054 |
| |
| #define SMAU_NIC_IDM_TZ_BASE 0x180150a0 |
| #define SMAU_DDR_TZ_BASE 0x18015200 |
| #define SMAU_FLASH0_TZ_BASE 0x18015300 |
| #define SMAU_FLASH1_TZ_BASE 0x18015308 |
| #define SMAU_FLASH2_TZ_BASE 0x18015310 |
| #define SMAU_FLASH3_TZ_BASE 0x18015318 |
| #define SMAU_TZ_BASE_ENABLE 0x00000001 |
| |
| #define CRMU_IPROC_ADDR_RANGE0_LOW 0x03024c30 |
| #define CRMU_IPROC_ADDR_RANGE0_HIGH 0x03024c34 |
| #define CRMU_ADDR_MASK 0xffffff00 |
| #define CRMU_ADDR_VALID 0x00000001 |
| #define CRMU_ADDR_START 0x03010000 |
| #define CRMU_ADDR_END 0x03100000 |
| |
| static void scu_ns_config(void) |
| { |
| /* |
| * Enable NS SCU access to ARM global timer, private timer, and |
| * components |
| */ |
| write32((void *)IHOST_SCU_SECURE_ACCESS, 0xFFF); |
| } |
| |
| static void smau_ns_config(void) |
| { |
| unsigned int val; |
| |
| /* Disable SMAU NIC IDM TZ */ |
| val = read32((void *)SMAU_NIC_IDM_TZ_BASE); |
| val &= ~SMAU_TZ_BASE_ENABLE; |
| write32((void *)SMAU_NIC_IDM_TZ_BASE, val); |
| |
| /* |
| * Disable DDR TZ base |
| * |
| * This means the entire DDR is marked as NS |
| * |
| * NOTE: In the future, multiple regions of DDR may need to be marked |
| * as SECURE for secure OS and other TZ usages |
| */ |
| val = read32((void *)SMAU_DDR_TZ_BASE); |
| val &= ~SMAU_TZ_BASE_ENABLE; |
| write32((void *)SMAU_DDR_TZ_BASE, val); |
| |
| |
| /* |
| * Disable flash TZ support |
| * |
| * The entire flash is currently marked as NS |
| * |
| * NOTE: In the future, multiple regions of flash may need to be marked |
| * as SECURE for secure OS and other TZ firmware/data storage |
| */ |
| |
| /* Flash 0: ROM */ |
| val = read32((void *)SMAU_FLASH0_TZ_BASE); |
| val &= ~SMAU_TZ_BASE_ENABLE; |
| write32((void *)SMAU_FLASH0_TZ_BASE, val); |
| |
| /* Flash 1: QSPI */ |
| val = read32((void *)SMAU_FLASH1_TZ_BASE); |
| val &= ~SMAU_TZ_BASE_ENABLE; |
| write32((void *)SMAU_FLASH1_TZ_BASE, val); |
| |
| /* Flash 2: NAND */ |
| val = read32((void *)SMAU_FLASH2_TZ_BASE); |
| val &= ~SMAU_TZ_BASE_ENABLE; |
| write32((void *)SMAU_FLASH2_TZ_BASE, val); |
| |
| /* Flash 3: PNOR */ |
| val = read32((void *)SMAU_FLASH3_TZ_BASE); |
| val &= ~SMAU_TZ_BASE_ENABLE; |
| write32((void *)SMAU_FLASH3_TZ_BASE, val); |
| } |
| |
| static void crmu_ns_config(void) |
| { |
| |
| /* |
| * Currently open up the entire CRMU to allow iPROC NS access |
| * |
| * NOTE: In the future, we might want to protect particular CRMU |
| * sub-blocks to allow SECURE access only. That can be done by |
| * programing the CRMU IPROC address range registers. Up to 4 access |
| * windows can be created |
| */ |
| write32((void *)CRMU_IPROC_ADDR_RANGE0_LOW, |
| (CRMU_ADDR_START & CRMU_ADDR_MASK) | CRMU_ADDR_VALID); |
| write32((void *)CRMU_IPROC_ADDR_RANGE0_HIGH, |
| (CRMU_ADDR_END & CRMU_ADDR_MASK) | CRMU_ADDR_VALID); |
| } |
| |
| static void tz_init(void) |
| { |
| /* Configure the Cygnus for non-secure access */ |
| /* ARM Cortex A9 SCU NS access configuration */ |
| scu_ns_config(); |
| |
| /* SMAU NS related configurations */ |
| smau_ns_config(); |
| |
| /* CRMU NS related configurations */ |
| crmu_ns_config(); |
| |
| /* |
| * Configure multiple masters and slaves to run in NS |
| */ |
| tz_set_non_virtual_slaves_security(0xFFFFFFFF, TZ_STATE_NON_SECURE); |
| tz_set_periph_security(0xFFFFFFFF, TZ_STATE_NON_SECURE); |
| tz_set_masters_security(0xFFFFFFFF, TZ_STATE_NON_SECURE); |
| tz_set_wrapper_security(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, |
| TZ_STATE_NON_SECURE); |
| tz_set_cfg_slaves_security(0xFFFFFFFF, TZ_STATE_NON_SECURE); |
| |
| tz_set_ext_slaves_security(0xFFFFFFFF, TZ_STATE_NON_SECURE); |
| |
| /* configure sec peripherals to be accessed from non-secure world */ |
| tz_set_sec_periphs_security(0xFFFFFFFF & |
| ~(CYGNUS_sec_periph_APBz_sotp | |
| CYGNUS_sec_periph_APBz_tzpc), |
| TZ_STATE_NON_SECURE); |
| |
| /* default sram to non-secure */ |
| tz_set_sram_sec_region(0); |
| } |
| |
| /***************************************************************************** |
| * DMAC |
| *****************************************************************************/ |
| #define DMAC_M0_IDM_RESET_CONTROL 0x1810f800 |
| #define DMAC_RESET_MASK 0x00000001 |
| #define DMAC_RESET_TIMEOUT 1000 |
| |
| static void dmac_init(void) |
| { |
| unsigned int val, timeout; |
| |
| /* bring the DMAC block out of reset */ |
| val = read32((void *)DMAC_M0_IDM_RESET_CONTROL); |
| val |= DMAC_RESET_MASK; |
| write32((void *)DMAC_M0_IDM_RESET_CONTROL, val); |
| udelay(10); |
| val &= ~DMAC_RESET_MASK; |
| write32((void *)DMAC_M0_IDM_RESET_CONTROL, val); |
| |
| timeout = 0; |
| while (read32((void *)DMAC_M0_IDM_RESET_CONTROL) & DMAC_RESET_MASK) { |
| udelay(1); |
| if (timeout++ > DMAC_RESET_TIMEOUT) |
| die("Failed to bring PL330 DMAC out of reset\n"); |
| } |
| } |
| |
| /***************************************************************************** |
| * Neon |
| *****************************************************************************/ |
| #define CRU_CONTROL 0x1800e000 |
| #define CRU_CONTROL_NEON_RESET_N 0x00000040 |
| |
| #define CRU_IHOST_PWRDWN_EN 0x1800e004 |
| #define CRU_IHOST_PWRDWN_EN_CLAMPON_NEON 0x00100000 |
| #define CRU_IHOST_PWRDWN_EN_PWRON_NEON 0x00200000 |
| #define CRU_IHOST_PWRDWN_EN_PWROK_NEON 0x00400000 |
| |
| #define CRU_IHOST_PWRDWN_STATUS 0x1800e008 |
| #define CRU_IHOST_PWRDWN_STATUS_PWRON_NEON 0x00200000 |
| #define CRU_IHOST_PWRDWN_STATUS_PWROK_NEON 0x00400000 |
| |
| #define CRU_STATUS_DELAY_US 1 |
| #define CRU_MAX_RETRY_COUNT 10 |
| #define CRU_RETRY_INTVL_US 1 |
| |
| static void neon_init(void) |
| { |
| unsigned int i, val; |
| |
| /* put Neon into reset */ |
| val = read32((void *)CRU_CONTROL); |
| val &= ~CRU_CONTROL_NEON_RESET_N; |
| write32((void *)CRU_CONTROL, val); |
| |
| /* assert the power on register bit */ |
| val = read32((void *)CRU_IHOST_PWRDWN_EN); |
| val |= CRU_IHOST_PWRDWN_EN_PWRON_NEON; |
| write32((void *)CRU_IHOST_PWRDWN_EN, val); |
| |
| /* wait for power on */ |
| i = 0; |
| while (!(read32((void *)CRU_IHOST_PWRDWN_STATUS) & |
| CRU_IHOST_PWRDWN_STATUS_PWRON_NEON)) { |
| udelay(CRU_RETRY_INTVL_US); |
| if (i++ >= CRU_MAX_RETRY_COUNT) |
| die("Failed to ack NEON power on\n"); |
| } |
| |
| udelay(CRU_STATUS_DELAY_US); |
| |
| /* assert the power ok register bit */ |
| val = read32((void *)CRU_IHOST_PWRDWN_EN); |
| val |= CRU_IHOST_PWRDWN_EN_PWROK_NEON; |
| write32((void *)CRU_IHOST_PWRDWN_EN, val); |
| |
| /* wait for power ok */ |
| i = 0; |
| while (!(read32((void *)CRU_IHOST_PWRDWN_STATUS) & |
| CRU_IHOST_PWRDWN_STATUS_PWROK_NEON)) { |
| udelay(CRU_RETRY_INTVL_US); |
| if (i++ >= CRU_MAX_RETRY_COUNT) |
| die("Failed to ack NEON power ok\n"); |
| } |
| |
| udelay(CRU_STATUS_DELAY_US); |
| |
| /* clamp off for the NEON block */ |
| val = read32((void *)CRU_IHOST_PWRDWN_EN); |
| val &= ~CRU_IHOST_PWRDWN_EN_CLAMPON_NEON; |
| write32((void *)CRU_IHOST_PWRDWN_EN, val); |
| |
| udelay(CRU_STATUS_DELAY_US); |
| |
| /* bring NEON out of reset */ |
| val = read32((void *)CRU_CONTROL); |
| val |= CRU_CONTROL_NEON_RESET_N; |
| write32((void *)CRU_CONTROL, val); |
| } |
| |
| /***************************************************************************** |
| * PCIe |
| *****************************************************************************/ |
| #define CRMU_PCIE_CFG 0x0301d0a0 |
| #define PCIE0_LNK_PHY_IDDQ 0x00000004 |
| #define PCIE1_LNK_PHY_IDDQ 0x00000400 |
| |
| static void pcie_init(void) |
| { |
| unsigned int val; |
| |
| /* |
| * Force all AFEs of both PCIe0 and PCIe1 to be powered down, including |
| * pad biasing |
| * |
| * This brings down the PCIe interfaces to the lowest possible power |
| * mode |
| */ |
| val = read32((void *)CRMU_PCIE_CFG); |
| val |= PCIE1_LNK_PHY_IDDQ | PCIE0_LNK_PHY_IDDQ; |
| write32((void *)CRMU_PCIE_CFG, val); |
| } |
| |
| /***************************************************************************** |
| * M0 |
| *****************************************************************************/ |
| #define CRMU_MCU_ACCESS_CONTROL 0x03024c00 |
| #define CRMU_MCU_ACCESS_MODE_SECURE 0x2 |
| |
| static void M0_init(void) |
| { |
| /* Set M0 as a secure master */ |
| write32((void *)CRMU_MCU_ACCESS_CONTROL, CRMU_MCU_ACCESS_MODE_SECURE); |
| } |
| |
| /***************************************************************************** |
| * CCU |
| *****************************************************************************/ |
| #define IHOST_PROC_CLK_WR_ACCESS 0x19000000 |
| #define IHOST_PROC_CLK_POLICY_FREQ 0x19000008 |
| #define IHOST_PROC_CLK_POLICY_CTL 0x1900000c |
| #define IHOST_PROC_CLK_POLICY0_MASK 0x19000010 |
| #define IHOST_PROC_CLK_POLICY1_MASK 0x19000014 |
| #define IHOST_PROC_CLK_POLICY2_MASK 0x19000018 |
| #define IHOST_PROC_CLK_POLICY3_MASK 0x1900001c |
| #define IHOST_PROC_CLK_INTEN 0x19000020 |
| #define IHOST_PROC_CLK_INTSTAT 0x19000024 |
| #define IHOST_PROC_CLK_LVM_EN 0x19000034 |
| #define IHOST_PROC_CLK_LVM0_3 0x19000038 |
| #define IHOST_PROC_CLK_LVM4_7 0x1900003c |
| #define IHOST_PROC_CLK_VLT0_3 0x19000040 |
| #define IHOST_PROC_CLK_VLT4_7 0x19000044 |
| #define IHOST_PROC_CLK_BUS_QUIESC 0x19000100 |
| #define IHOST_PROC_CLK_CORE0_CLKGATE 0x19000200 |
| #define IHOST_PROC_CLK_CORE1_CLKGATE 0x19000204 |
| #define IHOST_PROC_CLK_ARM_SWITCH_CLKGATE 0x19000210 |
| #define IHOST_PROC_CLK_ARM_PERIPH_CLKGATE 0x19000300 |
| #define IHOST_PROC_CLK_APB0_CLKGATE 0x19000400 |
| #define IHOST_PROC_CLK_PL310_DIV 0x19000a00 |
| #define IHOST_PROC_CLK_PL310_TRIGGER 0x19000a04 |
| #define IHOST_PROC_CLK_ARM_SWITCH_DIV 0x19000a08 |
| #define IHOST_PROC_CLK_ARM_SWITCH_TRIGGER 0x19000a0c |
| #define IHOST_PROC_CLK_APB_DIV 0x19000a10 |
| #define IHOST_PROC_CLK_APB_DIV_TRIGGER 0x19000a14 |
| #define IHOST_PROC_CLK_PLLARMA 0x19000c00 |
| #define IHOST_PROC_CLK_PLLARMB 0x19000c04 |
| #define IHOST_PROC_CLK_PLLARMC 0x19000c08 |
| #define IHOST_PROC_CLK_PLLARMCTRL0 0x19000c0c |
| #define IHOST_PROC_CLK_PLLARMCTRL1 0x19000c10 |
| #define IHOST_PROC_CLK_PLLARMCTRL2 0x19000c14 |
| #define IHOST_PROC_CLK_PLLARMCTRL3 0x19000c18 |
| #define IHOST_PROC_CLK_PLLARMCTRL4 0x19000c1c |
| #define IHOST_PROC_CLK_PLLARMCTRL5 0x19000c20 |
| #define IHOST_PROC_CLK_PLLARM_OFFSET 0x19000c24 |
| #define IHOST_PROC_CLK_ARM_DIV 0x19000e00 |
| #define IHOST_PROC_CLK_ARM_SEG_TRG 0x19000e04 |
| #define IHOST_PROC_CLK_ARM_SEG_TRG_OVERRIDE 0x19000e08 |
| #define IHOST_PROC_CLK_PLL_DEBUG 0x19000e10 |
| #define IHOST_PROC_CLK_ACTIVITY_MON1 0x19000e20 |
| #define IHOST_PROC_CLK_ACTIVITY_MON2 0x19000e24 |
| #define IHOST_PROC_CLK_CLKGATE_DBG 0x19000e40 |
| #define IHOST_PROC_CLK_APB_CLKGATE_DBG1 0x19000e48 |
| #define IHOST_PROC_CLK_CLKMON 0x19000e64 |
| #define IHOST_PROC_CLK_POLICY_DBG 0x19000ec0 |
| #define IHOST_PROC_CLK_TGTMASK_DBG1 0x19000ec4 |
| #define IHOST_PROC_RST_WR_ACCESS 0x19000f00 |
| #define IHOST_PROC_RST_SOFT_RSTN 0x19000f04 |
| #define IHOST_PROC_RST_A9_CORE_SOFT_RSTN 0x19000f08 |
| |
| #define WR_ACCESS_PRIVATE_ACCESS_MODE 0x80000000 |
| |
| static uint32_t ccu_reg[] = { |
| IHOST_PROC_CLK_WR_ACCESS, |
| IHOST_PROC_CLK_POLICY_FREQ, |
| IHOST_PROC_CLK_POLICY_CTL, |
| IHOST_PROC_CLK_POLICY0_MASK, |
| IHOST_PROC_CLK_POLICY1_MASK, |
| IHOST_PROC_CLK_POLICY2_MASK, |
| IHOST_PROC_CLK_POLICY3_MASK, |
| IHOST_PROC_CLK_INTEN, |
| IHOST_PROC_CLK_INTSTAT, |
| IHOST_PROC_CLK_LVM_EN, |
| IHOST_PROC_CLK_LVM0_3, |
| IHOST_PROC_CLK_LVM4_7, |
| IHOST_PROC_CLK_VLT0_3, |
| IHOST_PROC_CLK_VLT4_7, |
| IHOST_PROC_CLK_BUS_QUIESC, |
| IHOST_PROC_CLK_CORE0_CLKGATE, |
| IHOST_PROC_CLK_CORE1_CLKGATE, |
| IHOST_PROC_CLK_ARM_SWITCH_CLKGATE, |
| IHOST_PROC_CLK_ARM_PERIPH_CLKGATE, |
| IHOST_PROC_CLK_APB0_CLKGATE, |
| IHOST_PROC_CLK_PL310_DIV, |
| IHOST_PROC_CLK_PL310_TRIGGER, |
| IHOST_PROC_CLK_ARM_SWITCH_DIV, |
| IHOST_PROC_CLK_ARM_SWITCH_TRIGGER, |
| IHOST_PROC_CLK_APB_DIV, |
| IHOST_PROC_CLK_APB_DIV_TRIGGER, |
| IHOST_PROC_CLK_PLLARMA, |
| IHOST_PROC_CLK_PLLARMB, |
| IHOST_PROC_CLK_PLLARMC, |
| IHOST_PROC_CLK_PLLARMCTRL0, |
| IHOST_PROC_CLK_PLLARMCTRL1, |
| IHOST_PROC_CLK_PLLARMCTRL2, |
| IHOST_PROC_CLK_PLLARMCTRL3, |
| IHOST_PROC_CLK_PLLARMCTRL4, |
| IHOST_PROC_CLK_PLLARMCTRL5, |
| IHOST_PROC_CLK_PLLARM_OFFSET, |
| IHOST_PROC_CLK_ARM_DIV, |
| IHOST_PROC_CLK_ARM_SEG_TRG, |
| IHOST_PROC_CLK_ARM_SEG_TRG_OVERRIDE, |
| IHOST_PROC_CLK_PLL_DEBUG, |
| IHOST_PROC_CLK_ACTIVITY_MON1, |
| IHOST_PROC_CLK_ACTIVITY_MON2, |
| IHOST_PROC_CLK_CLKGATE_DBG, |
| IHOST_PROC_CLK_APB_CLKGATE_DBG1, |
| IHOST_PROC_CLK_CLKMON, |
| IHOST_PROC_CLK_POLICY_DBG, |
| IHOST_PROC_CLK_TGTMASK_DBG1, |
| IHOST_PROC_RST_WR_ACCESS, |
| IHOST_PROC_RST_SOFT_RSTN, |
| IHOST_PROC_RST_A9_CORE_SOFT_RSTN |
| }; |
| |
| #define CCU_REG_TABLE_SIZE (sizeof(ccu_reg)/sizeof(ccu_reg[0])) |
| |
| /* Set priv_access_mode field to unrestricted (0) */ |
| static void ccu_init(void) |
| { |
| uint32_t val; |
| uint32_t i; |
| for (i = 0; i < CCU_REG_TABLE_SIZE; i++) { |
| val = read32((void *)(ccu_reg[i])); |
| val &= ~WR_ACCESS_PRIVATE_ACCESS_MODE; |
| write32((void *)(ccu_reg[i]), val); |
| } |
| } |
| |
| /***************************************************************************** |
| * LCD |
| *****************************************************************************/ |
| #define ASIU_TOP_CLK_GATING_CTRL 0x180aa024 |
| #define ASIU_TOP_CLK_GATING_CTRL_LCD_CLK_GATE_EN 0x00000010 |
| #define ASIU_TOP_CLK_GATING_CTRL_MIPI_DSI_CLK_GATE_EN 0x00000008 |
| #define ASIU_TOP_CLK_GATING_CTRL_GFX_CLK_GATE_EN 0x00000001 |
| #define ASIU_TOP_CLK_GATING_CTRL_AUD_CLK_GATE_EN 0x00000002 |
| |
| static void lcd_init(void) |
| { |
| unsigned int val; |
| |
| /* make sure the LCD clock is ungated */ |
| val = read32((void *)ASIU_TOP_CLK_GATING_CTRL); |
| val |= ASIU_TOP_CLK_GATING_CTRL_LCD_CLK_GATE_EN; |
| write32((void *)ASIU_TOP_CLK_GATING_CTRL, val); |
| } |
| |
| /******************************************************************* |
| * Default priority settings in Cygnus |
| * |
| * Master Name Default Priority |
| * ==================== ================= |
| * ihost_m0 12 |
| * mhost0_m0 12 |
| * mhost1_m0 ` 12 |
| * pcie0_m0 9 |
| * pcie0_m1 9 |
| * cmicd_m0 7 |
| * amac_m0 7 |
| * amac_m1 7 |
| * ext_m0 (LCD) 5 |
| * ext_m1 (V3D) 5 |
| * sdio_m0 3 |
| * sdio_m1 3 |
| * usb2h_m0 3 |
| * usb2d_m0 3 |
| * dmu_m0 3 |
| * a9jtag_m0 0 |
| * |
| *****************************************************************************/ |
| |
| #define AXIIC_EXT_M0_READ_QOS 0x1a057100 |
| #define AXIIC_EXT_M0_READ_MASK 0x0000000f |
| #define AXIIC_EXT_M0_WRITE_QOS 0x1a057104 |
| #define AXIIC_EXT_M0_WRITE_MASK 0x0000000f |
| |
| static void lcd_qos_init(unsigned int qos) |
| { |
| unsigned int val; |
| |
| val = read32((void *)AXIIC_EXT_M0_READ_QOS); |
| val &= ~AXIIC_EXT_M0_READ_MASK; |
| val |= (qos & AXIIC_EXT_M0_READ_MASK); |
| write32((void *)AXIIC_EXT_M0_READ_QOS, val); |
| |
| val = read32((void *)AXIIC_EXT_M0_WRITE_QOS); |
| val &= ~AXIIC_EXT_M0_WRITE_MASK; |
| val |= (qos & AXIIC_EXT_M0_WRITE_MASK); |
| write32((void *)AXIIC_EXT_M0_WRITE_QOS, val); |
| } |
| |
| /***************************************************************************** |
| * V3D |
| *****************************************************************************/ |
| static void v3d_init(void) |
| { |
| unsigned int val; |
| |
| /* make sure the V3D clock is ungated */ |
| val = read32((void *)ASIU_TOP_CLK_GATING_CTRL); |
| val |= ASIU_TOP_CLK_GATING_CTRL_MIPI_DSI_CLK_GATE_EN | |
| ASIU_TOP_CLK_GATING_CTRL_GFX_CLK_GATE_EN; |
| write32((void *)ASIU_TOP_CLK_GATING_CTRL, val); |
| } |
| |
| /***************************************************************************** |
| * Audio |
| *****************************************************************************/ |
| #define CRMU_PLL_AON_CTRL 0x0301c020 |
| #define CRMU_PLL_AON_CTRL_ASIU_AUDIO_GENPLL_PWRON_PLL 0x00000800 |
| #define CRMU_PLL_AON_CTRL_ASIU_AUDIO_GENPLL_PWRON_BG 0x00000400 |
| #define CRMU_PLL_AON_CTRL_ASIU_AUDIO_GENPLL_PWRON_LDO 0x00000200 |
| #define CRMU_PLL_AON_CTRL_ASIU_AUDIO_GENPLL_ISO_IN 0x00000100 |
| |
| static void audio_init(void) |
| { |
| unsigned int val; |
| |
| /* Ungate (enable) audio clock. */ |
| val = read32((void *)ASIU_TOP_CLK_GATING_CTRL); |
| val |= ASIU_TOP_CLK_GATING_CTRL_AUD_CLK_GATE_EN; |
| write32((void *)ASIU_TOP_CLK_GATING_CTRL, val); |
| |
| /* Power on audio GEN PLL, LDO, and BG. Input isolation = normal. */ |
| val = read32((void *)CRMU_PLL_AON_CTRL); |
| val |= CRMU_PLL_AON_CTRL_ASIU_AUDIO_GENPLL_PWRON_BG; |
| val |= CRMU_PLL_AON_CTRL_ASIU_AUDIO_GENPLL_PWRON_LDO; |
| val |= CRMU_PLL_AON_CTRL_ASIU_AUDIO_GENPLL_PWRON_PLL; |
| val &= ~CRMU_PLL_AON_CTRL_ASIU_AUDIO_GENPLL_ISO_IN; |
| write32((void *)CRMU_PLL_AON_CTRL, val); |
| } |
| |
| /***************************************************************************** |
| * SDIO |
| *****************************************************************************/ |
| #define CRMU_SDIO_1P8_FAIL_CONTROL 0x0301c0a0 |
| #define UHS1_18V_VREG_FAIL 0x00000001 |
| |
| #define SDIO_IDM0_IO_CONTROL_DIRECT 0x18116408 |
| #define SDIO_IDM1_IO_CONTROL_DIRECT 0x18117408 |
| #define SDIO_CMD_COMFLICT_DISABLE 0x00400000 |
| #define SDIO_FEEDBACK_CLK_EN 0x00200000 |
| #define SDIO_CLK_ENABLE 0x00000001 |
| |
| #define CDRU_SDIO0_IO_CONTROL 0x0301d144 |
| #define CDRU_SDIO1_IO_CONTROL 0x0301d140 |
| #define INPUT_DISABLE 0x00000080 |
| #define SLEW_RATE_ENABLE 0x00000040 |
| #define PULL_UP_ENABLE 0x00000020 |
| #define PULL_DOWN_ENABLE 0x00000010 |
| #define HYSTERESIS_ENABLE 0x00000008 |
| #define SDIO_DEFAULT_DRIVE_STRENGTH 0x4 /* 8 mA */ |
| |
| #define SDIO_IDM0_IDM_RESET_CONTROL 0x18116800 |
| #define SDIO_IDM1_IDM_RESET_CONTROL 0x18117800 |
| #define SDIO_RESET_MASK 0x00000001 |
| #define SDIO_RESET_TIMEOUT 1000 |
| |
| #define CRMU_SDIO_CONTROL0 0x0301d088 |
| #define CRMU_SDIO_CONTROL1 0x0301d08c |
| #define CRMU_SDIO_CONTROL2 0x0301d090 |
| #define CRMU_SDIO_CONTROL3 0x0301d094 |
| #define CRMU_SDIO_CONTROL4 0x0301d098 |
| #define CRMU_SDIO_CONTROL5 0x0301d09c |
| |
| /* |
| * SDIO_CAPS_L |
| * |
| * Field Bit(s) |
| * =========================== |
| * DDR50 31 |
| * SDR104 30 |
| * SDR50 29 |
| * SLOTTYPE 28:27 |
| * ASYNCHIRQ 26 |
| * SYSBUS64 25 |
| * V18 24 |
| * V3 23 |
| * V33 22 |
| * SUPRSM 21 |
| * SDMA 20 |
| * HSPEED 19 |
| * ADMA2 18 |
| * EXTBUSMED 17 |
| * MAXBLK 16:15 |
| * BCLK 14:7 |
| * TOUT 6 |
| * TOUTFREQ 5:0 |
| */ |
| #define SDIO_CAPS_L 0xA17C0000 |
| |
| /* |
| * SDIO_CAPS_H |
| * |
| * Field Bit(s) |
| * =========================== |
| * reserved 31:20 |
| * SPIBLOCKMODE 19 |
| * SPIMODE_CAP 18 |
| * CLOCKMULT 17:10 |
| * RETUNE_MODE 9:8 |
| * USETUNE_SDR50 7 |
| * TMRCNT_RETUNE 6:3 |
| * DRVR_TYPED 2 |
| * DRVR_TYPEC 1 |
| * DRVR_TYPEA 0 |
| */ |
| #define SDIO_CAPS_H 0x000C0087 |
| |
| /* |
| * Preset value |
| * |
| * Field Bit(s) |
| * =========================== |
| * Driver Strength 12:11 |
| * Clock Generator 10 |
| * SDCLK Frequeency 9:0 |
| */ |
| |
| /* |
| * SDIO_PRESETVAL1 |
| * |
| * Field Bit(s) Description |
| * ============================================================ |
| * DDR50_PRESET 25:13 Preset Value for DDR50 |
| * DEFAULT_PRESET 12:0 Preset Value for Default Speed |
| */ |
| #define SDIO_PRESETVAL1 0x01004004 |
| |
| /* |
| * SDIO_PRESETVAL2 |
| * |
| * Field Bit(s) Description |
| * ============================================================ |
| * HIGH_SPEED_PRESET 25:13 Preset Value for High Speed |
| * INIT_PRESET 12:0 Preset Value for Initialization |
| */ |
| #define SDIO_PRESETVAL2 0x01004100 |
| |
| /* |
| * SDIO_PRESETVAL3 |
| * |
| * Field Bit(s) Description |
| * ============================================================ |
| * SDR104_PRESET 25:13 Preset Value for SDR104 |
| * SDR12_PRESET 12:0 Preset Value for SDR12 |
| */ |
| #define SDIO_PRESETVAL3 0x00000004 |
| |
| /* |
| * SDIO_PRESETVAL4 |
| * |
| * Field Bit(s) Description |
| * ============================================================ |
| * SDR25_PRESET 25:13 Preset Value for SDR25 |
| * SDR50_PRESET 12:0 Preset Value for SDR50 |
| */ |
| #define SDIO_PRESETVAL4 0x01005001 |
| |
| static void sdio_ctrl_init(unsigned int idx) |
| { |
| unsigned int sdio_idm_io_control_direct_reg; |
| unsigned int cdru_sdio_io_control_reg; |
| unsigned int sdio_idm_reset_control_reg; |
| unsigned int val, timeout; |
| |
| switch (idx) { |
| case 0: |
| sdio_idm_io_control_direct_reg = SDIO_IDM0_IO_CONTROL_DIRECT; |
| cdru_sdio_io_control_reg = CDRU_SDIO0_IO_CONTROL; |
| sdio_idm_reset_control_reg = SDIO_IDM0_IDM_RESET_CONTROL; |
| break; |
| case 1: |
| sdio_idm_io_control_direct_reg = SDIO_IDM1_IO_CONTROL_DIRECT; |
| cdru_sdio_io_control_reg = CDRU_SDIO1_IO_CONTROL; |
| sdio_idm_reset_control_reg = SDIO_IDM1_IDM_RESET_CONTROL; |
| break; |
| default: |
| return; |
| } |
| |
| /* |
| * Disable the cmd conflict error interrupt and enable feedback clock |
| */ |
| val = read32((void *)sdio_idm_io_control_direct_reg); |
| val |= SDIO_CMD_COMFLICT_DISABLE | SDIO_FEEDBACK_CLK_EN | |
| SDIO_CLK_ENABLE; |
| write32((void *)sdio_idm_io_control_direct_reg, val); |
| |
| /* |
| * Set drive strength, enable hysteresis and slew rate control |
| */ |
| val = SDIO_DEFAULT_DRIVE_STRENGTH | |
| HYSTERESIS_ENABLE | SLEW_RATE_ENABLE; |
| write32((void *)cdru_sdio_io_control_reg, val); |
| |
| /* Reset SDIO controller */ |
| val = read32((void *)sdio_idm_reset_control_reg); |
| val |= SDIO_RESET_MASK; |
| write32((void *)sdio_idm_reset_control_reg, SDIO_RESET_MASK); |
| udelay(10); |
| val &= ~SDIO_RESET_MASK; |
| write32((void *)sdio_idm_reset_control_reg, val); |
| |
| timeout = 0; |
| while (read32((void *)sdio_idm_reset_control_reg) & SDIO_RESET_MASK) { |
| udelay(1); |
| if (timeout++ > SDIO_RESET_TIMEOUT) |
| die("Failed to bring SDIO out of reset\n"); |
| } |
| } |
| |
| static void sdio_init(void) |
| { |
| unsigned int val; |
| |
| /* |
| * Configure SDIO host controller capabilities |
| * (common setting for all SDIO controllers) |
| */ |
| write32((void *)CRMU_SDIO_CONTROL0, SDIO_CAPS_H); |
| write32((void *)CRMU_SDIO_CONTROL1, SDIO_CAPS_L); |
| /* |
| * Configure SDIO host controller preset values |
| * (common setting for all SDIO controllers) |
| */ |
| write32((void *)CRMU_SDIO_CONTROL2, SDIO_PRESETVAL1); |
| write32((void *)CRMU_SDIO_CONTROL3, SDIO_PRESETVAL2); |
| write32((void *)CRMU_SDIO_CONTROL4, SDIO_PRESETVAL3); |
| write32((void *)CRMU_SDIO_CONTROL5, SDIO_PRESETVAL4); |
| |
| /* |
| * The sdhci driver attempts to change the SDIO IO voltage for UHS-I |
| * cards by setting the EN1P8V in control2 register then checks the |
| * outcome by reading it back. |
| * Cygnus does not have an internal regulator for the SDIO IO voltage |
| * but can be configured to indicate success (leave EN1P8V set) |
| * or failure (clear EN1P8V). |
| * |
| * Clear CRMU_SDIO_UHS1_18V_VREG_FAIL in CRMU_SDIO_1P8_FAIL_CONTROL |
| * register to indicate success. |
| * (common setting for all SDIO controllers) |
| */ |
| val = read32((void *)CRMU_SDIO_1P8_FAIL_CONTROL); |
| val &= ~UHS1_18V_VREG_FAIL; |
| write32((void *)CRMU_SDIO_1P8_FAIL_CONTROL, val); |
| |
| /* |
| * Initialize each SDIO controller |
| */ |
| sdio_ctrl_init(0); |
| sdio_ctrl_init(1); |
| } |
| |
| void hw_init(void) |
| { |
| tz_init(); |
| printk(BIOS_INFO, "trustzone initialized\n"); |
| dmac_init(); |
| printk(BIOS_INFO, "PL330 DMAC initialized\n"); |
| lcd_init(); |
| lcd_qos_init(15); |
| printk(BIOS_INFO, "LCD initialized\n"); |
| v3d_init(); |
| printk(BIOS_INFO, "V3D initialized\n"); |
| audio_init(); |
| printk(BIOS_INFO, "audio initialized\n"); |
| neon_init(); |
| printk(BIOS_INFO, "neon initialized\n"); |
| pcie_init(); |
| printk(BIOS_INFO, "PCIe initialized\n"); |
| M0_init(); |
| printk(BIOS_INFO, "M0 initialized\n"); |
| ccu_init(); |
| printk(BIOS_INFO, "CCU initialized\n"); |
| sdio_init(); |
| printk(BIOS_INFO, "SDIO initialized\n"); |
| } |