#define SLCR_LOCK_MAGIC 0x767B
#define SLCR_UNLOCK_MAGIC 0xDF0D
+#define SLCR_QSPI_ENABLE 0x02
+#define SLCR_QSPI_ENABLE_MASK 0x03
+
+/*
+ * zynq_slcr_mio_get_status - Get the status of MIO peripheral.
+ *
+ * @peri_name: Name of the peripheral for checking MIO status
+ * @get_pins: Pointer to array of get pin for this peripheral
+ * @num_pins: Number of pins for this peripheral
+ * @mask: Mask value
+ * @check_val: Required check value to get the status of periph
+ */
+struct zynq_slcr_mio_get_status {
+ const char *peri_name;
+ const int *get_pins;
+ int num_pins;
+ u32 mask;
+ u32 check_val;
+};
+
+static const int qspi0_pins[] = {
+ 1, 2, 3, 4, 5, 6
+};
+
+static const int qspi1_cs_pin[] = {
+ 0
+};
+
+static const int qspi1_pins[] = {
+ 9, 10, 11, 12, 13
+};
+
+static const struct zynq_slcr_mio_get_status mio_periphs[] = {
+ {
+ "qspi0",
+ qspi0_pins,
+ ARRAY_SIZE(qspi0_pins),
+ SLCR_QSPI_ENABLE_MASK,
+ SLCR_QSPI_ENABLE,
+ },
+ {
+ "qspi1_cs",
+ qspi1_cs_pin,
+ ARRAY_SIZE(qspi1_cs_pin),
+ SLCR_QSPI_ENABLE_MASK,
+ SLCR_QSPI_ENABLE,
+ },
+ {
+ "qspi1",
+ qspi1_pins,
+ ARRAY_SIZE(qspi1_pins),
+ SLCR_QSPI_ENABLE_MASK,
+ SLCR_QSPI_ENABLE,
+ },
+};
+
static int slcr_lock = 1; /* 1 means locked, 0 means unlocked */
void zynq_slcr_lock(void)
/* Get the bootmode register value */
return readl(&slcr_base->boot_mode);
}
+
+/*
+ * zynq_slcr_get_mio_pin_status - Get the MIO pin status of peripheral.
+ *
+ * @periph: Name of the peripheral
+ *
+ * Returns count to indicate the number of pins configured for the
+ * given @periph.
+ */
+int zynq_slcr_get_mio_pin_status(const char *periph)
+{
+ const struct zynq_slcr_mio_get_status *mio_ptr;
+ int val, i, j;
+ int mio = 0;
+
+ for (i = 0; i < ARRAY_SIZE(mio_periphs); i++) {
+ if (strcmp(periph, mio_periphs[i].peri_name) == 0) {
+ mio_ptr = &mio_periphs[i];
+ for (j = 0; j < mio_ptr->num_pins; j++) {
+ val = readl(&slcr_base->mio_pin
+ [mio_ptr->get_pins[j]]);
+ if ((val & mio_ptr->mask) == mio_ptr->check_val)
+ mio++;
+ }
+ break;
+ }
+ }
+
+ return mio;
+}
#include <ubi_uboot.h>
#include <spi.h>
#include <asm/io.h>
-#include <asm/arch/hardware.h>
+#include <asm/arch/sys_proto.h>
/* QSPI Transmit Data Register */
#define XQSPIPS_TXD_00_00_OFFSET 0x1C /* Transmit 4-byte inst, WO */
#define XQSPIPS_QUEUE_RUNNING 1
/* QSPI MIO's count for different connection topologies */
-#define XQSPIPS_MIO_SINGLE 6
-#define XQSPIPS_MIO_DUAL_PARALLEL 6
-#define XQSPIPS_MIO_DUAL_STACKED 7
+#define XQSPIPS_MIO_NUM_QSPI0 6
+#define XQSPIPS_MIO_NUM_QSPI1 5
+#define XQSPIPS_MIO_NUM_QSPI1_CS 1
/* QSPI connections topology */
enum xqspips_con_topology {
- MODE_SINGLE = 0,
- MODE_DUAL_PARALLEL = 1,
- MODE_DUAL_STACKED = 2,
+ MODE_UNKNOWN = -1,
+ MODE_SINGLE,
+ MODE_DUAL_PARALLEL,
+ MODE_DUAL_STACKED,
};
/* Definitions of the flash commands - Flash opcodes in ascending order */
* @regs_base: base address of SLCR
*/
-static int xqspips_check_is_dual_flash(void __iomem *regs_base)
+static int xqspips_check_is_dual_flash(void)
{
- int is_dual = -1, lower_mio = 0, upper_mio = 0, val;
- u16 mask = 3, type = 2;
- u32 mio_pin_index;
- void *mio_base;
-
- mio_base = regs_base + 0x700;
-
- /* checking single QSPI MIO's */
- val = (u32) readl(mio_base + 4 * 1);
- if ((val & mask) == type) {
- lower_mio++;
- for (mio_pin_index = 2; mio_pin_index < 7; mio_pin_index++) {
- val = (u32) readl(mio_base + 4 * mio_pin_index);
- if ((val & mask) == type)
- lower_mio++;
- }
- }
+ int is_dual = MODE_UNKNOWN;
+ int lower_mio = 0, upper_mio = 0, upper_mio_cs1 = 0;
- /* checking dual QSPI MIO's */
- val = (u32) readl(mio_base + 4 * 0);
- if ((val & mask) == type) {
- lower_mio++;
- upper_mio++;
- for (mio_pin_index = 9; mio_pin_index < 14; mio_pin_index++) {
- val = (u32) readl(mio_base + 4 * mio_pin_index);
- if ((val & mask) == type)
- upper_mio++;
- }
- }
+ lower_mio = zynq_slcr_get_mio_pin_status("qspi0");
+ if (lower_mio == XQSPIPS_MIO_NUM_QSPI0)
+ is_dual = MODE_SINGLE;
- if ((lower_mio == XQSPIPS_MIO_DUAL_STACKED) &&
- (upper_mio == XQSPIPS_MIO_DUAL_PARALLEL))
- is_dual = MODE_DUAL_PARALLEL;
- else if (lower_mio == XQSPIPS_MIO_DUAL_STACKED)
+ upper_mio_cs1 = zynq_slcr_get_mio_pin_status("qspi1_cs");
+ if ((lower_mio == XQSPIPS_MIO_NUM_QSPI0) &&
+ (upper_mio_cs1 == XQSPIPS_MIO_NUM_QSPI1_CS))
is_dual = MODE_DUAL_STACKED;
- else if (lower_mio == XQSPIPS_MIO_SINGLE)
- is_dual = MODE_SINGLE;
+
+ upper_mio = zynq_slcr_get_mio_pin_status("qspi1");
+ if ((lower_mio == XQSPIPS_MIO_NUM_QSPI0) &&
+ (upper_mio_cs1 == XQSPIPS_MIO_NUM_QSPI1_CS) &&
+ (upper_mio == XQSPIPS_MIO_NUM_QSPI1))
+ is_dual = MODE_DUAL_PARALLEL;
return is_dual;
}
if (!spi_cs_is_valid(bus, cs))
return NULL;
- is_dual = xqspips_check_is_dual_flash((void *)XPSS_SYS_CTRL_BASEADDR);
+ is_dual = xqspips_check_is_dual_flash();
- if (is_dual == -1) {
+ if (is_dual == MODE_UNKNOWN) {
printf("SPI error: No QSPI device detected based"
" on MIO settings\n");
return NULL;