uboot/arch/arm/mach-zynq/slcr.c
<<
>>
Prefs
   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 */
  32struct 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
  40static const int nand8_pins[] = {
  41        0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
  42};
  43
  44static const int nand16_pins[] = {
  45        16, 17, 18, 19, 20, 21, 22, 23
  46};
  47
  48static const int usb0_pins[] = {
  49        28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39
  50};
  51
  52static const int usb1_pins[] = {
  53        40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
  54};
  55
  56static 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
  87static int slcr_lock = 1; /* 1 means locked, 0 means unlocked */
  88
  89void 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
  97void 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 */
 106void 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
 125void 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
 145void 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
 158u32 zynq_slcr_get_boot_mode(void)
 159{
 160        /* Get the bootmode register value */
 161        return readl(&slcr_base->boot_mode);
 162}
 163
 164u32 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 */
 178int 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