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