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