1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2013 - 2017 Xilinx Inc. 4 */ 5 6 #include <common.h> 7 #include <asm/io.h> 8 #include <malloc.h> 9 #include <asm/arch/hardware.h> 10 #include <asm/arch/sys_proto.h> 11 12 #define SLCR_LOCK_MAGIC 0x767B 13 #define SLCR_UNLOCK_MAGIC 0xDF0D 14 15 #define SLCR_NAND_L2_SEL 0x10 16 #define SLCR_NAND_L2_SEL_MASK 0x1F 17 18 #define SLCR_USB_L1_SEL 0x04 19 20 #define SLCR_IDCODE_MASK 0x1F000 21 #define SLCR_IDCODE_SHIFT 12 22 23 /* 24 * zynq_slcr_mio_get_status - Get the status of MIO peripheral. 25 * 26 * @peri_name: Name of the peripheral for checking MIO status 27 * @get_pins: Pointer to array of get pin for this peripheral 28 * @num_pins: Number of pins for this peripheral 29 * @mask: Mask value 30 * @check_val: Required check value to get the status of periph 31 */ 32 struct zynq_slcr_mio_get_status { 33 const char *peri_name; 34 const int *get_pins; 35 int num_pins; 36 u32 mask; 37 u32 check_val; 38 }; 39 40 static const int nand8_pins[] = { 41 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 42 }; 43 44 static const int nand16_pins[] = { 45 16, 17, 18, 19, 20, 21, 22, 23 46 }; 47 48 static const int usb0_pins[] = { 49 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39 50 }; 51 52 static const int usb1_pins[] = { 53 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 54 }; 55 56 static const struct zynq_slcr_mio_get_status mio_periphs[] = { 57 { 58 "nand8", 59 nand8_pins, 60 ARRAY_SIZE(nand8_pins), 61 SLCR_NAND_L2_SEL_MASK, 62 SLCR_NAND_L2_SEL, 63 }, 64 { 65 "nand16", 66 nand16_pins, 67 ARRAY_SIZE(nand16_pins), 68 SLCR_NAND_L2_SEL_MASK, 69 SLCR_NAND_L2_SEL, 70 }, 71 { 72 "usb0", 73 usb0_pins, 74 ARRAY_SIZE(usb0_pins), 75 SLCR_USB_L1_SEL, 76 SLCR_USB_L1_SEL, 77 }, 78 { 79 "usb1", 80 usb1_pins, 81 ARRAY_SIZE(usb1_pins), 82 SLCR_USB_L1_SEL, 83 SLCR_USB_L1_SEL, 84 }, 85 }; 86 87 static int slcr_lock = 1; /* 1 means locked, 0 means unlocked */ 88 89 void zynq_slcr_lock(void) 90 { 91 if (!slcr_lock) { 92 writel(SLCR_LOCK_MAGIC, &slcr_base->slcr_lock); 93 slcr_lock = 1; 94 } 95 } 96 97 void zynq_slcr_unlock(void) 98 { 99 if (slcr_lock) { 100 writel(SLCR_UNLOCK_MAGIC, &slcr_base->slcr_unlock); 101 slcr_lock = 0; 102 } 103 } 104 105 /* Reset the entire system */ 106 void zynq_slcr_cpu_reset(void) 107 { 108 /* 109 * Unlock the SLCR then reset the system. 110 * Note that this seems to require raw i/o 111 * functions or there's a lockup? 112 */ 113 zynq_slcr_unlock(); 114 115 /* 116 * Clear 0x0F000000 bits of reboot status register to workaround 117 * the FSBL not loading the bitstream after soft-reboot 118 * This is a temporary solution until we know more. 119 */ 120 clrbits_le32(&slcr_base->reboot_status, 0xF000000); 121 122 writel(1, &slcr_base->pss_rst_ctrl); 123 } 124 125 void zynq_slcr_devcfg_disable(void) 126 { 127 u32 reg_val; 128 129 zynq_slcr_unlock(); 130 131 /* Disable AXI interface by asserting FPGA resets */ 132 writel(0xF, &slcr_base->fpga_rst_ctrl); 133 134 /* Disable Level shifters before setting PS-PL */ 135 reg_val = readl(&slcr_base->lvl_shftr_en); 136 reg_val &= ~0xF; 137 writel(reg_val, &slcr_base->lvl_shftr_en); 138 139 /* Set Level Shifters DT618760 */ 140 writel(0xA, &slcr_base->lvl_shftr_en); 141 142 zynq_slcr_lock(); 143 } 144 145 void zynq_slcr_devcfg_enable(void) 146 { 147 zynq_slcr_unlock(); 148 149 /* Set Level Shifters DT618760 */ 150 writel(0xF, &slcr_base->lvl_shftr_en); 151 152 /* Enable AXI interface by de-asserting FPGA resets */ 153 writel(0x0, &slcr_base->fpga_rst_ctrl); 154 155 zynq_slcr_lock(); 156 } 157 158 u32 zynq_slcr_get_boot_mode(void) 159 { 160 /* Get the bootmode register value */ 161 return readl(&slcr_base->boot_mode); 162 } 163 164 u32 zynq_slcr_get_idcode(void) 165 { 166 return (readl(&slcr_base->pss_idcode) & SLCR_IDCODE_MASK) >> 167 SLCR_IDCODE_SHIFT; 168 } 169 170 /* 171 * zynq_slcr_get_mio_pin_status - Get the MIO pin status of peripheral. 172 * 173 * @periph: Name of the peripheral 174 * 175 * Returns count to indicate the number of pins configured for the 176 * given @periph. 177 */ 178 int zynq_slcr_get_mio_pin_status(const char *periph) 179 { 180 const struct zynq_slcr_mio_get_status *mio_ptr; 181 int val, j; 182 int mio = 0; 183 u32 i; 184 185 for (i = 0; i < ARRAY_SIZE(mio_periphs); i++) { 186 if (strcmp(periph, mio_periphs[i].peri_name) == 0) { 187 mio_ptr = &mio_periphs[i]; 188 for (j = 0; j < mio_ptr->num_pins; j++) { 189 val = readl(&slcr_base->mio_pin 190 [mio_ptr->get_pins[j]]); 191 if ((val & mio_ptr->mask) == mio_ptr->check_val) 192 mio++; 193 } 194 break; 195 } 196 } 197 198 return mio; 199 } 200