1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <errno.h> 8*91f16700Schasinglulu 9*91f16700Schasinglulu #include <common/debug.h> 10*91f16700Schasinglulu #include <lib/mmio.h> 11*91f16700Schasinglulu #include <lib/smccc.h> 12*91f16700Schasinglulu #include <lib/xlat_tables/xlat_tables_v2.h> 13*91f16700Schasinglulu #include <services/arm_arch_svc.h> 14*91f16700Schasinglulu 15*91f16700Schasinglulu #include <sunxi_def.h> 16*91f16700Schasinglulu #include <sunxi_mmap.h> 17*91f16700Schasinglulu #include <sunxi_private.h> 18*91f16700Schasinglulu 19*91f16700Schasinglulu static const mmap_region_t sunxi_mmap[MAX_STATIC_MMAP_REGIONS + 1] = { 20*91f16700Schasinglulu MAP_REGION_FLAT(SUNXI_SRAM_BASE, SUNXI_SRAM_SIZE, 21*91f16700Schasinglulu MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER), 22*91f16700Schasinglulu MAP_REGION_FLAT(SUNXI_DEV_BASE, SUNXI_DEV_SIZE, 23*91f16700Schasinglulu MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER), 24*91f16700Schasinglulu MAP_REGION(PRELOADED_BL33_BASE, SUNXI_BL33_VIRT_BASE, 25*91f16700Schasinglulu SUNXI_DRAM_MAP_SIZE, MT_RW_DATA | MT_NS), 26*91f16700Schasinglulu {}, 27*91f16700Schasinglulu }; 28*91f16700Schasinglulu 29*91f16700Schasinglulu unsigned int plat_get_syscnt_freq2(void) 30*91f16700Schasinglulu { 31*91f16700Schasinglulu return SUNXI_OSC24M_CLK_IN_HZ; 32*91f16700Schasinglulu } 33*91f16700Schasinglulu 34*91f16700Schasinglulu void sunxi_configure_mmu_el3(int flags) 35*91f16700Schasinglulu { 36*91f16700Schasinglulu mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, 37*91f16700Schasinglulu BL_CODE_END - BL_CODE_BASE, 38*91f16700Schasinglulu MT_CODE | MT_SECURE); 39*91f16700Schasinglulu mmap_add_region(BL_CODE_END, BL_CODE_END, 40*91f16700Schasinglulu BL_END - BL_CODE_END, 41*91f16700Schasinglulu MT_RW_DATA | MT_SECURE); 42*91f16700Schasinglulu #if SEPARATE_CODE_AND_RODATA 43*91f16700Schasinglulu mmap_add_region(BL_RO_DATA_BASE, BL_RO_DATA_BASE, 44*91f16700Schasinglulu BL_RO_DATA_END - BL_RO_DATA_BASE, 45*91f16700Schasinglulu MT_RO_DATA | MT_SECURE); 46*91f16700Schasinglulu #endif 47*91f16700Schasinglulu #if SEPARATE_NOBITS_REGION 48*91f16700Schasinglulu mmap_add_region(BL_NOBITS_BASE, BL_NOBITS_BASE, 49*91f16700Schasinglulu BL_NOBITS_END - BL_NOBITS_BASE, 50*91f16700Schasinglulu MT_RW_DATA | MT_SECURE); 51*91f16700Schasinglulu #endif 52*91f16700Schasinglulu #if USE_COHERENT_MEM 53*91f16700Schasinglulu mmap_add_region(BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_BASE, 54*91f16700Schasinglulu BL_COHERENT_RAM_END - BL_COHERENT_RAM_BASE, 55*91f16700Schasinglulu MT_DEVICE | MT_RW | MT_SECURE | MT_EXECUTE_NEVER); 56*91f16700Schasinglulu #endif 57*91f16700Schasinglulu 58*91f16700Schasinglulu mmap_add(sunxi_mmap); 59*91f16700Schasinglulu init_xlat_tables(); 60*91f16700Schasinglulu 61*91f16700Schasinglulu enable_mmu_el3(0); 62*91f16700Schasinglulu } 63*91f16700Schasinglulu 64*91f16700Schasinglulu #define SRAM_VER_REG (SUNXI_SYSCON_BASE + 0x24) 65*91f16700Schasinglulu uint16_t sunxi_read_soc_id(void) 66*91f16700Schasinglulu { 67*91f16700Schasinglulu uint32_t reg = mmio_read_32(SRAM_VER_REG); 68*91f16700Schasinglulu 69*91f16700Schasinglulu /* Set bit 15 to prepare for the SOCID read. */ 70*91f16700Schasinglulu mmio_write_32(SRAM_VER_REG, reg | BIT(15)); 71*91f16700Schasinglulu 72*91f16700Schasinglulu reg = mmio_read_32(SRAM_VER_REG); 73*91f16700Schasinglulu 74*91f16700Schasinglulu /* deactivate the SOCID access again */ 75*91f16700Schasinglulu mmio_write_32(SRAM_VER_REG, reg & ~BIT(15)); 76*91f16700Schasinglulu 77*91f16700Schasinglulu return reg >> 16; 78*91f16700Schasinglulu } 79*91f16700Schasinglulu 80*91f16700Schasinglulu /* 81*91f16700Schasinglulu * Configure a given pin to the GPIO-OUT function and sets its level. 82*91f16700Schasinglulu * The port is given as a capital letter, the pin is the number within 83*91f16700Schasinglulu * this port group. 84*91f16700Schasinglulu * So to set pin PC7 to high, use: sunxi_set_gpio_out('C', 7, true); 85*91f16700Schasinglulu */ 86*91f16700Schasinglulu void sunxi_set_gpio_out(char port, int pin, bool level_high) 87*91f16700Schasinglulu { 88*91f16700Schasinglulu uintptr_t port_base; 89*91f16700Schasinglulu 90*91f16700Schasinglulu if (port < 'A' || port > 'L') 91*91f16700Schasinglulu return; 92*91f16700Schasinglulu if (port == 'L') 93*91f16700Schasinglulu port_base = SUNXI_R_PIO_BASE; 94*91f16700Schasinglulu else 95*91f16700Schasinglulu port_base = SUNXI_PIO_BASE + (port - 'A') * 0x24; 96*91f16700Schasinglulu 97*91f16700Schasinglulu /* Set the new level first before configuring the pin. */ 98*91f16700Schasinglulu if (level_high) 99*91f16700Schasinglulu mmio_setbits_32(port_base + 0x10, BIT(pin)); 100*91f16700Schasinglulu else 101*91f16700Schasinglulu mmio_clrbits_32(port_base + 0x10, BIT(pin)); 102*91f16700Schasinglulu 103*91f16700Schasinglulu /* configure pin as GPIO out (4(3) bits per pin, 1: GPIO out */ 104*91f16700Schasinglulu mmio_clrsetbits_32(port_base + (pin / 8) * 4, 105*91f16700Schasinglulu 0x7 << ((pin % 8) * 4), 106*91f16700Schasinglulu 0x1 << ((pin % 8) * 4)); 107*91f16700Schasinglulu } 108*91f16700Schasinglulu 109*91f16700Schasinglulu int sunxi_init_platform_r_twi(uint16_t socid, bool use_rsb) 110*91f16700Schasinglulu { 111*91f16700Schasinglulu uint32_t pin_func = 0x77; 112*91f16700Schasinglulu uint32_t device_bit; 113*91f16700Schasinglulu unsigned int reset_offset = 0xb0; 114*91f16700Schasinglulu 115*91f16700Schasinglulu switch (socid) { 116*91f16700Schasinglulu case SUNXI_SOC_H5: 117*91f16700Schasinglulu if (use_rsb) 118*91f16700Schasinglulu return -ENODEV; 119*91f16700Schasinglulu pin_func = 0x22; 120*91f16700Schasinglulu device_bit = BIT(6); 121*91f16700Schasinglulu break; 122*91f16700Schasinglulu case SUNXI_SOC_H6: 123*91f16700Schasinglulu case SUNXI_SOC_H616: 124*91f16700Schasinglulu pin_func = use_rsb ? 0x22 : 0x33; 125*91f16700Schasinglulu device_bit = BIT(16); 126*91f16700Schasinglulu reset_offset = use_rsb ? 0x1bc : 0x19c; 127*91f16700Schasinglulu break; 128*91f16700Schasinglulu case SUNXI_SOC_A64: 129*91f16700Schasinglulu pin_func = use_rsb ? 0x22 : 0x33; 130*91f16700Schasinglulu device_bit = use_rsb ? BIT(3) : BIT(6); 131*91f16700Schasinglulu break; 132*91f16700Schasinglulu default: 133*91f16700Schasinglulu INFO("R_I2C/RSB on Allwinner 0x%x SoC not supported\n", socid); 134*91f16700Schasinglulu return -ENODEV; 135*91f16700Schasinglulu } 136*91f16700Schasinglulu 137*91f16700Schasinglulu /* un-gate R_PIO clock */ 138*91f16700Schasinglulu if (socid != SUNXI_SOC_H6 && socid != SUNXI_SOC_H616) 139*91f16700Schasinglulu mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, BIT(0)); 140*91f16700Schasinglulu 141*91f16700Schasinglulu /* switch pins PL0 and PL1 to the desired function */ 142*91f16700Schasinglulu mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x00, 0xffU, pin_func); 143*91f16700Schasinglulu 144*91f16700Schasinglulu /* level 2 drive strength */ 145*91f16700Schasinglulu mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x14, 0x0fU, 0xaU); 146*91f16700Schasinglulu 147*91f16700Schasinglulu /* set both pins to pull-up */ 148*91f16700Schasinglulu mmio_clrsetbits_32(SUNXI_R_PIO_BASE + 0x1c, 0x0fU, 0x5U); 149*91f16700Schasinglulu 150*91f16700Schasinglulu /* un-gate clock */ 151*91f16700Schasinglulu if (socid != SUNXI_SOC_H6 && socid != SUNXI_SOC_H616) 152*91f16700Schasinglulu mmio_setbits_32(SUNXI_R_PRCM_BASE + 0x28, device_bit); 153*91f16700Schasinglulu else 154*91f16700Schasinglulu mmio_setbits_32(SUNXI_R_PRCM_BASE + reset_offset, BIT(0)); 155*91f16700Schasinglulu 156*91f16700Schasinglulu /* assert, then de-assert reset of I2C/RSB controller */ 157*91f16700Schasinglulu mmio_clrbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit); 158*91f16700Schasinglulu mmio_setbits_32(SUNXI_R_PRCM_BASE + reset_offset, device_bit); 159*91f16700Schasinglulu 160*91f16700Schasinglulu return 0; 161*91f16700Schasinglulu } 162*91f16700Schasinglulu 163*91f16700Schasinglulu int32_t plat_is_smccc_feature_available(u_register_t fid) 164*91f16700Schasinglulu { 165*91f16700Schasinglulu switch (fid) { 166*91f16700Schasinglulu case SMCCC_ARCH_SOC_ID: 167*91f16700Schasinglulu return SMC_ARCH_CALL_SUCCESS; 168*91f16700Schasinglulu default: 169*91f16700Schasinglulu return SMC_ARCH_CALL_NOT_SUPPORTED; 170*91f16700Schasinglulu } 171*91f16700Schasinglulu } 172*91f16700Schasinglulu 173*91f16700Schasinglulu int32_t plat_get_soc_version(void) 174*91f16700Schasinglulu { 175*91f16700Schasinglulu int32_t ret; 176*91f16700Schasinglulu 177*91f16700Schasinglulu ret = SOC_ID_SET_JEP_106(JEDEC_ALLWINNER_BKID, JEDEC_ALLWINNER_MFID); 178*91f16700Schasinglulu 179*91f16700Schasinglulu return ret | (sunxi_read_soc_id() & SOC_ID_IMPL_DEF_MASK); 180*91f16700Schasinglulu } 181*91f16700Schasinglulu 182*91f16700Schasinglulu int32_t plat_get_soc_revision(void) 183*91f16700Schasinglulu { 184*91f16700Schasinglulu uint32_t reg = mmio_read_32(SRAM_VER_REG); 185*91f16700Schasinglulu 186*91f16700Schasinglulu return reg & SUNXI_VER_BITS_MASK; 187*91f16700Schasinglulu } 188