summaryrefslogtreecommitdiffstats
path: root/qemu/roms/u-boot/drivers/spi
diff options
context:
space:
mode:
authorYang Zhang <yang.z.zhang@intel.com>2015-08-28 09:58:54 +0800
committerYang Zhang <yang.z.zhang@intel.com>2015-09-01 12:44:00 +0800
commite44e3482bdb4d0ebde2d8b41830ac2cdb07948fb (patch)
tree66b09f592c55df2878107a468a91d21506104d3f /qemu/roms/u-boot/drivers/spi
parent9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00 (diff)
Add qemu 2.4.0
Change-Id: Ic99cbad4b61f8b127b7dc74d04576c0bcbaaf4f5 Signed-off-by: Yang Zhang <yang.z.zhang@intel.com>
Diffstat (limited to 'qemu/roms/u-boot/drivers/spi')
-rw-r--r--qemu/roms/u-boot/drivers/spi/Makefile42
-rw-r--r--qemu/roms/u-boot/drivers/spi/altera_spi.c168
-rw-r--r--qemu/roms/u-boot/drivers/spi/andes_spi.c284
-rw-r--r--qemu/roms/u-boot/drivers/spi/andes_spi.h115
-rw-r--r--qemu/roms/u-boot/drivers/spi/armada100_spi.c203
-rw-r--r--qemu/roms/u-boot/drivers/spi/atmel_dataflash_spi.c184
-rw-r--r--qemu/roms/u-boot/drivers/spi/atmel_spi.c211
-rw-r--r--qemu/roms/u-boot/drivers/spi/atmel_spi.h96
-rw-r--r--qemu/roms/u-boot/drivers/spi/bfin_spi.c308
-rw-r--r--qemu/roms/u-boot/drivers/spi/bfin_spi6xx.c304
-rw-r--r--qemu/roms/u-boot/drivers/spi/cf_qspi.c355
-rw-r--r--qemu/roms/u-boot/drivers/spi/cf_spi.c347
-rw-r--r--qemu/roms/u-boot/drivers/spi/davinci_spi.c321
-rw-r--r--qemu/roms/u-boot/drivers/spi/davinci_spi.h121
-rw-r--r--qemu/roms/u-boot/drivers/spi/exynos_spi.c579
-rw-r--r--qemu/roms/u-boot/drivers/spi/fdt_spi.c186
-rw-r--r--qemu/roms/u-boot/drivers/spi/fsl_espi.c315
-rw-r--r--qemu/roms/u-boot/drivers/spi/ftssp010_spi.c508
-rw-r--r--qemu/roms/u-boot/drivers/spi/ich.c741
-rw-r--r--qemu/roms/u-boot/drivers/spi/ich.h127
-rw-r--r--qemu/roms/u-boot/drivers/spi/kirkwood_spi.c214
-rw-r--r--qemu/roms/u-boot/drivers/spi/mpc52xx_spi.c90
-rw-r--r--qemu/roms/u-boot/drivers/spi/mpc8xxx_spi.c166
-rw-r--r--qemu/roms/u-boot/drivers/spi/mxc_spi.c448
-rw-r--r--qemu/roms/u-boot/drivers/spi/mxs_spi.c362
-rw-r--r--qemu/roms/u-boot/drivers/spi/oc_tiny_spi.c245
-rw-r--r--qemu/roms/u-boot/drivers/spi/omap3_spi.c453
-rw-r--r--qemu/roms/u-boot/drivers/spi/omap3_spi.h109
-rw-r--r--qemu/roms/u-boot/drivers/spi/sandbox_spi.c217
-rw-r--r--qemu/roms/u-boot/drivers/spi/sh_qspi.c278
-rw-r--r--qemu/roms/u-boot/drivers/spi/sh_spi.c265
-rw-r--r--qemu/roms/u-boot/drivers/spi/sh_spi.h80
-rw-r--r--qemu/roms/u-boot/drivers/spi/soft_spi.c175
-rw-r--r--qemu/roms/u-boot/drivers/spi/spi.c58
-rw-r--r--qemu/roms/u-boot/drivers/spi/tegra114_spi.c398
-rw-r--r--qemu/roms/u-boot/drivers/spi/tegra20_sflash.c341
-rw-r--r--qemu/roms/u-boot/drivers/spi/tegra20_slink.c359
-rw-r--r--qemu/roms/u-boot/drivers/spi/ti_qspi.c341
-rw-r--r--qemu/roms/u-boot/drivers/spi/xilinx_spi.c215
-rw-r--r--qemu/roms/u-boot/drivers/spi/xilinx_spi.h138
-rw-r--r--qemu/roms/u-boot/drivers/spi/zynq_spi.c280
41 files changed, 10747 insertions, 0 deletions
diff --git a/qemu/roms/u-boot/drivers/spi/Makefile b/qemu/roms/u-boot/drivers/spi/Makefile
new file mode 100644
index 000000000..81b6af669
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/Makefile
@@ -0,0 +1,42 @@
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# SPDX-License-Identifier: GPL-2.0+
+#
+
+# There are many options which enable SPI, so make this library available
+obj-y += spi.o
+
+obj-$(CONFIG_ALTERA_SPI) += altera_spi.o
+obj-$(CONFIG_ANDES_SPI) += andes_spi.o
+obj-$(CONFIG_ARMADA100_SPI) += armada100_spi.o
+obj-$(CONFIG_ATMEL_DATAFLASH_SPI) += atmel_dataflash_spi.o
+obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o
+obj-$(CONFIG_BFIN_SPI) += bfin_spi.o
+obj-$(CONFIG_BFIN_SPI6XX) += bfin_spi6xx.o
+obj-$(CONFIG_CF_SPI) += cf_spi.o
+obj-$(CONFIG_CF_QSPI) += cf_qspi.o
+obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o
+obj-$(CONFIG_EXYNOS_SPI) += exynos_spi.o
+obj-$(CONFIG_FTSSP010_SPI) += ftssp010_spi.o
+obj-$(CONFIG_ICH_SPI) += ich.o
+obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
+obj-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
+obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
+obj-$(CONFIG_MXC_SPI) += mxc_spi.o
+obj-$(CONFIG_MXS_SPI) += mxs_spi.o
+obj-$(CONFIG_OC_TINY_SPI) += oc_tiny_spi.o
+obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
+obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o
+obj-$(CONFIG_SOFT_SPI) += soft_spi.o
+obj-$(CONFIG_SH_SPI) += sh_spi.o
+obj-$(CONFIG_SH_QSPI) += sh_qspi.o
+obj-$(CONFIG_FSL_ESPI) += fsl_espi.o
+obj-$(CONFIG_FDT_SPI) += fdt_spi.o
+obj-$(CONFIG_TEGRA20_SFLASH) += tegra20_sflash.o
+obj-$(CONFIG_TEGRA20_SLINK) += tegra20_slink.o
+obj-$(CONFIG_TEGRA114_SPI) += tegra114_spi.o
+obj-$(CONFIG_TI_QSPI) += ti_qspi.o
+obj-$(CONFIG_XILINX_SPI) += xilinx_spi.o
+obj-$(CONFIG_ZYNQ_SPI) += zynq_spi.o
diff --git a/qemu/roms/u-boot/drivers/spi/altera_spi.c b/qemu/roms/u-boot/drivers/spi/altera_spi.c
new file mode 100644
index 000000000..5accbb5c2
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/altera_spi.c
@@ -0,0 +1,168 @@
+/*
+ * Altera SPI driver
+ *
+ * based on bfin_spi.c
+ * Copyright (c) 2005-2008 Analog Devices Inc.
+ * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <spi.h>
+
+#define ALTERA_SPI_RXDATA 0
+#define ALTERA_SPI_TXDATA 4
+#define ALTERA_SPI_STATUS 8
+#define ALTERA_SPI_CONTROL 12
+#define ALTERA_SPI_SLAVE_SEL 20
+
+#define ALTERA_SPI_STATUS_ROE_MSK (0x8)
+#define ALTERA_SPI_STATUS_TOE_MSK (0x10)
+#define ALTERA_SPI_STATUS_TMT_MSK (0x20)
+#define ALTERA_SPI_STATUS_TRDY_MSK (0x40)
+#define ALTERA_SPI_STATUS_RRDY_MSK (0x80)
+#define ALTERA_SPI_STATUS_E_MSK (0x100)
+
+#define ALTERA_SPI_CONTROL_IROE_MSK (0x8)
+#define ALTERA_SPI_CONTROL_ITOE_MSK (0x10)
+#define ALTERA_SPI_CONTROL_ITRDY_MSK (0x40)
+#define ALTERA_SPI_CONTROL_IRRDY_MSK (0x80)
+#define ALTERA_SPI_CONTROL_IE_MSK (0x100)
+#define ALTERA_SPI_CONTROL_SSO_MSK (0x400)
+
+#ifndef CONFIG_SYS_ALTERA_SPI_LIST
+#define CONFIG_SYS_ALTERA_SPI_LIST { CONFIG_SYS_SPI_BASE }
+#endif
+
+static ulong altera_spi_base_list[] = CONFIG_SYS_ALTERA_SPI_LIST;
+
+struct altera_spi_slave {
+ struct spi_slave slave;
+ ulong base;
+};
+#define to_altera_spi_slave(s) container_of(s, struct altera_spi_slave, slave)
+
+__attribute__((weak))
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ return bus < ARRAY_SIZE(altera_spi_base_list) && cs < 32;
+}
+
+__attribute__((weak))
+void spi_cs_activate(struct spi_slave *slave)
+{
+ struct altera_spi_slave *altspi = to_altera_spi_slave(slave);
+ writel(1 << slave->cs, altspi->base + ALTERA_SPI_SLAVE_SEL);
+ writel(ALTERA_SPI_CONTROL_SSO_MSK, altspi->base + ALTERA_SPI_CONTROL);
+}
+
+__attribute__((weak))
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct altera_spi_slave *altspi = to_altera_spi_slave(slave);
+ writel(0, altspi->base + ALTERA_SPI_CONTROL);
+ writel(0, altspi->base + ALTERA_SPI_SLAVE_SEL);
+}
+
+void spi_init(void)
+{
+}
+
+void spi_set_speed(struct spi_slave *slave, uint hz)
+{
+ /* altera spi core does not support programmable speed */
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct altera_spi_slave *altspi;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ altspi = spi_alloc_slave(struct altera_spi_slave, bus, cs);
+ if (!altspi)
+ return NULL;
+
+ altspi->base = altera_spi_base_list[bus];
+ debug("%s: bus:%i cs:%i base:%lx\n", __func__,
+ bus, cs, altspi->base);
+
+ return &altspi->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct altera_spi_slave *altspi = to_altera_spi_slave(slave);
+ free(altspi);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct altera_spi_slave *altspi = to_altera_spi_slave(slave);
+
+ debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
+ writel(0, altspi->base + ALTERA_SPI_CONTROL);
+ writel(0, altspi->base + ALTERA_SPI_SLAVE_SEL);
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ struct altera_spi_slave *altspi = to_altera_spi_slave(slave);
+
+ debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
+ writel(0, altspi->base + ALTERA_SPI_SLAVE_SEL);
+}
+
+#ifndef CONFIG_ALTERA_SPI_IDLE_VAL
+# define CONFIG_ALTERA_SPI_IDLE_VAL 0xff
+#endif
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct altera_spi_slave *altspi = to_altera_spi_slave(slave);
+ /* assume spi core configured to do 8 bit transfers */
+ uint bytes = bitlen / 8;
+ const uchar *txp = dout;
+ uchar *rxp = din;
+
+ debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
+ slave->bus, slave->cs, bitlen, bytes, flags);
+ if (bitlen == 0)
+ goto done;
+
+ if (bitlen % 8) {
+ flags |= SPI_XFER_END;
+ goto done;
+ }
+
+ /* empty read buffer */
+ if (readl(altspi->base + ALTERA_SPI_STATUS) &
+ ALTERA_SPI_STATUS_RRDY_MSK)
+ readl(altspi->base + ALTERA_SPI_RXDATA);
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ while (bytes--) {
+ uchar d = txp ? *txp++ : CONFIG_ALTERA_SPI_IDLE_VAL;
+ debug("%s: tx:%x ", __func__, d);
+ writel(d, altspi->base + ALTERA_SPI_TXDATA);
+ while (!(readl(altspi->base + ALTERA_SPI_STATUS) &
+ ALTERA_SPI_STATUS_RRDY_MSK))
+ ;
+ d = readl(altspi->base + ALTERA_SPI_RXDATA);
+ if (rxp)
+ *rxp++ = d;
+ debug("rx:%x\n", d);
+ }
+ done:
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/andes_spi.c b/qemu/roms/u-boot/drivers/spi/andes_spi.c
new file mode 100644
index 000000000..82aed75ca
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/andes_spi.c
@@ -0,0 +1,284 @@
+/*
+ * Driver of Andes SPI Controller
+ *
+ * (C) Copyright 2011 Andes Technology
+ * Macpaul Lin <macpaul@andestech.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+
+#include <asm/io.h>
+#include "andes_spi.h"
+
+void spi_init(void)
+{
+ /* do nothing */
+}
+
+static void andes_spi_spit_en(struct andes_spi_slave *ds)
+{
+ unsigned int dcr = readl(&ds->regs->dcr);
+
+ debug("%s: dcr: %x, write value: %x\n",
+ __func__, dcr, (dcr | ANDES_SPI_DCR_SPIT));
+
+ writel((dcr | ANDES_SPI_DCR_SPIT), &ds->regs->dcr);
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct andes_spi_slave *ds;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ ds = spi_alloc_slave(struct andes_spi_slave, bus, cs);
+ if (!ds)
+ return NULL;
+
+ ds->regs = (struct andes_spi_regs *)CONFIG_SYS_SPI_BASE;
+
+ /*
+ * The hardware of andes_spi will set its frequency according
+ * to APB/AHB bus clock. Hence the hardware doesn't allow changing of
+ * requency and so the user requested speed is always ignored.
+ */
+ ds->freq = max_hz;
+
+ return &ds->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct andes_spi_slave *ds = to_andes_spi(slave);
+
+ free(ds);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct andes_spi_slave *ds = to_andes_spi(slave);
+ unsigned int apb;
+ unsigned int baud;
+
+ /* Enable the SPI hardware */
+ writel(ANDES_SPI_CR_SPIRST, &ds->regs->cr);
+ udelay(1000);
+
+ /* setup format */
+ baud = ((CONFIG_SYS_CLK_FREQ / CONFIG_SYS_SPI_CLK / 2) - 1) & 0xFF;
+
+ /*
+ * SPI_CLK = AHB bus clock / ((BAUD + 1)*2)
+ * BAUD = AHB bus clock / SPI_CLK / 2) - 1
+ */
+ apb = (readl(&ds->regs->apb) & 0xffffff00) | baud;
+ writel(apb, &ds->regs->apb);
+
+ /* no interrupts */
+ writel(0, &ds->regs->ie);
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ struct andes_spi_slave *ds = to_andes_spi(slave);
+
+ /* Disable the SPI hardware */
+ writel(ANDES_SPI_CR_SPIRST, &ds->regs->cr);
+}
+
+static int andes_spi_read(struct spi_slave *slave, unsigned int len,
+ u8 *rxp, unsigned long flags)
+{
+ struct andes_spi_slave *ds = to_andes_spi(slave);
+ unsigned int i, left;
+ unsigned int data;
+
+ debug("%s: slave: %x, len: %d, rxp: %x, flags: %d\n",
+ __func__, slave, len, rxp, flags);
+
+ debug("%s: data: ", __func__);
+ while (len > 0) {
+ left = min(len, 4);
+ data = readl(&ds->regs->data);
+
+ debug(" ");
+ for (i = 0; i < left; i++) {
+ debug("%02x ", data & 0xff);
+ *rxp++ = data;
+ data >>= 8;
+ len--;
+ }
+ }
+ debug("\n");
+
+ return 0;
+}
+
+static int andes_spi_write(struct spi_slave *slave, unsigned int wlen,
+ unsigned int rlen, const u8 *txp, unsigned long flags)
+{
+ struct andes_spi_slave *ds = to_andes_spi(slave);
+ unsigned int data;
+ unsigned int i, left;
+ unsigned int spit_enabled = 0;
+
+ debug("%s: slave: %x, wlen: %d, rlen: %d, txp: %x, flags: %x\n",
+ __func__, slave, wlen, rlen, txp, flags);
+
+ /* The value of wlen and rlen wrote to register must minus 1 */
+ if (rlen == 0) /* write only */
+ writel(ANDES_SPI_DCR_MODE_WO | ANDES_SPI_DCR_WCNT(wlen-1) |
+ ANDES_SPI_DCR_RCNT(0), &ds->regs->dcr);
+ else /* write then read */
+ writel(ANDES_SPI_DCR_MODE_WR | ANDES_SPI_DCR_WCNT(wlen-1) |
+ ANDES_SPI_DCR_RCNT(rlen-1), &ds->regs->dcr);
+
+ /* wait till SPIBSY is cleared */
+ while (readl(&ds->regs->st) & ANDES_SPI_ST_SPIBSY)
+ ;
+
+ /* data write process */
+ debug("%s: txp: ", __func__);
+ while (wlen > 0) {
+ /* clear the data */
+ data = 0;
+
+ /* data are usually be read 32bits once a time */
+ left = min(wlen, 4);
+
+ for (i = 0; i < left; i++) {
+ debug("%x ", *txp);
+ data |= *txp++ << (i * 8);
+ wlen--;
+ }
+ debug("\n");
+
+ debug("data: %08x\n", data);
+ debug("streg before write: %08x\n", readl(&ds->regs->st));
+ /* wait till TXFULL is deasserted */
+ while (readl(&ds->regs->st) & ANDES_SPI_ST_TXFEL)
+ ;
+ writel(data, &ds->regs->data);
+ debug("streg after write: %08x\n", readl(&ds->regs->st));
+
+
+ if (spit_enabled == 0) {
+ /* enable SPIT bit - trigger the tx and rx progress */
+ andes_spi_spit_en(ds);
+ spit_enabled = 1;
+ }
+
+ }
+ debug("\n");
+
+ return 0;
+}
+
+/*
+ * spi_xfer:
+ * Since andes_spi doesn't support independent command transaction,
+ * that is, write and than read must be operated in continuous
+ * execution, there is no need to set dcr and trigger spit again in
+ * RX process.
+ */
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
+{
+ unsigned int len;
+ static int op_nextime;
+ static u8 tmp_cmd[5];
+ static int tmp_wlen;
+ unsigned int i;
+
+ if (bitlen == 0)
+ /* Finish any previously submitted transfers */
+ goto out;
+
+ if (bitlen % 8) {
+ /* Errors always terminate an ongoing transfer */
+ flags |= SPI_XFER_END;
+ goto out;
+ }
+
+ len = bitlen / 8;
+
+ debug("%s: slave: %08x, bitlen: %d, dout: "
+ "%08x, din: %08x, flags: %d, len: %d\n",
+ __func__, slave, bitlen, dout, din, flags, len);
+
+ /*
+ * Important:
+ * andes_spi's hardware doesn't support 2 data channel. The read
+ * and write cmd/data share the same register (data register).
+ *
+ * If a command has write and read transaction, you cannot do write
+ * this time and then do read on next time.
+ *
+ * A command writes first with a read response must indicating
+ * the read length in write operation. Hence the write action must
+ * be stored temporary and wait until the next read action has been
+ * arrived. Then we flush the write and read action out together.
+ */
+ if (!dout) {
+ if (op_nextime == 1) {
+ /* flags should be SPI_XFER_END, value is 2 */
+ op_nextime = 0;
+ andes_spi_write(slave, tmp_wlen, len, tmp_cmd, flags);
+ }
+ return andes_spi_read(slave, len, din, flags);
+ } else if (!din) {
+ if (flags == SPI_XFER_BEGIN) {
+ /* store the write command and do operation next time */
+ op_nextime = 1;
+ memset(tmp_cmd, 0, sizeof(tmp_cmd));
+ memcpy(tmp_cmd, dout, len);
+
+ debug("%s: tmp_cmd: ", __func__);
+ for (i = 0; i < len; i++)
+ debug("%x ", *(tmp_cmd + i));
+ debug("\n");
+
+ tmp_wlen = len;
+ } else {
+ /*
+ * flags should be (SPI_XFER_BEGIN | SPI_XFER_END),
+ * the value is 3.
+ */
+ if (op_nextime == 1) {
+ /* flags should be SPI_XFER_END, value is 2 */
+ op_nextime = 0;
+ /* flags 3 implies write only */
+ andes_spi_write(slave, tmp_wlen, 0, tmp_cmd, 3);
+ }
+
+ debug("flags: %x\n", flags);
+ return andes_spi_write(slave, len, 0, dout, flags);
+ }
+ }
+
+out:
+ return 0;
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ return bus == 0 && cs == 0;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ /* do nothing */
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ /* do nothing */
+}
diff --git a/qemu/roms/u-boot/drivers/spi/andes_spi.h b/qemu/roms/u-boot/drivers/spi/andes_spi.h
new file mode 100644
index 000000000..b7d294599
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/andes_spi.h
@@ -0,0 +1,115 @@
+/*
+ * Register definitions for the Andes SPI Controller
+ *
+ * (C) Copyright 2011 Andes Technology
+ * Macpaul Lin <macpaul@andestech.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef __ANDES_SPI_H
+#define __ANDES_SPI_H
+
+struct andes_spi_regs {
+ unsigned int apb; /* 0x00 - APB SPI interface setting */
+ unsigned int pio; /* 0x04 - PIO reg */
+ unsigned int cr; /* 0x08 - SPI Control reg */
+ unsigned int st; /* 0x0c - SPI Status reg */
+ unsigned int ie; /* 0x10 - Interrupt Enable reg */
+ unsigned int ist; /* 0x14 - Interrupt Status reg */
+ unsigned int dcr; /* 0x18 - data control reg */
+ unsigned int data; /* 0x1c - data register */
+ unsigned int ahb; /* 0x20 - AHB SPI interface setting */
+ unsigned int ver; /* 0x3c - SPI version reg */
+};
+
+#define BIT(x) (1 << (x))
+
+/* 0x00 - APB SPI interface setting register */
+#define ANDES_SPI_APB_BAUD(x) (((x) & 0xff) < 0)
+#define ANDES_SPI_APB_CSHT(x) (((x) & 0xf) < 16)
+#define ANDES_SPI_APB_SPNTS BIT(20) /* 0: normal, 1: delay */
+#define ANDES_SPI_APB_CPHA BIT(24) /* 0: Sampling at odd edges */
+#define ANDES_SPI_APB_CPOL BIT(25) /* 0: SCK low, 1: SCK high */
+#define ANDES_SPI_APB_MSSL BIT(26) /* 0: SPI Master, 1: slave */
+
+/* 0x04 - PIO register */
+#define ANDES_SPI_PIO_MISO BIT(0) /* input value of pin MISO */
+#define ANDES_SPI_PIO_MOSI BIT(1) /* I/O value of pin MOSI */
+#define ANDES_SPI_PIO_SCK BIT(2) /* I/O value of pin SCK */
+#define ANDES_SPI_PIO_CS BIT(3) /* I/O value of pin CS */
+#define ANDES_SPI_PIO_PIOE BIT(4) /* Programming IO Enable */
+
+/* 0x08 - SPI Control register */
+#define ANDES_SPI_CR_SPIRST BIT(0) /* SPI mode reset */
+#define ANDES_SPI_CR_RXFRST BIT(1) /* RxFIFO reset */
+#define ANDES_SPI_CR_TXFRST BIT(2) /* TxFIFO reset */
+#define ANDES_SPI_CR_RXFTH(x) (((x) & 0x1f) << 10) /* RxFIFO Threshold */
+#define ANDES_SPI_CR_TXFTH(x) (((x) & 0x1f) << 18) /* TxFIFO Threshold */
+
+/* 0x0c - SPI Status register */
+#define ANDES_SPI_ST_SPIBSY BIT(0) /* SPI Transfer is active */
+#define ANDES_SPI_ST_RXFEM BIT(8) /* RxFIFO Empty Flag */
+#define ANDES_SPI_ST_RXFEL BIT(9) /* RxFIFO Full Flag */
+#define ANDES_SPI_ST_RXFVE(x) (((x) >> 10) & 0x1f)
+#define ANDES_SPI_ST_TXFEM BIT(16) /* TxFIFO Empty Flag */
+#define ANDES_SPI_ST_TXFEL BIT(7) /* TxFIFO Full Flag */
+#define ANDES_SPI_ST_TXFVE(x) (((x) >> 18) & 0x1f)
+
+/* 0x10 - Interrupt Enable register */
+#define ANDES_SPI_IE_RXFORIE BIT(0) /* RxFIFO overrun intr */
+#define ANDES_SPI_IE_TXFURIE BIT(1) /* TxFOFO underrun intr */
+#define ANDES_SPI_IE_RXFTHIE BIT(2) /* RxFIFO threshold intr */
+#define ANDES_SPI_IE_TXFTHIE BIT(3) /* TxFIFO threshold intr */
+#define ANDES_SPI_IE_SPIEIE BIT(4) /* SPI transmit END intr */
+#define ANDES_SPI_IE_SPCFIE BIT(5) /* AHB/APB TxReq conflict */
+
+/* 0x14 - Interrupt Status Register */
+#define ANDES_SPI_IST_RXFORI BIT(0) /* has RxFIFO overrun */
+#define ANDES_SPI_IST_TXFURI BIT(1) /* has TxFOFO underrun */
+#define ANDES_SPI_IST_RXFTHI BIT(2) /* has RxFIFO threshold */
+#define ANDES_SPI_IST_TXFTHI BIT(3) /* has TxFIFO threshold */
+#define ANDES_SPI_IST_SPIEI BIT(4) /* has SPI transmit END */
+#define ANDES_SPI_IST_SPCFI BIT(5) /* has AHB/APB TxReq conflict */
+
+/* 0x18 - Data Control Register */
+#define ANDES_SPI_DCR_RCNT(x) (((x) & 0x3ff) << 0)
+#define ANDES_SPI_DCR_DYCNT(x) (((x) & 0x7) << 12)
+#define ANDES_SPI_DCR_WCNT(x) (((x) & 0x3ff) << 16)
+#define ANDES_SPI_DCR_TRAMODE(x) (((x) & 0x7) << 28)
+#define ANDES_SPI_DCR_SPIT BIT(31) /* SPI bus trigger */
+
+#define ANDES_SPI_DCR_MODE_WRCON ANDES_SPI_DCR_TRAMODE(0) /* w/r at the same time */
+#define ANDES_SPI_DCR_MODE_WO ANDES_SPI_DCR_TRAMODE(1) /* write only */
+#define ANDES_SPI_DCR_MODE_RO ANDES_SPI_DCR_TRAMODE(2) /* read only */
+#define ANDES_SPI_DCR_MODE_WR ANDES_SPI_DCR_TRAMODE(3) /* write, read */
+#define ANDES_SPI_DCR_MODE_RW ANDES_SPI_DCR_TRAMODE(4) /* read, write */
+#define ANDES_SPI_DCR_MODE_WDR ANDES_SPI_DCR_TRAMODE(5) /* write, dummy, read */
+#define ANDES_SPI_DCR_MODE_RDW ANDES_SPI_DCR_TRAMODE(6) /* read, dummy, write */
+#define ANDES_SPI_DCR_MODE_RECEIVE ANDES_SPI_DCR_TRAMODE(7) /* receive */
+
+/* 0x20 - AHB SPI interface setting register */
+#define ANDES_SPI_AHB_BAUD(x) (((x) & 0xff) < 0)
+#define ANDES_SPI_AHB_CSHT(x) (((x) & 0xf) < 16)
+#define ANDES_SPI_AHB_SPNTS BIT(20) /* 0: normal, 1: delay */
+#define ANDES_SPI_AHB_CPHA BIT(24) /* 0: Sampling at odd edges */
+#define ANDES_SPI_AHB_CPOL BIT(25) /* 0: SCK low, 1: SCK high */
+#define ANDES_SPI_AHB_MSSL BIT(26) /* only Master mode */
+
+/* 0x3c - Version Register - (Year V.MAJOR.MINOR) */
+#define ANDES_SPI_VER_MINOR(x) (((x) >> 0) & 0xf)
+#define ANDES_SPI_VER_MAJOR(x) (((x) >> 8) & 0xf)
+#define ANDES_SPI_VER_YEAR(x) (((x) >> 16) & 0xf)
+
+struct andes_spi_slave {
+ struct spi_slave slave;
+ struct andes_spi_regs *regs;
+ unsigned int freq;
+};
+
+static inline struct andes_spi_slave *to_andes_spi(struct spi_slave *slave)
+{
+ return container_of(slave, struct andes_spi_slave, slave);
+}
+
+#endif /* __ANDES_SPI_H */
diff --git a/qemu/roms/u-boot/drivers/spi/armada100_spi.c b/qemu/roms/u-boot/drivers/spi/armada100_spi.c
new file mode 100644
index 000000000..53aaf9534
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/armada100_spi.c
@@ -0,0 +1,203 @@
+/*
+ * (C) Copyright 2011
+ * eInfochips Ltd. <www.einfochips.com>
+ * Written-by: Ajay Bhargav <ajay.bhargav@einfochips.com>
+ *
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ * Based on SSP driver
+ * Written-by: Lei Wen <leiwen@marvell.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+
+#include <asm/io.h>
+#include <asm/arch/spi.h>
+#include <asm/gpio.h>
+
+#define to_armd_spi_slave(s) container_of(s, struct armd_spi_slave, slave)
+
+struct armd_spi_slave {
+ struct spi_slave slave;
+ struct ssp_reg *spi_reg;
+ u32 cr0, cr1;
+ u32 int_cr1;
+ u32 clear_sr;
+ const void *tx;
+ void *rx;
+ int gpio_cs_inverted;
+};
+
+static int spi_armd_write(struct armd_spi_slave *pss)
+{
+ int wait_timeout = SSP_FLUSH_NUM;
+ while (--wait_timeout && !(readl(&pss->spi_reg->sssr) & SSSR_TNF))
+ ;
+ if (!wait_timeout) {
+ debug("%s: timeout error\n", __func__);
+ return -1;
+ }
+
+ if (pss->tx != NULL) {
+ writel(*(u8 *)pss->tx, &pss->spi_reg->ssdr);
+ ++pss->tx;
+ } else {
+ writel(0, &pss->spi_reg->ssdr);
+ }
+ return 0;
+}
+
+static int spi_armd_read(struct armd_spi_slave *pss)
+{
+ int wait_timeout = SSP_FLUSH_NUM;
+ while (--wait_timeout && !(readl(&pss->spi_reg->sssr) & SSSR_RNE))
+ ;
+ if (!wait_timeout) {
+ debug("%s: timeout error\n", __func__);
+ return -1;
+ }
+
+ if (pss->rx != NULL) {
+ *(u8 *)pss->rx = readl(&pss->spi_reg->ssdr);
+ ++pss->rx;
+ } else {
+ readl(&pss->spi_reg->ssdr);
+ }
+ return 0;
+}
+
+static int spi_armd_flush(struct armd_spi_slave *pss)
+{
+ unsigned long limit = SSP_FLUSH_NUM;
+
+ do {
+ while (readl(&pss->spi_reg->sssr) & SSSR_RNE)
+ readl(&pss->spi_reg->ssdr);
+ } while ((readl(&pss->spi_reg->sssr) & SSSR_BSY) && limit--);
+
+ writel(SSSR_ROR, &pss->spi_reg->sssr);
+
+ return limit;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ struct armd_spi_slave *pss = to_armd_spi_slave(slave);
+
+ gpio_set_value(slave->cs, pss->gpio_cs_inverted);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct armd_spi_slave *pss = to_armd_spi_slave(slave);
+
+ gpio_set_value(slave->cs, !pss->gpio_cs_inverted);
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct armd_spi_slave *pss;
+
+ pss = spi_alloc_slave(struct armd_spi_slave, bus, cs);
+ if (!pss)
+ return NULL;
+
+ pss->spi_reg = (struct ssp_reg *)SSP_REG_BASE(CONFIG_SYS_SSP_PORT);
+
+ pss->cr0 = SSCR0_MOTO | SSCR0_DATASIZE(DEFAULT_WORD_LEN) | SSCR0_SSE;
+
+ pss->cr1 = (SSCR1_RXTRESH(RX_THRESH_DEF) & SSCR1_RFT) |
+ (SSCR1_TXTRESH(TX_THRESH_DEF) & SSCR1_TFT);
+ pss->cr1 &= ~(SSCR1_SPO | SSCR1_SPH);
+ pss->cr1 |= (((mode & SPI_CPHA) != 0) ? SSCR1_SPH : 0)
+ | (((mode & SPI_CPOL) != 0) ? SSCR1_SPO : 0);
+
+ pss->int_cr1 = SSCR1_TIE | SSCR1_RIE | SSCR1_TINTE;
+ pss->clear_sr = SSSR_ROR | SSSR_TINT;
+
+ pss->gpio_cs_inverted = mode & SPI_CS_HIGH;
+ gpio_set_value(cs, !pss->gpio_cs_inverted);
+
+ return &pss->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct armd_spi_slave *pss = to_armd_spi_slave(slave);
+
+ free(pss);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct armd_spi_slave *pss = to_armd_spi_slave(slave);
+
+ debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
+ if (spi_armd_flush(pss) == 0)
+ return -1;
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct armd_spi_slave *pss = to_armd_spi_slave(slave);
+ uint bytes = bitlen / 8;
+ unsigned long limit;
+ int ret = 0;
+
+ if (bitlen == 0)
+ goto done;
+
+ /* we can only do 8 bit transfers */
+ if (bitlen % 8) {
+ flags |= SPI_XFER_END;
+ goto done;
+ }
+
+ pss->tx = dout;
+ pss->rx = din;
+
+ if (flags & SPI_XFER_BEGIN) {
+ spi_cs_activate(slave);
+ writel(pss->cr1 | pss->int_cr1, &pss->spi_reg->sscr1);
+ writel(TIMEOUT_DEF, &pss->spi_reg->ssto);
+ writel(pss->cr0, &pss->spi_reg->sscr0);
+ }
+
+ while (bytes--) {
+ limit = SSP_FLUSH_NUM;
+ ret = spi_armd_write(pss);
+ if (ret)
+ break;
+
+ while ((readl(&pss->spi_reg->sssr) & SSSR_BSY) && limit--)
+ udelay(1);
+
+ ret = spi_armd_read(pss);
+ if (ret)
+ break;
+ }
+
+ done:
+ if (flags & SPI_XFER_END) {
+ /* Stop SSP */
+ writel(pss->clear_sr, &pss->spi_reg->sssr);
+ clrbits_le32(&pss->spi_reg->sscr1, pss->int_cr1);
+ writel(0, &pss->spi_reg->ssto);
+ spi_cs_deactivate(slave);
+ }
+
+ return ret;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/atmel_dataflash_spi.c b/qemu/roms/u-boot/drivers/spi/atmel_dataflash_spi.c
new file mode 100644
index 000000000..a2e9c00ea
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/atmel_dataflash_spi.c
@@ -0,0 +1,184 @@
+/*
+ * Driver for ATMEL DataFlash support
+ * Author : Hamid Ikdoumi (Atmel)
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*
+ * This driver desperately needs rework:
+ *
+ * - use structure SoC access
+ * - get rid of including asm/arch/at91_spi.h
+ * - remove asm/arch/at91_spi.h
+ * - get rid of all CONFIG_ATMEL_LEGACY defines and uses
+ *
+ * 02-Aug-2010 Reinhard Meyer <uboot@emk-elektronik.de>
+ */
+
+#include <common.h>
+#ifndef CONFIG_ATMEL_LEGACY
+# define CONFIG_ATMEL_LEGACY
+#endif
+#include <spi.h>
+#include <malloc.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/clk.h>
+#include <asm/arch/hardware.h>
+
+#include "atmel_spi.h"
+
+#include <asm/arch/gpio.h>
+#include <asm/arch/at91_pio.h>
+#include <asm/arch/at91_spi.h>
+
+#include <dataflash.h>
+
+#define AT91_SPI_PCS0_DATAFLASH_CARD 0xE /* Chip Select 0: NPCS0%1110 */
+#define AT91_SPI_PCS1_DATAFLASH_CARD 0xD /* Chip Select 1: NPCS1%1101 */
+#define AT91_SPI_PCS2_DATAFLASH_CARD 0xB /* Chip Select 2: NPCS2%1011 */
+#define AT91_SPI_PCS3_DATAFLASH_CARD 0x7 /* Chip Select 3: NPCS3%0111 */
+
+void AT91F_SpiInit(void)
+{
+ /* Reset the SPI */
+ writel(AT91_SPI_SWRST, ATMEL_BASE_SPI0 + AT91_SPI_CR);
+
+ /* Configure SPI in Master Mode with No CS selected !!! */
+ writel(AT91_SPI_MSTR | AT91_SPI_MODFDIS | AT91_SPI_PCS,
+ ATMEL_BASE_SPI0 + AT91_SPI_MR);
+
+ /* Configure CS0 */
+ writel(AT91_SPI_NCPHA |
+ (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
+ (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
+ ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
+ ATMEL_BASE_SPI0 + AT91_SPI_CSR(0));
+
+#ifdef CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS1
+ /* Configure CS1 */
+ writel(AT91_SPI_NCPHA |
+ (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
+ (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
+ ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
+ ATMEL_BASE_SPI0 + AT91_SPI_CSR(1));
+#endif
+#ifdef CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS2
+ /* Configure CS2 */
+ writel(AT91_SPI_NCPHA |
+ (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
+ (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
+ ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
+ ATMEL_BASE_SPI0 + AT91_SPI_CSR(2));
+#endif
+#ifdef CONFIG_SYS_DATAFLASH_LOGIC_ADDR_CS3
+ /* Configure CS3 */
+ writel(AT91_SPI_NCPHA |
+ (AT91_SPI_DLYBS & DATAFLASH_TCSS) |
+ (AT91_SPI_DLYBCT & DATAFLASH_TCHS) |
+ ((get_mck_clk_rate() / AT91_SPI_CLK) << 8),
+ ATMEL_BASE_SPI0 + AT91_SPI_CSR(3));
+#endif
+
+ /* SPI_Enable */
+ writel(AT91_SPI_SPIEN, ATMEL_BASE_SPI0 + AT91_SPI_CR);
+
+ while (!(readl(ATMEL_BASE_SPI0 + AT91_SPI_SR) & AT91_SPI_SPIENS))
+ ;
+
+ /*
+ * Add tempo to get SPI in a safe state.
+ * Should not be needed for new silicon (Rev B)
+ */
+ udelay(500000);
+ readl(ATMEL_BASE_SPI0 + AT91_SPI_SR);
+ readl(ATMEL_BASE_SPI0 + AT91_SPI_RDR);
+
+}
+
+void AT91F_SpiEnable(int cs)
+{
+ unsigned long mode;
+
+ mode = readl(ATMEL_BASE_SPI0 + AT91_SPI_MR);
+ mode &= ~AT91_SPI_PCS;
+
+ switch (cs) {
+ case 0:
+ mode |= AT91_SPI_PCS0_DATAFLASH_CARD << 16;
+ break;
+ case 1:
+ mode |= AT91_SPI_PCS1_DATAFLASH_CARD << 16;
+ break;
+ case 2:
+ mode |= AT91_SPI_PCS2_DATAFLASH_CARD << 16;
+ break;
+ case 3:
+ mode |= AT91_SPI_PCS3_DATAFLASH_CARD << 16;
+ break;
+ }
+
+ writel(mode, ATMEL_BASE_SPI0 + AT91_SPI_MR);
+
+ /* SPI_Enable */
+ writel(AT91_SPI_SPIEN, ATMEL_BASE_SPI0 + AT91_SPI_CR);
+}
+
+unsigned int AT91F_SpiWrite1(AT91PS_DataflashDesc pDesc);
+
+unsigned int AT91F_SpiWrite(AT91PS_DataflashDesc pDesc)
+{
+ unsigned int timeout;
+ unsigned int timebase;
+
+ pDesc->state = BUSY;
+
+ writel(AT91_SPI_TXTDIS + AT91_SPI_RXTDIS,
+ ATMEL_BASE_SPI0 + AT91_SPI_PTCR);
+
+ /* Initialize the Transmit and Receive Pointer */
+ writel((unsigned int)pDesc->rx_cmd_pt,
+ ATMEL_BASE_SPI0 + AT91_SPI_RPR);
+ writel((unsigned int)pDesc->tx_cmd_pt,
+ ATMEL_BASE_SPI0 + AT91_SPI_TPR);
+
+ /* Intialize the Transmit and Receive Counters */
+ writel(pDesc->rx_cmd_size, ATMEL_BASE_SPI0 + AT91_SPI_RCR);
+ writel(pDesc->tx_cmd_size, ATMEL_BASE_SPI0 + AT91_SPI_TCR);
+
+ if (pDesc->tx_data_size != 0) {
+ /* Initialize the Next Transmit and Next Receive Pointer */
+ writel((unsigned int)pDesc->rx_data_pt,
+ ATMEL_BASE_SPI0 + AT91_SPI_RNPR);
+ writel((unsigned int)pDesc->tx_data_pt,
+ ATMEL_BASE_SPI0 + AT91_SPI_TNPR);
+
+ /* Intialize the Next Transmit and Next Receive Counters */
+ writel(pDesc->rx_data_size,
+ ATMEL_BASE_SPI0 + AT91_SPI_RNCR);
+ writel(pDesc->tx_data_size,
+ ATMEL_BASE_SPI0 + AT91_SPI_TNCR);
+ }
+
+ /* arm simple, non interrupt dependent timer */
+ timebase = get_timer(0);
+ timeout = 0;
+
+ writel(AT91_SPI_TXTEN + AT91_SPI_RXTEN,
+ ATMEL_BASE_SPI0 + AT91_SPI_PTCR);
+ while (!(readl(ATMEL_BASE_SPI0 + AT91_SPI_SR) & AT91_SPI_RXBUFF) &&
+ ((timeout = get_timer(timebase)) < CONFIG_SYS_SPI_WRITE_TOUT))
+ ;
+ writel(AT91_SPI_TXTDIS + AT91_SPI_RXTDIS,
+ ATMEL_BASE_SPI0 + AT91_SPI_PTCR);
+ pDesc->state = IDLE;
+
+ if (timeout >= CONFIG_SYS_SPI_WRITE_TOUT) {
+ printf("Error Timeout\n\r");
+ return DATAFLASH_ERROR;
+ }
+
+ return DATAFLASH_OK;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/atmel_spi.c b/qemu/roms/u-boot/drivers/spi/atmel_spi.c
new file mode 100644
index 000000000..ed6278b86
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/atmel_spi.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#include <common.h>
+#include <spi.h>
+#include <malloc.h>
+
+#include <asm/io.h>
+
+#include <asm/arch/clk.h>
+#include <asm/arch/hardware.h>
+
+#include "atmel_spi.h"
+
+static int spi_has_wdrbt(struct atmel_spi_slave *slave)
+{
+ unsigned int ver;
+
+ ver = spi_readl(slave, VERSION);
+
+ return (ATMEL_SPI_VERSION_REV(ver) >= 0x210);
+}
+
+void spi_init()
+{
+
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct atmel_spi_slave *as;
+ unsigned int scbr;
+ u32 csrx;
+ void *regs;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ switch (bus) {
+ case 0:
+ regs = (void *)ATMEL_BASE_SPI0;
+ break;
+#ifdef ATMEL_BASE_SPI1
+ case 1:
+ regs = (void *)ATMEL_BASE_SPI1;
+ break;
+#endif
+#ifdef ATMEL_BASE_SPI2
+ case 2:
+ regs = (void *)ATMEL_BASE_SPI2;
+ break;
+#endif
+#ifdef ATMEL_BASE_SPI3
+ case 3:
+ regs = (void *)ATMEL_BASE_SPI3;
+ break;
+#endif
+ default:
+ return NULL;
+ }
+
+
+ scbr = (get_spi_clk_rate(bus) + max_hz - 1) / max_hz;
+ if (scbr > ATMEL_SPI_CSRx_SCBR_MAX)
+ /* Too low max SCK rate */
+ return NULL;
+ if (scbr < 1)
+ scbr = 1;
+
+ csrx = ATMEL_SPI_CSRx_SCBR(scbr);
+ csrx |= ATMEL_SPI_CSRx_BITS(ATMEL_SPI_BITS_8);
+ if (!(mode & SPI_CPHA))
+ csrx |= ATMEL_SPI_CSRx_NCPHA;
+ if (mode & SPI_CPOL)
+ csrx |= ATMEL_SPI_CSRx_CPOL;
+
+ as = spi_alloc_slave(struct atmel_spi_slave, bus, cs);
+ if (!as)
+ return NULL;
+
+ as->regs = regs;
+ as->mr = ATMEL_SPI_MR_MSTR | ATMEL_SPI_MR_MODFDIS
+ | ATMEL_SPI_MR_PCS(~(1 << cs) & 0xf);
+ if (spi_has_wdrbt(as))
+ as->mr |= ATMEL_SPI_MR_WDRBT;
+
+ spi_writel(as, CSR(cs), csrx);
+
+ return &as->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct atmel_spi_slave *as = to_atmel_spi(slave);
+
+ free(as);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct atmel_spi_slave *as = to_atmel_spi(slave);
+
+ /* Enable the SPI hardware */
+ spi_writel(as, CR, ATMEL_SPI_CR_SPIEN);
+
+ /*
+ * Select the slave. This should set SCK to the correct
+ * initial state, etc.
+ */
+ spi_writel(as, MR, as->mr);
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ struct atmel_spi_slave *as = to_atmel_spi(slave);
+
+ /* Disable the SPI hardware */
+ spi_writel(as, CR, ATMEL_SPI_CR_SPIDIS);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
+{
+ struct atmel_spi_slave *as = to_atmel_spi(slave);
+ unsigned int len_tx;
+ unsigned int len_rx;
+ unsigned int len;
+ u32 status;
+ const u8 *txp = dout;
+ u8 *rxp = din;
+ u8 value;
+
+ if (bitlen == 0)
+ /* Finish any previously submitted transfers */
+ goto out;
+
+ /*
+ * TODO: The controller can do non-multiple-of-8 bit
+ * transfers, but this driver currently doesn't support it.
+ *
+ * It's also not clear how such transfers are supposed to be
+ * represented as a stream of bytes...this is a limitation of
+ * the current SPI interface.
+ */
+ if (bitlen % 8) {
+ /* Errors always terminate an ongoing transfer */
+ flags |= SPI_XFER_END;
+ goto out;
+ }
+
+ len = bitlen / 8;
+
+ /*
+ * The controller can do automatic CS control, but it is
+ * somewhat quirky, and it doesn't really buy us much anyway
+ * in the context of U-Boot.
+ */
+ if (flags & SPI_XFER_BEGIN) {
+ spi_cs_activate(slave);
+ /*
+ * sometimes the RDR is not empty when we get here,
+ * in theory that should not happen, but it DOES happen.
+ * Read it here to be on the safe side.
+ * That also clears the OVRES flag. Required if the
+ * following loop exits due to OVRES!
+ */
+ spi_readl(as, RDR);
+ }
+
+ for (len_tx = 0, len_rx = 0; len_rx < len; ) {
+ status = spi_readl(as, SR);
+
+ if (status & ATMEL_SPI_SR_OVRES)
+ return -1;
+
+ if (len_tx < len && (status & ATMEL_SPI_SR_TDRE)) {
+ if (txp)
+ value = *txp++;
+ else
+ value = 0;
+ spi_writel(as, TDR, value);
+ len_tx++;
+ }
+ if (status & ATMEL_SPI_SR_RDRF) {
+ value = spi_readl(as, RDR);
+ if (rxp)
+ *rxp++ = value;
+ len_rx++;
+ }
+ }
+
+out:
+ if (flags & SPI_XFER_END) {
+ /*
+ * Wait until the transfer is completely done before
+ * we deactivate CS.
+ */
+ do {
+ status = spi_readl(as, SR);
+ } while (!(status & ATMEL_SPI_SR_TXEMPTY));
+
+ spi_cs_deactivate(slave);
+ }
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/atmel_spi.h b/qemu/roms/u-boot/drivers/spi/atmel_spi.h
new file mode 100644
index 000000000..d2409454f
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/atmel_spi.h
@@ -0,0 +1,96 @@
+/*
+ * Register definitions for the Atmel AT32/AT91 SPI Controller
+ */
+
+/* Register offsets */
+#define ATMEL_SPI_CR 0x0000
+#define ATMEL_SPI_MR 0x0004
+#define ATMEL_SPI_RDR 0x0008
+#define ATMEL_SPI_TDR 0x000c
+#define ATMEL_SPI_SR 0x0010
+#define ATMEL_SPI_IER 0x0014
+#define ATMEL_SPI_IDR 0x0018
+#define ATMEL_SPI_IMR 0x001c
+#define ATMEL_SPI_CSR(x) (0x0030 + 4 * (x))
+#define ATMEL_SPI_VERSION 0x00fc
+
+/* Bits in CR */
+#define ATMEL_SPI_CR_SPIEN (1 << 0)
+#define ATMEL_SPI_CR_SPIDIS (1 << 1)
+#define ATMEL_SPI_CR_SWRST (1 << 7)
+#define ATMEL_SPI_CR_LASTXFER (1 << 24)
+
+/* Bits in MR */
+#define ATMEL_SPI_MR_MSTR (1 << 0)
+#define ATMEL_SPI_MR_PS (1 << 1)
+#define ATMEL_SPI_MR_PCSDEC (1 << 2)
+#define ATMEL_SPI_MR_FDIV (1 << 3)
+#define ATMEL_SPI_MR_MODFDIS (1 << 4)
+#define ATMEL_SPI_MR_WDRBT (1 << 5)
+#define ATMEL_SPI_MR_LLB (1 << 7)
+#define ATMEL_SPI_MR_PCS(x) (((x) & 15) << 16)
+#define ATMEL_SPI_MR_DLYBCS(x) ((x) << 24)
+
+/* Bits in RDR */
+#define ATMEL_SPI_RDR_RD(x) (x)
+#define ATMEL_SPI_RDR_PCS(x) ((x) << 16)
+
+/* Bits in TDR */
+#define ATMEL_SPI_TDR_TD(x) (x)
+#define ATMEL_SPI_TDR_PCS(x) ((x) << 16)
+#define ATMEL_SPI_TDR_LASTXFER (1 << 24)
+
+/* Bits in SR/IER/IDR/IMR */
+#define ATMEL_SPI_SR_RDRF (1 << 0)
+#define ATMEL_SPI_SR_TDRE (1 << 1)
+#define ATMEL_SPI_SR_MODF (1 << 2)
+#define ATMEL_SPI_SR_OVRES (1 << 3)
+#define ATMEL_SPI_SR_ENDRX (1 << 4)
+#define ATMEL_SPI_SR_ENDTX (1 << 5)
+#define ATMEL_SPI_SR_RXBUFF (1 << 6)
+#define ATMEL_SPI_SR_TXBUFE (1 << 7)
+#define ATMEL_SPI_SR_NSSR (1 << 8)
+#define ATMEL_SPI_SR_TXEMPTY (1 << 9)
+#define ATMEL_SPI_SR_SPIENS (1 << 16)
+
+/* Bits in CSRx */
+#define ATMEL_SPI_CSRx_CPOL (1 << 0)
+#define ATMEL_SPI_CSRx_NCPHA (1 << 1)
+#define ATMEL_SPI_CSRx_CSAAT (1 << 3)
+#define ATMEL_SPI_CSRx_BITS(x) ((x) << 4)
+#define ATMEL_SPI_CSRx_SCBR(x) ((x) << 8)
+#define ATMEL_SPI_CSRx_SCBR_MAX 0xff
+#define ATMEL_SPI_CSRx_DLYBS(x) ((x) << 16)
+#define ATMEL_SPI_CSRx_DLYBCT(x) ((x) << 24)
+
+/* Bits in VERSION */
+#define ATMEL_SPI_VERSION_REV(x) ((x) & 0xfff)
+#define ATMEL_SPI_VERSION_MFN(x) ((x) << 16)
+
+/* Constants for CSRx:BITS */
+#define ATMEL_SPI_BITS_8 0
+#define ATMEL_SPI_BITS_9 1
+#define ATMEL_SPI_BITS_10 2
+#define ATMEL_SPI_BITS_11 3
+#define ATMEL_SPI_BITS_12 4
+#define ATMEL_SPI_BITS_13 5
+#define ATMEL_SPI_BITS_14 6
+#define ATMEL_SPI_BITS_15 7
+#define ATMEL_SPI_BITS_16 8
+
+struct atmel_spi_slave {
+ struct spi_slave slave;
+ void *regs;
+ u32 mr;
+};
+
+static inline struct atmel_spi_slave *to_atmel_spi(struct spi_slave *slave)
+{
+ return container_of(slave, struct atmel_spi_slave, slave);
+}
+
+/* Register access macros */
+#define spi_readl(as, reg) \
+ readl(as->regs + ATMEL_SPI_##reg)
+#define spi_writel(as, reg, value) \
+ writel(value, as->regs + ATMEL_SPI_##reg)
diff --git a/qemu/roms/u-boot/drivers/spi/bfin_spi.c b/qemu/roms/u-boot/drivers/spi/bfin_spi.c
new file mode 100644
index 000000000..71a31d012
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/bfin_spi.c
@@ -0,0 +1,308 @@
+/*
+ * Driver for Blackfin On-Chip SPI device
+ *
+ * Copyright (c) 2005-2010 Analog Devices Inc.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+/*#define DEBUG*/
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+
+#include <asm/blackfin.h>
+#include <asm/clock.h>
+#include <asm/gpio.h>
+#include <asm/portmux.h>
+#include <asm/mach-common/bits/spi.h>
+
+struct bfin_spi_slave {
+ struct spi_slave slave;
+ void *mmr_base;
+ u16 ctl, baud, flg;
+};
+
+#define MAKE_SPI_FUNC(mmr, off) \
+static inline void write_##mmr(struct bfin_spi_slave *bss, u16 val) { bfin_write16(bss->mmr_base + off, val); } \
+static inline u16 read_##mmr(struct bfin_spi_slave *bss) { return bfin_read16(bss->mmr_base + off); }
+MAKE_SPI_FUNC(SPI_CTL, 0x00)
+MAKE_SPI_FUNC(SPI_FLG, 0x04)
+MAKE_SPI_FUNC(SPI_STAT, 0x08)
+MAKE_SPI_FUNC(SPI_TDBR, 0x0c)
+MAKE_SPI_FUNC(SPI_RDBR, 0x10)
+MAKE_SPI_FUNC(SPI_BAUD, 0x14)
+
+#define to_bfin_spi_slave(s) container_of(s, struct bfin_spi_slave, slave)
+
+#define gpio_cs(cs) ((cs) - MAX_CTRL_CS)
+#ifdef CONFIG_BFIN_SPI_GPIO_CS
+# define is_gpio_cs(cs) ((cs) > MAX_CTRL_CS)
+#else
+# define is_gpio_cs(cs) 0
+#endif
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ if (is_gpio_cs(cs))
+ return gpio_is_valid(gpio_cs(cs));
+ else
+ return (cs >= 1 && cs <= MAX_CTRL_CS);
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
+
+ if (is_gpio_cs(slave->cs)) {
+ unsigned int cs = gpio_cs(slave->cs);
+ gpio_set_value(cs, bss->flg);
+ debug("%s: SPI_CS_GPIO:%x\n", __func__, gpio_get_value(cs));
+ } else {
+ write_SPI_FLG(bss,
+ (read_SPI_FLG(bss) &
+ ~((!bss->flg << 8) << slave->cs)) |
+ (1 << slave->cs));
+ debug("%s: SPI_FLG:%x\n", __func__, read_SPI_FLG(bss));
+ }
+
+ SSYNC();
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
+
+ if (is_gpio_cs(slave->cs)) {
+ unsigned int cs = gpio_cs(slave->cs);
+ gpio_set_value(cs, !bss->flg);
+ debug("%s: SPI_CS_GPIO:%x\n", __func__, gpio_get_value(cs));
+ } else {
+ u16 flg;
+
+ /* make sure we force the cs to deassert rather than let the
+ * pin float back up. otherwise, exact timings may not be
+ * met some of the time leading to random behavior (ugh).
+ */
+ flg = read_SPI_FLG(bss) | ((!bss->flg << 8) << slave->cs);
+ write_SPI_FLG(bss, flg);
+ SSYNC();
+ debug("%s: SPI_FLG:%x\n", __func__, read_SPI_FLG(bss));
+
+ flg &= ~(1 << slave->cs);
+ write_SPI_FLG(bss, flg);
+ debug("%s: SPI_FLG:%x\n", __func__, read_SPI_FLG(bss));
+ }
+
+ SSYNC();
+}
+
+void spi_init()
+{
+}
+
+#ifdef SPI_CTL
+# define SPI0_CTL SPI_CTL
+#endif
+
+#define SPI_PINS(n) \
+ [n] = { 0, P_SPI##n##_SCK, P_SPI##n##_MISO, P_SPI##n##_MOSI, 0 }
+static unsigned short pins[][5] = {
+#ifdef SPI0_CTL
+ SPI_PINS(0),
+#endif
+#ifdef SPI1_CTL
+ SPI_PINS(1),
+#endif
+#ifdef SPI2_CTL
+ SPI_PINS(2),
+#endif
+};
+
+#define SPI_CS_PINS(n) \
+ [n] = { \
+ P_SPI##n##_SSEL1, P_SPI##n##_SSEL2, P_SPI##n##_SSEL3, \
+ P_SPI##n##_SSEL4, P_SPI##n##_SSEL5, P_SPI##n##_SSEL6, \
+ P_SPI##n##_SSEL7, \
+ }
+static const unsigned short cs_pins[][7] = {
+#ifdef SPI0_CTL
+ SPI_CS_PINS(0),
+#endif
+#ifdef SPI1_CTL
+ SPI_CS_PINS(1),
+#endif
+#ifdef SPI2_CTL
+ SPI_CS_PINS(2),
+#endif
+};
+
+void spi_set_speed(struct spi_slave *slave, uint hz)
+{
+ struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
+ ulong clk;
+ u32 baud;
+
+ clk = get_spi_clk();
+ /* baud should be rounded up */
+ baud = DIV_ROUND_UP(clk, 2 * hz);
+ if (baud < 2)
+ baud = 2;
+ else if (baud > (u16)-1)
+ baud = -1;
+ bss->baud = baud;
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct bfin_spi_slave *bss;
+ u32 mmr_base;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ switch (bus) {
+#ifdef SPI0_CTL
+ case 0:
+ mmr_base = SPI0_CTL; break;
+#endif
+#ifdef SPI1_CTL
+ case 1:
+ mmr_base = SPI1_CTL; break;
+#endif
+#ifdef SPI2_CTL
+ case 2:
+ mmr_base = SPI2_CTL; break;
+#endif
+ default:
+ debug("%s: invalid bus %u\n", __func__, bus);
+ return NULL;
+ }
+
+ bss = spi_alloc_slave(struct bfin_spi_slave, bus, cs);
+ if (!bss)
+ return NULL;
+
+ bss->mmr_base = (void *)mmr_base;
+ bss->ctl = SPE | MSTR | TDBR_CORE;
+ if (mode & SPI_CPHA) bss->ctl |= CPHA;
+ if (mode & SPI_CPOL) bss->ctl |= CPOL;
+ if (mode & SPI_LSB_FIRST) bss->ctl |= LSBF;
+ bss->flg = mode & SPI_CS_HIGH ? 1 : 0;
+ spi_set_speed(&bss->slave, max_hz);
+
+ debug("%s: bus:%i cs:%i mmr:%x ctl:%x baud:%i flg:%i\n", __func__,
+ bus, cs, mmr_base, bss->ctl, bss->baud, bss->flg);
+
+ return &bss->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
+ free(bss);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
+
+ debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
+
+ if (is_gpio_cs(slave->cs)) {
+ unsigned int cs = gpio_cs(slave->cs);
+ gpio_request(cs, "bfin-spi");
+ gpio_direction_output(cs, !bss->flg);
+ pins[slave->bus][0] = P_DONTCARE;
+ } else
+ pins[slave->bus][0] = cs_pins[slave->bus][slave->cs - 1];
+ peripheral_request_list(pins[slave->bus], "bfin-spi");
+
+ write_SPI_CTL(bss, bss->ctl);
+ write_SPI_BAUD(bss, bss->baud);
+ SSYNC();
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
+
+ debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
+
+ peripheral_free_list(pins[slave->bus]);
+ if (is_gpio_cs(slave->cs))
+ gpio_free(gpio_cs(slave->cs));
+
+ write_SPI_CTL(bss, 0);
+ SSYNC();
+}
+
+#ifndef CONFIG_BFIN_SPI_IDLE_VAL
+# define CONFIG_BFIN_SPI_IDLE_VAL 0xff
+#endif
+
+static int spi_pio_xfer(struct bfin_spi_slave *bss, const u8 *tx, u8 *rx,
+ uint bytes)
+{
+ /* discard invalid data and clear RXS */
+ read_SPI_RDBR(bss);
+ /* todo: take advantage of hardware fifos */
+ while (bytes--) {
+ u8 value = (tx ? *tx++ : CONFIG_BFIN_SPI_IDLE_VAL);
+ debug("%s: tx:%x ", __func__, value);
+ write_SPI_TDBR(bss, value);
+ SSYNC();
+ while ((read_SPI_STAT(bss) & TXS))
+ if (ctrlc())
+ return -1;
+ while (!(read_SPI_STAT(bss) & SPIF))
+ if (ctrlc())
+ return -1;
+ while (!(read_SPI_STAT(bss) & RXS))
+ if (ctrlc())
+ return -1;
+ value = read_SPI_RDBR(bss);
+ if (rx)
+ *rx++ = value;
+ debug("rx:%x\n", value);
+ }
+
+ return 0;
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
+ const u8 *tx = dout;
+ u8 *rx = din;
+ uint bytes = bitlen / 8;
+ int ret = 0;
+
+ debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
+ slave->bus, slave->cs, bitlen, bytes, flags);
+
+ if (bitlen == 0)
+ goto done;
+
+ /* we can only do 8 bit transfers */
+ if (bitlen % 8) {
+ flags |= SPI_XFER_END;
+ goto done;
+ }
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ ret = spi_pio_xfer(bss, tx, rx, bytes);
+
+ done:
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ return ret;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/bfin_spi6xx.c b/qemu/roms/u-boot/drivers/spi/bfin_spi6xx.c
new file mode 100644
index 000000000..eba01d16f
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/bfin_spi6xx.c
@@ -0,0 +1,304 @@
+/*
+ * Analog Devices SPI3 controller driver
+ *
+ * Copyright (c) 2011 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+
+#include <asm/blackfin.h>
+#include <asm/clock.h>
+#include <asm/gpio.h>
+#include <asm/portmux.h>
+#include <asm/mach-common/bits/spi6xx.h>
+
+struct bfin_spi_slave {
+ struct spi_slave slave;
+ u32 control, clock;
+ struct bfin_spi_regs *regs;
+ int cs_pol;
+};
+
+#define to_bfin_spi_slave(s) container_of(s, struct bfin_spi_slave, slave)
+
+#define gpio_cs(cs) ((cs) - MAX_CTRL_CS)
+#ifdef CONFIG_BFIN_SPI_GPIO_CS
+# define is_gpio_cs(cs) ((cs) > MAX_CTRL_CS)
+#else
+# define is_gpio_cs(cs) 0
+#endif
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ if (is_gpio_cs(cs))
+ return gpio_is_valid(gpio_cs(cs));
+ else
+ return (cs >= 1 && cs <= MAX_CTRL_CS);
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
+
+ if (is_gpio_cs(slave->cs)) {
+ unsigned int cs = gpio_cs(slave->cs);
+ gpio_set_value(cs, bss->cs_pol);
+ } else {
+ u32 ssel;
+ ssel = bfin_read32(&bss->regs->ssel);
+ ssel |= 1 << slave->cs;
+ if (bss->cs_pol)
+ ssel |= (1 << 8) << slave->cs;
+ else
+ ssel &= ~((1 << 8) << slave->cs);
+ bfin_write32(&bss->regs->ssel, ssel);
+ }
+
+ SSYNC();
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
+
+ if (is_gpio_cs(slave->cs)) {
+ unsigned int cs = gpio_cs(slave->cs);
+ gpio_set_value(cs, !bss->cs_pol);
+ } else {
+ u32 ssel;
+ ssel = bfin_read32(&bss->regs->ssel);
+ if (bss->cs_pol)
+ ssel &= ~((1 << 8) << slave->cs);
+ else
+ ssel |= (1 << 8) << slave->cs;
+ /* deassert cs */
+ bfin_write32(&bss->regs->ssel, ssel);
+ SSYNC();
+ /* disable cs */
+ ssel &= ~(1 << slave->cs);
+ bfin_write32(&bss->regs->ssel, ssel);
+ }
+
+ SSYNC();
+}
+
+void spi_init()
+{
+}
+
+#define SPI_PINS(n) \
+ { 0, P_SPI##n##_SCK, P_SPI##n##_MISO, P_SPI##n##_MOSI, 0 }
+static unsigned short pins[][5] = {
+#ifdef SPI0_REGBASE
+ [0] = SPI_PINS(0),
+#endif
+#ifdef SPI1_REGBASE
+ [1] = SPI_PINS(1),
+#endif
+#ifdef SPI2_REGBASE
+ [2] = SPI_PINS(2),
+#endif
+};
+
+#define SPI_CS_PINS(n) \
+ { \
+ P_SPI##n##_SSEL1, P_SPI##n##_SSEL2, P_SPI##n##_SSEL3, \
+ P_SPI##n##_SSEL4, P_SPI##n##_SSEL5, P_SPI##n##_SSEL6, \
+ P_SPI##n##_SSEL7, \
+ }
+static const unsigned short cs_pins[][7] = {
+#ifdef SPI0_REGBASE
+ [0] = SPI_CS_PINS(0),
+#endif
+#ifdef SPI1_REGBASE
+ [1] = SPI_CS_PINS(1),
+#endif
+#ifdef SPI2_REGBASE
+ [2] = SPI_CS_PINS(2),
+#endif
+};
+
+void spi_set_speed(struct spi_slave *slave, uint hz)
+{
+ struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
+ ulong clk;
+ u32 clock;
+
+ clk = get_spi_clk();
+ clock = clk / hz;
+ if (clock)
+ clock--;
+ bss->clock = clock;
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct bfin_spi_slave *bss;
+ u32 reg_base;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ switch (bus) {
+#ifdef SPI0_REGBASE
+ case 0:
+ reg_base = SPI0_REGBASE;
+ break;
+#endif
+#ifdef SPI1_REGBASE
+ case 1:
+ reg_base = SPI1_REGBASE;
+ break;
+#endif
+#ifdef SPI2_REGBASE
+ case 2:
+ reg_base = SPI2_REGBASE;
+ break;
+#endif
+ default:
+ debug("%s: invalid bus %u\n", __func__, bus);
+ return NULL;
+ }
+
+ bss = spi_alloc_slave(struct bfin_spi_slave, bus, cs);
+ if (!bss)
+ return NULL;
+
+ bss->regs = (struct bfin_spi_regs *)reg_base;
+ bss->control = SPI_CTL_EN | SPI_CTL_MSTR;
+ if (mode & SPI_CPHA)
+ bss->control |= SPI_CTL_CPHA;
+ if (mode & SPI_CPOL)
+ bss->control |= SPI_CTL_CPOL;
+ if (mode & SPI_LSB_FIRST)
+ bss->control |= SPI_CTL_LSBF;
+ bss->control &= ~SPI_CTL_ASSEL;
+ bss->cs_pol = mode & SPI_CS_HIGH ? 1 : 0;
+ spi_set_speed(&bss->slave, max_hz);
+
+ return &bss->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
+ free(bss);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
+
+ debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
+
+ if (is_gpio_cs(slave->cs)) {
+ unsigned int cs = gpio_cs(slave->cs);
+ gpio_request(cs, "bfin-spi");
+ gpio_direction_output(cs, !bss->cs_pol);
+ pins[slave->bus][0] = P_DONTCARE;
+ } else
+ pins[slave->bus][0] = cs_pins[slave->bus][slave->cs - 1];
+ peripheral_request_list(pins[slave->bus], "bfin-spi");
+
+ bfin_write32(&bss->regs->control, bss->control);
+ bfin_write32(&bss->regs->clock, bss->clock);
+ bfin_write32(&bss->regs->delay, 0x0);
+ bfin_write32(&bss->regs->rx_control, SPI_RXCTL_REN);
+ bfin_write32(&bss->regs->tx_control, SPI_TXCTL_TEN | SPI_TXCTL_TTI);
+ SSYNC();
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
+
+ debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
+
+ peripheral_free_list(pins[slave->bus]);
+ if (is_gpio_cs(slave->cs))
+ gpio_free(gpio_cs(slave->cs));
+
+ bfin_write32(&bss->regs->rx_control, 0x0);
+ bfin_write32(&bss->regs->tx_control, 0x0);
+ bfin_write32(&bss->regs->control, 0x0);
+ SSYNC();
+}
+
+#ifndef CONFIG_BFIN_SPI_IDLE_VAL
+# define CONFIG_BFIN_SPI_IDLE_VAL 0xff
+#endif
+
+static int spi_pio_xfer(struct bfin_spi_slave *bss, const u8 *tx, u8 *rx,
+ uint bytes)
+{
+ /* discard invalid rx data and empty rfifo */
+ while (!(bfin_read32(&bss->regs->status) & SPI_STAT_RFE))
+ bfin_read32(&bss->regs->rfifo);
+
+ while (bytes--) {
+ u8 value = (tx ? *tx++ : CONFIG_BFIN_SPI_IDLE_VAL);
+ debug("%s: tx:%x ", __func__, value);
+ bfin_write32(&bss->regs->tfifo, value);
+ SSYNC();
+ while (bfin_read32(&bss->regs->status) & SPI_STAT_RFE)
+ if (ctrlc())
+ return -1;
+ value = bfin_read32(&bss->regs->rfifo);
+ if (rx)
+ *rx++ = value;
+ debug("rx:%x\n", value);
+ }
+
+ return 0;
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct bfin_spi_slave *bss = to_bfin_spi_slave(slave);
+ const u8 *tx = dout;
+ u8 *rx = din;
+ uint bytes = bitlen / 8;
+ int ret = 0;
+
+ debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
+ slave->bus, slave->cs, bitlen, bytes, flags);
+
+ if (bitlen == 0)
+ goto done;
+
+ /* we can only do 8 bit transfers */
+ if (bitlen % 8) {
+ flags |= SPI_XFER_END;
+ goto done;
+ }
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ ret = spi_pio_xfer(bss, tx, rx, bytes);
+
+ done:
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ return ret;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/cf_qspi.c b/qemu/roms/u-boot/drivers/spi/cf_qspi.c
new file mode 100644
index 000000000..6b8563366
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/cf_qspi.c
@@ -0,0 +1,355 @@
+/*
+ * Freescale Coldfire Queued SPI driver
+ *
+ * NOTE:
+ * This driver is written to transfer 8 bit at-a-time and uses the dedicated
+ * SPI slave select pins as bit-banged GPIO to work with spi_flash subsystem.
+ *
+ * Copyright (C) 2011 Ruggedcom, Inc.
+ * Richard Retanubun (richardretanubun@freescale.com)
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/immap.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define clamp(x, low, high) (min(max(low, x), high))
+#define to_cf_qspi_slave(s) container_of(s, struct cf_qspi_slave, s)
+
+struct cf_qspi_slave {
+ struct spi_slave slave; /* Specific bus:cs ID for each device */
+ qspi_t *regs; /* Pointer to SPI controller registers */
+ u16 qmr; /* QMR: Queued Mode Register */
+ u16 qwr; /* QWR: Queued Wrap Register */
+ u16 qcr; /* QCR: Queued Command Ram */
+};
+
+/* Register write wrapper functions */
+static void write_qmr(volatile qspi_t *qspi, u16 val) { qspi->mr = val; }
+static void write_qdlyr(volatile qspi_t *qspi, u16 val) { qspi->dlyr = val; }
+static void write_qwr(volatile qspi_t *qspi, u16 val) { qspi->wr = val; }
+static void write_qir(volatile qspi_t *qspi, u16 val) { qspi->ir = val; }
+static void write_qar(volatile qspi_t *qspi, u16 val) { qspi->ar = val; }
+static void write_qdr(volatile qspi_t *qspi, u16 val) { qspi->dr = val; }
+/* Register read wrapper functions */
+static u16 read_qdlyr(volatile qspi_t *qspi) { return qspi->dlyr; }
+static u16 read_qwr(volatile qspi_t *qspi) { return qspi->wr; }
+static u16 read_qir(volatile qspi_t *qspi) { return qspi->ir; }
+static u16 read_qdr(volatile qspi_t *qspi) { return qspi->dr; }
+
+/* These call points may be different for each ColdFire CPU */
+extern void cfspi_port_conf(void);
+static void cfspi_cs_activate(uint bus, uint cs, uint cs_active_high);
+static void cfspi_cs_deactivate(uint bus, uint cs, uint cs_active_high);
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ return 0;
+}
+void spi_release_bus(struct spi_slave *slave)
+{
+}
+
+__attribute__((weak))
+void spi_init(void)
+{
+ cfspi_port_conf();
+}
+
+__attribute__((weak))
+void spi_cs_activate(struct spi_slave *slave)
+{
+ struct cf_qspi_slave *dev = to_cf_qspi_slave(slave);
+
+ cfspi_cs_activate(slave->bus, slave->cs, !(dev->qwr & QSPI_QWR_CSIV));
+}
+
+__attribute__((weak))
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct cf_qspi_slave *dev = to_cf_qspi_slave(slave);
+
+ cfspi_cs_deactivate(slave->bus, slave->cs, !(dev->qwr & QSPI_QWR_CSIV));
+}
+
+__attribute__((weak))
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ /* Only 1 bus and 4 chipselect per controller */
+ if (bus == 0 && (cs >= 0 && cs < 4))
+ return 1;
+ else
+ return 0;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct cf_qspi_slave *dev = to_cf_qspi_slave(slave);
+
+ free(dev);
+}
+
+/* Translate information given by spi_setup_slave to members of cf_qspi_slave */
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct cf_qspi_slave *dev = NULL;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ dev = spi_alloc_slave(struct cf_qspi_slave, bus, cs);
+ if (!dev)
+ return NULL;
+
+ /* Initialize to known value */
+ dev->regs = (qspi_t *)MMAP_QSPI;
+ dev->qmr = 0;
+ dev->qwr = 0;
+ dev->qcr = 0;
+
+
+ /* Map max_hz to QMR[BAUD] */
+ if (max_hz == 0) /* Go as fast as possible */
+ dev->qmr = 2u;
+ else /* Get the closest baud rate */
+ dev->qmr = clamp(((gd->bus_clk >> 2) + max_hz - 1)/max_hz,
+ 2u, 255u);
+
+ /* Map mode to QMR[CPOL] and QMR[CPHA] */
+ if (mode & SPI_CPOL)
+ dev->qmr |= QSPI_QMR_CPOL;
+
+ if (mode & SPI_CPHA)
+ dev->qmr |= QSPI_QMR_CPHA;
+
+ /* Hardcode bit length to 8 bit per transter */
+ dev->qmr |= QSPI_QMR_BITS_8;
+
+ /* Set QMR[MSTR] to enable QSPI as master */
+ dev->qmr |= QSPI_QMR_MSTR;
+
+ /*
+ * Set QCR and QWR to default values for spi flash operation.
+ * If more custom QCR and QRW are needed, overload mode variable
+ */
+ dev->qcr = (QSPI_QDR_CONT | QSPI_QDR_BITSE);
+
+ if (!(mode & SPI_CS_HIGH))
+ dev->qwr |= QSPI_QWR_CSIV;
+
+ return &dev->slave;
+}
+
+/* Transfer 8 bit at a time */
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct cf_qspi_slave *dev = to_cf_qspi_slave(slave);
+ volatile qspi_t *qspi = dev->regs;
+ u8 *txbuf = (u8 *)dout;
+ u8 *rxbuf = (u8 *)din;
+ u32 count = DIV_ROUND_UP(bitlen, 8);
+ u32 n, i = 0;
+
+ /* Sanitize arguments */
+ if (slave == NULL) {
+ printf("%s: NULL slave ptr\n", __func__);
+ return -1;
+ }
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ /* There is something to send, lets process it. spi_xfer is also called
+ * just to toggle chip select, so bitlen of 0 is valid */
+ if (count > 0) {
+ /*
+ * NOTE: Since chip select is driven as a bit-bang-ed GPIO
+ * using spi_cs_activate() and spi_cs_deactivate(),
+ * the chip select settings inside the controller
+ * (i.e. QCR[CONT] and QWR[CSIV]) are moot. The bits are set to
+ * keep the controller settings consistent with the actual
+ * operation of the bus.
+ */
+
+ /* Write the slave device's settings for the controller.*/
+ write_qmr(qspi, dev->qmr);
+ write_qwr(qspi, dev->qwr);
+
+ /* Limit transfer to 16 at a time */
+ n = min(count, 16u);
+ do {
+ /* Setup queue end point */
+ write_qwr(qspi, ((read_qwr(qspi) & QSPI_QWR_ENDQP_MASK)
+ | QSPI_QWR_ENDQP((n-1))));
+
+ /* Write Command RAM */
+ write_qar(qspi, QSPI_QAR_CMD);
+ for (i = 0; i < n; ++i)
+ write_qdr(qspi, dev->qcr);
+
+ /* Write TxBuf, if none given, fill with ZEROes */
+ write_qar(qspi, QSPI_QAR_TRANS);
+ if (txbuf) {
+ for (i = 0; i < n; ++i)
+ write_qdr(qspi, *txbuf++);
+ } else {
+ for (i = 0; i < n; ++i)
+ write_qdr(qspi, 0);
+ }
+
+ /* Clear QIR[SPIF] by writing a 1 to it */
+ write_qir(qspi, read_qir(qspi) | QSPI_QIR_SPIF);
+ /* Set QDLYR[SPE] to start sending */
+ write_qdlyr(qspi, read_qdlyr(qspi) | QSPI_QDLYR_SPE);
+
+ /* Poll QIR[SPIF] for transfer completion */
+ while ((read_qir(qspi) & QSPI_QIR_SPIF) != 1)
+ udelay(1);
+
+ /* If given read RxBuf, load data to it */
+ if (rxbuf) {
+ write_qar(qspi, QSPI_QAR_RECV);
+ for (i = 0; i < n; ++i)
+ *rxbuf++ = read_qdr(qspi);
+ }
+
+ /* Decrement count */
+ count -= n;
+ } while (count);
+ }
+
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ return 0;
+}
+
+/* Each MCF CPU may have different pin assignments for chip selects. */
+#if defined(CONFIG_M5271)
+/* Assert chip select, val = [1|0] , dir = out, mode = GPIO */
+void cfspi_cs_activate(uint bus, uint cs, uint cs_active_high)
+{
+ debug("%s: bus %d cs %d cs_active_high %d\n",
+ __func__, bus, cs, cs_active_high);
+
+ switch (cs) {
+ case 0: /* QSPI_CS[0] = PQSPI[3] */
+ if (cs_active_high)
+ mbar_writeByte(MCF_GPIO_PPDSDR_QSPI, 0x08);
+ else
+ mbar_writeByte(MCF_GPIO_PCLRR_QSPI, 0xF7);
+
+ mbar_writeByte(MCF_GPIO_PDDR_QSPI,
+ mbar_readByte(MCF_GPIO_PDDR_QSPI) | 0x08);
+
+ mbar_writeByte(MCF_GPIO_PAR_QSPI,
+ mbar_readByte(MCF_GPIO_PAR_QSPI) & 0xDF);
+ break;
+ case 1: /* QSPI_CS[1] = PQSPI[4] */
+ if (cs_active_high)
+ mbar_writeByte(MCF_GPIO_PPDSDR_QSPI, 0x10);
+ else
+ mbar_writeByte(MCF_GPIO_PCLRR_QSPI, 0xEF);
+
+ mbar_writeByte(MCF_GPIO_PDDR_QSPI,
+ mbar_readByte(MCF_GPIO_PDDR_QSPI) | 0x10);
+
+ mbar_writeByte(MCF_GPIO_PAR_QSPI,
+ mbar_readByte(MCF_GPIO_PAR_QSPI) & 0x3F);
+ break;
+ case 2: /* QSPI_CS[2] = PTIMER[7] */
+ if (cs_active_high)
+ mbar_writeByte(MCF_GPIO_PPDSDR_TIMER, 0x80);
+ else
+ mbar_writeByte(MCF_GPIO_PCLRR_TIMER, 0x7F);
+
+ mbar_writeByte(MCF_GPIO_PDDR_TIMER,
+ mbar_readByte(MCF_GPIO_PDDR_TIMER) | 0x80);
+
+ mbar_writeShort(MCF_GPIO_PAR_TIMER,
+ mbar_readShort(MCF_GPIO_PAR_TIMER) & 0x3FFF);
+ break;
+ case 3: /* QSPI_CS[3] = PTIMER[3] */
+ if (cs_active_high)
+ mbar_writeByte(MCF_GPIO_PPDSDR_TIMER, 0x08);
+ else
+ mbar_writeByte(MCF_GPIO_PCLRR_TIMER, 0xF7);
+
+ mbar_writeByte(MCF_GPIO_PDDR_TIMER,
+ mbar_readByte(MCF_GPIO_PDDR_TIMER) | 0x08);
+
+ mbar_writeShort(MCF_GPIO_PAR_TIMER,
+ mbar_readShort(MCF_GPIO_PAR_TIMER) & 0xFF3F);
+ break;
+ }
+}
+
+/* Deassert chip select, val = [1|0], dir = in, mode = GPIO
+ * direction set as IN to undrive the pin, external pullup/pulldown will bring
+ * bus to deassert state.
+ */
+void cfspi_cs_deactivate(uint bus, uint cs, uint cs_active_high)
+{
+ debug("%s: bus %d cs %d cs_active_high %d\n",
+ __func__, bus, cs, cs_active_high);
+
+ switch (cs) {
+ case 0: /* QSPI_CS[0] = PQSPI[3] */
+ if (cs_active_high)
+ mbar_writeByte(MCF_GPIO_PCLRR_QSPI, 0xF7);
+ else
+ mbar_writeByte(MCF_GPIO_PPDSDR_QSPI, 0x08);
+
+ mbar_writeByte(MCF_GPIO_PDDR_QSPI,
+ mbar_readByte(MCF_GPIO_PDDR_QSPI) & 0xF7);
+
+ mbar_writeByte(MCF_GPIO_PAR_QSPI,
+ mbar_readByte(MCF_GPIO_PAR_QSPI) & 0xDF);
+ break;
+ case 1: /* QSPI_CS[1] = PQSPI[4] */
+ if (cs_active_high)
+ mbar_writeByte(MCF_GPIO_PCLRR_QSPI, 0xEF);
+ else
+ mbar_writeByte(MCF_GPIO_PPDSDR_QSPI, 0x10);
+
+ mbar_writeByte(MCF_GPIO_PDDR_QSPI,
+ mbar_readByte(MCF_GPIO_PDDR_QSPI) & 0xEF);
+
+ mbar_writeByte(MCF_GPIO_PAR_QSPI,
+ mbar_readByte(MCF_GPIO_PAR_QSPI) & 0x3F);
+ break;
+ case 2: /* QSPI_CS[2] = PTIMER[7] */
+ if (cs_active_high)
+ mbar_writeByte(MCF_GPIO_PCLRR_TIMER, 0x7F);
+ else
+ mbar_writeByte(MCF_GPIO_PPDSDR_TIMER, 0x80);
+
+ mbar_writeByte(MCF_GPIO_PDDR_TIMER,
+ mbar_readByte(MCF_GPIO_PDDR_TIMER) & 0x7F);
+
+ mbar_writeShort(MCF_GPIO_PAR_TIMER,
+ mbar_readShort(MCF_GPIO_PAR_TIMER) & 0x3FFF);
+ break;
+ case 3: /* QSPI_CS[3] = PTIMER[3] */
+ if (cs_active_high)
+ mbar_writeByte(MCF_GPIO_PCLRR_TIMER, 0xF7);
+ else
+ mbar_writeByte(MCF_GPIO_PPDSDR_TIMER, 0x08);
+
+ mbar_writeByte(MCF_GPIO_PDDR_TIMER,
+ mbar_readByte(MCF_GPIO_PDDR_TIMER) & 0xF7);
+
+ mbar_writeShort(MCF_GPIO_PAR_TIMER,
+ mbar_readShort(MCF_GPIO_PAR_TIMER) & 0xFF3F);
+ break;
+ }
+}
+#endif /* CONFIG_M5271 */
diff --git a/qemu/roms/u-boot/drivers/spi/cf_spi.c b/qemu/roms/u-boot/drivers/spi/cf_spi.c
new file mode 100644
index 000000000..879a809cb
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/cf_spi.c
@@ -0,0 +1,347 @@
+/*
+ *
+ * (C) Copyright 2000-2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Copyright (C) 2004-2009 Freescale Semiconductor, Inc.
+ * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <spi.h>
+#include <malloc.h>
+#include <asm/immap.h>
+
+struct cf_spi_slave {
+ struct spi_slave slave;
+ uint baudrate;
+ int charbit;
+};
+
+int cfspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout,
+ void *din, ulong flags);
+struct spi_slave *cfspi_setup_slave(struct cf_spi_slave *cfslave, uint mode);
+void cfspi_init(void);
+void cfspi_tx(u32 ctrl, u16 data);
+u16 cfspi_rx(void);
+
+extern void cfspi_port_conf(void);
+extern int cfspi_claim_bus(uint bus, uint cs);
+extern void cfspi_release_bus(uint bus, uint cs);
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#ifndef CONFIG_SPI_IDLE_VAL
+#if defined(CONFIG_SPI_MMC)
+#define CONFIG_SPI_IDLE_VAL 0xFFFF
+#else
+#define CONFIG_SPI_IDLE_VAL 0x0
+#endif
+#endif
+
+#if defined(CONFIG_CF_DSPI)
+/* DSPI specific mode */
+#define SPI_MODE_MOD 0x00200000
+#define SPI_DBLRATE 0x00100000
+
+void cfspi_init(void)
+{
+ volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI;
+
+ cfspi_port_conf(); /* port configuration */
+
+ dspi->mcr = DSPI_MCR_MSTR | DSPI_MCR_CSIS7 | DSPI_MCR_CSIS6 |
+ DSPI_MCR_CSIS5 | DSPI_MCR_CSIS4 | DSPI_MCR_CSIS3 |
+ DSPI_MCR_CSIS2 | DSPI_MCR_CSIS1 | DSPI_MCR_CSIS0 |
+ DSPI_MCR_CRXF | DSPI_MCR_CTXF;
+
+ /* Default setting in platform configuration */
+#ifdef CONFIG_SYS_DSPI_CTAR0
+ dspi->ctar[0] = CONFIG_SYS_DSPI_CTAR0;
+#endif
+#ifdef CONFIG_SYS_DSPI_CTAR1
+ dspi->ctar[1] = CONFIG_SYS_DSPI_CTAR1;
+#endif
+#ifdef CONFIG_SYS_DSPI_CTAR2
+ dspi->ctar[2] = CONFIG_SYS_DSPI_CTAR2;
+#endif
+#ifdef CONFIG_SYS_DSPI_CTAR3
+ dspi->ctar[3] = CONFIG_SYS_DSPI_CTAR3;
+#endif
+#ifdef CONFIG_SYS_DSPI_CTAR4
+ dspi->ctar[4] = CONFIG_SYS_DSPI_CTAR4;
+#endif
+#ifdef CONFIG_SYS_DSPI_CTAR5
+ dspi->ctar[5] = CONFIG_SYS_DSPI_CTAR5;
+#endif
+#ifdef CONFIG_SYS_DSPI_CTAR6
+ dspi->ctar[6] = CONFIG_SYS_DSPI_CTAR6;
+#endif
+#ifdef CONFIG_SYS_DSPI_CTAR7
+ dspi->ctar[7] = CONFIG_SYS_DSPI_CTAR7;
+#endif
+}
+
+void cfspi_tx(u32 ctrl, u16 data)
+{
+ volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI;
+
+ while ((dspi->sr & 0x0000F000) >= 4) ;
+
+ dspi->tfr = (ctrl | data);
+}
+
+u16 cfspi_rx(void)
+{
+ volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI;
+
+ while ((dspi->sr & 0x000000F0) == 0) ;
+
+ return (dspi->rfr & 0xFFFF);
+}
+
+int cfspi_xfer(struct spi_slave *slave, uint bitlen, const void *dout,
+ void *din, ulong flags)
+{
+ struct cf_spi_slave *cfslave = (struct cf_spi_slave *)slave;
+ u16 *spi_rd16 = NULL, *spi_wr16 = NULL;
+ u8 *spi_rd = NULL, *spi_wr = NULL;
+ static u32 ctrl = 0;
+ uint len = bitlen >> 3;
+
+ if (cfslave->charbit == 16) {
+ bitlen >>= 1;
+ spi_wr16 = (u16 *) dout;
+ spi_rd16 = (u16 *) din;
+ } else {
+ spi_wr = (u8 *) dout;
+ spi_rd = (u8 *) din;
+ }
+
+ if ((flags & SPI_XFER_BEGIN) == SPI_XFER_BEGIN)
+ ctrl |= DSPI_TFR_CONT;
+
+ ctrl = (ctrl & 0xFF000000) | ((1 << slave->cs) << 16);
+
+ if (len > 1) {
+ int tmp_len = len - 1;
+ while (tmp_len--) {
+ if (dout != NULL) {
+ if (cfslave->charbit == 16)
+ cfspi_tx(ctrl, *spi_wr16++);
+ else
+ cfspi_tx(ctrl, *spi_wr++);
+ cfspi_rx();
+ }
+
+ if (din != NULL) {
+ cfspi_tx(ctrl, CONFIG_SPI_IDLE_VAL);
+ if (cfslave->charbit == 16)
+ *spi_rd16++ = cfspi_rx();
+ else
+ *spi_rd++ = cfspi_rx();
+ }
+ }
+
+ len = 1; /* remaining byte */
+ }
+
+ if ((flags & SPI_XFER_END) == SPI_XFER_END)
+ ctrl &= ~DSPI_TFR_CONT;
+
+ if (len) {
+ if (dout != NULL) {
+ if (cfslave->charbit == 16)
+ cfspi_tx(ctrl, *spi_wr16);
+ else
+ cfspi_tx(ctrl, *spi_wr);
+ cfspi_rx();
+ }
+
+ if (din != NULL) {
+ cfspi_tx(ctrl, CONFIG_SPI_IDLE_VAL);
+ if (cfslave->charbit == 16)
+ *spi_rd16 = cfspi_rx();
+ else
+ *spi_rd = cfspi_rx();
+ }
+ } else {
+ /* dummy read */
+ cfspi_tx(ctrl, CONFIG_SPI_IDLE_VAL);
+ cfspi_rx();
+ }
+
+ return 0;
+}
+
+struct spi_slave *cfspi_setup_slave(struct cf_spi_slave *cfslave, uint mode)
+{
+ /*
+ * bit definition for mode:
+ * bit 31 - 28: Transfer size 3 to 16 bits
+ * 27 - 26: PCS to SCK delay prescaler
+ * 25 - 24: After SCK delay prescaler
+ * 23 - 22: Delay after transfer prescaler
+ * 21 : Allow overwrite for bit 31-22 and bit 20-8
+ * 20 : Double baud rate
+ * 19 - 16: PCS to SCK delay scaler
+ * 15 - 12: After SCK delay scaler
+ * 11 - 8: Delay after transfer scaler
+ * 7 - 0: SPI_CPHA, SPI_CPOL, SPI_LSB_FIRST
+ */
+ volatile dspi_t *dspi = (dspi_t *) MMAP_DSPI;
+ int prescaler[] = { 2, 3, 5, 7 };
+ int scaler[] = {
+ 2, 4, 6, 8,
+ 16, 32, 64, 128,
+ 256, 512, 1024, 2048,
+ 4096, 8192, 16384, 32768
+ };
+ int i, j, pbrcnt, brcnt, diff, tmp, dbr = 0;
+ int best_i, best_j, bestmatch = 0x7FFFFFFF, baud_speed;
+ u32 bus_setup = 0;
+
+ tmp = (prescaler[3] * scaler[15]);
+ /* Maximum and minimum baudrate it can handle */
+ if ((cfslave->baudrate > (gd->bus_clk >> 1)) ||
+ (cfslave->baudrate < (gd->bus_clk / tmp))) {
+ printf("Exceed baudrate limitation: Max %d - Min %d\n",
+ (int)(gd->bus_clk >> 1), (int)(gd->bus_clk / tmp));
+ return NULL;
+ }
+
+ /* Activate Double Baud when it exceed 1/4 the bus clk */
+ if ((CONFIG_SYS_DSPI_CTAR0 & DSPI_CTAR_DBR) ||
+ (cfslave->baudrate > (gd->bus_clk / (prescaler[0] * scaler[0])))) {
+ bus_setup |= DSPI_CTAR_DBR;
+ dbr = 1;
+ }
+
+ if (mode & SPI_CPOL)
+ bus_setup |= DSPI_CTAR_CPOL;
+ if (mode & SPI_CPHA)
+ bus_setup |= DSPI_CTAR_CPHA;
+ if (mode & SPI_LSB_FIRST)
+ bus_setup |= DSPI_CTAR_LSBFE;
+
+ /* Overwrite default value set in platform configuration file */
+ if (mode & SPI_MODE_MOD) {
+
+ if ((mode & 0xF0000000) == 0)
+ bus_setup |=
+ dspi->ctar[cfslave->slave.bus] & 0x78000000;
+ else
+ bus_setup |= ((mode & 0xF0000000) >> 1);
+
+ /*
+ * Check to see if it is enabled by default in platform
+ * config, or manual setting passed by mode parameter
+ */
+ if (mode & SPI_DBLRATE) {
+ bus_setup |= DSPI_CTAR_DBR;
+ dbr = 1;
+ }
+ bus_setup |= (mode & 0x0FC00000) >> 4; /* PSCSCK, PASC, PDT */
+ bus_setup |= (mode & 0x000FFF00) >> 4; /* CSSCK, ASC, DT */
+ } else
+ bus_setup |= (dspi->ctar[cfslave->slave.bus] & 0x78FCFFF0);
+
+ cfslave->charbit =
+ ((dspi->ctar[cfslave->slave.bus] & 0x78000000) ==
+ 0x78000000) ? 16 : 8;
+
+ pbrcnt = sizeof(prescaler) / sizeof(int);
+ brcnt = sizeof(scaler) / sizeof(int);
+
+ /* baudrate calculation - to closer value, may not be exact match */
+ for (best_i = 0, best_j = 0, i = 0; i < pbrcnt; i++) {
+ baud_speed = gd->bus_clk / prescaler[i];
+ for (j = 0; j < brcnt; j++) {
+ tmp = (baud_speed / scaler[j]) * (1 + dbr);
+
+ if (tmp > cfslave->baudrate)
+ diff = tmp - cfslave->baudrate;
+ else
+ diff = cfslave->baudrate - tmp;
+
+ if (diff < bestmatch) {
+ bestmatch = diff;
+ best_i = i;
+ best_j = j;
+ }
+ }
+ }
+ bus_setup |= (DSPI_CTAR_PBR(best_i) | DSPI_CTAR_BR(best_j));
+ dspi->ctar[cfslave->slave.bus] = bus_setup;
+
+ return &cfslave->slave;
+}
+#endif /* CONFIG_CF_DSPI */
+
+#ifdef CONFIG_CF_QSPI
+/* 52xx, 53xx */
+#endif /* CONFIG_CF_QSPI */
+
+#ifdef CONFIG_CMD_SPI
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ if (((cs >= 0) && (cs < 8)) && ((bus >= 0) && (bus < 8)))
+ return 1;
+ else
+ return 0;
+}
+
+void spi_init_f(void)
+{
+}
+
+void spi_init_r(void)
+{
+}
+
+void spi_init(void)
+{
+ cfspi_init();
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct cf_spi_slave *cfslave;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ cfslave = spi_alloc_slave(struct cf_spi_slave, bus, cs);
+ if (!cfslave)
+ return NULL;
+
+ cfslave->baudrate = max_hz;
+
+ /* specific setup */
+ return cfspi_setup_slave(cfslave, mode);
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ free(slave);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ return cfspi_claim_bus(slave->bus, slave->cs);
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ cfspi_release_bus(slave->bus, slave->cs);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ return cfspi_xfer(slave, bitlen, dout, din, flags);
+}
+#endif /* CONFIG_CMD_SPI */
diff --git a/qemu/roms/u-boot/drivers/spi/davinci_spi.c b/qemu/roms/u-boot/drivers/spi/davinci_spi.c
new file mode 100644
index 000000000..28fb3a2e9
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/davinci_spi.c
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Driver for SPI controller on DaVinci. Based on atmel_spi.c
+ * by Atmel Corporation
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+#include <common.h>
+#include <spi.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+#include "davinci_spi.h"
+
+void spi_init()
+{
+ /* do nothing */
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct davinci_spi_slave *ds;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ ds = spi_alloc_slave(struct davinci_spi_slave, bus, cs);
+ if (!ds)
+ return NULL;
+
+ ds->slave.bus = bus;
+ ds->slave.cs = cs;
+
+ switch (bus) {
+ case SPI0_BUS:
+ ds->regs = (struct davinci_spi_regs *)SPI0_BASE;
+ break;
+#ifdef CONFIG_SYS_SPI1
+ case SPI1_BUS:
+ ds->regs = (struct davinci_spi_regs *)SPI0_BASE;
+ break;
+#endif
+#ifdef CONFIG_SYS_SPI2
+ case SPI2_BUS:
+ ds->regs = (struct davinci_spi_regs *)SPI2_BASE;
+ break;
+#endif
+ default: /* Invalid bus number */
+ return NULL;
+ }
+
+ ds->freq = max_hz;
+
+ return &ds->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct davinci_spi_slave *ds = to_davinci_spi(slave);
+
+ free(ds);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct davinci_spi_slave *ds = to_davinci_spi(slave);
+ unsigned int scalar;
+
+ /* Enable the SPI hardware */
+ writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
+ udelay(1000);
+ writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0);
+
+ /* Set master mode, powered up and not activated */
+ writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1);
+
+ /* CS, CLK, SIMO and SOMI are functional pins */
+ writel(((1 << slave->cs) | SPIPC0_CLKFUN_MASK |
+ SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0);
+
+ /* setup format */
+ scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF;
+
+ /*
+ * Use following format:
+ * character length = 8,
+ * clock signal delayed by half clk cycle,
+ * clock low in idle state - Mode 0,
+ * MSB shifted out first
+ */
+ writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) |
+ (1 << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0);
+
+ /*
+ * Including a minor delay. No science here. Should be good even with
+ * no delay
+ */
+ writel((50 << SPI_C2TDELAY_SHIFT) |
+ (50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay);
+
+ /* default chip select register */
+ writel(SPIDEF_CSDEF0_MASK, &ds->regs->def);
+
+ /* no interrupts */
+ writel(0, &ds->regs->int0);
+ writel(0, &ds->regs->lvl);
+
+ /* enable SPI */
+ writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ struct davinci_spi_slave *ds = to_davinci_spi(slave);
+
+ /* Disable the SPI hardware */
+ writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
+}
+
+/*
+ * This functions needs to act like a macro to avoid pipeline reloads in the
+ * loops below. Use always_inline. This gains us about 160KiB/s and the bloat
+ * appears to be zero bytes (da830).
+ */
+__attribute__((always_inline))
+static inline u32 davinci_spi_xfer_data(struct davinci_spi_slave *ds, u32 data)
+{
+ u32 buf_reg_val;
+
+ /* send out data */
+ writel(data, &ds->regs->dat1);
+
+ /* wait for the data to clock in/out */
+ while ((buf_reg_val = readl(&ds->regs->buf)) & SPIBUF_RXEMPTY_MASK)
+ ;
+
+ return buf_reg_val;
+}
+
+static int davinci_spi_read(struct spi_slave *slave, unsigned int len,
+ u8 *rxp, unsigned long flags)
+{
+ struct davinci_spi_slave *ds = to_davinci_spi(slave);
+ unsigned int data1_reg_val;
+
+ /* enable CS hold, CS[n] and clear the data bits */
+ data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
+ (slave->cs << SPIDAT1_CSNR_SHIFT));
+
+ /* wait till TXFULL is deasserted */
+ while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
+ ;
+
+ /* preload the TX buffer to avoid clock starvation */
+ writel(data1_reg_val, &ds->regs->dat1);
+
+ /* keep reading 1 byte until only 1 byte left */
+ while ((len--) > 1)
+ *rxp++ = davinci_spi_xfer_data(ds, data1_reg_val);
+
+ /* clear CS hold when we reach the end */
+ if (flags & SPI_XFER_END)
+ data1_reg_val &= ~(1 << SPIDAT1_CSHOLD_SHIFT);
+
+ /* read the last byte */
+ *rxp = davinci_spi_xfer_data(ds, data1_reg_val);
+
+ return 0;
+}
+
+static int davinci_spi_write(struct spi_slave *slave, unsigned int len,
+ const u8 *txp, unsigned long flags)
+{
+ struct davinci_spi_slave *ds = to_davinci_spi(slave);
+ unsigned int data1_reg_val;
+
+ /* enable CS hold and clear the data bits */
+ data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
+ (slave->cs << SPIDAT1_CSNR_SHIFT));
+
+ /* wait till TXFULL is deasserted */
+ while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
+ ;
+
+ /* preload the TX buffer to avoid clock starvation */
+ if (len > 2) {
+ writel(data1_reg_val | *txp++, &ds->regs->dat1);
+ len--;
+ }
+
+ /* keep writing 1 byte until only 1 byte left */
+ while ((len--) > 1)
+ davinci_spi_xfer_data(ds, data1_reg_val | *txp++);
+
+ /* clear CS hold when we reach the end */
+ if (flags & SPI_XFER_END)
+ data1_reg_val &= ~(1 << SPIDAT1_CSHOLD_SHIFT);
+
+ /* write the last byte */
+ davinci_spi_xfer_data(ds, data1_reg_val | *txp);
+
+ return 0;
+}
+
+#ifndef CONFIG_SPI_HALF_DUPLEX
+static int davinci_spi_read_write(struct spi_slave *slave, unsigned int len,
+ u8 *rxp, const u8 *txp, unsigned long flags)
+{
+ struct davinci_spi_slave *ds = to_davinci_spi(slave);
+ unsigned int data1_reg_val;
+
+ /* enable CS hold and clear the data bits */
+ data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
+ (slave->cs << SPIDAT1_CSNR_SHIFT));
+
+ /* wait till TXFULL is deasserted */
+ while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
+ ;
+
+ /* keep reading and writing 1 byte until only 1 byte left */
+ while ((len--) > 1)
+ *rxp++ = davinci_spi_xfer_data(ds, data1_reg_val | *txp++);
+
+ /* clear CS hold when we reach the end */
+ if (flags & SPI_XFER_END)
+ data1_reg_val &= ~(1 << SPIDAT1_CSHOLD_SHIFT);
+
+ /* read and write the last byte */
+ *rxp = davinci_spi_xfer_data(ds, data1_reg_val | *txp);
+
+ return 0;
+}
+#endif
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
+{
+ unsigned int len;
+
+ if (bitlen == 0)
+ /* Finish any previously submitted transfers */
+ goto out;
+
+ /*
+ * It's not clear how non-8-bit-aligned transfers are supposed to be
+ * represented as a stream of bytes...this is a limitation of
+ * the current SPI interface - here we terminate on receiving such a
+ * transfer request.
+ */
+ if (bitlen % 8) {
+ /* Errors always terminate an ongoing transfer */
+ flags |= SPI_XFER_END;
+ goto out;
+ }
+
+ len = bitlen / 8;
+
+ if (!dout)
+ return davinci_spi_read(slave, len, din, flags);
+ else if (!din)
+ return davinci_spi_write(slave, len, dout, flags);
+#ifndef CONFIG_SPI_HALF_DUPLEX
+ else
+ return davinci_spi_read_write(slave, len, din, dout, flags);
+#else
+ printf("SPI full duplex transaction requested with "
+ "CONFIG_SPI_HALF_DUPLEX defined.\n");
+ flags |= SPI_XFER_END;
+#endif
+
+out:
+ if (flags & SPI_XFER_END) {
+ u8 dummy = 0;
+ davinci_spi_write(slave, 1, &dummy, flags);
+ }
+ return 0;
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ int ret = 0;
+
+ switch (bus) {
+ case SPI0_BUS:
+ if (cs < SPI0_NUM_CS)
+ ret = 1;
+ break;
+#ifdef CONFIG_SYS_SPI1
+ case SPI1_BUS:
+ if (cs < SPI1_NUM_CS)
+ ret = 1;
+ break;
+#endif
+#ifdef CONFIG_SYS_SPI2
+ case SPI2_BUS:
+ if (cs < SPI2_NUM_CS)
+ ret = 1;
+ break;
+#endif
+ default:
+ /* Invalid bus number. Do nothing */
+ break;
+ }
+ return ret;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ /* do nothing */
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ /* do nothing */
+}
diff --git a/qemu/roms/u-boot/drivers/spi/davinci_spi.h b/qemu/roms/u-boot/drivers/spi/davinci_spi.h
new file mode 100644
index 000000000..d4612d352
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/davinci_spi.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Register definitions for the DaVinci SPI Controller
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _DAVINCI_SPI_H_
+#define _DAVINCI_SPI_H_
+
+struct davinci_spi_regs {
+ dv_reg gcr0; /* 0x00 */
+ dv_reg gcr1; /* 0x04 */
+ dv_reg int0; /* 0x08 */
+ dv_reg lvl; /* 0x0c */
+ dv_reg flg; /* 0x10 */
+ dv_reg pc0; /* 0x14 */
+ dv_reg pc1; /* 0x18 */
+ dv_reg pc2; /* 0x1c */
+ dv_reg pc3; /* 0x20 */
+ dv_reg pc4; /* 0x24 */
+ dv_reg pc5; /* 0x28 */
+ dv_reg rsvd[3];
+ dv_reg dat0; /* 0x38 */
+ dv_reg dat1; /* 0x3c */
+ dv_reg buf; /* 0x40 */
+ dv_reg emu; /* 0x44 */
+ dv_reg delay; /* 0x48 */
+ dv_reg def; /* 0x4c */
+ dv_reg fmt0; /* 0x50 */
+ dv_reg fmt1; /* 0x54 */
+ dv_reg fmt2; /* 0x58 */
+ dv_reg fmt3; /* 0x5c */
+ dv_reg intvec0; /* 0x60 */
+ dv_reg intvec1; /* 0x64 */
+};
+
+#define BIT(x) (1 << (x))
+
+/* SPIGCR0 */
+#define SPIGCR0_SPIENA_MASK 0x1
+#define SPIGCR0_SPIRST_MASK 0x0
+
+/* SPIGCR0 */
+#define SPIGCR1_CLKMOD_MASK BIT(1)
+#define SPIGCR1_MASTER_MASK BIT(0)
+#define SPIGCR1_SPIENA_MASK BIT(24)
+
+/* SPIPC0 */
+#define SPIPC0_DIFUN_MASK BIT(11) /* SIMO */
+#define SPIPC0_DOFUN_MASK BIT(10) /* SOMI */
+#define SPIPC0_CLKFUN_MASK BIT(9) /* CLK */
+#define SPIPC0_EN0FUN_MASK BIT(0)
+
+/* SPIFMT0 */
+#define SPIFMT_SHIFTDIR_SHIFT 20
+#define SPIFMT_POLARITY_SHIFT 17
+#define SPIFMT_PHASE_SHIFT 16
+#define SPIFMT_PRESCALE_SHIFT 8
+
+/* SPIDAT1 */
+#define SPIDAT1_CSHOLD_SHIFT 28
+#define SPIDAT1_CSNR_SHIFT 16
+
+/* SPIDELAY */
+#define SPI_C2TDELAY_SHIFT 24
+#define SPI_T2CDELAY_SHIFT 16
+
+/* SPIBUF */
+#define SPIBUF_RXEMPTY_MASK BIT(31)
+#define SPIBUF_TXFULL_MASK BIT(29)
+
+/* SPIDEF */
+#define SPIDEF_CSDEF0_MASK BIT(0)
+
+#define SPI0_BUS 0
+#define SPI0_BASE CONFIG_SYS_SPI_BASE
+/*
+ * Define default SPI0_NUM_CS as 1 for existing platforms that uses this
+ * driver. Platform can configure number of CS using CONFIG_SYS_SPI0_NUM_CS
+ * if more than one CS is supported and by defining CONFIG_SYS_SPI0.
+ */
+#ifndef CONFIG_SYS_SPI0
+#define SPI0_NUM_CS 1
+#else
+#define SPI0_NUM_CS CONFIG_SYS_SPI0_NUM_CS
+#endif
+
+/*
+ * define CONFIG_SYS_SPI1 when platform has spi-1 device (bus #1) and
+ * CONFIG_SYS_SPI1_NUM_CS defines number of CS on this bus
+ */
+#ifdef CONFIG_SYS_SPI1
+#define SPI1_BUS 1
+#define SPI1_NUM_CS CONFIG_SYS_SPI1_NUM_CS
+#define SPI1_BASE CONFIG_SYS_SPI1_BASE
+#endif
+
+/*
+ * define CONFIG_SYS_SPI2 when platform has spi-2 device (bus #2) and
+ * CONFIG_SYS_SPI2_NUM_CS defines number of CS on this bus
+ */
+#ifdef CONFIG_SYS_SPI2
+#define SPI2_BUS 2
+#define SPI2_NUM_CS CONFIG_SYS_SPI2_NUM_CS
+#define SPI2_BASE CONFIG_SYS_SPI2_BASE
+#endif
+
+struct davinci_spi_slave {
+ struct spi_slave slave;
+ struct davinci_spi_regs *regs;
+ unsigned int freq;
+};
+
+static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave)
+{
+ return container_of(slave, struct davinci_spi_slave, slave);
+}
+
+#endif /* _DAVINCI_SPI_H_ */
diff --git a/qemu/roms/u-boot/drivers/spi/exynos_spi.c b/qemu/roms/u-boot/drivers/spi/exynos_spi.c
new file mode 100644
index 000000000..4d5def2d3
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/exynos_spi.c
@@ -0,0 +1,579 @@
+/*
+ * (C) Copyright 2012 SAMSUNG Electronics
+ * Padmavathi Venna <padma.v@samsung.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <fdtdec.h>
+#include <asm/arch/clk.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/cpu.h>
+#include <asm/arch/gpio.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch-exynos/spi.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* Information about each SPI controller */
+struct spi_bus {
+ enum periph_id periph_id;
+ s32 frequency; /* Default clock frequency, -1 for none */
+ struct exynos_spi *regs;
+ int inited; /* 1 if this bus is ready for use */
+ int node;
+ uint deactivate_delay_us; /* Delay to wait after deactivate */
+};
+
+/* A list of spi buses that we know about */
+static struct spi_bus spi_bus[EXYNOS5_SPI_NUM_CONTROLLERS];
+static unsigned int bus_count;
+
+struct exynos_spi_slave {
+ struct spi_slave slave;
+ struct exynos_spi *regs;
+ unsigned int freq; /* Default frequency */
+ unsigned int mode;
+ enum periph_id periph_id; /* Peripheral ID for this device */
+ unsigned int fifo_size;
+ int skip_preamble;
+ struct spi_bus *bus; /* Pointer to our SPI bus info */
+ ulong last_transaction_us; /* Time of last transaction end */
+};
+
+static struct spi_bus *spi_get_bus(unsigned dev_index)
+{
+ if (dev_index < bus_count)
+ return &spi_bus[dev_index];
+ debug("%s: invalid bus %d", __func__, dev_index);
+
+ return NULL;
+}
+
+static inline struct exynos_spi_slave *to_exynos_spi(struct spi_slave *slave)
+{
+ return container_of(slave, struct exynos_spi_slave, slave);
+}
+
+/**
+ * Setup the driver private data
+ *
+ * @param bus ID of the bus that the slave is attached to
+ * @param cs ID of the chip select connected to the slave
+ * @param max_hz Required spi frequency
+ * @param mode Required spi mode (clk polarity, clk phase and
+ * master or slave)
+ * @return new device or NULL
+ */
+struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct exynos_spi_slave *spi_slave;
+ struct spi_bus *bus;
+
+ if (!spi_cs_is_valid(busnum, cs)) {
+ debug("%s: Invalid bus/chip select %d, %d\n", __func__,
+ busnum, cs);
+ return NULL;
+ }
+
+ spi_slave = spi_alloc_slave(struct exynos_spi_slave, busnum, cs);
+ if (!spi_slave) {
+ debug("%s: Could not allocate spi_slave\n", __func__);
+ return NULL;
+ }
+
+ bus = &spi_bus[busnum];
+ spi_slave->bus = bus;
+ spi_slave->regs = bus->regs;
+ spi_slave->mode = mode;
+ spi_slave->periph_id = bus->periph_id;
+ if (bus->periph_id == PERIPH_ID_SPI1 ||
+ bus->periph_id == PERIPH_ID_SPI2)
+ spi_slave->fifo_size = 64;
+ else
+ spi_slave->fifo_size = 256;
+
+ spi_slave->skip_preamble = 0;
+ spi_slave->last_transaction_us = timer_get_us();
+
+ spi_slave->freq = bus->frequency;
+ if (max_hz)
+ spi_slave->freq = min(max_hz, spi_slave->freq);
+
+ return &spi_slave->slave;
+}
+
+/**
+ * Free spi controller
+ *
+ * @param slave Pointer to spi_slave to which controller has to
+ * communicate with
+ */
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+
+ free(spi_slave);
+}
+
+/**
+ * Flush spi tx, rx fifos and reset the SPI controller
+ *
+ * @param slave Pointer to spi_slave to which controller has to
+ * communicate with
+ */
+static void spi_flush_fifo(struct spi_slave *slave)
+{
+ struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+ struct exynos_spi *regs = spi_slave->regs;
+
+ clrsetbits_le32(&regs->ch_cfg, SPI_CH_HS_EN, SPI_CH_RST);
+ clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
+ setbits_le32(&regs->ch_cfg, SPI_TX_CH_ON | SPI_RX_CH_ON);
+}
+
+/**
+ * Initialize the spi base registers, set the required clock frequency and
+ * initialize the gpios
+ *
+ * @param slave Pointer to spi_slave to which controller has to
+ * communicate with
+ * @return zero on success else a negative value
+ */
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+ struct exynos_spi *regs = spi_slave->regs;
+ u32 reg = 0;
+ int ret;
+
+ ret = set_spi_clk(spi_slave->periph_id,
+ spi_slave->freq);
+ if (ret < 0) {
+ debug("%s: Failed to setup spi clock\n", __func__);
+ return ret;
+ }
+
+ exynos_pinmux_config(spi_slave->periph_id, PINMUX_FLAG_NONE);
+
+ spi_flush_fifo(slave);
+
+ reg = readl(&regs->ch_cfg);
+ reg &= ~(SPI_CH_CPHA_B | SPI_CH_CPOL_L);
+
+ if (spi_slave->mode & SPI_CPHA)
+ reg |= SPI_CH_CPHA_B;
+
+ if (spi_slave->mode & SPI_CPOL)
+ reg |= SPI_CH_CPOL_L;
+
+ writel(reg, &regs->ch_cfg);
+ writel(SPI_FB_DELAY_180, &regs->fb_clk);
+
+ return 0;
+}
+
+/**
+ * Reset the spi H/W and flush the tx and rx fifos
+ *
+ * @param slave Pointer to spi_slave to which controller has to
+ * communicate with
+ */
+void spi_release_bus(struct spi_slave *slave)
+{
+ spi_flush_fifo(slave);
+}
+
+static void spi_get_fifo_levels(struct exynos_spi *regs,
+ int *rx_lvl, int *tx_lvl)
+{
+ uint32_t spi_sts = readl(&regs->spi_sts);
+
+ *rx_lvl = (spi_sts >> SPI_RX_LVL_OFFSET) & SPI_FIFO_LVL_MASK;
+ *tx_lvl = (spi_sts >> SPI_TX_LVL_OFFSET) & SPI_FIFO_LVL_MASK;
+}
+
+/**
+ * If there's something to transfer, do a software reset and set a
+ * transaction size.
+ *
+ * @param regs SPI peripheral registers
+ * @param count Number of bytes to transfer
+ * @param step Number of bytes to transfer in each packet (1 or 4)
+ */
+static void spi_request_bytes(struct exynos_spi *regs, int count, int step)
+{
+ /* For word address we need to swap bytes */
+ if (step == 4) {
+ setbits_le32(&regs->mode_cfg,
+ SPI_MODE_CH_WIDTH_WORD | SPI_MODE_BUS_WIDTH_WORD);
+ count /= 4;
+ setbits_le32(&regs->swap_cfg, SPI_TX_SWAP_EN | SPI_RX_SWAP_EN |
+ SPI_TX_BYTE_SWAP | SPI_RX_BYTE_SWAP |
+ SPI_TX_HWORD_SWAP | SPI_RX_HWORD_SWAP);
+ } else {
+ /* Select byte access and clear the swap configuration */
+ clrbits_le32(&regs->mode_cfg,
+ SPI_MODE_CH_WIDTH_WORD | SPI_MODE_BUS_WIDTH_WORD);
+ writel(0, &regs->swap_cfg);
+ }
+
+ assert(count && count < (1 << 16));
+ setbits_le32(&regs->ch_cfg, SPI_CH_RST);
+ clrbits_le32(&regs->ch_cfg, SPI_CH_RST);
+
+ writel(count | SPI_PACKET_CNT_EN, &regs->pkt_cnt);
+}
+
+static int spi_rx_tx(struct exynos_spi_slave *spi_slave, int todo,
+ void **dinp, void const **doutp, unsigned long flags)
+{
+ struct exynos_spi *regs = spi_slave->regs;
+ uchar *rxp = *dinp;
+ const uchar *txp = *doutp;
+ int rx_lvl, tx_lvl;
+ uint out_bytes, in_bytes;
+ int toread;
+ unsigned start = get_timer(0);
+ int stopping;
+ int step;
+
+ out_bytes = in_bytes = todo;
+
+ stopping = spi_slave->skip_preamble && (flags & SPI_XFER_END) &&
+ !(spi_slave->mode & SPI_SLAVE);
+
+ /*
+ * Try to transfer words if we can. This helps read performance at
+ * SPI clock speeds above about 20MHz.
+ */
+ step = 1;
+ if (!((todo | (uintptr_t)rxp | (uintptr_t)txp) & 3) &&
+ !spi_slave->skip_preamble)
+ step = 4;
+
+ /*
+ * If there's something to send, do a software reset and set a
+ * transaction size.
+ */
+ spi_request_bytes(regs, todo, step);
+
+ /*
+ * Bytes are transmitted/received in pairs. Wait to receive all the
+ * data because then transmission will be done as well.
+ */
+ toread = in_bytes;
+
+ while (in_bytes) {
+ int temp;
+
+ /* Keep the fifos full/empty. */
+ spi_get_fifo_levels(regs, &rx_lvl, &tx_lvl);
+
+ /*
+ * Don't completely fill the txfifo, since we don't want our
+ * rxfifo to overflow, and it may already contain data.
+ */
+ while (tx_lvl < spi_slave->fifo_size/2 && out_bytes) {
+ if (!txp)
+ temp = -1;
+ else if (step == 4)
+ temp = *(uint32_t *)txp;
+ else
+ temp = *txp;
+ writel(temp, &regs->tx_data);
+ out_bytes -= step;
+ if (txp)
+ txp += step;
+ tx_lvl += step;
+ }
+ if (rx_lvl >= step) {
+ while (rx_lvl >= step) {
+ temp = readl(&regs->rx_data);
+ if (spi_slave->skip_preamble) {
+ if (temp == SPI_PREAMBLE_END_BYTE) {
+ spi_slave->skip_preamble = 0;
+ stopping = 0;
+ }
+ } else {
+ if (rxp || stopping) {
+ *rxp = temp;
+ rxp += step;
+ }
+ in_bytes -= step;
+ }
+ toread -= step;
+ rx_lvl -= step;
+ }
+ } else if (!toread) {
+ /*
+ * We have run out of input data, but haven't read
+ * enough bytes after the preamble yet. Read some more,
+ * and make sure that we transmit dummy bytes too, to
+ * keep things going.
+ */
+ assert(!out_bytes);
+ out_bytes = in_bytes;
+ toread = in_bytes;
+ txp = NULL;
+ spi_request_bytes(regs, toread, step);
+ }
+ if (spi_slave->skip_preamble && get_timer(start) > 100) {
+ printf("SPI timeout: in_bytes=%d, out_bytes=%d, ",
+ in_bytes, out_bytes);
+ return -1;
+ }
+ }
+
+ *dinp = rxp;
+ *doutp = txp;
+
+ return 0;
+}
+
+/**
+ * Transfer and receive data
+ *
+ * @param slave Pointer to spi_slave to which controller has to
+ * communicate with
+ * @param bitlen No of bits to tranfer or receive
+ * @param dout Pointer to transfer buffer
+ * @param din Pointer to receive buffer
+ * @param flags Flags for transfer begin and end
+ * @return zero on success else a negative value
+ */
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+ int upto, todo;
+ int bytelen;
+ int ret = 0;
+
+ /* spi core configured to do 8 bit transfers */
+ if (bitlen % 8) {
+ debug("Non byte aligned SPI transfer.\n");
+ return -1;
+ }
+
+ /* Start the transaction, if necessary. */
+ if ((flags & SPI_XFER_BEGIN))
+ spi_cs_activate(slave);
+
+ /*
+ * Exynos SPI limits each transfer to 65535 transfers. To keep
+ * things simple, allow a maximum of 65532 bytes. We could allow
+ * more in word mode, but the performance difference is small.
+ */
+ bytelen = bitlen / 8;
+ for (upto = 0; !ret && upto < bytelen; upto += todo) {
+ todo = min(bytelen - upto, (1 << 16) - 4);
+ ret = spi_rx_tx(spi_slave, todo, &din, &dout, flags);
+ if (ret)
+ break;
+ }
+
+ /* Stop the transaction, if necessary. */
+ if ((flags & SPI_XFER_END) && !(spi_slave->mode & SPI_SLAVE)) {
+ spi_cs_deactivate(slave);
+ if (spi_slave->skip_preamble) {
+ assert(!spi_slave->skip_preamble);
+ debug("Failed to complete premable transaction\n");
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * Validates the bus and chip select numbers
+ *
+ * @param bus ID of the bus that the slave is attached to
+ * @param cs ID of the chip select connected to the slave
+ * @return one on success else zero
+ */
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ return spi_get_bus(bus) && cs == 0;
+}
+
+/**
+ * Activate the CS by driving it LOW
+ *
+ * @param slave Pointer to spi_slave to which controller has to
+ * communicate with
+ */
+void spi_cs_activate(struct spi_slave *slave)
+{
+ struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+
+ /* If it's too soon to do another transaction, wait */
+ if (spi_slave->bus->deactivate_delay_us &&
+ spi_slave->last_transaction_us) {
+ ulong delay_us; /* The delay completed so far */
+ delay_us = timer_get_us() - spi_slave->last_transaction_us;
+ if (delay_us < spi_slave->bus->deactivate_delay_us)
+ udelay(spi_slave->bus->deactivate_delay_us - delay_us);
+ }
+
+ clrbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
+ debug("Activate CS, bus %d\n", spi_slave->slave.bus);
+ spi_slave->skip_preamble = spi_slave->mode & SPI_PREAMBLE;
+
+ /* Remember time of this transaction so we can honour the bus delay */
+ if (spi_slave->bus->deactivate_delay_us)
+ spi_slave->last_transaction_us = timer_get_us();
+}
+
+/**
+ * Deactivate the CS by driving it HIGH
+ *
+ * @param slave Pointer to spi_slave to which controller has to
+ * communicate with
+ */
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
+
+ setbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
+ debug("Deactivate CS, bus %d\n", spi_slave->slave.bus);
+}
+
+static inline struct exynos_spi *get_spi_base(int dev_index)
+{
+ if (dev_index < 3)
+ return (struct exynos_spi *)samsung_get_base_spi() + dev_index;
+ else
+ return (struct exynos_spi *)samsung_get_base_spi_isp() +
+ (dev_index - 3);
+}
+
+/*
+ * Read the SPI config from the device tree node.
+ *
+ * @param blob FDT blob to read from
+ * @param node Node offset to read from
+ * @param bus SPI bus structure to fill with information
+ * @return 0 if ok, or -FDT_ERR_NOTFOUND if something was missing
+ */
+#ifdef CONFIG_OF_CONTROL
+static int spi_get_config(const void *blob, int node, struct spi_bus *bus)
+{
+ bus->node = node;
+ bus->regs = (struct exynos_spi *)fdtdec_get_addr(blob, node, "reg");
+ bus->periph_id = pinmux_decode_periph_id(blob, node);
+
+ if (bus->periph_id == PERIPH_ID_NONE) {
+ debug("%s: Invalid peripheral ID %d\n", __func__,
+ bus->periph_id);
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ /* Use 500KHz as a suitable default */
+ bus->frequency = fdtdec_get_int(blob, node, "spi-max-frequency",
+ 500000);
+ bus->deactivate_delay_us = fdtdec_get_int(blob, node,
+ "spi-deactivate-delay", 0);
+
+ return 0;
+}
+
+/*
+ * Process a list of nodes, adding them to our list of SPI ports.
+ *
+ * @param blob fdt blob
+ * @param node_list list of nodes to process (any <=0 are ignored)
+ * @param count number of nodes to process
+ * @param is_dvc 1 if these are DVC ports, 0 if standard I2C
+ * @return 0 if ok, -1 on error
+ */
+static int process_nodes(const void *blob, int node_list[], int count)
+{
+ int i;
+
+ /* build the i2c_controllers[] for each controller */
+ for (i = 0; i < count; i++) {
+ int node = node_list[i];
+ struct spi_bus *bus;
+
+ if (node <= 0)
+ continue;
+
+ bus = &spi_bus[i];
+ if (spi_get_config(blob, node, bus)) {
+ printf("exynos spi_init: failed to decode bus %d\n",
+ i);
+ return -1;
+ }
+
+ debug("spi: controller bus %d at %p, periph_id %d\n",
+ i, bus->regs, bus->periph_id);
+ bus->inited = 1;
+ bus_count++;
+ }
+
+ return 0;
+}
+#endif
+
+/**
+ * Set up a new SPI slave for an fdt node
+ *
+ * @param blob Device tree blob
+ * @param node SPI peripheral node to use
+ * @return 0 if ok, -1 on error
+ */
+struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
+ int spi_node)
+{
+ struct spi_bus *bus;
+ unsigned int i;
+
+ for (i = 0, bus = spi_bus; i < bus_count; i++, bus++) {
+ if (bus->node == spi_node)
+ return spi_base_setup_slave_fdt(blob, i, slave_node);
+ }
+
+ debug("%s: Failed to find bus node %d\n", __func__, spi_node);
+ return NULL;
+}
+
+/* Sadly there is no error return from this function */
+void spi_init(void)
+{
+ int count;
+
+#ifdef CONFIG_OF_CONTROL
+ int node_list[EXYNOS5_SPI_NUM_CONTROLLERS];
+ const void *blob = gd->fdt_blob;
+
+ count = fdtdec_find_aliases_for_id(blob, "spi",
+ COMPAT_SAMSUNG_EXYNOS_SPI, node_list,
+ EXYNOS5_SPI_NUM_CONTROLLERS);
+ if (process_nodes(blob, node_list, count))
+ return;
+
+#else
+ struct spi_bus *bus;
+
+ for (count = 0; count < EXYNOS5_SPI_NUM_CONTROLLERS; count++) {
+ bus = &spi_bus[count];
+ bus->regs = get_spi_base(count);
+ bus->periph_id = PERIPH_ID_SPI0 + count;
+
+ /* Although Exynos5 supports upto 50Mhz speed,
+ * we are setting it to 10Mhz for safe side
+ */
+ bus->frequency = 10000000;
+ bus->inited = 1;
+ bus->node = 0;
+ bus_count = EXYNOS5_SPI_NUM_CONTROLLERS;
+ }
+#endif
+}
diff --git a/qemu/roms/u-boot/drivers/spi/fdt_spi.c b/qemu/roms/u-boot/drivers/spi/fdt_spi.c
new file mode 100644
index 000000000..58f139a54
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/fdt_spi.c
@@ -0,0 +1,186 @@
+/*
+ * Common fdt based SPI driver front end
+ *
+ * Copyright (c) 2013 NVIDIA Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/arch/clock.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra20/tegra20_sflash.h>
+#include <asm/arch-tegra20/tegra20_slink.h>
+#include <asm/arch-tegra114/tegra114_spi.h>
+#include <spi.h>
+#include <fdtdec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct fdt_spi_driver {
+ int compat;
+ int max_ctrls;
+ int (*init)(int *node_list, int count);
+ int (*claim_bus)(struct spi_slave *slave);
+ int (*release_bus)(struct spi_slave *slave);
+ int (*cs_is_valid)(unsigned int bus, unsigned int cs);
+ struct spi_slave *(*setup_slave)(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode);
+ void (*free_slave)(struct spi_slave *slave);
+ void (*cs_activate)(struct spi_slave *slave);
+ void (*cs_deactivate)(struct spi_slave *slave);
+ int (*xfer)(struct spi_slave *slave, unsigned int bitlen,
+ const void *data_out, void *data_in, unsigned long flags);
+};
+
+static struct fdt_spi_driver fdt_spi_drivers[] = {
+#ifdef CONFIG_TEGRA20_SFLASH
+ {
+ .compat = COMPAT_NVIDIA_TEGRA20_SFLASH,
+ .max_ctrls = 1,
+ .init = tegra20_spi_init,
+ .claim_bus = tegra20_spi_claim_bus,
+ .cs_is_valid = tegra20_spi_cs_is_valid,
+ .setup_slave = tegra20_spi_setup_slave,
+ .free_slave = tegra20_spi_free_slave,
+ .cs_activate = tegra20_spi_cs_activate,
+ .cs_deactivate = tegra20_spi_cs_deactivate,
+ .xfer = tegra20_spi_xfer,
+ },
+#endif
+#ifdef CONFIG_TEGRA20_SLINK
+ {
+ .compat = COMPAT_NVIDIA_TEGRA20_SLINK,
+ .max_ctrls = CONFIG_TEGRA_SLINK_CTRLS,
+ .init = tegra30_spi_init,
+ .claim_bus = tegra30_spi_claim_bus,
+ .cs_is_valid = tegra30_spi_cs_is_valid,
+ .setup_slave = tegra30_spi_setup_slave,
+ .free_slave = tegra30_spi_free_slave,
+ .cs_activate = tegra30_spi_cs_activate,
+ .cs_deactivate = tegra30_spi_cs_deactivate,
+ .xfer = tegra30_spi_xfer,
+ },
+#endif
+#ifdef CONFIG_TEGRA114_SPI
+ {
+ .compat = COMPAT_NVIDIA_TEGRA114_SPI,
+ .max_ctrls = CONFIG_TEGRA114_SPI_CTRLS,
+ .init = tegra114_spi_init,
+ .claim_bus = tegra114_spi_claim_bus,
+ .cs_is_valid = tegra114_spi_cs_is_valid,
+ .setup_slave = tegra114_spi_setup_slave,
+ .free_slave = tegra114_spi_free_slave,
+ .cs_activate = tegra114_spi_cs_activate,
+ .cs_deactivate = tegra114_spi_cs_deactivate,
+ .xfer = tegra114_spi_xfer,
+ },
+#endif
+};
+
+static struct fdt_spi_driver *driver;
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ if (!driver)
+ return 0;
+ else if (!driver->cs_is_valid)
+ return 1;
+ else
+ return driver->cs_is_valid(bus, cs);
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ if (!driver || !driver->setup_slave)
+ return NULL;
+
+ return driver->setup_slave(bus, cs, max_hz, mode);
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ if (driver && driver->free_slave)
+ return driver->free_slave(slave);
+}
+
+static int spi_init_driver(struct fdt_spi_driver *driver)
+{
+ int count;
+ int node_list[driver->max_ctrls];
+
+ count = fdtdec_find_aliases_for_id(gd->fdt_blob, "spi",
+ driver->compat,
+ node_list,
+ driver->max_ctrls);
+ return driver->init(node_list, count);
+}
+
+void spi_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(fdt_spi_drivers); i++) {
+ driver = &fdt_spi_drivers[i];
+ if (!spi_init_driver(driver))
+ break;
+ }
+ if (i == ARRAY_SIZE(fdt_spi_drivers))
+ driver = NULL;
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ if (!driver)
+ return 1;
+ if (!driver->claim_bus)
+ return 0;
+
+ return driver->claim_bus(slave);
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ if (driver && driver->release_bus)
+ driver->release_bus(slave);
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ if (driver && driver->cs_activate)
+ driver->cs_activate(slave);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ if (driver && driver->cs_deactivate)
+ driver->cs_deactivate(slave);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+ const void *data_out, void *data_in, unsigned long flags)
+{
+ if (!driver || !driver->xfer)
+ return -1;
+
+ return driver->xfer(slave, bitlen, data_out, data_in, flags);
+}
diff --git a/qemu/roms/u-boot/drivers/spi/fsl_espi.c b/qemu/roms/u-boot/drivers/spi/fsl_espi.c
new file mode 100644
index 000000000..7c8458276
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/fsl_espi.c
@@ -0,0 +1,315 @@
+/*
+ * eSPI controller driver.
+ *
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * Author: Mingkai Hu (Mingkai.hu@freescale.com)
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+
+#include <malloc.h>
+#include <spi.h>
+#include <asm/immap_85xx.h>
+
+struct fsl_spi_slave {
+ struct spi_slave slave;
+ unsigned int div16;
+ unsigned int pm;
+ unsigned int mode;
+ size_t cmd_len;
+ u8 cmd_buf[16];
+ size_t data_len;
+ unsigned int max_transfer_length;
+};
+
+#define to_fsl_spi_slave(s) container_of(s, struct fsl_spi_slave, slave)
+
+#define ESPI_MAX_CS_NUM 4
+
+#define ESPI_EV_RNE (1 << 9)
+#define ESPI_EV_TNF (1 << 8)
+
+#define ESPI_MODE_EN (1 << 31) /* Enable interface */
+#define ESPI_MODE_TXTHR(x) ((x) << 8) /* Tx FIFO threshold */
+#define ESPI_MODE_RXTHR(x) ((x) << 0) /* Rx FIFO threshold */
+
+#define ESPI_COM_CS(x) ((x) << 30)
+#define ESPI_COM_TRANLEN(x) ((x) << 0)
+
+#define ESPI_CSMODE_CI_INACTIVEHIGH (1 << 31)
+#define ESPI_CSMODE_CP_BEGIN_EDGCLK (1 << 30)
+#define ESPI_CSMODE_REV_MSB_FIRST (1 << 29)
+#define ESPI_CSMODE_DIV16 (1 << 28)
+#define ESPI_CSMODE_PM(x) ((x) << 24)
+#define ESPI_CSMODE_POL_ASSERTED_LOW (1 << 20)
+#define ESPI_CSMODE_LEN(x) ((x) << 16)
+#define ESPI_CSMODE_CSBEF(x) ((x) << 12)
+#define ESPI_CSMODE_CSAFT(x) ((x) << 8)
+#define ESPI_CSMODE_CSCG(x) ((x) << 3)
+
+#define ESPI_CSMODE_INIT_VAL (ESPI_CSMODE_POL_ASSERTED_LOW | \
+ ESPI_CSMODE_CSBEF(0) | ESPI_CSMODE_CSAFT(0) | \
+ ESPI_CSMODE_CSCG(1))
+
+#define ESPI_MAX_DATA_TRANSFER_LEN 0xFFF0
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct fsl_spi_slave *fsl;
+ sys_info_t sysinfo;
+ unsigned long spibrg = 0;
+ unsigned char pm = 0;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ fsl = spi_alloc_slave(struct fsl_spi_slave, bus, cs);
+ if (!fsl)
+ return NULL;
+
+ fsl->mode = mode;
+ fsl->max_transfer_length = ESPI_MAX_DATA_TRANSFER_LEN;
+
+ /* Set eSPI BRG clock source */
+ get_sys_info(&sysinfo);
+ spibrg = sysinfo.freq_systembus / 2;
+ fsl->div16 = 0;
+ if ((spibrg / max_hz) > 32) {
+ fsl->div16 = ESPI_CSMODE_DIV16;
+ pm = spibrg / (max_hz * 16 * 2);
+ if (pm > 16) {
+ pm = 16;
+ debug("Requested speed is too low: %d Hz, %ld Hz "
+ "is used.\n", max_hz, spibrg / (32 * 16));
+ }
+ } else
+ pm = spibrg / (max_hz * 2);
+ if (pm)
+ pm--;
+ fsl->pm = pm;
+
+ return &fsl->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave);
+ free(fsl);
+}
+
+void spi_init(void)
+{
+
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave);
+ ccsr_espi_t *espi = (void *)(CONFIG_SYS_MPC85xx_ESPI_ADDR);
+ unsigned char pm = fsl->pm;
+ unsigned int cs = slave->cs;
+ unsigned int mode = fsl->mode;
+ unsigned int div16 = fsl->div16;
+ int i;
+
+ debug("%s: bus:%i cs:%i\n", __func__, slave->bus, cs);
+
+ /* Enable eSPI interface */
+ out_be32(&espi->mode, ESPI_MODE_RXTHR(3)
+ | ESPI_MODE_TXTHR(4) | ESPI_MODE_EN);
+
+ out_be32(&espi->event, 0xffffffff); /* Clear all eSPI events */
+ out_be32(&espi->mask, 0x00000000); /* Mask all eSPI interrupts */
+
+ /* Init CS mode interface */
+ for (i = 0; i < ESPI_MAX_CS_NUM; i++)
+ out_be32(&espi->csmode[i], ESPI_CSMODE_INIT_VAL);
+
+ out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs]) &
+ ~(ESPI_CSMODE_PM(0xF) | ESPI_CSMODE_DIV16
+ | ESPI_CSMODE_CI_INACTIVEHIGH | ESPI_CSMODE_CP_BEGIN_EDGCLK
+ | ESPI_CSMODE_REV_MSB_FIRST | ESPI_CSMODE_LEN(0xF)));
+
+ /* Set eSPI BRG clock source */
+ out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs])
+ | ESPI_CSMODE_PM(pm) | div16);
+
+ /* Set eSPI mode */
+ if (mode & SPI_CPHA)
+ out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs])
+ | ESPI_CSMODE_CP_BEGIN_EDGCLK);
+ if (mode & SPI_CPOL)
+ out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs])
+ | ESPI_CSMODE_CI_INACTIVEHIGH);
+
+ /* Character bit order: msb first */
+ out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs])
+ | ESPI_CSMODE_REV_MSB_FIRST);
+
+ /* Character length in bits, between 0x3~0xf, i.e. 4bits~16bits */
+ out_be32(&espi->csmode[cs], in_be32(&espi->csmode[cs])
+ | ESPI_CSMODE_LEN(7));
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *data_out,
+ void *data_in, unsigned long flags)
+{
+ struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave);
+ ccsr_espi_t *espi = (void *)(CONFIG_SYS_MPC85xx_ESPI_ADDR);
+ unsigned int tmpdout, tmpdin, event;
+ const void *dout = NULL;
+ void *din = NULL;
+ int len = 0;
+ int num_blks, num_chunks, max_tran_len, tran_len;
+ int num_bytes;
+ unsigned char *ch;
+ unsigned char *buffer = NULL;
+ size_t buf_len;
+ u8 *cmd_buf = fsl->cmd_buf;
+ size_t cmd_len = fsl->cmd_len;
+ size_t data_len = bitlen / 8;
+ size_t rx_offset = 0;
+
+ max_tran_len = fsl->max_transfer_length;
+ switch (flags) {
+ case SPI_XFER_BEGIN:
+ cmd_len = fsl->cmd_len = data_len;
+ memcpy(cmd_buf, data_out, cmd_len);
+ return 0;
+ case 0:
+ case SPI_XFER_END:
+ if (bitlen == 0) {
+ spi_cs_deactivate(slave);
+ return 0;
+ }
+ buf_len = 2 * cmd_len + min(data_len, max_tran_len);
+ len = cmd_len + data_len;
+ rx_offset = cmd_len;
+ buffer = (unsigned char *)malloc(buf_len);
+ if (!buffer) {
+ debug("SF: Failed to malloc memory.\n");
+ return 1;
+ }
+ memcpy(buffer, cmd_buf, cmd_len);
+ if (data_in == NULL)
+ memcpy(buffer + cmd_len, data_out, data_len);
+ break;
+ case SPI_XFER_BEGIN | SPI_XFER_END:
+ len = data_len;
+ buffer = (unsigned char *)malloc(len * 2);
+ if (!buffer) {
+ debug("SF: Failed to malloc memory.\n");
+ return 1;
+ }
+ memcpy(buffer, data_out, len);
+ rx_offset = len;
+ cmd_len = 0;
+ break;
+ }
+
+ debug("spi_xfer: slave %u:%u dout %08X(%p) din %08X(%p) len %u\n",
+ slave->bus, slave->cs, *(uint *) dout,
+ dout, *(uint *) din, din, len);
+
+ num_chunks = DIV_ROUND_UP(data_len, max_tran_len);
+ while (num_chunks--) {
+ if (data_in)
+ din = buffer + rx_offset;
+ dout = buffer;
+ tran_len = min(data_len , max_tran_len);
+ num_blks = DIV_ROUND_UP(tran_len + cmd_len, 4);
+ num_bytes = (tran_len + cmd_len) % 4;
+ fsl->data_len = tran_len + cmd_len;
+ spi_cs_activate(slave);
+
+ /* Clear all eSPI events */
+ out_be32(&espi->event , 0xffffffff);
+ /* handle data in 32-bit chunks */
+ while (num_blks--) {
+
+ event = in_be32(&espi->event);
+ if (event & ESPI_EV_TNF) {
+ tmpdout = *(u32 *)dout;
+
+ /* Set up the next iteration */
+ if (len > 4) {
+ len -= 4;
+ dout += 4;
+ }
+
+ out_be32(&espi->tx, tmpdout);
+ out_be32(&espi->event, ESPI_EV_TNF);
+ debug("***spi_xfer:...%08x written\n", tmpdout);
+ }
+
+ /* Wait for eSPI transmit to get out */
+ udelay(80);
+
+ event = in_be32(&espi->event);
+ if (event & ESPI_EV_RNE) {
+ tmpdin = in_be32(&espi->rx);
+ if (num_blks == 0 && num_bytes != 0) {
+ ch = (unsigned char *)&tmpdin;
+ while (num_bytes--)
+ *(unsigned char *)din++ = *ch++;
+ } else {
+ *(u32 *) din = tmpdin;
+ din += 4;
+ }
+
+ out_be32(&espi->event, in_be32(&espi->event)
+ | ESPI_EV_RNE);
+ debug("***spi_xfer:...%08x readed\n", tmpdin);
+ }
+ }
+ if (data_in) {
+ memcpy(data_in, buffer + 2 * cmd_len, tran_len);
+ if (*buffer == 0x0b) {
+ data_in += tran_len;
+ data_len -= tran_len;
+ *(int *)buffer += tran_len;
+ }
+ }
+ spi_cs_deactivate(slave);
+ }
+
+ free(buffer);
+ return 0;
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ return bus == 0 && cs < ESPI_MAX_CS_NUM;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ struct fsl_spi_slave *fsl = to_fsl_spi_slave(slave);
+ ccsr_espi_t *espi = (void *)(CONFIG_SYS_MPC85xx_ESPI_ADDR);
+ unsigned int com = 0;
+ size_t data_len = fsl->data_len;
+
+ com &= ~(ESPI_COM_CS(0x3) | ESPI_COM_TRANLEN(0xFFFF));
+ com |= ESPI_COM_CS(slave->cs);
+ com |= ESPI_COM_TRANLEN(data_len - 1);
+ out_be32(&espi->com, com);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ ccsr_espi_t *espi = (void *)(CONFIG_SYS_MPC85xx_ESPI_ADDR);
+
+ /* clear the RXCNT and TXCNT */
+ out_be32(&espi->mode, in_be32(&espi->mode) & (~ESPI_MODE_EN));
+ out_be32(&espi->mode, in_be32(&espi->mode) | ESPI_MODE_EN);
+}
diff --git a/qemu/roms/u-boot/drivers/spi/ftssp010_spi.c b/qemu/roms/u-boot/drivers/spi/ftssp010_spi.c
new file mode 100644
index 000000000..aa3b5a01c
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/ftssp010_spi.c
@@ -0,0 +1,508 @@
+/*
+ * (C) Copyright 2013
+ * Faraday Technology Corporation. <http://www.faraday-tech.com/tw/>
+ * Kuo-Jung Su <dantesu@gmail.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/compat.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <spi.h>
+
+#ifndef CONFIG_FTSSP010_BASE_LIST
+#define CONFIG_FTSSP010_BASE_LIST { CONFIG_FTSSP010_BASE }
+#endif
+
+#ifndef CONFIG_FTSSP010_GPIO_BASE
+#define CONFIG_FTSSP010_GPIO_BASE 0
+#endif
+
+#ifndef CONFIG_FTSSP010_GPIO_LIST
+#define CONFIG_FTSSP010_GPIO_LIST { CONFIG_FTSSP010_GPIO_BASE }
+#endif
+
+#ifndef CONFIG_FTSSP010_CLOCK
+#define CONFIG_FTSSP010_CLOCK clk_get_rate("SSP");
+#endif
+
+#ifndef CONFIG_FTSSP010_TIMEOUT
+#define CONFIG_FTSSP010_TIMEOUT 100
+#endif
+
+/* FTSSP010 chip registers */
+struct ftssp010_regs {
+ uint32_t cr[3];/* control register */
+ uint32_t sr; /* status register */
+ uint32_t icr; /* interrupt control register */
+ uint32_t isr; /* interrupt status register */
+ uint32_t dr; /* data register */
+ uint32_t rsvd[17];
+ uint32_t revr; /* revision register */
+ uint32_t fear; /* feature register */
+};
+
+/* Control Register 0 */
+#define CR0_FFMT_MASK (7 << 12)
+#define CR0_FFMT_SSP (0 << 12)
+#define CR0_FFMT_SPI (1 << 12)
+#define CR0_FFMT_MICROWIRE (2 << 12)
+#define CR0_FFMT_I2S (3 << 12)
+#define CR0_FFMT_AC97 (4 << 12)
+#define CR0_FLASH (1 << 11)
+#define CR0_FSDIST(x) (((x) & 0x03) << 8)
+#define CR0_LOOP (1 << 7) /* loopback mode */
+#define CR0_LSB (1 << 6) /* LSB */
+#define CR0_FSPO (1 << 5) /* fs atcive low (I2S only) */
+#define CR0_FSJUSTIFY (1 << 4)
+#define CR0_OPM_SLAVE (0 << 2)
+#define CR0_OPM_MASTER (3 << 2)
+#define CR0_OPM_I2S_MSST (3 << 2) /* master stereo mode */
+#define CR0_OPM_I2S_MSMO (2 << 2) /* master mono mode */
+#define CR0_OPM_I2S_SLST (1 << 2) /* slave stereo mode */
+#define CR0_OPM_I2S_SLMO (0 << 2) /* slave mono mode */
+#define CR0_SCLKPO (1 << 1) /* clock polarity */
+#define CR0_SCLKPH (1 << 0) /* clock phase */
+
+/* Control Register 1 */
+#define CR1_PDL(x) (((x) & 0xff) << 24) /* padding length */
+#define CR1_SDL(x) ((((x) - 1) & 0x1f) << 16) /* data length */
+#define CR1_DIV(x) (((x) - 1) & 0xffff) /* clock divider */
+
+/* Control Register 2 */
+#define CR2_CS(x) (((x) & 3) << 10) /* CS/FS select */
+#define CR2_FS (1 << 9) /* CS/FS signal level */
+#define CR2_TXEN (1 << 8) /* tx enable */
+#define CR2_RXEN (1 << 7) /* rx enable */
+#define CR2_RESET (1 << 6) /* chip reset */
+#define CR2_TXFC (1 << 3) /* tx fifo Clear */
+#define CR2_RXFC (1 << 2) /* rx fifo Clear */
+#define CR2_TXDOE (1 << 1) /* tx data output enable */
+#define CR2_EN (1 << 0) /* chip enable */
+
+/* Status Register */
+#define SR_RFF (1 << 0) /* rx fifo full */
+#define SR_TFNF (1 << 1) /* tx fifo not full */
+#define SR_BUSY (1 << 2) /* chip busy */
+#define SR_RFVE(reg) (((reg) >> 4) & 0x1f) /* rx fifo valid entries */
+#define SR_TFVE(reg) (((reg) >> 12) & 0x1f) /* tx fifo valid entries */
+
+/* Feature Register */
+#define FEAR_BITS(reg) ((((reg) >> 0) & 0xff) + 1) /* data width */
+#define FEAR_RFSZ(reg) ((((reg) >> 8) & 0xff) + 1) /* rx fifo size */
+#define FEAR_TFSZ(reg) ((((reg) >> 16) & 0xff) + 1) /* tx fifo size */
+#define FEAR_AC97 (1 << 24)
+#define FEAR_I2S (1 << 25)
+#define FEAR_SPI_MWR (1 << 26)
+#define FEAR_SSP (1 << 27)
+#define FEAR_SPDIF (1 << 28)
+
+/* FTGPIO010 chip registers */
+struct ftgpio010_regs {
+ uint32_t out; /* 0x00: Data Output */
+ uint32_t in; /* 0x04: Data Input */
+ uint32_t dir; /* 0x08: Direction */
+ uint32_t bypass; /* 0x0c: Bypass */
+ uint32_t set; /* 0x10: Data Set */
+ uint32_t clr; /* 0x14: Data Clear */
+ uint32_t pull_up; /* 0x18: Pull-Up Enabled */
+ uint32_t pull_st; /* 0x1c: Pull State (0=pull-down, 1=pull-up) */
+};
+
+struct ftssp010_gpio {
+ struct ftgpio010_regs *regs;
+ uint32_t pin;
+};
+
+struct ftssp010_spi {
+ struct spi_slave slave;
+ struct ftssp010_gpio gpio;
+ struct ftssp010_regs *regs;
+ uint32_t fifo;
+ uint32_t mode;
+ uint32_t div;
+ uint32_t clk;
+ uint32_t speed;
+ uint32_t revision;
+};
+
+static inline struct ftssp010_spi *to_ftssp010_spi(struct spi_slave *slave)
+{
+ return container_of(slave, struct ftssp010_spi, slave);
+}
+
+static int get_spi_chip(int bus, struct ftssp010_spi *chip)
+{
+ uint32_t fear, base[] = CONFIG_FTSSP010_BASE_LIST;
+
+ if (bus >= ARRAY_SIZE(base) || !base[bus])
+ return -1;
+
+ chip->regs = (struct ftssp010_regs *)base[bus];
+
+ chip->revision = readl(&chip->regs->revr);
+
+ fear = readl(&chip->regs->fear);
+ chip->fifo = min_t(uint32_t, FEAR_TFSZ(fear), FEAR_RFSZ(fear));
+
+ return 0;
+}
+
+static int get_spi_gpio(int bus, struct ftssp010_gpio *chip)
+{
+ uint32_t base[] = CONFIG_FTSSP010_GPIO_LIST;
+
+ if (bus >= ARRAY_SIZE(base) || !base[bus])
+ return -1;
+
+ chip->regs = (struct ftgpio010_regs *)(base[bus] & 0xfff00000);
+ chip->pin = base[bus] & 0x1f;
+
+ /* make it an output pin */
+ setbits_le32(&chip->regs->dir, 1 << chip->pin);
+
+ return 0;
+}
+
+static int ftssp010_wait(struct ftssp010_spi *chip)
+{
+ struct ftssp010_regs *regs = chip->regs;
+ int ret = -1;
+ ulong t;
+
+ /* wait until device idle */
+ for (t = get_timer(0); get_timer(t) < CONFIG_FTSSP010_TIMEOUT; ) {
+ if (readl(&regs->sr) & SR_BUSY)
+ continue;
+ ret = 0;
+ break;
+ }
+
+ if (ret)
+ puts("ftspi010: busy timeout\n");
+
+ return ret;
+}
+
+static int ftssp010_wait_tx(struct ftssp010_spi *chip)
+{
+ struct ftssp010_regs *regs = chip->regs;
+ int ret = -1;
+ ulong t;
+
+ /* wait until tx fifo not full */
+ for (t = get_timer(0); get_timer(t) < CONFIG_FTSSP010_TIMEOUT; ) {
+ if (!(readl(&regs->sr) & SR_TFNF))
+ continue;
+ ret = 0;
+ break;
+ }
+
+ if (ret)
+ puts("ftssp010: tx timeout\n");
+
+ return ret;
+}
+
+static int ftssp010_wait_rx(struct ftssp010_spi *chip)
+{
+ struct ftssp010_regs *regs = chip->regs;
+ int ret = -1;
+ ulong t;
+
+ /* wait until rx fifo not empty */
+ for (t = get_timer(0); get_timer(t) < CONFIG_FTSSP010_TIMEOUT; ) {
+ if (!SR_RFVE(readl(&regs->sr)))
+ continue;
+ ret = 0;
+ break;
+ }
+
+ if (ret)
+ puts("ftssp010: rx timeout\n");
+
+ return ret;
+}
+
+static int ftssp010_spi_work_transfer_v2(struct ftssp010_spi *chip,
+ const void *tx_buf, void *rx_buf, int len, uint flags)
+{
+ struct ftssp010_regs *regs = chip->regs;
+ const uint8_t *txb = tx_buf;
+ uint8_t *rxb = rx_buf;
+
+ while (len > 0) {
+ int i, depth = min(chip->fifo >> 2, len);
+ uint32_t xmsk = 0;
+
+ if (tx_buf) {
+ for (i = 0; i < depth; ++i) {
+ ftssp010_wait_tx(chip);
+ writel(*txb++, &regs->dr);
+ }
+ xmsk |= CR2_TXEN | CR2_TXDOE;
+ if ((readl(&regs->cr[2]) & xmsk) != xmsk)
+ setbits_le32(&regs->cr[2], xmsk);
+ }
+ if (rx_buf) {
+ xmsk |= CR2_RXEN;
+ if ((readl(&regs->cr[2]) & xmsk) != xmsk)
+ setbits_le32(&regs->cr[2], xmsk);
+ for (i = 0; i < depth; ++i) {
+ ftssp010_wait_rx(chip);
+ *rxb++ = (uint8_t)readl(&regs->dr);
+ }
+ }
+
+ len -= depth;
+ }
+
+ return 0;
+}
+
+static int ftssp010_spi_work_transfer_v1(struct ftssp010_spi *chip,
+ const void *tx_buf, void *rx_buf, int len, uint flags)
+{
+ struct ftssp010_regs *regs = chip->regs;
+ const uint8_t *txb = tx_buf;
+ uint8_t *rxb = rx_buf;
+
+ while (len > 0) {
+ int i, depth = min(chip->fifo >> 2, len);
+ uint32_t tmp;
+
+ for (i = 0; i < depth; ++i) {
+ ftssp010_wait_tx(chip);
+ writel(txb ? (*txb++) : 0, &regs->dr);
+ }
+ for (i = 0; i < depth; ++i) {
+ ftssp010_wait_rx(chip);
+ tmp = readl(&regs->dr);
+ if (rxb)
+ *rxb++ = (uint8_t)tmp;
+ }
+
+ len -= depth;
+ }
+
+ return 0;
+}
+
+static void ftssp010_cs_set(struct ftssp010_spi *chip, int high)
+{
+ struct ftssp010_regs *regs = chip->regs;
+ struct ftssp010_gpio *gpio = &chip->gpio;
+ uint32_t mask;
+
+ /* cs pull high/low */
+ if (chip->revision >= 0x11900) {
+ mask = CR2_CS(chip->slave.cs) | (high ? CR2_FS : 0);
+ writel(mask, &regs->cr[2]);
+ } else if (gpio->regs) {
+ mask = 1 << gpio->pin;
+ if (high)
+ writel(mask, &gpio->regs->set);
+ else
+ writel(mask, &gpio->regs->clr);
+ }
+
+ /* extra delay for signal propagation */
+ udelay_masked(1);
+}
+
+/*
+ * Determine if a SPI chipselect is valid.
+ * This function is provided by the board if the low-level SPI driver
+ * needs it to determine if a given chipselect is actually valid.
+ *
+ * Returns: 1 if bus:cs identifies a valid chip on this board, 0
+ * otherwise.
+ */
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ struct ftssp010_spi chip;
+
+ if (get_spi_chip(bus, &chip))
+ return 0;
+
+ if (!cs)
+ return 1;
+ else if ((cs < 4) && (chip.revision >= 0x11900))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * Activate a SPI chipselect.
+ * This function is provided by the board code when using a driver
+ * that can't control its chipselects automatically (e.g.
+ * common/soft_spi.c). When called, it should activate the chip select
+ * to the device identified by "slave".
+ */
+void spi_cs_activate(struct spi_slave *slave)
+{
+ struct ftssp010_spi *chip = to_ftssp010_spi(slave);
+ struct ftssp010_regs *regs = chip->regs;
+
+ /* cs pull */
+ if (chip->mode & SPI_CS_HIGH)
+ ftssp010_cs_set(chip, 1);
+ else
+ ftssp010_cs_set(chip, 0);
+
+ /* chip enable + fifo clear */
+ setbits_le32(&regs->cr[2], CR2_EN | CR2_TXFC | CR2_RXFC);
+}
+
+/*
+ * Deactivate a SPI chipselect.
+ * This function is provided by the board code when using a driver
+ * that can't control its chipselects automatically (e.g.
+ * common/soft_spi.c). When called, it should deactivate the chip
+ * select to the device identified by "slave".
+ */
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct ftssp010_spi *chip = to_ftssp010_spi(slave);
+
+ /* wait until chip idle */
+ ftssp010_wait(chip);
+
+ /* cs pull */
+ if (chip->mode & SPI_CS_HIGH)
+ ftssp010_cs_set(chip, 0);
+ else
+ ftssp010_cs_set(chip, 1);
+}
+
+void spi_init(void)
+{
+ /* nothing to do */
+}
+
+struct spi_slave *spi_setup_slave(uint bus, uint cs, uint max_hz, uint mode)
+{
+ struct ftssp010_spi *chip;
+
+ if (mode & SPI_3WIRE) {
+ puts("ftssp010: can't do 3-wire\n");
+ return NULL;
+ }
+
+ if (mode & SPI_SLAVE) {
+ puts("ftssp010: can't do slave mode\n");
+ return NULL;
+ }
+
+ if (mode & SPI_PREAMBLE) {
+ puts("ftssp010: can't skip preamble bytes\n");
+ return NULL;
+ }
+
+ if (!spi_cs_is_valid(bus, cs)) {
+ puts("ftssp010: invalid (bus, cs)\n");
+ return NULL;
+ }
+
+ chip = spi_alloc_slave(struct ftssp010_spi, bus, cs);
+ if (!chip)
+ return NULL;
+
+ if (get_spi_chip(bus, chip))
+ goto free_out;
+
+ if (chip->revision < 0x11900 && get_spi_gpio(bus, &chip->gpio)) {
+ puts("ftssp010: Before revision 1.19.0, its clock & cs are\n"
+ "controlled by tx engine which is not synced with rx engine,\n"
+ "so the clock & cs might be shutdown before rx engine\n"
+ "finishs its jobs.\n"
+ "If possible, please add a dedicated gpio for it.\n");
+ }
+
+ chip->mode = mode;
+ chip->clk = CONFIG_FTSSP010_CLOCK;
+ chip->div = 2;
+ if (max_hz) {
+ while (chip->div < 0xffff) {
+ if ((chip->clk / (2 * chip->div)) <= max_hz)
+ break;
+ chip->div += 1;
+ }
+ }
+ chip->speed = chip->clk / (2 * chip->div);
+
+ return &chip->slave;
+
+free_out:
+ free(chip);
+ return NULL;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ free(slave);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct ftssp010_spi *chip = to_ftssp010_spi(slave);
+ struct ftssp010_regs *regs = chip->regs;
+
+ writel(CR1_SDL(8) | CR1_DIV(chip->div), &regs->cr[1]);
+
+ if (chip->revision >= 0x11900) {
+ writel(CR0_OPM_MASTER | CR0_FFMT_SPI | CR0_FSPO | CR0_FLASH,
+ &regs->cr[0]);
+ writel(CR2_TXFC | CR2_RXFC,
+ &regs->cr[2]);
+ } else {
+ writel(CR0_OPM_MASTER | CR0_FFMT_SPI | CR0_FSPO,
+ &regs->cr[0]);
+ writel(CR2_TXFC | CR2_RXFC | CR2_EN | CR2_TXDOE,
+ &regs->cr[2]);
+ }
+
+ if (chip->mode & SPI_LOOP)
+ setbits_le32(&regs->cr[0], CR0_LOOP);
+
+ if (chip->mode & SPI_CPOL)
+ setbits_le32(&regs->cr[0], CR0_SCLKPO);
+
+ if (chip->mode & SPI_CPHA)
+ setbits_le32(&regs->cr[0], CR0_SCLKPH);
+
+ spi_cs_deactivate(slave);
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ struct ftssp010_spi *chip = to_ftssp010_spi(slave);
+ struct ftssp010_regs *regs = chip->regs;
+
+ writel(0, &regs->cr[2]);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
+{
+ struct ftssp010_spi *chip = to_ftssp010_spi(slave);
+ uint32_t len = bitlen >> 3;
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ if (chip->revision >= 0x11900)
+ ftssp010_spi_work_transfer_v2(chip, dout, din, len, flags);
+ else
+ ftssp010_spi_work_transfer_v1(chip, dout, din, len, flags);
+
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/ich.c b/qemu/roms/u-boot/drivers/spi/ich.c
new file mode 100644
index 000000000..f5c6f3e7d
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/ich.c
@@ -0,0 +1,741 @@
+/*
+ * Copyright (c) 2011-12 The Chromium OS Authors.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This file is derived from the flashrom project.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <pci.h>
+#include <pci_ids.h>
+#include <asm/io.h>
+
+#include "ich.h"
+
+#define SPI_OPCODE_WREN 0x06
+#define SPI_OPCODE_FAST_READ 0x0b
+
+struct ich_ctlr {
+ pci_dev_t dev; /* PCI device number */
+ int ich_version; /* Controller version, 7 or 9 */
+ int ichspi_lock;
+ int locked;
+ uint8_t *opmenu;
+ int menubytes;
+ void *base; /* Base of register set */
+ uint16_t *preop;
+ uint16_t *optype;
+ uint32_t *addr;
+ uint8_t *data;
+ unsigned databytes;
+ uint8_t *status;
+ uint16_t *control;
+ uint32_t *bbar;
+ uint32_t *pr; /* only for ich9 */
+ uint8_t *speed; /* pointer to speed control */
+ ulong max_speed; /* Maximum bus speed in MHz */
+};
+
+struct ich_ctlr ctlr;
+
+static inline struct ich_spi_slave *to_ich_spi(struct spi_slave *slave)
+{
+ return container_of(slave, struct ich_spi_slave, slave);
+}
+
+static unsigned int ich_reg(const void *addr)
+{
+ return (unsigned)(addr - ctlr.base) & 0xffff;
+}
+
+static u8 ich_readb(const void *addr)
+{
+ u8 value = readb(addr);
+
+ debug("read %2.2x from %4.4x\n", value, ich_reg(addr));
+
+ return value;
+}
+
+static u16 ich_readw(const void *addr)
+{
+ u16 value = readw(addr);
+
+ debug("read %4.4x from %4.4x\n", value, ich_reg(addr));
+
+ return value;
+}
+
+static u32 ich_readl(const void *addr)
+{
+ u32 value = readl(addr);
+
+ debug("read %8.8x from %4.4x\n", value, ich_reg(addr));
+
+ return value;
+}
+
+static void ich_writeb(u8 value, void *addr)
+{
+ writeb(value, addr);
+ debug("wrote %2.2x to %4.4x\n", value, ich_reg(addr));
+}
+
+static void ich_writew(u16 value, void *addr)
+{
+ writew(value, addr);
+ debug("wrote %4.4x to %4.4x\n", value, ich_reg(addr));
+}
+
+static void ich_writel(u32 value, void *addr)
+{
+ writel(value, addr);
+ debug("wrote %8.8x to %4.4x\n", value, ich_reg(addr));
+}
+
+static void write_reg(const void *value, void *dest, uint32_t size)
+{
+ memcpy_toio(dest, value, size);
+}
+
+static void read_reg(const void *src, void *value, uint32_t size)
+{
+ memcpy_fromio(value, src, size);
+}
+
+static void ich_set_bbar(struct ich_ctlr *ctlr, uint32_t minaddr)
+{
+ const uint32_t bbar_mask = 0x00ffff00;
+ uint32_t ichspi_bbar;
+
+ minaddr &= bbar_mask;
+ ichspi_bbar = ich_readl(ctlr->bbar) & ~bbar_mask;
+ ichspi_bbar |= minaddr;
+ ich_writel(ichspi_bbar, ctlr->bbar);
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ puts("spi_cs_is_valid used but not implemented\n");
+ return 0;
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct ich_spi_slave *ich;
+
+ ich = spi_alloc_slave(struct ich_spi_slave, bus, cs);
+ if (!ich) {
+ puts("ICH SPI: Out of memory\n");
+ return NULL;
+ }
+
+ /*
+ * Yes this controller can only write a small number of bytes at
+ * once! The limit is typically 64 bytes.
+ */
+ ich->slave.max_write_size = ctlr.databytes;
+ ich->speed = max_hz;
+
+ return &ich->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct ich_spi_slave *ich = to_ich_spi(slave);
+
+ free(ich);
+}
+
+/*
+ * Check if this device ID matches one of supported Intel PCH devices.
+ *
+ * Return the ICH version if there is a match, or zero otherwise.
+ */
+static int get_ich_version(uint16_t device_id)
+{
+ if (device_id == PCI_DEVICE_ID_INTEL_TGP_LPC)
+ return 7;
+
+ if ((device_id >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN &&
+ device_id <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX) ||
+ (device_id >= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MIN &&
+ device_id <= PCI_DEVICE_ID_INTEL_PANTHERPOINT_LPC_MAX))
+ return 9;
+
+ return 0;
+}
+
+/* @return 1 if the SPI flash supports the 33MHz speed */
+static int ich9_can_do_33mhz(pci_dev_t dev)
+{
+ u32 fdod, speed;
+
+ /* Observe SPI Descriptor Component Section 0 */
+ pci_write_config_dword(dev, 0xb0, 0x1000);
+
+ /* Extract the Write/Erase SPI Frequency from descriptor */
+ pci_read_config_dword(dev, 0xb4, &fdod);
+
+ /* Bits 23:21 have the fast read clock frequency, 0=20MHz, 1=33MHz */
+ speed = (fdod >> 21) & 7;
+
+ return speed == 1;
+}
+
+static int ich_find_spi_controller(pci_dev_t *devp, int *ich_versionp)
+{
+ int last_bus = pci_last_busno();
+ int bus;
+
+ if (last_bus == -1) {
+ debug("No PCI busses?\n");
+ return -1;
+ }
+
+ for (bus = 0; bus <= last_bus; bus++) {
+ uint16_t vendor_id, device_id;
+ uint32_t ids;
+ pci_dev_t dev;
+
+ dev = PCI_BDF(bus, 31, 0);
+ pci_read_config_dword(dev, 0, &ids);
+ vendor_id = ids;
+ device_id = ids >> 16;
+
+ if (vendor_id == PCI_VENDOR_ID_INTEL) {
+ *devp = dev;
+ *ich_versionp = get_ich_version(device_id);
+ return 0;
+ }
+ }
+
+ debug("ICH SPI: No ICH found.\n");
+ return -1;
+}
+
+static int ich_init_controller(struct ich_ctlr *ctlr)
+{
+ uint8_t *rcrb; /* Root Complex Register Block */
+ uint32_t rcba; /* Root Complex Base Address */
+
+ pci_read_config_dword(ctlr->dev, 0xf0, &rcba);
+ /* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable. */
+ rcrb = (uint8_t *)(rcba & 0xffffc000);
+ if (ctlr->ich_version == 7) {
+ struct ich7_spi_regs *ich7_spi;
+
+ ich7_spi = (struct ich7_spi_regs *)(rcrb + 0x3020);
+ ctlr->ichspi_lock = ich_readw(&ich7_spi->spis) & SPIS_LOCK;
+ ctlr->opmenu = ich7_spi->opmenu;
+ ctlr->menubytes = sizeof(ich7_spi->opmenu);
+ ctlr->optype = &ich7_spi->optype;
+ ctlr->addr = &ich7_spi->spia;
+ ctlr->data = (uint8_t *)ich7_spi->spid;
+ ctlr->databytes = sizeof(ich7_spi->spid);
+ ctlr->status = (uint8_t *)&ich7_spi->spis;
+ ctlr->control = &ich7_spi->spic;
+ ctlr->bbar = &ich7_spi->bbar;
+ ctlr->preop = &ich7_spi->preop;
+ ctlr->base = ich7_spi;
+ } else if (ctlr->ich_version == 9) {
+ struct ich9_spi_regs *ich9_spi;
+
+ ich9_spi = (struct ich9_spi_regs *)(rcrb + 0x3800);
+ ctlr->ichspi_lock = ich_readw(&ich9_spi->hsfs) & HSFS_FLOCKDN;
+ ctlr->opmenu = ich9_spi->opmenu;
+ ctlr->menubytes = sizeof(ich9_spi->opmenu);
+ ctlr->optype = &ich9_spi->optype;
+ ctlr->addr = &ich9_spi->faddr;
+ ctlr->data = (uint8_t *)ich9_spi->fdata;
+ ctlr->databytes = sizeof(ich9_spi->fdata);
+ ctlr->status = &ich9_spi->ssfs;
+ ctlr->control = (uint16_t *)ich9_spi->ssfc;
+ ctlr->speed = ich9_spi->ssfc + 2;
+ ctlr->bbar = &ich9_spi->bbar;
+ ctlr->preop = &ich9_spi->preop;
+ ctlr->pr = &ich9_spi->pr[0];
+ ctlr->base = ich9_spi;
+ } else {
+ debug("ICH SPI: Unrecognized ICH version %d.\n",
+ ctlr->ich_version);
+ return -1;
+ }
+ debug("ICH SPI: Version %d detected\n", ctlr->ich_version);
+
+ /* Work out the maximum speed we can support */
+ ctlr->max_speed = 20000000;
+ if (ctlr->ich_version == 9 && ich9_can_do_33mhz(ctlr->dev))
+ ctlr->max_speed = 33000000;
+
+ ich_set_bbar(ctlr, 0);
+
+ return 0;
+}
+
+void spi_init(void)
+{
+ uint8_t bios_cntl;
+
+ if (ich_find_spi_controller(&ctlr.dev, &ctlr.ich_version)) {
+ printf("ICH SPI: Cannot find device\n");
+ return;
+ }
+
+ if (ich_init_controller(&ctlr)) {
+ printf("ICH SPI: Cannot setup controller\n");
+ return;
+ }
+
+ /*
+ * Disable the BIOS write protect so write commands are allowed. On
+ * v9, deassert SMM BIOS Write Protect Disable.
+ */
+ pci_read_config_byte(ctlr.dev, 0xdc, &bios_cntl);
+ if (ctlr.ich_version == 9)
+ bios_cntl &= ~(1 << 5);
+ pci_write_config_byte(ctlr.dev, 0xdc, bios_cntl | 0x1);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ /* Handled by ICH automatically. */
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ /* Handled by ICH automatically. */
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ /* Handled by ICH automatically. */
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ /* Handled by ICH automatically. */
+}
+
+static inline void spi_use_out(struct spi_trans *trans, unsigned bytes)
+{
+ trans->out += bytes;
+ trans->bytesout -= bytes;
+}
+
+static inline void spi_use_in(struct spi_trans *trans, unsigned bytes)
+{
+ trans->in += bytes;
+ trans->bytesin -= bytes;
+}
+
+static void spi_setup_type(struct spi_trans *trans, int data_bytes)
+{
+ trans->type = 0xFF;
+
+ /* Try to guess spi type from read/write sizes. */
+ if (trans->bytesin == 0) {
+ if (trans->bytesout + data_bytes > 4)
+ /*
+ * If bytesin = 0 and bytesout > 4, we presume this is
+ * a write data operation, which is accompanied by an
+ * address.
+ */
+ trans->type = SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS;
+ else
+ trans->type = SPI_OPCODE_TYPE_WRITE_NO_ADDRESS;
+ return;
+ }
+
+ if (trans->bytesout == 1) { /* and bytesin is > 0 */
+ trans->type = SPI_OPCODE_TYPE_READ_NO_ADDRESS;
+ return;
+ }
+
+ if (trans->bytesout == 4) /* and bytesin is > 0 */
+ trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
+
+ /* Fast read command is called with 5 bytes instead of 4 */
+ if (trans->out[0] == SPI_OPCODE_FAST_READ && trans->bytesout == 5) {
+ trans->type = SPI_OPCODE_TYPE_READ_WITH_ADDRESS;
+ --trans->bytesout;
+ }
+}
+
+static int spi_setup_opcode(struct spi_trans *trans)
+{
+ uint16_t optypes;
+ uint8_t opmenu[ctlr.menubytes];
+
+ trans->opcode = trans->out[0];
+ spi_use_out(trans, 1);
+ if (!ctlr.ichspi_lock) {
+ /* The lock is off, so just use index 0. */
+ ich_writeb(trans->opcode, ctlr.opmenu);
+ optypes = ich_readw(ctlr.optype);
+ optypes = (optypes & 0xfffc) | (trans->type & 0x3);
+ ich_writew(optypes, ctlr.optype);
+ return 0;
+ } else {
+ /* The lock is on. See if what we need is on the menu. */
+ uint8_t optype;
+ uint16_t opcode_index;
+
+ /* Write Enable is handled as atomic prefix */
+ if (trans->opcode == SPI_OPCODE_WREN)
+ return 0;
+
+ read_reg(ctlr.opmenu, opmenu, sizeof(opmenu));
+ for (opcode_index = 0; opcode_index < ctlr.menubytes;
+ opcode_index++) {
+ if (opmenu[opcode_index] == trans->opcode)
+ break;
+ }
+
+ if (opcode_index == ctlr.menubytes) {
+ printf("ICH SPI: Opcode %x not found\n",
+ trans->opcode);
+ return -1;
+ }
+
+ optypes = ich_readw(ctlr.optype);
+ optype = (optypes >> (opcode_index * 2)) & 0x3;
+ if (trans->type == SPI_OPCODE_TYPE_WRITE_NO_ADDRESS &&
+ optype == SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS &&
+ trans->bytesout >= 3) {
+ /* We guessed wrong earlier. Fix it up. */
+ trans->type = optype;
+ }
+ if (optype != trans->type) {
+ printf("ICH SPI: Transaction doesn't fit type %d\n",
+ optype);
+ return -1;
+ }
+ return opcode_index;
+ }
+}
+
+static int spi_setup_offset(struct spi_trans *trans)
+{
+ /* Separate the SPI address and data. */
+ switch (trans->type) {
+ case SPI_OPCODE_TYPE_READ_NO_ADDRESS:
+ case SPI_OPCODE_TYPE_WRITE_NO_ADDRESS:
+ return 0;
+ case SPI_OPCODE_TYPE_READ_WITH_ADDRESS:
+ case SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS:
+ trans->offset = ((uint32_t)trans->out[0] << 16) |
+ ((uint32_t)trans->out[1] << 8) |
+ ((uint32_t)trans->out[2] << 0);
+ spi_use_out(trans, 3);
+ return 1;
+ default:
+ printf("Unrecognized SPI transaction type %#x\n", trans->type);
+ return -1;
+ }
+}
+
+/*
+ * Wait for up to 6s til status register bit(s) turn 1 (in case wait_til_set
+ * below is true) or 0. In case the wait was for the bit(s) to set - write
+ * those bits back, which would cause resetting them.
+ *
+ * Return the last read status value on success or -1 on failure.
+ */
+static int ich_status_poll(u16 bitmask, int wait_til_set)
+{
+ int timeout = 600000; /* This will result in 6s */
+ u16 status = 0;
+
+ while (timeout--) {
+ status = ich_readw(ctlr.status);
+ if (wait_til_set ^ ((status & bitmask) == 0)) {
+ if (wait_til_set)
+ ich_writew((status & bitmask), ctlr.status);
+ return status;
+ }
+ udelay(10);
+ }
+
+ printf("ICH SPI: SCIP timeout, read %x, expected %x\n",
+ status, bitmask);
+ return -1;
+}
+
+/*
+int spi_xfer(struct spi_slave *slave, const void *dout,
+ unsigned int bitsout, void *din, unsigned int bitsin)
+*/
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct ich_spi_slave *ich = to_ich_spi(slave);
+ uint16_t control;
+ int16_t opcode_index;
+ int with_address;
+ int status;
+ int bytes = bitlen / 8;
+ struct spi_trans *trans = &ich->trans;
+ unsigned type = flags & (SPI_XFER_BEGIN | SPI_XFER_END);
+ int using_cmd = 0;
+ /* Align read transactions to 64-byte boundaries */
+ char buff[ctlr.databytes];
+
+ /* Ee don't support writing partial bytes. */
+ if (bitlen % 8) {
+ debug("ICH SPI: Accessing partial bytes not supported\n");
+ return -1;
+ }
+
+ /* An empty end transaction can be ignored */
+ if (type == SPI_XFER_END && !dout && !din)
+ return 0;
+
+ if (type & SPI_XFER_BEGIN)
+ memset(trans, '\0', sizeof(*trans));
+
+ /* Dp we need to come back later to finish it? */
+ if (dout && type == SPI_XFER_BEGIN) {
+ if (bytes > ICH_MAX_CMD_LEN) {
+ debug("ICH SPI: Command length limit exceeded\n");
+ return -1;
+ }
+ memcpy(trans->cmd, dout, bytes);
+ trans->cmd_len = bytes;
+ debug("ICH SPI: Saved %d bytes\n", bytes);
+ return 0;
+ }
+
+ /*
+ * We process a 'middle' spi_xfer() call, which has no
+ * SPI_XFER_BEGIN/END, as an independent transaction as if it had
+ * an end. We therefore repeat the command. This is because ICH
+ * seems to have no support for this, or because interest (in digging
+ * out the details and creating a special case in the code) is low.
+ */
+ if (trans->cmd_len) {
+ trans->out = trans->cmd;
+ trans->bytesout = trans->cmd_len;
+ using_cmd = 1;
+ debug("ICH SPI: Using %d bytes\n", trans->cmd_len);
+ } else {
+ trans->out = dout;
+ trans->bytesout = dout ? bytes : 0;
+ }
+
+ trans->in = din;
+ trans->bytesin = din ? bytes : 0;
+
+ /* There has to always at least be an opcode. */
+ if (!trans->bytesout) {
+ debug("ICH SPI: No opcode for transfer\n");
+ return -1;
+ }
+
+ if (ich_status_poll(SPIS_SCIP, 0) == -1)
+ return -1;
+
+ ich_writew(SPIS_CDS | SPIS_FCERR, ctlr.status);
+
+ spi_setup_type(trans, using_cmd ? bytes : 0);
+ opcode_index = spi_setup_opcode(trans);
+ if (opcode_index < 0)
+ return -1;
+ with_address = spi_setup_offset(trans);
+ if (with_address < 0)
+ return -1;
+
+ if (trans->opcode == SPI_OPCODE_WREN) {
+ /*
+ * Treat Write Enable as Atomic Pre-Op if possible
+ * in order to prevent the Management Engine from
+ * issuing a transaction between WREN and DATA.
+ */
+ if (!ctlr.ichspi_lock)
+ ich_writew(trans->opcode, ctlr.preop);
+ return 0;
+ }
+
+ if (ctlr.speed && ctlr.max_speed >= 33000000) {
+ int byte;
+
+ byte = ich_readb(ctlr.speed);
+ if (ich->speed >= 33000000)
+ byte |= SSFC_SCF_33MHZ;
+ else
+ byte &= ~SSFC_SCF_33MHZ;
+ ich_writeb(byte, ctlr.speed);
+ }
+
+ /* See if we have used up the command data */
+ if (using_cmd && dout && bytes) {
+ trans->out = dout;
+ trans->bytesout = bytes;
+ debug("ICH SPI: Moving to data, %d bytes\n", bytes);
+ }
+
+ /* Preset control fields */
+ control = ich_readw(ctlr.control);
+ control &= ~SSFC_RESERVED;
+ control = SPIC_SCGO | ((opcode_index & 0x07) << 4);
+
+ /* Issue atomic preop cycle if needed */
+ if (ich_readw(ctlr.preop))
+ control |= SPIC_ACS;
+
+ if (!trans->bytesout && !trans->bytesin) {
+ /* SPI addresses are 24 bit only */
+ if (with_address)
+ ich_writel(trans->offset & 0x00FFFFFF, ctlr.addr);
+
+ /*
+ * This is a 'no data' command (like Write Enable), its
+ * bitesout size was 1, decremented to zero while executing
+ * spi_setup_opcode() above. Tell the chip to send the
+ * command.
+ */
+ ich_writew(control, ctlr.control);
+
+ /* wait for the result */
+ status = ich_status_poll(SPIS_CDS | SPIS_FCERR, 1);
+ if (status == -1)
+ return -1;
+
+ if (status & SPIS_FCERR) {
+ debug("ICH SPI: Command transaction error\n");
+ return -1;
+ }
+
+ return 0;
+ }
+
+ /*
+ * Check if this is a write command atempting to transfer more bytes
+ * than the controller can handle. Iterations for writes are not
+ * supported here because each SPI write command needs to be preceded
+ * and followed by other SPI commands, and this sequence is controlled
+ * by the SPI chip driver.
+ */
+ if (trans->bytesout > ctlr.databytes) {
+ debug("ICH SPI: Too much to write. This should be prevented by the driver's max_write_size?\n");
+ return -1;
+ }
+
+ /*
+ * Read or write up to databytes bytes at a time until everything has
+ * been sent.
+ */
+ while (trans->bytesout || trans->bytesin) {
+ uint32_t data_length;
+ uint32_t aligned_offset;
+ uint32_t diff;
+
+ aligned_offset = trans->offset & ~(ctlr.databytes - 1);
+ diff = trans->offset - aligned_offset;
+
+ /* SPI addresses are 24 bit only */
+ ich_writel(aligned_offset & 0x00FFFFFF, ctlr.addr);
+
+ if (trans->bytesout)
+ data_length = min(trans->bytesout, ctlr.databytes);
+ else
+ data_length = min(trans->bytesin, ctlr.databytes);
+
+ /* Program data into FDATA0 to N */
+ if (trans->bytesout) {
+ write_reg(trans->out, ctlr.data, data_length);
+ spi_use_out(trans, data_length);
+ if (with_address)
+ trans->offset += data_length;
+ }
+
+ /* Add proper control fields' values */
+ control &= ~((ctlr.databytes - 1) << 8);
+ control |= SPIC_DS;
+ control |= (data_length - 1) << 8;
+
+ /* write it */
+ ich_writew(control, ctlr.control);
+
+ /* Wait for Cycle Done Status or Flash Cycle Error. */
+ status = ich_status_poll(SPIS_CDS | SPIS_FCERR, 1);
+ if (status == -1)
+ return -1;
+
+ if (status & SPIS_FCERR) {
+ debug("ICH SPI: Data transaction error\n");
+ return -1;
+ }
+
+ if (trans->bytesin) {
+ if (diff) {
+ data_length -= diff;
+ read_reg(ctlr.data, buff, ctlr.databytes);
+ memcpy(trans->in, buff + diff, data_length);
+ } else {
+ read_reg(ctlr.data, trans->in, data_length);
+ }
+ spi_use_in(trans, data_length);
+ if (with_address)
+ trans->offset += data_length;
+ }
+ }
+
+ /* Clear atomic preop now that xfer is done */
+ ich_writew(0, ctlr.preop);
+
+ return 0;
+}
+
+
+/*
+ * This uses the SPI controller from the Intel Cougar Point and Panther Point
+ * PCH to write-protect portions of the SPI flash until reboot. The changes
+ * don't actually take effect until the HSFS[FLOCKDN] bit is set, but that's
+ * done elsewhere.
+ */
+int spi_write_protect_region(uint32_t lower_limit, uint32_t length, int hint)
+{
+ uint32_t tmplong;
+ uint32_t upper_limit;
+
+ if (!ctlr.pr) {
+ printf("%s: operation not supported on this chipset\n",
+ __func__);
+ return -1;
+ }
+
+ if (length == 0 ||
+ lower_limit > (0xFFFFFFFFUL - length) + 1 ||
+ hint < 0 || hint > 4) {
+ printf("%s(0x%x, 0x%x, %d): invalid args\n", __func__,
+ lower_limit, length, hint);
+ return -1;
+ }
+
+ upper_limit = lower_limit + length - 1;
+
+ /*
+ * Determine bits to write, as follows:
+ * 31 Write-protection enable (includes erase operation)
+ * 30:29 reserved
+ * 28:16 Upper Limit (FLA address bits 24:12, with 11:0 == 0xfff)
+ * 15 Read-protection enable
+ * 14:13 reserved
+ * 12:0 Lower Limit (FLA address bits 24:12, with 11:0 == 0x000)
+ */
+ tmplong = 0x80000000 |
+ ((upper_limit & 0x01fff000) << 4) |
+ ((lower_limit & 0x01fff000) >> 12);
+
+ printf("%s: writing 0x%08x to %p\n", __func__, tmplong,
+ &ctlr.pr[hint]);
+ ctlr.pr[hint] = tmplong;
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/ich.h b/qemu/roms/u-boot/drivers/spi/ich.h
new file mode 100644
index 000000000..d2e4b8523
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/ich.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This file is derived from the flashrom project.
+ */
+
+struct ich7_spi_regs {
+ uint16_t spis;
+ uint16_t spic;
+ uint32_t spia;
+ uint64_t spid[8];
+ uint64_t _pad;
+ uint32_t bbar;
+ uint16_t preop;
+ uint16_t optype;
+ uint8_t opmenu[8];
+} __packed;
+
+struct ich9_spi_regs {
+ uint32_t bfpr; /* 0x00 */
+ uint16_t hsfs;
+ uint16_t hsfc;
+ uint32_t faddr;
+ uint32_t _reserved0;
+ uint32_t fdata[16]; /* 0x10 */
+ uint32_t frap; /* 0x50 */
+ uint32_t freg[5];
+ uint32_t _reserved1[3];
+ uint32_t pr[5]; /* 0x74 */
+ uint32_t _reserved2[2];
+ uint8_t ssfs; /* 0x90 */
+ uint8_t ssfc[3];
+ uint16_t preop; /* 0x94 */
+ uint16_t optype;
+ uint8_t opmenu[8]; /* 0x98 */
+ uint32_t bbar;
+ uint8_t _reserved3[12];
+ uint32_t fdoc;
+ uint32_t fdod;
+ uint8_t _reserved4[8];
+ uint32_t afc;
+ uint32_t lvscc;
+ uint32_t uvscc;
+ uint8_t _reserved5[4];
+ uint32_t fpb;
+ uint8_t _reserved6[28];
+ uint32_t srdl;
+ uint32_t srdc;
+ uint32_t srd;
+} __packed;
+
+enum {
+ SPIS_SCIP = 0x0001,
+ SPIS_GRANT = 0x0002,
+ SPIS_CDS = 0x0004,
+ SPIS_FCERR = 0x0008,
+ SSFS_AEL = 0x0010,
+ SPIS_LOCK = 0x8000,
+ SPIS_RESERVED_MASK = 0x7ff0,
+ SSFS_RESERVED_MASK = 0x7fe2
+};
+
+enum {
+ SPIC_SCGO = 0x000002,
+ SPIC_ACS = 0x000004,
+ SPIC_SPOP = 0x000008,
+ SPIC_DBC = 0x003f00,
+ SPIC_DS = 0x004000,
+ SPIC_SME = 0x008000,
+ SSFC_SCF_MASK = 0x070000,
+ SSFC_RESERVED = 0xf80000,
+
+ /* Mask for speed byte, biuts 23:16 of SSFC */
+ SSFC_SCF_33MHZ = 0x01,
+};
+
+enum {
+ HSFS_FDONE = 0x0001,
+ HSFS_FCERR = 0x0002,
+ HSFS_AEL = 0x0004,
+ HSFS_BERASE_MASK = 0x0018,
+ HSFS_BERASE_SHIFT = 3,
+ HSFS_SCIP = 0x0020,
+ HSFS_FDOPSS = 0x2000,
+ HSFS_FDV = 0x4000,
+ HSFS_FLOCKDN = 0x8000
+};
+
+enum {
+ HSFC_FGO = 0x0001,
+ HSFC_FCYCLE_MASK = 0x0006,
+ HSFC_FCYCLE_SHIFT = 1,
+ HSFC_FDBC_MASK = 0x3f00,
+ HSFC_FDBC_SHIFT = 8,
+ HSFC_FSMIE = 0x8000
+};
+
+enum {
+ SPI_OPCODE_TYPE_READ_NO_ADDRESS = 0,
+ SPI_OPCODE_TYPE_WRITE_NO_ADDRESS = 1,
+ SPI_OPCODE_TYPE_READ_WITH_ADDRESS = 2,
+ SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS = 3
+};
+
+enum {
+ ICH_MAX_CMD_LEN = 5,
+};
+
+struct spi_trans {
+ uint8_t cmd[ICH_MAX_CMD_LEN];
+ int cmd_len;
+ const uint8_t *out;
+ uint32_t bytesout;
+ uint8_t *in;
+ uint32_t bytesin;
+ uint8_t type;
+ uint8_t opcode;
+ uint32_t offset;
+};
+
+struct ich_spi_slave {
+ struct spi_slave slave;
+ struct spi_trans trans; /* current transaction in progress */
+ int speed; /* SPI speed in Hz */
+};
diff --git a/qemu/roms/u-boot/drivers/spi/kirkwood_spi.c b/qemu/roms/u-boot/drivers/spi/kirkwood_spi.c
new file mode 100644
index 000000000..942a208c2
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/kirkwood_spi.c
@@ -0,0 +1,214 @@
+/*
+ * (C) Copyright 2009
+ * Marvell Semiconductor <www.marvell.com>
+ * Written-by: Prafulla Wadaskar <prafulla@marvell.com>
+ *
+ * Derived from drivers/spi/mpc8xxx_spi.c
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <asm/arch/kirkwood.h>
+#include <asm/arch/spi.h>
+#include <asm/arch/mpp.h>
+
+static struct kwspi_registers *spireg = (struct kwspi_registers *)KW_SPI_BASE;
+
+u32 cs_spi_mpp_back[2];
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct spi_slave *slave;
+ u32 data;
+ static const u32 kwspi_mpp_config[2][2] = {
+ { MPP0_SPI_SCn, 0 }, /* if cs == 0 */
+ { MPP7_SPI_SCn, 0 } /* if cs != 0 */
+ };
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ slave = spi_alloc_slave_base(bus, cs);
+ if (!slave)
+ return NULL;
+
+ writel(~KWSPI_CSN_ACT | KWSPI_SMEMRDY, &spireg->ctrl);
+
+ /* calculate spi clock prescaller using max_hz */
+ data = ((CONFIG_SYS_TCLK / 2) / max_hz) + 0x10;
+ data = data < KWSPI_CLKPRESCL_MIN ? KWSPI_CLKPRESCL_MIN : data;
+ data = data > KWSPI_CLKPRESCL_MASK ? KWSPI_CLKPRESCL_MASK : data;
+
+ /* program spi clock prescaller using max_hz */
+ writel(KWSPI_ADRLEN_3BYTE | data, &spireg->cfg);
+ debug("data = 0x%08x \n", data);
+
+ writel(KWSPI_SMEMRDIRQ, &spireg->irq_cause);
+ writel(KWSPI_IRQMASK, &spireg->irq_mask);
+
+ /* program mpp registers to select SPI_CSn */
+ kirkwood_mpp_conf(kwspi_mpp_config[cs ? 1 : 0], cs_spi_mpp_back);
+
+ return slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ kirkwood_mpp_conf(cs_spi_mpp_back, NULL);
+ free(slave);
+}
+
+#if defined(CONFIG_SYS_KW_SPI_MPP)
+u32 spi_mpp_backup[4];
+#endif
+
+__attribute__((weak)) int board_spi_claim_bus(struct spi_slave *slave)
+{
+ return 0;
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+#if defined(CONFIG_SYS_KW_SPI_MPP)
+ u32 config;
+ u32 spi_mpp_config[4];
+
+ config = CONFIG_SYS_KW_SPI_MPP;
+
+ if (config & MOSI_MPP6)
+ spi_mpp_config[0] = MPP6_SPI_MOSI;
+ else
+ spi_mpp_config[0] = MPP1_SPI_MOSI;
+
+ if (config & SCK_MPP10)
+ spi_mpp_config[1] = MPP10_SPI_SCK;
+ else
+ spi_mpp_config[1] = MPP2_SPI_SCK;
+
+ if (config & MISO_MPP11)
+ spi_mpp_config[2] = MPP11_SPI_MISO;
+ else
+ spi_mpp_config[2] = MPP3_SPI_MISO;
+
+ spi_mpp_config[3] = 0;
+ spi_mpp_backup[3] = 0;
+
+ /* set new spi mpp and save current mpp config */
+ kirkwood_mpp_conf(spi_mpp_config, spi_mpp_backup);
+
+#endif
+
+ return board_spi_claim_bus(slave);
+}
+
+__attribute__((weak)) void board_spi_release_bus(struct spi_slave *slave)
+{
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+#if defined(CONFIG_SYS_KW_SPI_MPP)
+ kirkwood_mpp_conf(spi_mpp_backup, NULL);
+#endif
+
+ board_spi_release_bus(slave);
+}
+
+#ifndef CONFIG_SPI_CS_IS_VALID
+/*
+ * you can define this function board specific
+ * define above CONFIG in board specific config file and
+ * provide the function in board specific src file
+ */
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ return (bus == 0 && (cs == 0 || cs == 1));
+}
+#endif
+
+void spi_init(void)
+{
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ writel(readl(&spireg->ctrl) | KWSPI_IRQUNMASK, &spireg->ctrl);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ writel(readl(&spireg->ctrl) & KWSPI_IRQMASK, &spireg->ctrl);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ unsigned int tmpdout, tmpdin;
+ int tm, isread = 0;
+
+ debug("spi_xfer: slave %u:%u dout %p din %p bitlen %u\n",
+ slave->bus, slave->cs, dout, din, bitlen);
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ /*
+ * handle data in 8-bit chunks
+ * TBD: 2byte xfer mode to be enabled
+ */
+ writel(((readl(&spireg->cfg) & ~KWSPI_XFERLEN_MASK) |
+ KWSPI_XFERLEN_1BYTE), &spireg->cfg);
+
+ while (bitlen > 4) {
+ debug("loopstart bitlen %d\n", bitlen);
+ tmpdout = 0;
+
+ /* Shift data so it's msb-justified */
+ if (dout)
+ tmpdout = *(u32 *) dout & 0x0ff;
+
+ writel(~KWSPI_SMEMRDIRQ, &spireg->irq_cause);
+ writel(tmpdout, &spireg->dout); /* Write the data out */
+ debug("*** spi_xfer: ... %08x written, bitlen %d\n",
+ tmpdout, bitlen);
+
+ /*
+ * Wait for SPI transmit to get out
+ * or time out (1 second = 1000 ms)
+ * The NE event must be read and cleared first
+ */
+ for (tm = 0, isread = 0; tm < KWSPI_TIMEOUT; ++tm) {
+ if (readl(&spireg->irq_cause) & KWSPI_SMEMRDIRQ) {
+ isread = 1;
+ tmpdin = readl(&spireg->din);
+ debug
+ ("spi_xfer: din %p..%08x read\n",
+ din, tmpdin);
+
+ if (din) {
+ *((u8 *) din) = (u8) tmpdin;
+ din += 1;
+ }
+ if (dout)
+ dout += 1;
+ bitlen -= 8;
+ }
+ if (isread)
+ break;
+ }
+ if (tm >= KWSPI_TIMEOUT)
+ printf("*** spi_xfer: Time out during SPI transfer\n");
+
+ debug("loopend bitlen %d\n", bitlen);
+ }
+
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/mpc52xx_spi.c b/qemu/roms/u-boot/drivers/spi/mpc52xx_spi.c
new file mode 100644
index 000000000..4613bec2a
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/mpc52xx_spi.c
@@ -0,0 +1,90 @@
+/*
+ * (C) Copyright 2009
+ * Frank Bodammer <frank.bodammer@gcd-solutions.de>
+ * (C) Copyright 2009 Semihalf, Grzegorz Bernacki
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <spi.h>
+#include <mpc5xxx.h>
+
+void spi_init(void)
+{
+ struct mpc5xxx_spi *spi = (struct mpc5xxx_spi *)MPC5XXX_SPI;
+ /*
+ * Its important to use the correct order when initializing the
+ * registers
+ */
+ out_8(&spi->ddr, 0x0F); /* set all SPI pins as output */
+ out_8(&spi->pdr, 0x00); /* set SS low */
+ /* SPI is master, SS is general purpose output */
+ out_8(&spi->cr1, SPI_CR_MSTR | SPI_CR_SPE);
+ out_8(&spi->cr2, 0x00); /* normal operation */
+ out_8(&spi->brr, 0x77); /* baud rate: IPB clock / 2048 */
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct spi_slave *slave;
+
+ slave = spi_alloc_slave_base(bus, cs);
+ if (!slave)
+ return NULL;
+
+ return slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ free(slave);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ return;
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct mpc5xxx_spi *spi = (struct mpc5xxx_spi *)MPC5XXX_SPI;
+ int i, iter = bitlen >> 3;
+ const uchar *txp = dout;
+ uchar *rxp = din;
+
+ debug("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
+ slave->bus, slave->cs, *(uint *) dout, *(uint *) din, bitlen);
+
+ if (flags & SPI_XFER_BEGIN)
+ setbits_8(&spi->pdr, SPI_PDR_SS);
+
+ for (i = 0; i < iter; i++) {
+ udelay(1000);
+ debug("spi_xfer: sending %x\n", txp[i]);
+ out_8(&spi->dr, txp[i]);
+ while (!(in_8(&spi->sr) & SPI_SR_SPIF)) {
+ udelay(1000);
+ if (in_8(&spi->sr) & SPI_SR_WCOL) {
+ rxp[i] = in_8(&spi->dr);
+ puts("spi_xfer: write collision\n");
+ return -1;
+ }
+ }
+ rxp[i] = in_8(&spi->dr);
+ debug("spi_xfer: received %x\n", rxp[i]);
+ }
+ if (flags & SPI_XFER_END)
+ clrbits_8(&spi->pdr, SPI_PDR_SS);
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/mpc8xxx_spi.c b/qemu/roms/u-boot/drivers/spi/mpc8xxx_spi.c
new file mode 100644
index 000000000..0d59c3615
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/mpc8xxx_spi.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2006 Ben Warren, Qstreams Networks Inc.
+ * With help from the common/soft_spi and arch/powerpc/cpu/mpc8260 drivers
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+
+#include <malloc.h>
+#include <spi.h>
+#include <asm/mpc8xxx_spi.h>
+
+#define SPI_EV_NE (0x80000000 >> 22) /* Receiver Not Empty */
+#define SPI_EV_NF (0x80000000 >> 23) /* Transmitter Not Full */
+
+#define SPI_MODE_LOOP (0x80000000 >> 1) /* Loopback mode */
+#define SPI_MODE_REV (0x80000000 >> 5) /* Reverse mode - MSB first */
+#define SPI_MODE_MS (0x80000000 >> 6) /* Always master */
+#define SPI_MODE_EN (0x80000000 >> 7) /* Enable interface */
+
+#define SPI_TIMEOUT 1000
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct spi_slave *slave;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ slave = spi_alloc_slave_base(bus, cs);
+ if (!slave)
+ return NULL;
+
+ /*
+ * TODO: Some of the code in spi_init() should probably move
+ * here, or into spi_claim_bus() below.
+ */
+
+ return slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ free(slave);
+}
+
+void spi_init(void)
+{
+ volatile spi8xxx_t *spi = &((immap_t *) (CONFIG_SYS_IMMR))->spi;
+
+ /*
+ * SPI pins on the MPC83xx are not muxed, so all we do is initialize
+ * some registers
+ */
+ spi->mode = SPI_MODE_REV | SPI_MODE_MS | SPI_MODE_EN;
+ spi->mode = (spi->mode & 0xfff0ffff) | (1 << 16); /* Use SYSCLK / 8
+ (16.67MHz typ.) */
+ spi->event = 0xffffffff; /* Clear all SPI events */
+ spi->mask = 0x00000000; /* Mask all SPI interrupts */
+ spi->com = 0; /* LST bit doesn't do anything, so disregard */
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ volatile spi8xxx_t *spi = &((immap_t *) (CONFIG_SYS_IMMR))->spi;
+ unsigned int tmpdout, tmpdin, event;
+ int numBlks = DIV_ROUND_UP(bitlen, 32);
+ int tm, isRead = 0;
+ unsigned char charSize = 32;
+
+ debug("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
+ slave->bus, slave->cs, *(uint *) dout, *(uint *) din, bitlen);
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ spi->event = 0xffffffff; /* Clear all SPI events */
+
+ /* handle data in 32-bit chunks */
+ while (numBlks--) {
+ tmpdout = 0;
+ charSize = (bitlen >= 32 ? 32 : bitlen);
+
+ /* Shift data so it's msb-justified */
+ tmpdout = *(u32 *) dout >> (32 - charSize);
+
+ /* The LEN field of the SPMODE register is set as follows:
+ *
+ * Bit length setting
+ * len <= 4 3
+ * 4 < len <= 16 len - 1
+ * len > 16 0
+ */
+
+ spi->mode &= ~SPI_MODE_EN;
+
+ if (bitlen <= 16) {
+ if (bitlen <= 4)
+ spi->mode = (spi->mode & 0xff0fffff) |
+ (3 << 20);
+ else
+ spi->mode = (spi->mode & 0xff0fffff) |
+ ((bitlen - 1) << 20);
+ } else {
+ spi->mode = (spi->mode & 0xff0fffff);
+ /* Set up the next iteration if sending > 32 bits */
+ bitlen -= 32;
+ dout += 4;
+ }
+
+ spi->mode |= SPI_MODE_EN;
+
+ spi->tx = tmpdout; /* Write the data out */
+ debug("*** spi_xfer: ... %08x written\n", tmpdout);
+
+ /*
+ * Wait for SPI transmit to get out
+ * or time out (1 second = 1000 ms)
+ * The NE event must be read and cleared first
+ */
+ for (tm = 0, isRead = 0; tm < SPI_TIMEOUT; ++tm) {
+ event = spi->event;
+ if (event & SPI_EV_NE) {
+ tmpdin = spi->rx;
+ spi->event |= SPI_EV_NE;
+ isRead = 1;
+
+ *(u32 *) din = (tmpdin << (32 - charSize));
+ if (charSize == 32) {
+ /* Advance output buffer by 32 bits */
+ din += 4;
+ }
+ }
+ /*
+ * Only bail when we've had both NE and NF events.
+ * This will cause timeouts on RO devices, so maybe
+ * in the future put an arbitrary delay after writing
+ * the device. Arbitrary delays suck, though...
+ */
+ if (isRead && (event & SPI_EV_NF))
+ break;
+ }
+ if (tm >= SPI_TIMEOUT)
+ puts("*** spi_xfer: Time out during SPI transfer");
+
+ debug("*** spi_xfer: transfer ended. Value=%08x\n", tmpdin);
+ }
+
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/mxc_spi.c b/qemu/roms/u-boot/drivers/spi/mxc_spi.c
new file mode 100644
index 000000000..f3f029d63
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/mxc_spi.c
@@ -0,0 +1,448 @@
+/*
+ * Copyright (C) 2008, Guennadi Liakhovetski <lg@denx.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/clock.h>
+
+#ifdef CONFIG_MX27
+/* i.MX27 has a completely wrong register layout and register definitions in the
+ * datasheet, the correct one is in the Freescale's Linux driver */
+
+#error "i.MX27 CSPI not supported due to drastic differences in register definitions" \
+"See linux mxc_spi driver from Freescale for details."
+#endif
+
+static unsigned long spi_bases[] = {
+ MXC_SPI_BASE_ADDRESSES
+};
+
+#define OUT MXC_GPIO_DIRECTION_OUT
+
+#define reg_read readl
+#define reg_write(a, v) writel(v, a)
+
+struct mxc_spi_slave {
+ struct spi_slave slave;
+ unsigned long base;
+ u32 ctrl_reg;
+#if defined(MXC_ECSPI)
+ u32 cfg_reg;
+#endif
+ int gpio;
+ int ss_pol;
+};
+
+static inline struct mxc_spi_slave *to_mxc_spi_slave(struct spi_slave *slave)
+{
+ return container_of(slave, struct mxc_spi_slave, slave);
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
+ if (mxcs->gpio > 0)
+ gpio_set_value(mxcs->gpio, mxcs->ss_pol);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
+ if (mxcs->gpio > 0)
+ gpio_set_value(mxcs->gpio,
+ !(mxcs->ss_pol));
+}
+
+u32 get_cspi_div(u32 div)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ if (div <= (4 << i))
+ return i;
+ }
+ return i;
+}
+
+#ifdef MXC_CSPI
+static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ unsigned int ctrl_reg;
+ u32 clk_src;
+ u32 div;
+
+ clk_src = mxc_get_clock(MXC_CSPI_CLK);
+
+ div = DIV_ROUND_UP(clk_src, max_hz);
+ div = get_cspi_div(div);
+
+ debug("clk %d Hz, div %d, real clk %d Hz\n",
+ max_hz, div, clk_src / (4 << div));
+
+ ctrl_reg = MXC_CSPICTRL_CHIPSELECT(cs) |
+ MXC_CSPICTRL_BITCOUNT(MXC_CSPICTRL_MAXBITS) |
+ MXC_CSPICTRL_DATARATE(div) |
+ MXC_CSPICTRL_EN |
+#ifdef CONFIG_MX35
+ MXC_CSPICTRL_SSCTL |
+#endif
+ MXC_CSPICTRL_MODE;
+
+ if (mode & SPI_CPHA)
+ ctrl_reg |= MXC_CSPICTRL_PHA;
+ if (mode & SPI_CPOL)
+ ctrl_reg |= MXC_CSPICTRL_POL;
+ if (mode & SPI_CS_HIGH)
+ ctrl_reg |= MXC_CSPICTRL_SSPOL;
+ mxcs->ctrl_reg = ctrl_reg;
+
+ return 0;
+}
+#endif
+
+#ifdef MXC_ECSPI
+static s32 spi_cfg_mxc(struct mxc_spi_slave *mxcs, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ u32 clk_src = mxc_get_clock(MXC_CSPI_CLK);
+ s32 reg_ctrl, reg_config;
+ u32 ss_pol = 0, sclkpol = 0, sclkpha = 0, sclkctl = 0;
+ u32 pre_div = 0, post_div = 0;
+ struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
+
+ if (max_hz == 0) {
+ printf("Error: desired clock is 0\n");
+ return -1;
+ }
+
+ /*
+ * Reset SPI and set all CSs to master mode, if toggling
+ * between slave and master mode we might see a glitch
+ * on the clock line
+ */
+ reg_ctrl = MXC_CSPICTRL_MODE_MASK;
+ reg_write(&regs->ctrl, reg_ctrl);
+ reg_ctrl |= MXC_CSPICTRL_EN;
+ reg_write(&regs->ctrl, reg_ctrl);
+
+ if (clk_src > max_hz) {
+ pre_div = (clk_src - 1) / max_hz;
+ /* fls(1) = 1, fls(0x80000000) = 32, fls(16) = 5 */
+ post_div = fls(pre_div);
+ if (post_div > 4) {
+ post_div -= 4;
+ if (post_div >= 16) {
+ printf("Error: no divider for the freq: %d\n",
+ max_hz);
+ return -1;
+ }
+ pre_div >>= post_div;
+ } else {
+ post_div = 0;
+ }
+ }
+
+ debug("pre_div = %d, post_div=%d\n", pre_div, post_div);
+ reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_SELCHAN(3)) |
+ MXC_CSPICTRL_SELCHAN(cs);
+ reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_PREDIV(0x0F)) |
+ MXC_CSPICTRL_PREDIV(pre_div);
+ reg_ctrl = (reg_ctrl & ~MXC_CSPICTRL_POSTDIV(0x0F)) |
+ MXC_CSPICTRL_POSTDIV(post_div);
+
+ /* We need to disable SPI before changing registers */
+ reg_ctrl &= ~MXC_CSPICTRL_EN;
+
+ if (mode & SPI_CS_HIGH)
+ ss_pol = 1;
+
+ if (mode & SPI_CPOL) {
+ sclkpol = 1;
+ sclkctl = 1;
+ }
+
+ if (mode & SPI_CPHA)
+ sclkpha = 1;
+
+ reg_config = reg_read(&regs->cfg);
+
+ /*
+ * Configuration register setup
+ * The MX51 supports different setup for each SS
+ */
+ reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_SSPOL))) |
+ (ss_pol << (cs + MXC_CSPICON_SSPOL));
+ reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_POL))) |
+ (sclkpol << (cs + MXC_CSPICON_POL));
+ reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_CTL))) |
+ (sclkctl << (cs + MXC_CSPICON_CTL));
+ reg_config = (reg_config & ~(1 << (cs + MXC_CSPICON_PHA))) |
+ (sclkpha << (cs + MXC_CSPICON_PHA));
+
+ debug("reg_ctrl = 0x%x\n", reg_ctrl);
+ reg_write(&regs->ctrl, reg_ctrl);
+ debug("reg_config = 0x%x\n", reg_config);
+ reg_write(&regs->cfg, reg_config);
+
+ /* save config register and control register */
+ mxcs->ctrl_reg = reg_ctrl;
+ mxcs->cfg_reg = reg_config;
+
+ /* clear interrupt reg */
+ reg_write(&regs->intr, 0);
+ reg_write(&regs->stat, MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
+
+ return 0;
+}
+#endif
+
+int spi_xchg_single(struct spi_slave *slave, unsigned int bitlen,
+ const u8 *dout, u8 *din, unsigned long flags)
+{
+ struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
+ int nbytes = DIV_ROUND_UP(bitlen, 8);
+ u32 data, cnt, i;
+ struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
+
+ debug("%s: bitlen %d dout 0x%x din 0x%x\n",
+ __func__, bitlen, (u32)dout, (u32)din);
+
+ mxcs->ctrl_reg = (mxcs->ctrl_reg &
+ ~MXC_CSPICTRL_BITCOUNT(MXC_CSPICTRL_MAXBITS)) |
+ MXC_CSPICTRL_BITCOUNT(bitlen - 1);
+
+ reg_write(&regs->ctrl, mxcs->ctrl_reg | MXC_CSPICTRL_EN);
+#ifdef MXC_ECSPI
+ reg_write(&regs->cfg, mxcs->cfg_reg);
+#endif
+
+ /* Clear interrupt register */
+ reg_write(&regs->stat, MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
+
+ /*
+ * The SPI controller works only with words,
+ * check if less than a word is sent.
+ * Access to the FIFO is only 32 bit
+ */
+ if (bitlen % 32) {
+ data = 0;
+ cnt = (bitlen % 32) / 8;
+ if (dout) {
+ for (i = 0; i < cnt; i++) {
+ data = (data << 8) | (*dout++ & 0xFF);
+ }
+ }
+ debug("Sending SPI 0x%x\n", data);
+
+ reg_write(&regs->txdata, data);
+ nbytes -= cnt;
+ }
+
+ data = 0;
+
+ while (nbytes > 0) {
+ data = 0;
+ if (dout) {
+ /* Buffer is not 32-bit aligned */
+ if ((unsigned long)dout & 0x03) {
+ data = 0;
+ for (i = 0; i < 4; i++)
+ data = (data << 8) | (*dout++ & 0xFF);
+ } else {
+ data = *(u32 *)dout;
+ data = cpu_to_be32(data);
+ dout += 4;
+ }
+ }
+ debug("Sending SPI 0x%x\n", data);
+ reg_write(&regs->txdata, data);
+ nbytes -= 4;
+ }
+
+ /* FIFO is written, now starts the transfer setting the XCH bit */
+ reg_write(&regs->ctrl, mxcs->ctrl_reg |
+ MXC_CSPICTRL_EN | MXC_CSPICTRL_XCH);
+
+ /* Wait until the TC (Transfer completed) bit is set */
+ while ((reg_read(&regs->stat) & MXC_CSPICTRL_TC) == 0)
+ ;
+
+ /* Transfer completed, clear any pending request */
+ reg_write(&regs->stat, MXC_CSPICTRL_TC | MXC_CSPICTRL_RXOVF);
+
+ nbytes = DIV_ROUND_UP(bitlen, 8);
+
+ cnt = nbytes % 32;
+
+ if (bitlen % 32) {
+ data = reg_read(&regs->rxdata);
+ cnt = (bitlen % 32) / 8;
+ data = cpu_to_be32(data) >> ((sizeof(data) - cnt) * 8);
+ debug("SPI Rx unaligned: 0x%x\n", data);
+ if (din) {
+ memcpy(din, &data, cnt);
+ din += cnt;
+ }
+ nbytes -= cnt;
+ }
+
+ while (nbytes > 0) {
+ u32 tmp;
+ tmp = reg_read(&regs->rxdata);
+ data = cpu_to_be32(tmp);
+ debug("SPI Rx: 0x%x 0x%x\n", tmp, data);
+ cnt = min(nbytes, sizeof(data));
+ if (din) {
+ memcpy(din, &data, cnt);
+ din += cnt;
+ }
+ nbytes -= cnt;
+ }
+
+ return 0;
+
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ int n_bytes = DIV_ROUND_UP(bitlen, 8);
+ int n_bits;
+ int ret;
+ u32 blk_size;
+ u8 *p_outbuf = (u8 *)dout;
+ u8 *p_inbuf = (u8 *)din;
+
+ if (!slave)
+ return -1;
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ while (n_bytes > 0) {
+ if (n_bytes < MAX_SPI_BYTES)
+ blk_size = n_bytes;
+ else
+ blk_size = MAX_SPI_BYTES;
+
+ n_bits = blk_size * 8;
+
+ ret = spi_xchg_single(slave, n_bits, p_outbuf, p_inbuf, 0);
+
+ if (ret)
+ return ret;
+ if (dout)
+ p_outbuf += blk_size;
+ if (din)
+ p_inbuf += blk_size;
+ n_bytes -= blk_size;
+ }
+
+ if (flags & SPI_XFER_END) {
+ spi_cs_deactivate(slave);
+ }
+
+ return 0;
+}
+
+void spi_init(void)
+{
+}
+
+static int decode_cs(struct mxc_spi_slave *mxcs, unsigned int cs)
+{
+ int ret;
+
+ /*
+ * Some SPI devices require active chip-select over multiple
+ * transactions, we achieve this using a GPIO. Still, the SPI
+ * controller has to be configured to use one of its own chipselects.
+ * To use this feature you have to call spi_setup_slave() with
+ * cs = internal_cs | (gpio << 8), and you have to use some unused
+ * on this SPI controller cs between 0 and 3.
+ */
+ if (cs > 3) {
+ mxcs->gpio = cs >> 8;
+ cs &= 3;
+ ret = gpio_direction_output(mxcs->gpio, !(mxcs->ss_pol));
+ if (ret) {
+ printf("mxc_spi: cannot setup gpio %d\n", mxcs->gpio);
+ return -EINVAL;
+ }
+ } else {
+ mxcs->gpio = -1;
+ }
+
+ return cs;
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct mxc_spi_slave *mxcs;
+ int ret;
+
+ if (bus >= ARRAY_SIZE(spi_bases))
+ return NULL;
+
+ mxcs = spi_alloc_slave(struct mxc_spi_slave, bus, cs);
+ if (!mxcs) {
+ puts("mxc_spi: SPI Slave not allocated !\n");
+ return NULL;
+ }
+
+ mxcs->ss_pol = (mode & SPI_CS_HIGH) ? 1 : 0;
+
+ ret = decode_cs(mxcs, cs);
+ if (ret < 0) {
+ free(mxcs);
+ return NULL;
+ }
+
+ cs = ret;
+
+ mxcs->base = spi_bases[bus];
+
+ ret = spi_cfg_mxc(mxcs, cs, max_hz, mode);
+ if (ret) {
+ printf("mxc_spi: cannot setup SPI controller\n");
+ free(mxcs);
+ return NULL;
+ }
+ return &mxcs->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
+
+ free(mxcs);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct mxc_spi_slave *mxcs = to_mxc_spi_slave(slave);
+ struct cspi_regs *regs = (struct cspi_regs *)mxcs->base;
+
+ reg_write(&regs->rxdata, 1);
+ udelay(1);
+ reg_write(&regs->ctrl, mxcs->ctrl_reg);
+ reg_write(&regs->period, MXC_CSPIPERIOD_32KHZ);
+ reg_write(&regs->intr, 0);
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ /* TODO: Shut the controller down */
+}
diff --git a/qemu/roms/u-boot/drivers/spi/mxs_spi.c b/qemu/roms/u-boot/drivers/spi/mxs_spi.c
new file mode 100644
index 000000000..2b9f395a9
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/mxs_spi.c
@@ -0,0 +1,362 @@
+/*
+ * Freescale i.MX28 SPI driver
+ *
+ * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
+ * on behalf of DENX Software Engineering GmbH
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * NOTE: This driver only supports the SPI-controller chipselects,
+ * GPIO driven chipselects are not supported.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/errno.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/sys_proto.h>
+#include <asm/imx-common/dma.h>
+
+#define MXS_SPI_MAX_TIMEOUT 1000000
+#define MXS_SPI_PORT_OFFSET 0x2000
+#define MXS_SSP_CHIPSELECT_MASK 0x00300000
+#define MXS_SSP_CHIPSELECT_SHIFT 20
+
+#define MXSSSP_SMALL_TRANSFER 512
+
+struct mxs_spi_slave {
+ struct spi_slave slave;
+ uint32_t max_khz;
+ uint32_t mode;
+ struct mxs_ssp_regs *regs;
+};
+
+static inline struct mxs_spi_slave *to_mxs_slave(struct spi_slave *slave)
+{
+ return container_of(slave, struct mxs_spi_slave, slave);
+}
+
+void spi_init(void)
+{
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ /* MXS SPI: 4 ports and 3 chip selects maximum */
+ if (!mxs_ssp_bus_id_valid(bus) || cs > 2)
+ return 0;
+ else
+ return 1;
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct mxs_spi_slave *mxs_slave;
+
+ if (!spi_cs_is_valid(bus, cs)) {
+ printf("mxs_spi: invalid bus %d / chip select %d\n", bus, cs);
+ return NULL;
+ }
+
+ mxs_slave = spi_alloc_slave(struct mxs_spi_slave, bus, cs);
+ if (!mxs_slave)
+ return NULL;
+
+ if (mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + bus))
+ goto err_init;
+
+ mxs_slave->max_khz = max_hz / 1000;
+ mxs_slave->mode = mode;
+ mxs_slave->regs = mxs_ssp_regs_by_bus(bus);
+
+ return &mxs_slave->slave;
+
+err_init:
+ free(mxs_slave);
+ return NULL;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
+ free(mxs_slave);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
+ struct mxs_ssp_regs *ssp_regs = mxs_slave->regs;
+ uint32_t reg = 0;
+
+ mxs_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
+
+ writel((slave->cs << MXS_SSP_CHIPSELECT_SHIFT) |
+ SSP_CTRL0_BUS_WIDTH_ONE_BIT,
+ &ssp_regs->hw_ssp_ctrl0);
+
+ reg = SSP_CTRL1_SSP_MODE_SPI | SSP_CTRL1_WORD_LENGTH_EIGHT_BITS;
+ reg |= (mxs_slave->mode & SPI_CPOL) ? SSP_CTRL1_POLARITY : 0;
+ reg |= (mxs_slave->mode & SPI_CPHA) ? SSP_CTRL1_PHASE : 0;
+ writel(reg, &ssp_regs->hw_ssp_ctrl1);
+
+ writel(0, &ssp_regs->hw_ssp_cmd0);
+
+ mxs_set_ssp_busclock(slave->bus, mxs_slave->max_khz);
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+}
+
+static void mxs_spi_start_xfer(struct mxs_ssp_regs *ssp_regs)
+{
+ writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_set);
+ writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_clr);
+}
+
+static void mxs_spi_end_xfer(struct mxs_ssp_regs *ssp_regs)
+{
+ writel(SSP_CTRL0_LOCK_CS, &ssp_regs->hw_ssp_ctrl0_clr);
+ writel(SSP_CTRL0_IGNORE_CRC, &ssp_regs->hw_ssp_ctrl0_set);
+}
+
+static int mxs_spi_xfer_pio(struct mxs_spi_slave *slave,
+ char *data, int length, int write, unsigned long flags)
+{
+ struct mxs_ssp_regs *ssp_regs = slave->regs;
+
+ if (flags & SPI_XFER_BEGIN)
+ mxs_spi_start_xfer(ssp_regs);
+
+ while (length--) {
+ /* We transfer 1 byte */
+#if defined(CONFIG_MX23)
+ writel(SSP_CTRL0_XFER_COUNT_MASK, &ssp_regs->hw_ssp_ctrl0_clr);
+ writel(1, &ssp_regs->hw_ssp_ctrl0_set);
+#elif defined(CONFIG_MX28)
+ writel(1, &ssp_regs->hw_ssp_xfer_size);
+#endif
+
+ if ((flags & SPI_XFER_END) && !length)
+ mxs_spi_end_xfer(ssp_regs);
+
+ if (write)
+ writel(SSP_CTRL0_READ, &ssp_regs->hw_ssp_ctrl0_clr);
+ else
+ writel(SSP_CTRL0_READ, &ssp_regs->hw_ssp_ctrl0_set);
+
+ writel(SSP_CTRL0_RUN, &ssp_regs->hw_ssp_ctrl0_set);
+
+ if (mxs_wait_mask_set(&ssp_regs->hw_ssp_ctrl0_reg,
+ SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
+ printf("MXS SPI: Timeout waiting for start\n");
+ return -ETIMEDOUT;
+ }
+
+ if (write)
+ writel(*data++, &ssp_regs->hw_ssp_data);
+
+ writel(SSP_CTRL0_DATA_XFER, &ssp_regs->hw_ssp_ctrl0_set);
+
+ if (!write) {
+ if (mxs_wait_mask_clr(&ssp_regs->hw_ssp_status_reg,
+ SSP_STATUS_FIFO_EMPTY, MXS_SPI_MAX_TIMEOUT)) {
+ printf("MXS SPI: Timeout waiting for data\n");
+ return -ETIMEDOUT;
+ }
+
+ *data = readl(&ssp_regs->hw_ssp_data);
+ data++;
+ }
+
+ if (mxs_wait_mask_clr(&ssp_regs->hw_ssp_ctrl0_reg,
+ SSP_CTRL0_RUN, MXS_SPI_MAX_TIMEOUT)) {
+ printf("MXS SPI: Timeout waiting for finish\n");
+ return -ETIMEDOUT;
+ }
+ }
+
+ return 0;
+}
+
+static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,
+ char *data, int length, int write, unsigned long flags)
+{
+ const int xfer_max_sz = 0xff00;
+ const int desc_count = DIV_ROUND_UP(length, xfer_max_sz) + 1;
+ struct mxs_ssp_regs *ssp_regs = slave->regs;
+ struct mxs_dma_desc *dp;
+ uint32_t ctrl0;
+ uint32_t cache_data_count;
+ const uint32_t dstart = (uint32_t)data;
+ int dmach;
+ int tl;
+ int ret = 0;
+
+#if defined(CONFIG_MX23)
+ const int mxs_spi_pio_words = 1;
+#elif defined(CONFIG_MX28)
+ const int mxs_spi_pio_words = 4;
+#endif
+
+ ALLOC_CACHE_ALIGN_BUFFER(struct mxs_dma_desc, desc, desc_count);
+
+ memset(desc, 0, sizeof(struct mxs_dma_desc) * desc_count);
+
+ ctrl0 = readl(&ssp_regs->hw_ssp_ctrl0);
+ ctrl0 |= SSP_CTRL0_DATA_XFER;
+
+ if (flags & SPI_XFER_BEGIN)
+ ctrl0 |= SSP_CTRL0_LOCK_CS;
+ if (!write)
+ ctrl0 |= SSP_CTRL0_READ;
+
+ if (length % ARCH_DMA_MINALIGN)
+ cache_data_count = roundup(length, ARCH_DMA_MINALIGN);
+ else
+ cache_data_count = length;
+
+ /* Flush data to DRAM so DMA can pick them up */
+ if (write)
+ flush_dcache_range(dstart, dstart + cache_data_count);
+
+ /* Invalidate the area, so no writeback into the RAM races with DMA */
+ invalidate_dcache_range(dstart, dstart + cache_data_count);
+
+ dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + slave->slave.bus;
+
+ dp = desc;
+ while (length) {
+ dp->address = (dma_addr_t)dp;
+ dp->cmd.address = (dma_addr_t)data;
+
+ /*
+ * This is correct, even though it does indeed look insane.
+ * I hereby have to, wholeheartedly, thank Freescale Inc.,
+ * for always inventing insane hardware and keeping me busy
+ * and employed ;-)
+ */
+ if (write)
+ dp->cmd.data = MXS_DMA_DESC_COMMAND_DMA_READ;
+ else
+ dp->cmd.data = MXS_DMA_DESC_COMMAND_DMA_WRITE;
+
+ /*
+ * The DMA controller can transfer large chunks (64kB) at
+ * time by setting the transfer length to 0. Setting tl to
+ * 0x10000 will overflow below and make .data contain 0.
+ * Otherwise, 0xff00 is the transfer maximum.
+ */
+ if (length >= 0x10000)
+ tl = 0x10000;
+ else
+ tl = min(length, xfer_max_sz);
+
+ dp->cmd.data |=
+ ((tl & 0xffff) << MXS_DMA_DESC_BYTES_OFFSET) |
+ (mxs_spi_pio_words << MXS_DMA_DESC_PIO_WORDS_OFFSET) |
+ MXS_DMA_DESC_HALT_ON_TERMINATE |
+ MXS_DMA_DESC_TERMINATE_FLUSH;
+
+ data += tl;
+ length -= tl;
+
+ if (!length) {
+ dp->cmd.data |= MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM;
+
+ if (flags & SPI_XFER_END) {
+ ctrl0 &= ~SSP_CTRL0_LOCK_CS;
+ ctrl0 |= SSP_CTRL0_IGNORE_CRC;
+ }
+ }
+
+ /*
+ * Write CTRL0, CMD0, CMD1 and XFER_SIZE registers in
+ * case of MX28, write only CTRL0 in case of MX23 due
+ * to the difference in register layout. It is utterly
+ * essential that the XFER_SIZE register is written on
+ * a per-descriptor basis with the same size as is the
+ * descriptor!
+ */
+ dp->cmd.pio_words[0] = ctrl0;
+#ifdef CONFIG_MX28
+ dp->cmd.pio_words[1] = 0;
+ dp->cmd.pio_words[2] = 0;
+ dp->cmd.pio_words[3] = tl;
+#endif
+
+ mxs_dma_desc_append(dmach, dp);
+
+ dp++;
+ }
+
+ if (mxs_dma_go(dmach))
+ ret = -EINVAL;
+
+ /* The data arrived into DRAM, invalidate cache over them */
+ if (!write)
+ invalidate_dcache_range(dstart, dstart + cache_data_count);
+
+ return ret;
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
+{
+ struct mxs_spi_slave *mxs_slave = to_mxs_slave(slave);
+ struct mxs_ssp_regs *ssp_regs = mxs_slave->regs;
+ int len = bitlen / 8;
+ char dummy;
+ int write = 0;
+ char *data = NULL;
+ int dma = 1;
+
+ if (bitlen == 0) {
+ if (flags & SPI_XFER_END) {
+ din = (void *)&dummy;
+ len = 1;
+ } else
+ return 0;
+ }
+
+ /* Half-duplex only */
+ if (din && dout)
+ return -EINVAL;
+ /* No data */
+ if (!din && !dout)
+ return 0;
+
+ if (dout) {
+ data = (char *)dout;
+ write = 1;
+ } else if (din) {
+ data = (char *)din;
+ write = 0;
+ }
+
+ /*
+ * Check for alignment, if the buffer is aligned, do DMA transfer,
+ * PIO otherwise. This is a temporary workaround until proper bounce
+ * buffer is in place.
+ */
+ if (dma) {
+ if (((uint32_t)data) & (ARCH_DMA_MINALIGN - 1))
+ dma = 0;
+ if (((uint32_t)len) & (ARCH_DMA_MINALIGN - 1))
+ dma = 0;
+ }
+
+ if (!dma || (len < MXSSSP_SMALL_TRANSFER)) {
+ writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_clr);
+ return mxs_spi_xfer_pio(mxs_slave, data, len, write, flags);
+ } else {
+ writel(SSP_CTRL1_DMA_ENABLE, &ssp_regs->hw_ssp_ctrl1_set);
+ return mxs_spi_xfer_dma(mxs_slave, data, len, write, flags);
+ }
+}
diff --git a/qemu/roms/u-boot/drivers/spi/oc_tiny_spi.c b/qemu/roms/u-boot/drivers/spi/oc_tiny_spi.c
new file mode 100644
index 000000000..4de5d008a
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/oc_tiny_spi.c
@@ -0,0 +1,245 @@
+/*
+ * Opencore tiny_spi driver
+ *
+ * http://opencores.org/project,tiny_spi
+ *
+ * based on bfin_spi.c
+ * Copyright (c) 2005-2008 Analog Devices Inc.
+ * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/gpio.h>
+
+#define TINY_SPI_STATUS_TXE 0x1
+#define TINY_SPI_STATUS_TXR 0x2
+
+struct tiny_spi_regs {
+ unsigned rxdata; /* Rx data reg */
+ unsigned txdata; /* Tx data reg */
+ unsigned status; /* Status reg */
+ unsigned control; /* Control reg */
+ unsigned baud; /* Baud reg */
+};
+
+struct tiny_spi_host {
+ uint base;
+ uint freq;
+ uint baudwidth;
+};
+static const struct tiny_spi_host tiny_spi_host_list[] =
+ CONFIG_SYS_TINY_SPI_LIST;
+
+struct tiny_spi_slave {
+ struct spi_slave slave;
+ const struct tiny_spi_host *host;
+ uint mode;
+ uint baud;
+ uint flg;
+};
+#define to_tiny_spi_slave(s) container_of(s, struct tiny_spi_slave, slave)
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ return bus < ARRAY_SIZE(tiny_spi_host_list) && gpio_is_valid(cs);
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
+ unsigned int cs = slave->cs;
+
+ gpio_set_value(cs, tiny_spi->flg);
+ debug("%s: SPI_CS_GPIO:%x\n", __func__, gpio_get_value(cs));
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
+ unsigned int cs = slave->cs;
+
+ gpio_set_value(cs, !tiny_spi->flg);
+ debug("%s: SPI_CS_GPIO:%x\n", __func__, gpio_get_value(cs));
+}
+
+void spi_set_speed(struct spi_slave *slave, uint hz)
+{
+ struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
+ const struct tiny_spi_host *host = tiny_spi->host;
+
+ tiny_spi->baud = min(DIV_ROUND_UP(host->freq, hz * 2),
+ (1 << host->baudwidth)) - 1;
+ debug("%s: speed %u actual %u\n", __func__, hz,
+ host->freq / ((tiny_spi->baud + 1) * 2));
+}
+
+void spi_init(void)
+{
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int hz, unsigned int mode)
+{
+ struct tiny_spi_slave *tiny_spi;
+
+ if (!spi_cs_is_valid(bus, cs) || gpio_request(cs, "tiny_spi"))
+ return NULL;
+
+ tiny_spi = spi_alloc_slave(struct tiny_spi_slave, bus, cs);
+ if (!tiny_spi)
+ return NULL;
+
+ tiny_spi->host = &tiny_spi_host_list[bus];
+ tiny_spi->mode = mode & (SPI_CPOL | SPI_CPHA);
+ tiny_spi->flg = mode & SPI_CS_HIGH ? 1 : 0;
+ spi_set_speed(&tiny_spi->slave, hz);
+
+ debug("%s: bus:%i cs:%i base:%lx\n", __func__,
+ bus, cs, tiny_spi->host->base);
+ return &tiny_spi->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
+
+ gpio_free(slave->cs);
+ free(tiny_spi);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
+ struct tiny_spi_regs *regs = (void *)tiny_spi->host->base;
+
+ debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
+ gpio_direction_output(slave->cs, !tiny_spi->flg);
+ writel(tiny_spi->mode, &regs->control);
+ writel(tiny_spi->baud, &regs->baud);
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
+}
+
+#ifndef CONFIG_TINY_SPI_IDLE_VAL
+# define CONFIG_TINY_SPI_IDLE_VAL 0xff
+#endif
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
+ struct tiny_spi_regs *regs = (void *)tiny_spi->host->base;
+ const u8 *txp = dout;
+ u8 *rxp = din;
+ uint bytes = bitlen / 8;
+ uint i;
+
+ debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
+ slave->bus, slave->cs, bitlen, bytes, flags);
+ if (bitlen == 0)
+ goto done;
+
+ /* assume to do 8 bits transfers */
+ if (bitlen % 8) {
+ flags |= SPI_XFER_END;
+ goto done;
+ }
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ /* we need to tighten the transfer loop */
+ if (txp && rxp) {
+ writeb(*txp++, &regs->txdata);
+ if (bytes > 1) {
+ writeb(*txp++, &regs->txdata);
+ for (i = 2; i < bytes; i++) {
+ u8 rx, tx = *txp++;
+ while (!(readb(&regs->status) &
+ TINY_SPI_STATUS_TXR))
+ ;
+ rx = readb(&regs->txdata);
+ writeb(tx, &regs->txdata);
+ *rxp++ = rx;
+ }
+ while (!(readb(&regs->status) &
+ TINY_SPI_STATUS_TXR))
+ ;
+ *rxp++ = readb(&regs->txdata);
+ }
+ while (!(readb(&regs->status) &
+ TINY_SPI_STATUS_TXE))
+ ;
+ *rxp++ = readb(&regs->rxdata);
+ } else if (rxp) {
+ writeb(CONFIG_TINY_SPI_IDLE_VAL, &regs->txdata);
+ if (bytes > 1) {
+ writeb(CONFIG_TINY_SPI_IDLE_VAL,
+ &regs->txdata);
+ for (i = 2; i < bytes; i++) {
+ u8 rx;
+ while (!(readb(&regs->status) &
+ TINY_SPI_STATUS_TXR))
+ ;
+ rx = readb(&regs->txdata);
+ writeb(CONFIG_TINY_SPI_IDLE_VAL,
+ &regs->txdata);
+ *rxp++ = rx;
+ }
+ while (!(readb(&regs->status) &
+ TINY_SPI_STATUS_TXR))
+ ;
+ *rxp++ = readb(&regs->txdata);
+ }
+ while (!(readb(&regs->status) &
+ TINY_SPI_STATUS_TXE))
+ ;
+ *rxp++ = readb(&regs->rxdata);
+ } else if (txp) {
+ writeb(*txp++, &regs->txdata);
+ if (bytes > 1) {
+ writeb(*txp++, &regs->txdata);
+ for (i = 2; i < bytes; i++) {
+ u8 tx = *txp++;
+ while (!(readb(&regs->status) &
+ TINY_SPI_STATUS_TXR))
+ ;
+ writeb(tx, &regs->txdata);
+ }
+ }
+ while (!(readb(&regs->status) &
+ TINY_SPI_STATUS_TXE))
+ ;
+ } else {
+ writeb(CONFIG_TINY_SPI_IDLE_VAL, &regs->txdata);
+ if (bytes > 1) {
+ writeb(CONFIG_TINY_SPI_IDLE_VAL,
+ &regs->txdata);
+ for (i = 2; i < bytes; i++) {
+ while (!(readb(&regs->status) &
+ TINY_SPI_STATUS_TXR))
+ ;
+ writeb(CONFIG_TINY_SPI_IDLE_VAL,
+ &regs->txdata);
+ }
+ }
+ while (!(readb(&regs->status) &
+ TINY_SPI_STATUS_TXE))
+ ;
+ }
+
+ done:
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/omap3_spi.c b/qemu/roms/u-boot/drivers/spi/omap3_spi.c
new file mode 100644
index 000000000..651e46e4b
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/omap3_spi.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright (C) 2010 Dirk Behme <dirk.behme@googlemail.com>
+ *
+ * Driver for McSPI controller on OMAP3. Based on davinci_spi.c
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Copyright (C) 2007 Atmel Corporation
+ *
+ * Parts taken from linux/drivers/spi/omap2_mcspi.c
+ * Copyright (C) 2005, 2006 Nokia Corporation
+ *
+ * Modified by Ruslan Araslanov <ruslan.araslanov@vitecmm.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <spi.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include "omap3_spi.h"
+
+#define SPI_WAIT_TIMEOUT 3000000
+
+static void spi_reset(struct omap3_spi_slave *ds)
+{
+ unsigned int tmp;
+
+ writel(OMAP3_MCSPI_SYSCONFIG_SOFTRESET, &ds->regs->sysconfig);
+ do {
+ tmp = readl(&ds->regs->sysstatus);
+ } while (!(tmp & OMAP3_MCSPI_SYSSTATUS_RESETDONE));
+
+ writel(OMAP3_MCSPI_SYSCONFIG_AUTOIDLE |
+ OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP |
+ OMAP3_MCSPI_SYSCONFIG_SMARTIDLE,
+ &ds->regs->sysconfig);
+
+ writel(OMAP3_MCSPI_WAKEUPENABLE_WKEN, &ds->regs->wakeupenable);
+}
+
+static void omap3_spi_write_chconf(struct omap3_spi_slave *ds, int val)
+{
+ writel(val, &ds->regs->channel[ds->slave.cs].chconf);
+ /* Flash post writes to make immediate effect */
+ readl(&ds->regs->channel[ds->slave.cs].chconf);
+}
+
+static void omap3_spi_set_enable(struct omap3_spi_slave *ds, int enable)
+{
+ writel(enable, &ds->regs->channel[ds->slave.cs].chctrl);
+ /* Flash post writes to make immediate effect */
+ readl(&ds->regs->channel[ds->slave.cs].chctrl);
+}
+
+void spi_init()
+{
+ /* do nothing */
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct omap3_spi_slave *ds;
+ struct mcspi *regs;
+
+ /*
+ * OMAP3 McSPI (MultiChannel SPI) has 4 busses (modules)
+ * with different number of chip selects (CS, channels):
+ * McSPI1 has 4 CS (bus 0, cs 0 - 3)
+ * McSPI2 has 2 CS (bus 1, cs 0 - 1)
+ * McSPI3 has 2 CS (bus 2, cs 0 - 1)
+ * McSPI4 has 1 CS (bus 3, cs 0)
+ */
+
+ switch (bus) {
+ case 0:
+ regs = (struct mcspi *)OMAP3_MCSPI1_BASE;
+ break;
+#ifdef OMAP3_MCSPI2_BASE
+ case 1:
+ regs = (struct mcspi *)OMAP3_MCSPI2_BASE;
+ break;
+#endif
+#ifdef OMAP3_MCSPI3_BASE
+ case 2:
+ regs = (struct mcspi *)OMAP3_MCSPI3_BASE;
+ break;
+#endif
+#ifdef OMAP3_MCSPI4_BASE
+ case 3:
+ regs = (struct mcspi *)OMAP3_MCSPI4_BASE;
+ break;
+#endif
+ default:
+ printf("SPI error: unsupported bus %i. \
+ Supported busses 0 - 3\n", bus);
+ return NULL;
+ }
+
+ if (((bus == 0) && (cs > 3)) ||
+ ((bus == 1) && (cs > 1)) ||
+ ((bus == 2) && (cs > 1)) ||
+ ((bus == 3) && (cs > 0))) {
+ printf("SPI error: unsupported chip select %i \
+ on bus %i\n", cs, bus);
+ return NULL;
+ }
+
+ if (max_hz > OMAP3_MCSPI_MAX_FREQ) {
+ printf("SPI error: unsupported frequency %i Hz. \
+ Max frequency is 48 Mhz\n", max_hz);
+ return NULL;
+ }
+
+ if (mode > SPI_MODE_3) {
+ printf("SPI error: unsupported SPI mode %i\n", mode);
+ return NULL;
+ }
+
+ ds = spi_alloc_slave(struct omap3_spi_slave, bus, cs);
+ if (!ds) {
+ printf("SPI error: malloc of SPI structure failed\n");
+ return NULL;
+ }
+
+ ds->regs = regs;
+ ds->freq = max_hz;
+ ds->mode = mode;
+
+ return &ds->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct omap3_spi_slave *ds = to_omap3_spi(slave);
+
+ free(ds);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct omap3_spi_slave *ds = to_omap3_spi(slave);
+ unsigned int conf, div = 0;
+
+ /* McSPI global module configuration */
+
+ /*
+ * setup when switching from (reset default) slave mode
+ * to single-channel master mode
+ */
+ spi_reset(ds);
+ conf = readl(&ds->regs->modulctrl);
+ conf &= ~(OMAP3_MCSPI_MODULCTRL_STEST | OMAP3_MCSPI_MODULCTRL_MS);
+ conf |= OMAP3_MCSPI_MODULCTRL_SINGLE;
+ writel(conf, &ds->regs->modulctrl);
+
+ /* McSPI individual channel configuration */
+
+ /* Calculate clock divisor. Valid range: 0x0 - 0xC ( /1 - /4096 ) */
+ if (ds->freq) {
+ while (div <= 0xC && (OMAP3_MCSPI_MAX_FREQ / (1 << div))
+ > ds->freq)
+ div++;
+ } else
+ div = 0xC;
+
+ conf = readl(&ds->regs->channel[ds->slave.cs].chconf);
+
+ /* standard 4-wire master mode: SCK, MOSI/out, MISO/in, nCS
+ * REVISIT: this controller could support SPI_3WIRE mode.
+ */
+#ifdef CONFIG_OMAP3_SPI_D0_D1_SWAPPED
+ /*
+ * Some boards have D0 wired as MOSI / D1 as MISO instead of
+ * The normal D0 as MISO / D1 as MOSI.
+ */
+ conf &= ~OMAP3_MCSPI_CHCONF_DPE0;
+ conf |= OMAP3_MCSPI_CHCONF_IS|OMAP3_MCSPI_CHCONF_DPE1;
+#else
+ conf &= ~(OMAP3_MCSPI_CHCONF_IS|OMAP3_MCSPI_CHCONF_DPE1);
+ conf |= OMAP3_MCSPI_CHCONF_DPE0;
+#endif
+
+ /* wordlength */
+ conf &= ~OMAP3_MCSPI_CHCONF_WL_MASK;
+ conf |= (ds->slave.wordlen - 1) << 7;
+
+ /* set chipselect polarity; manage with FORCE */
+ if (!(ds->mode & SPI_CS_HIGH))
+ conf |= OMAP3_MCSPI_CHCONF_EPOL; /* active-low; normal */
+ else
+ conf &= ~OMAP3_MCSPI_CHCONF_EPOL;
+
+ /* set clock divisor */
+ conf &= ~OMAP3_MCSPI_CHCONF_CLKD_MASK;
+ conf |= div << 2;
+
+ /* set SPI mode 0..3 */
+ if (ds->mode & SPI_CPOL)
+ conf |= OMAP3_MCSPI_CHCONF_POL;
+ else
+ conf &= ~OMAP3_MCSPI_CHCONF_POL;
+ if (ds->mode & SPI_CPHA)
+ conf |= OMAP3_MCSPI_CHCONF_PHA;
+ else
+ conf &= ~OMAP3_MCSPI_CHCONF_PHA;
+
+ /* Transmit & receive mode */
+ conf &= ~OMAP3_MCSPI_CHCONF_TRM_MASK;
+
+ omap3_spi_write_chconf(ds,conf);
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ struct omap3_spi_slave *ds = to_omap3_spi(slave);
+
+ /* Reset the SPI hardware */
+ spi_reset(ds);
+}
+
+int omap3_spi_write(struct spi_slave *slave, unsigned int len, const void *txp,
+ unsigned long flags)
+{
+ struct omap3_spi_slave *ds = to_omap3_spi(slave);
+ int i;
+ int timeout = SPI_WAIT_TIMEOUT;
+ int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
+
+ /* Enable the channel */
+ omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
+
+ chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
+ chconf |= (ds->slave.wordlen - 1) << 7;
+ chconf |= OMAP3_MCSPI_CHCONF_TRM_TX_ONLY;
+ chconf |= OMAP3_MCSPI_CHCONF_FORCE;
+ omap3_spi_write_chconf(ds,chconf);
+
+ for (i = 0; i < len; i++) {
+ /* wait till TX register is empty (TXS == 1) */
+ while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
+ OMAP3_MCSPI_CHSTAT_TXS)) {
+ if (--timeout <= 0) {
+ printf("SPI TXS timed out, status=0x%08x\n",
+ readl(&ds->regs->channel[ds->slave.cs].chstat));
+ return -1;
+ }
+ }
+ /* Write the data */
+ unsigned int *tx = &ds->regs->channel[ds->slave.cs].tx;
+ if (ds->slave.wordlen > 16)
+ writel(((u32 *)txp)[i], tx);
+ else if (ds->slave.wordlen > 8)
+ writel(((u16 *)txp)[i], tx);
+ else
+ writel(((u8 *)txp)[i], tx);
+ }
+
+ /* wait to finish of transfer */
+ while ((readl(&ds->regs->channel[ds->slave.cs].chstat) &
+ (OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS)) !=
+ (OMAP3_MCSPI_CHSTAT_EOT | OMAP3_MCSPI_CHSTAT_TXS));
+
+ /* Disable the channel otherwise the next immediate RX will get affected */
+ omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
+
+ if (flags & SPI_XFER_END) {
+
+ chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
+ omap3_spi_write_chconf(ds,chconf);
+ }
+ return 0;
+}
+
+int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp,
+ unsigned long flags)
+{
+ struct omap3_spi_slave *ds = to_omap3_spi(slave);
+ int i;
+ int timeout = SPI_WAIT_TIMEOUT;
+ int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
+
+ /* Enable the channel */
+ omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
+
+ chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
+ chconf |= (ds->slave.wordlen - 1) << 7;
+ chconf |= OMAP3_MCSPI_CHCONF_TRM_RX_ONLY;
+ chconf |= OMAP3_MCSPI_CHCONF_FORCE;
+ omap3_spi_write_chconf(ds,chconf);
+
+ writel(0, &ds->regs->channel[ds->slave.cs].tx);
+
+ for (i = 0; i < len; i++) {
+ /* Wait till RX register contains data (RXS == 1) */
+ while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
+ OMAP3_MCSPI_CHSTAT_RXS)) {
+ if (--timeout <= 0) {
+ printf("SPI RXS timed out, status=0x%08x\n",
+ readl(&ds->regs->channel[ds->slave.cs].chstat));
+ return -1;
+ }
+ }
+
+ /* Disable the channel to prevent furher receiving */
+ if(i == (len - 1))
+ omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
+
+ /* Read the data */
+ unsigned int *rx = &ds->regs->channel[ds->slave.cs].rx;
+ if (ds->slave.wordlen > 16)
+ ((u32 *)rxp)[i] = readl(rx);
+ else if (ds->slave.wordlen > 8)
+ ((u16 *)rxp)[i] = (u16)readl(rx);
+ else
+ ((u8 *)rxp)[i] = (u8)readl(rx);
+ }
+
+ if (flags & SPI_XFER_END) {
+ chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
+ omap3_spi_write_chconf(ds,chconf);
+ }
+
+ return 0;
+}
+
+/*McSPI Transmit Receive Mode*/
+int omap3_spi_txrx(struct spi_slave *slave, unsigned int len,
+ const void *txp, void *rxp, unsigned long flags)
+{
+ struct omap3_spi_slave *ds = to_omap3_spi(slave);
+ int timeout = SPI_WAIT_TIMEOUT;
+ int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
+ int irqstatus = readl(&ds->regs->irqstatus);
+ int i=0;
+
+ /*Enable SPI channel*/
+ omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
+
+ /*set TRANSMIT-RECEIVE Mode*/
+ chconf &= ~(OMAP3_MCSPI_CHCONF_TRM_MASK | OMAP3_MCSPI_CHCONF_WL_MASK);
+ chconf |= (ds->slave.wordlen - 1) << 7;
+ chconf |= OMAP3_MCSPI_CHCONF_FORCE;
+ omap3_spi_write_chconf(ds,chconf);
+
+ /*Shift in and out 1 byte at time*/
+ for (i=0; i < len; i++){
+ /* Write: wait for TX empty (TXS == 1)*/
+ irqstatus |= (1<< (4*(ds->slave.bus)));
+ while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
+ OMAP3_MCSPI_CHSTAT_TXS)) {
+ if (--timeout <= 0) {
+ printf("SPI TXS timed out, status=0x%08x\n",
+ readl(&ds->regs->channel[ds->slave.cs].chstat));
+ return -1;
+ }
+ }
+ /* Write the data */
+ unsigned int *tx = &ds->regs->channel[ds->slave.cs].tx;
+ if (ds->slave.wordlen > 16)
+ writel(((u32 *)txp)[i], tx);
+ else if (ds->slave.wordlen > 8)
+ writel(((u16 *)txp)[i], tx);
+ else
+ writel(((u8 *)txp)[i], tx);
+
+ /*Read: wait for RX containing data (RXS == 1)*/
+ while (!(readl(&ds->regs->channel[ds->slave.cs].chstat) &
+ OMAP3_MCSPI_CHSTAT_RXS)) {
+ if (--timeout <= 0) {
+ printf("SPI RXS timed out, status=0x%08x\n",
+ readl(&ds->regs->channel[ds->slave.cs].chstat));
+ return -1;
+ }
+ }
+ /* Read the data */
+ unsigned int *rx = &ds->regs->channel[ds->slave.cs].rx;
+ if (ds->slave.wordlen > 16)
+ ((u32 *)rxp)[i] = readl(rx);
+ else if (ds->slave.wordlen > 8)
+ ((u16 *)rxp)[i] = (u16)readl(rx);
+ else
+ ((u8 *)rxp)[i] = (u8)readl(rx);
+ }
+ /* Disable the channel */
+ omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
+
+ /*if transfer must be terminated disable the channel*/
+ if (flags & SPI_XFER_END) {
+ chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
+ omap3_spi_write_chconf(ds,chconf);
+ }
+
+ return 0;
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
+{
+ struct omap3_spi_slave *ds = to_omap3_spi(slave);
+ unsigned int len;
+ int ret = -1;
+
+ if (ds->slave.wordlen < 4 || ds->slave.wordlen > 32) {
+ printf("omap3_spi: invalid wordlen %d\n", ds->slave.wordlen);
+ return -1;
+ }
+
+ if (bitlen % ds->slave.wordlen)
+ return -1;
+
+ len = bitlen / ds->slave.wordlen;
+
+ if (bitlen == 0) { /* only change CS */
+ int chconf = readl(&ds->regs->channel[ds->slave.cs].chconf);
+
+ if (flags & SPI_XFER_BEGIN) {
+ omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_EN);
+ chconf |= OMAP3_MCSPI_CHCONF_FORCE;
+ omap3_spi_write_chconf(ds,chconf);
+ }
+ if (flags & SPI_XFER_END) {
+ chconf &= ~OMAP3_MCSPI_CHCONF_FORCE;
+ omap3_spi_write_chconf(ds,chconf);
+ omap3_spi_set_enable(ds,OMAP3_MCSPI_CHCTRL_DIS);
+ }
+ ret = 0;
+ } else {
+ if (dout != NULL && din != NULL)
+ ret = omap3_spi_txrx(slave, len, dout, din, flags);
+ else if (dout != NULL)
+ ret = omap3_spi_write(slave, len, dout, flags);
+ else if (din != NULL)
+ ret = omap3_spi_read(slave, len, din, flags);
+ }
+ return ret;
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ return 1;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+}
diff --git a/qemu/roms/u-boot/drivers/spi/omap3_spi.h b/qemu/roms/u-boot/drivers/spi/omap3_spi.h
new file mode 100644
index 000000000..ab7cd8444
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/omap3_spi.h
@@ -0,0 +1,109 @@
+/*
+ * Register definitions for the OMAP3 McSPI Controller
+ *
+ * Copyright (C) 2010 Dirk Behme <dirk.behme@googlemail.com>
+ *
+ * Parts taken from linux/drivers/spi/omap2_mcspi.c
+ * Copyright (C) 2005, 2006 Nokia Corporation
+ *
+ * Modified by Ruslan Araslanov <ruslan.araslanov@vitecmm.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _OMAP3_SPI_H_
+#define _OMAP3_SPI_H_
+
+#ifdef CONFIG_AM33XX
+#define OMAP3_MCSPI1_BASE 0x48030100
+#define OMAP3_MCSPI2_BASE 0x481A0100
+#else
+#define OMAP3_MCSPI1_BASE 0x48098000
+#define OMAP3_MCSPI2_BASE 0x4809A000
+#define OMAP3_MCSPI3_BASE 0x480B8000
+#define OMAP3_MCSPI4_BASE 0x480BA000
+#endif
+
+#define OMAP3_MCSPI_MAX_FREQ 48000000
+
+/* OMAP3 McSPI registers */
+struct mcspi_channel {
+ unsigned int chconf; /* 0x2C, 0x40, 0x54, 0x68 */
+ unsigned int chstat; /* 0x30, 0x44, 0x58, 0x6C */
+ unsigned int chctrl; /* 0x34, 0x48, 0x5C, 0x70 */
+ unsigned int tx; /* 0x38, 0x4C, 0x60, 0x74 */
+ unsigned int rx; /* 0x3C, 0x50, 0x64, 0x78 */
+};
+
+struct mcspi {
+ unsigned char res1[0x10];
+ unsigned int sysconfig; /* 0x10 */
+ unsigned int sysstatus; /* 0x14 */
+ unsigned int irqstatus; /* 0x18 */
+ unsigned int irqenable; /* 0x1C */
+ unsigned int wakeupenable; /* 0x20 */
+ unsigned int syst; /* 0x24 */
+ unsigned int modulctrl; /* 0x28 */
+ struct mcspi_channel channel[4]; /* channel0: 0x2C - 0x3C, bus 0 & 1 & 2 & 3 */
+ /* channel1: 0x40 - 0x50, bus 0 & 1 */
+ /* channel2: 0x54 - 0x64, bus 0 & 1 */
+ /* channel3: 0x68 - 0x78, bus 0 */
+};
+
+/* per-register bitmasks */
+#define OMAP3_MCSPI_SYSCONFIG_SMARTIDLE (2 << 3)
+#define OMAP3_MCSPI_SYSCONFIG_ENAWAKEUP (1 << 2)
+#define OMAP3_MCSPI_SYSCONFIG_AUTOIDLE (1 << 0)
+#define OMAP3_MCSPI_SYSCONFIG_SOFTRESET (1 << 1)
+
+#define OMAP3_MCSPI_SYSSTATUS_RESETDONE (1 << 0)
+
+#define OMAP3_MCSPI_MODULCTRL_SINGLE (1 << 0)
+#define OMAP3_MCSPI_MODULCTRL_MS (1 << 2)
+#define OMAP3_MCSPI_MODULCTRL_STEST (1 << 3)
+
+#define OMAP3_MCSPI_CHCONF_PHA (1 << 0)
+#define OMAP3_MCSPI_CHCONF_POL (1 << 1)
+#define OMAP3_MCSPI_CHCONF_CLKD_MASK (0x0f << 2)
+#define OMAP3_MCSPI_CHCONF_EPOL (1 << 6)
+#define OMAP3_MCSPI_CHCONF_WL_MASK (0x1f << 7)
+#define OMAP3_MCSPI_CHCONF_TRM_RX_ONLY (0x01 << 12)
+#define OMAP3_MCSPI_CHCONF_TRM_TX_ONLY (0x02 << 12)
+#define OMAP3_MCSPI_CHCONF_TRM_MASK (0x03 << 12)
+#define OMAP3_MCSPI_CHCONF_DMAW (1 << 14)
+#define OMAP3_MCSPI_CHCONF_DMAR (1 << 15)
+#define OMAP3_MCSPI_CHCONF_DPE0 (1 << 16)
+#define OMAP3_MCSPI_CHCONF_DPE1 (1 << 17)
+#define OMAP3_MCSPI_CHCONF_IS (1 << 18)
+#define OMAP3_MCSPI_CHCONF_TURBO (1 << 19)
+#define OMAP3_MCSPI_CHCONF_FORCE (1 << 20)
+
+#define OMAP3_MCSPI_CHSTAT_RXS (1 << 0)
+#define OMAP3_MCSPI_CHSTAT_TXS (1 << 1)
+#define OMAP3_MCSPI_CHSTAT_EOT (1 << 2)
+
+#define OMAP3_MCSPI_CHCTRL_EN (1 << 0)
+#define OMAP3_MCSPI_CHCTRL_DIS (0 << 0)
+
+#define OMAP3_MCSPI_WAKEUPENABLE_WKEN (1 << 0)
+
+struct omap3_spi_slave {
+ struct spi_slave slave;
+ struct mcspi *regs;
+ unsigned int freq;
+ unsigned int mode;
+};
+
+static inline struct omap3_spi_slave *to_omap3_spi(struct spi_slave *slave)
+{
+ return container_of(slave, struct omap3_spi_slave, slave);
+}
+
+int omap3_spi_txrx(struct spi_slave *slave, unsigned int len, const void *txp,
+ void *rxp, unsigned long flags);
+int omap3_spi_write(struct spi_slave *slave, unsigned int len, const void *txp,
+ unsigned long flags);
+int omap3_spi_read(struct spi_slave *slave, unsigned int len, void *rxp,
+ unsigned long flags);
+
+#endif /* _OMAP3_SPI_H_ */
diff --git a/qemu/roms/u-boot/drivers/spi/sandbox_spi.c b/qemu/roms/u-boot/drivers/spi/sandbox_spi.c
new file mode 100644
index 000000000..12e9bdad3
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/sandbox_spi.c
@@ -0,0 +1,217 @@
+/*
+ * Simulate a SPI port
+ *
+ * Copyright (c) 2011-2013 The Chromium OS Authors.
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <os.h>
+
+#include <asm/errno.h>
+#include <asm/spi.h>
+#include <asm/state.h>
+
+#ifndef CONFIG_SPI_IDLE_VAL
+# define CONFIG_SPI_IDLE_VAL 0xFF
+#endif
+
+struct sandbox_spi_slave {
+ struct spi_slave slave;
+ const struct sandbox_spi_emu_ops *ops;
+ void *priv;
+};
+
+#define to_sandbox_spi_slave(s) container_of(s, struct sandbox_spi_slave, slave)
+
+const char *sandbox_spi_parse_spec(const char *arg, unsigned long *bus,
+ unsigned long *cs)
+{
+ char *endp;
+
+ *bus = simple_strtoul(arg, &endp, 0);
+ if (*endp != ':' || *bus >= CONFIG_SANDBOX_SPI_MAX_BUS)
+ return NULL;
+
+ *cs = simple_strtoul(endp + 1, &endp, 0);
+ if (*endp != ':' || *cs >= CONFIG_SANDBOX_SPI_MAX_CS)
+ return NULL;
+
+ return endp + 1;
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ return bus < CONFIG_SANDBOX_SPI_MAX_BUS &&
+ cs < CONFIG_SANDBOX_SPI_MAX_CS;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave);
+
+ debug("sandbox_spi: activating CS\n");
+ if (sss->ops->cs_activate)
+ sss->ops->cs_activate(sss->priv);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave);
+
+ debug("sandbox_spi: deactivating CS\n");
+ if (sss->ops->cs_deactivate)
+ sss->ops->cs_deactivate(sss->priv);
+}
+
+void spi_init(void)
+{
+}
+
+void spi_set_speed(struct spi_slave *slave, uint hz)
+{
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct sandbox_spi_slave *sss;
+ struct sandbox_state *state = state_get_current();
+ const char *spec;
+
+ if (!spi_cs_is_valid(bus, cs)) {
+ debug("sandbox_spi: Invalid SPI bus/cs\n");
+ return NULL;
+ }
+
+ sss = spi_alloc_slave(struct sandbox_spi_slave, bus, cs);
+ if (!sss) {
+ debug("sandbox_spi: Out of memory\n");
+ return NULL;
+ }
+
+ spec = state->spi[bus][cs].spec;
+ sss->ops = state->spi[bus][cs].ops;
+ if (!spec || !sss->ops || sss->ops->setup(&sss->priv, spec)) {
+ free(sss);
+ printf("sandbox_spi: unable to locate a slave client\n");
+ return NULL;
+ }
+
+ return &sss->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave);
+
+ debug("sandbox_spi: releasing slave\n");
+
+ if (sss->ops->free)
+ sss->ops->free(sss->priv);
+
+ free(sss);
+}
+
+static int spi_bus_claim_cnt[CONFIG_SANDBOX_SPI_MAX_BUS];
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ if (spi_bus_claim_cnt[slave->bus]++) {
+ printf("sandbox_spi: error: bus already claimed: %d!\n",
+ spi_bus_claim_cnt[slave->bus]);
+ }
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ if (--spi_bus_claim_cnt[slave->bus]) {
+ printf("sandbox_spi: error: bus freed too often: %d!\n",
+ spi_bus_claim_cnt[slave->bus]);
+ }
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct sandbox_spi_slave *sss = to_sandbox_spi_slave(slave);
+ uint bytes = bitlen / 8, i;
+ int ret = 0;
+ u8 *tx = (void *)dout, *rx = din;
+
+ if (bitlen == 0)
+ goto done;
+
+ /* we can only do 8 bit transfers */
+ if (bitlen % 8) {
+ printf("sandbox_spi: xfer: invalid bitlen size %u; needs to be 8bit\n",
+ bitlen);
+ flags |= SPI_XFER_END;
+ goto done;
+ }
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ /* make sure rx/tx buffers are full so clients can assume */
+ if (!tx) {
+ debug("sandbox_spi: xfer: auto-allocating tx scratch buffer\n");
+ tx = malloc(bytes);
+ if (!tx) {
+ debug("sandbox_spi: Out of memory\n");
+ return -ENOMEM;
+ }
+ }
+ if (!rx) {
+ debug("sandbox_spi: xfer: auto-allocating rx scratch buffer\n");
+ rx = malloc(bytes);
+ if (!rx) {
+ debug("sandbox_spi: Out of memory\n");
+ return -ENOMEM;
+ }
+ }
+
+ debug("sandbox_spi: xfer: bytes = %u\n tx:", bytes);
+ for (i = 0; i < bytes; ++i)
+ debug(" %u:%02x", i, tx[i]);
+ debug("\n");
+
+ ret = sss->ops->xfer(sss->priv, tx, rx, bytes);
+
+ debug("sandbox_spi: xfer: got back %i (that's %s)\n rx:",
+ ret, ret ? "bad" : "good");
+ for (i = 0; i < bytes; ++i)
+ debug(" %u:%02x", i, rx[i]);
+ debug("\n");
+
+ if (tx != dout)
+ free(tx);
+ if (rx != din)
+ free(rx);
+
+ done:
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ return ret;
+}
+
+/**
+ * Set up a new SPI slave for an fdt node
+ *
+ * @param blob Device tree blob
+ * @param node SPI peripheral node to use
+ * @return 0 if ok, -1 on error
+ */
+struct spi_slave *spi_setup_slave_fdt(const void *blob, int slave_node,
+ int spi_node)
+{
+ return NULL;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/sh_qspi.c b/qemu/roms/u-boot/drivers/spi/sh_qspi.c
new file mode 100644
index 000000000..77ede6bba
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/sh_qspi.c
@@ -0,0 +1,278 @@
+/*
+ * SH QSPI (Quad SPI) driver
+ *
+ * Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/arch/rmobile.h>
+#include <asm/io.h>
+
+/* SH QSPI register bit masks <REG>_<BIT> */
+#define SPCR_MSTR 0x08
+#define SPCR_SPE 0x40
+#define SPSR_SPRFF 0x80
+#define SPSR_SPTEF 0x20
+#define SPPCR_IO3FV 0x04
+#define SPPCR_IO2FV 0x02
+#define SPPCR_IO1FV 0x01
+#define SPBDCR_RXBC0 (1 << 0)
+#define SPCMD_SCKDEN (1 << 15)
+#define SPCMD_SLNDEN (1 << 14)
+#define SPCMD_SPNDEN (1 << 13)
+#define SPCMD_SSLKP (1 << 7)
+#define SPCMD_BRDV0 (1 << 2)
+#define SPCMD_INIT1 SPCMD_SCKDEN | SPCMD_SLNDEN | \
+ SPCMD_SPNDEN | SPCMD_SSLKP | \
+ SPCMD_BRDV0
+#define SPCMD_INIT2 SPCMD_SPNDEN | SPCMD_SSLKP | \
+ SPCMD_BRDV0
+#define SPBFCR_TXRST (1 << 7)
+#define SPBFCR_RXRST (1 << 6)
+
+/* SH QSPI register set */
+struct sh_qspi_regs {
+ unsigned char spcr;
+ unsigned char sslp;
+ unsigned char sppcr;
+ unsigned char spsr;
+ unsigned long spdr;
+ unsigned char spscr;
+ unsigned char spssr;
+ unsigned char spbr;
+ unsigned char spdcr;
+ unsigned char spckd;
+ unsigned char sslnd;
+ unsigned char spnd;
+ unsigned char dummy0;
+ unsigned short spcmd0;
+ unsigned short spcmd1;
+ unsigned short spcmd2;
+ unsigned short spcmd3;
+ unsigned char spbfcr;
+ unsigned char dummy1;
+ unsigned short spbdcr;
+ unsigned long spbmul0;
+ unsigned long spbmul1;
+ unsigned long spbmul2;
+ unsigned long spbmul3;
+};
+
+struct sh_qspi_slave {
+ struct spi_slave slave;
+ struct sh_qspi_regs *regs;
+};
+
+static inline struct sh_qspi_slave *to_sh_qspi(struct spi_slave *slave)
+{
+ return container_of(slave, struct sh_qspi_slave, slave);
+}
+
+static void sh_qspi_init(struct sh_qspi_slave *ss)
+{
+ /* QSPI initialize */
+ /* Set master mode only */
+ writeb(SPCR_MSTR, &ss->regs->spcr);
+
+ /* Set SSL signal level */
+ writeb(0x00, &ss->regs->sslp);
+
+ /* Set MOSI signal value when transfer is in idle state */
+ writeb(SPPCR_IO3FV|SPPCR_IO2FV, &ss->regs->sppcr);
+
+ /* Set bit rate. See 58.3.8 Quad Serial Peripheral Interface */
+ writeb(0x01, &ss->regs->spbr);
+
+ /* Disable Dummy Data Transmission */
+ writeb(0x00, &ss->regs->spdcr);
+
+ /* Set clock delay value */
+ writeb(0x00, &ss->regs->spckd);
+
+ /* Set SSL negation delay value */
+ writeb(0x00, &ss->regs->sslnd);
+
+ /* Set next-access delay value */
+ writeb(0x00, &ss->regs->spnd);
+
+ /* Set equence command */
+ writew(SPCMD_INIT2, &ss->regs->spcmd0);
+
+ /* Reset transfer and receive Buffer */
+ setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
+
+ /* Clear transfer and receive Buffer control bit */
+ clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
+
+ /* Set equence control method. Use equence0 only */
+ writeb(0x00, &ss->regs->spscr);
+
+ /* Enable SPI function */
+ setbits_8(&ss->regs->spcr, SPCR_SPE);
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ return 1;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ struct sh_qspi_slave *ss = to_sh_qspi(slave);
+
+ /* Set master mode only */
+ writeb(SPCR_MSTR, &ss->regs->spcr);
+
+ /* Set command */
+ writew(SPCMD_INIT1, &ss->regs->spcmd0);
+
+ /* Reset transfer and receive Buffer */
+ setbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
+
+ /* Clear transfer and receive Buffer control bit */
+ clrbits_8(&ss->regs->spbfcr, SPBFCR_TXRST|SPBFCR_RXRST);
+
+ /* Set equence control method. Use equence0 only */
+ writeb(0x00, &ss->regs->spscr);
+
+ /* Enable SPI function */
+ setbits_8(&ss->regs->spcr, SPCR_SPE);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct sh_qspi_slave *ss = to_sh_qspi(slave);
+
+ /* Disable SPI Function */
+ clrbits_8(&ss->regs->spcr, SPCR_SPE);
+}
+
+void spi_init(void)
+{
+ /* nothing to do */
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct sh_qspi_slave *ss;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ ss = spi_alloc_slave(struct sh_qspi_slave, bus, cs);
+ if (!ss) {
+ printf("SPI_error: Fail to allocate sh_qspi_slave\n");
+ return NULL;
+ }
+
+ ss->regs = (struct sh_qspi_regs *)SH_QSPI_BASE;
+
+ /* Init SH QSPI */
+ sh_qspi_init(ss);
+
+ return &ss->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct sh_qspi_slave *spi = to_sh_qspi(slave);
+
+ free(spi);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct sh_qspi_slave *ss = to_sh_qspi(slave);
+ unsigned long nbyte;
+ int ret = 0;
+ unsigned char dtdata = 0, drdata;
+ unsigned char *tdata = &dtdata, *rdata = &drdata;
+ unsigned long *spbmul0 = &ss->regs->spbmul0;
+
+ if (dout == NULL && din == NULL) {
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+ return 0;
+ }
+
+ if (bitlen % 8) {
+ printf("%s: bitlen is not 8bit alined %d", __func__, bitlen);
+ return 1;
+ }
+
+ nbyte = bitlen / 8;
+
+ if (flags & SPI_XFER_BEGIN) {
+ spi_cs_activate(slave);
+
+ /* Set 1048576 byte */
+ writel(0x100000, spbmul0);
+ }
+
+ if (flags & SPI_XFER_END)
+ writel(nbyte, spbmul0);
+
+ if (dout != NULL)
+ tdata = (unsigned char *)dout;
+
+ if (din != NULL)
+ rdata = din;
+
+ while (nbyte > 0) {
+ while (!(readb(&ss->regs->spsr) & SPSR_SPTEF)) {
+ if (ctrlc()) {
+ puts("abort\n");
+ return 1;
+ }
+ udelay(10);
+ }
+
+ writeb(*tdata, (unsigned char *)(&ss->regs->spdr));
+
+ while ((readw(&ss->regs->spbdcr) != SPBDCR_RXBC0)) {
+ if (ctrlc()) {
+ puts("abort\n");
+ return 1;
+ }
+ udelay(1);
+ }
+
+ while (!(readb(&ss->regs->spsr) & SPSR_SPRFF)) {
+ if (ctrlc()) {
+ puts("abort\n");
+ return 1;
+ }
+ udelay(10);
+ }
+
+ *rdata = readb((unsigned char *)(&ss->regs->spdr));
+
+ if (dout != NULL)
+ tdata++;
+ if (din != NULL)
+ rdata++;
+
+ nbyte--;
+ }
+
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ return ret;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/sh_spi.c b/qemu/roms/u-boot/drivers/spi/sh_spi.c
new file mode 100644
index 000000000..7ca5e363d
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/sh_spi.c
@@ -0,0 +1,265 @@
+/*
+ * SH SPI driver
+ *
+ * Copyright (C) 2011-2012 Renesas Solutions Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+#include "sh_spi.h"
+
+static void sh_spi_write(unsigned long data, unsigned long *reg)
+{
+ writel(data, reg);
+}
+
+static unsigned long sh_spi_read(unsigned long *reg)
+{
+ return readl(reg);
+}
+
+static void sh_spi_set_bit(unsigned long val, unsigned long *reg)
+{
+ unsigned long tmp;
+
+ tmp = sh_spi_read(reg);
+ tmp |= val;
+ sh_spi_write(tmp, reg);
+}
+
+static void sh_spi_clear_bit(unsigned long val, unsigned long *reg)
+{
+ unsigned long tmp;
+
+ tmp = sh_spi_read(reg);
+ tmp &= ~val;
+ sh_spi_write(tmp, reg);
+}
+
+static void clear_fifo(struct sh_spi *ss)
+{
+ sh_spi_set_bit(SH_SPI_RSTF, &ss->regs->cr2);
+ sh_spi_clear_bit(SH_SPI_RSTF, &ss->regs->cr2);
+}
+
+static int recvbuf_wait(struct sh_spi *ss)
+{
+ while (sh_spi_read(&ss->regs->cr1) & SH_SPI_RBE) {
+ if (ctrlc())
+ return 1;
+ udelay(10);
+ }
+ return 0;
+}
+
+static int write_fifo_empty_wait(struct sh_spi *ss)
+{
+ while (!(sh_spi_read(&ss->regs->cr1) & SH_SPI_TBE)) {
+ if (ctrlc())
+ return 1;
+ udelay(10);
+ }
+ return 0;
+}
+
+void spi_init(void)
+{
+}
+
+static void sh_spi_set_cs(struct sh_spi *ss, unsigned int cs)
+{
+ unsigned long val = 0;
+
+ if (cs & 0x01)
+ val |= SH_SPI_SSS0;
+ if (cs & 0x02)
+ val |= SH_SPI_SSS1;
+
+ sh_spi_clear_bit(SH_SPI_SSS0 | SH_SPI_SSS1, &ss->regs->cr4);
+ sh_spi_set_bit(val, &ss->regs->cr4);
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct sh_spi *ss;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ ss = spi_alloc_slave(struct sh_spi, bus, cs);
+ if (!ss)
+ return NULL;
+
+ ss->regs = (struct sh_spi_regs *)CONFIG_SH_SPI_BASE;
+
+ /* SPI sycle stop */
+ sh_spi_write(0xfe, &ss->regs->cr1);
+ /* CR1 init */
+ sh_spi_write(0x00, &ss->regs->cr1);
+ /* CR3 init */
+ sh_spi_write(0x00, &ss->regs->cr3);
+ sh_spi_set_cs(ss, cs);
+
+ clear_fifo(ss);
+
+ /* 1/8 clock */
+ sh_spi_write(sh_spi_read(&ss->regs->cr2) | 0x07, &ss->regs->cr2);
+ udelay(10);
+
+ return &ss->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct sh_spi *spi = to_sh_spi(slave);
+
+ free(spi);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ struct sh_spi *ss = to_sh_spi(slave);
+
+ sh_spi_write(sh_spi_read(&ss->regs->cr1) &
+ ~(SH_SPI_SSA | SH_SPI_SSDB | SH_SPI_SSD), &ss->regs->cr1);
+}
+
+static int sh_spi_send(struct sh_spi *ss, const unsigned char *tx_data,
+ unsigned int len, unsigned long flags)
+{
+ int i, cur_len, ret = 0;
+ int remain = (int)len;
+
+ if (len >= SH_SPI_FIFO_SIZE)
+ sh_spi_set_bit(SH_SPI_SSA, &ss->regs->cr1);
+
+ while (remain > 0) {
+ cur_len = (remain < SH_SPI_FIFO_SIZE) ?
+ remain : SH_SPI_FIFO_SIZE;
+ for (i = 0; i < cur_len &&
+ !(sh_spi_read(&ss->regs->cr4) & SH_SPI_WPABRT) &&
+ !(sh_spi_read(&ss->regs->cr1) & SH_SPI_TBF);
+ i++)
+ sh_spi_write(tx_data[i], &ss->regs->tbr_rbr);
+
+ cur_len = i;
+
+ if (sh_spi_read(&ss->regs->cr4) & SH_SPI_WPABRT) {
+ /* Abort the transaction */
+ flags |= SPI_XFER_END;
+ sh_spi_set_bit(SH_SPI_WPABRT, &ss->regs->cr4);
+ ret = 1;
+ break;
+ }
+
+ remain -= cur_len;
+ tx_data += cur_len;
+
+ if (remain > 0)
+ write_fifo_empty_wait(ss);
+ }
+
+ if (flags & SPI_XFER_END) {
+ sh_spi_clear_bit(SH_SPI_SSD | SH_SPI_SSDB, &ss->regs->cr1);
+ sh_spi_set_bit(SH_SPI_SSA, &ss->regs->cr1);
+ udelay(100);
+ write_fifo_empty_wait(ss);
+ }
+
+ return ret;
+}
+
+static int sh_spi_receive(struct sh_spi *ss, unsigned char *rx_data,
+ unsigned int len, unsigned long flags)
+{
+ int i;
+
+ if (len > SH_SPI_MAX_BYTE)
+ sh_spi_write(SH_SPI_MAX_BYTE, &ss->regs->cr3);
+ else
+ sh_spi_write(len, &ss->regs->cr3);
+
+ sh_spi_clear_bit(SH_SPI_SSD | SH_SPI_SSDB, &ss->regs->cr1);
+ sh_spi_set_bit(SH_SPI_SSA, &ss->regs->cr1);
+
+ for (i = 0; i < len; i++) {
+ if (recvbuf_wait(ss))
+ return 0;
+
+ rx_data[i] = (unsigned char)sh_spi_read(&ss->regs->tbr_rbr);
+ }
+ sh_spi_write(0, &ss->regs->cr3);
+
+ return 0;
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct sh_spi *ss = to_sh_spi(slave);
+ const unsigned char *tx_data = dout;
+ unsigned char *rx_data = din;
+ unsigned int len = bitlen / 8;
+ int ret = 0;
+
+ if (flags & SPI_XFER_BEGIN)
+ sh_spi_write(sh_spi_read(&ss->regs->cr1) & ~SH_SPI_SSA,
+ &ss->regs->cr1);
+
+ if (tx_data)
+ ret = sh_spi_send(ss, tx_data, len, flags);
+
+ if (ret == 0 && rx_data)
+ ret = sh_spi_receive(ss, rx_data, len, flags);
+
+ if (flags & SPI_XFER_END) {
+ sh_spi_set_bit(SH_SPI_SSD, &ss->regs->cr1);
+ udelay(100);
+
+ sh_spi_clear_bit(SH_SPI_SSA | SH_SPI_SSDB | SH_SPI_SSD,
+ &ss->regs->cr1);
+ clear_fifo(ss);
+ }
+
+ return ret;
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ if (!bus && cs < SH_SPI_NUM_CS)
+ return 1;
+ else
+ return 0;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+
+}
diff --git a/qemu/roms/u-boot/drivers/spi/sh_spi.h b/qemu/roms/u-boot/drivers/spi/sh_spi.h
new file mode 100644
index 000000000..96b4b6850
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/sh_spi.h
@@ -0,0 +1,80 @@
+/*
+ * SH SPI driver
+ *
+ * Copyright (C) 2011 Renesas Solutions Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef __SH_SPI_H__
+#define __SH_SPI_H__
+
+#include <spi.h>
+
+struct sh_spi_regs {
+ unsigned long tbr_rbr;
+ unsigned long resv1;
+ unsigned long cr1;
+ unsigned long resv2;
+ unsigned long cr2;
+ unsigned long resv3;
+ unsigned long cr3;
+ unsigned long resv4;
+ unsigned long cr4;
+};
+
+/* CR1 */
+#define SH_SPI_TBE 0x80
+#define SH_SPI_TBF 0x40
+#define SH_SPI_RBE 0x20
+#define SH_SPI_RBF 0x10
+#define SH_SPI_PFONRD 0x08
+#define SH_SPI_SSDB 0x04
+#define SH_SPI_SSD 0x02
+#define SH_SPI_SSA 0x01
+
+/* CR2 */
+#define SH_SPI_RSTF 0x80
+#define SH_SPI_LOOPBK 0x40
+#define SH_SPI_CPOL 0x20
+#define SH_SPI_CPHA 0x10
+#define SH_SPI_L1M0 0x08
+
+/* CR3 */
+#define SH_SPI_MAX_BYTE 0xFF
+
+/* CR4 */
+#define SH_SPI_TBEI 0x80
+#define SH_SPI_TBFI 0x40
+#define SH_SPI_RBEI 0x20
+#define SH_SPI_RBFI 0x10
+#define SH_SPI_SSS1 0x08
+#define SH_SPI_WPABRT 0x04
+#define SH_SPI_SSS0 0x01
+
+#define SH_SPI_FIFO_SIZE 32
+#define SH_SPI_NUM_CS 4
+
+struct sh_spi {
+ struct spi_slave slave;
+ struct sh_spi_regs *regs;
+};
+
+static inline struct sh_spi *to_sh_spi(struct spi_slave *slave)
+{
+ return container_of(slave, struct sh_spi, slave);
+}
+
+#endif
diff --git a/qemu/roms/u-boot/drivers/spi/soft_spi.c b/qemu/roms/u-boot/drivers/spi/soft_spi.c
new file mode 100644
index 000000000..5d2235129
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/soft_spi.c
@@ -0,0 +1,175 @@
+/*
+ * (C) Copyright 2002
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
+ *
+ * Influenced by code from:
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <spi.h>
+
+#include <malloc.h>
+
+/*-----------------------------------------------------------------------
+ * Definitions
+ */
+
+#ifdef DEBUG_SPI
+#define PRINTD(fmt,args...) printf (fmt ,##args)
+#else
+#define PRINTD(fmt,args...)
+#endif
+
+struct soft_spi_slave {
+ struct spi_slave slave;
+ unsigned int mode;
+};
+
+static inline struct soft_spi_slave *to_soft_spi(struct spi_slave *slave)
+{
+ return container_of(slave, struct soft_spi_slave, slave);
+}
+
+/*=====================================================================*/
+/* Public Functions */
+/*=====================================================================*/
+
+/*-----------------------------------------------------------------------
+ * Initialization
+ */
+void spi_init (void)
+{
+#ifdef SPI_INIT
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+
+ SPI_INIT;
+#endif
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct soft_spi_slave *ss;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ ss = spi_alloc_slave(struct soft_spi_slave, bus, cs);
+ if (!ss)
+ return NULL;
+
+ ss->mode = mode;
+
+ /* TODO: Use max_hz to limit the SCK rate */
+
+ return &ss->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct soft_spi_slave *ss = to_soft_spi(slave);
+
+ free(ss);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+#ifdef CONFIG_SYS_IMMR
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+#endif
+ struct soft_spi_slave *ss = to_soft_spi(slave);
+
+ /*
+ * Make sure the SPI clock is in idle state as defined for
+ * this slave.
+ */
+ if (ss->mode & SPI_CPOL)
+ SPI_SCL(1);
+ else
+ SPI_SCL(0);
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ /* Nothing to do */
+}
+
+/*-----------------------------------------------------------------------
+ * SPI transfer
+ *
+ * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks
+ * "bitlen" bits in the SPI MISO port. That's just the way SPI works.
+ *
+ * The source of the outgoing bits is the "dout" parameter and the
+ * destination of the input bits is the "din" parameter. Note that "dout"
+ * and "din" can point to the same memory location, in which case the
+ * input data overwrites the output data (since both are buffered by
+ * temporary variables, this is OK).
+ */
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
+{
+#ifdef CONFIG_SYS_IMMR
+ volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
+#endif
+ struct soft_spi_slave *ss = to_soft_spi(slave);
+ uchar tmpdin = 0;
+ uchar tmpdout = 0;
+ const u8 *txd = dout;
+ u8 *rxd = din;
+ int cpol = ss->mode & SPI_CPOL;
+ int cpha = ss->mode & SPI_CPHA;
+ unsigned int j;
+
+ PRINTD("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
+ slave->bus, slave->cs, *(uint *)txd, *(uint *)rxd, bitlen);
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ for(j = 0; j < bitlen; j++) {
+ /*
+ * Check if it is time to work on a new byte.
+ */
+ if((j % 8) == 0) {
+ tmpdout = *txd++;
+ if(j != 0) {
+ *rxd++ = tmpdin;
+ }
+ tmpdin = 0;
+ }
+
+ if (!cpha)
+ SPI_SCL(!cpol);
+ SPI_SDA(tmpdout & 0x80);
+ SPI_DELAY;
+ if (cpha)
+ SPI_SCL(!cpol);
+ else
+ SPI_SCL(cpol);
+ tmpdin <<= 1;
+ tmpdin |= SPI_READ;
+ tmpdout <<= 1;
+ SPI_DELAY;
+ if (cpha)
+ SPI_SCL(cpol);
+ }
+ /*
+ * If the number of bits isn't a multiple of 8, shift the last
+ * bits over to left-justify them. Then store the last byte
+ * read in.
+ */
+ if((bitlen % 8) != 0)
+ tmpdin <<= 8 - (bitlen % 8);
+ *rxd++ = tmpdin;
+
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ return(0);
+}
diff --git a/qemu/roms/u-boot/drivers/spi/spi.c b/qemu/roms/u-boot/drivers/spi/spi.c
new file mode 100644
index 000000000..7ddea9b02
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/spi.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors.
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <malloc.h>
+#include <spi.h>
+
+int spi_set_wordlen(struct spi_slave *slave, unsigned int wordlen)
+{
+ if (wordlen == 0 || wordlen > 32) {
+ printf("spi: invalid wordlen %d\n", wordlen);
+ return -1;
+ }
+
+ slave->wordlen = wordlen;
+
+ return 0;
+}
+
+void *spi_do_alloc_slave(int offset, int size, unsigned int bus,
+ unsigned int cs)
+{
+ struct spi_slave *slave;
+ void *ptr;
+
+ ptr = malloc(size);
+ if (ptr) {
+ memset(ptr, '\0', size);
+ slave = (struct spi_slave *)(ptr + offset);
+ slave->bus = bus;
+ slave->cs = cs;
+ slave->wordlen = SPI_DEFAULT_WORDLEN;
+ }
+
+ return ptr;
+}
+
+#ifdef CONFIG_OF_SPI
+struct spi_slave *spi_base_setup_slave_fdt(const void *blob, int busnum,
+ int node)
+{
+ int cs, max_hz, mode = 0;
+
+ cs = fdtdec_get_int(blob, node, "reg", -1);
+ max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", 100000);
+ if (fdtdec_get_bool(blob, node, "spi-cpol"))
+ mode |= SPI_CPOL;
+ if (fdtdec_get_bool(blob, node, "spi-cpha"))
+ mode |= SPI_CPHA;
+ if (fdtdec_get_bool(blob, node, "spi-cs-high"))
+ mode |= SPI_CS_HIGH;
+ return spi_setup_slave(busnum, cs, max_hz, mode);
+}
+#endif
diff --git a/qemu/roms/u-boot/drivers/spi/tegra114_spi.c b/qemu/roms/u-boot/drivers/spi/tegra114_spi.c
new file mode 100644
index 000000000..810fa4718
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/tegra114_spi.c
@@ -0,0 +1,398 @@
+/*
+ * NVIDIA Tegra SPI controller (T114 and later)
+ *
+ * Copyright (c) 2010-2013 NVIDIA Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/arch/clock.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra114/tegra114_spi.h>
+#include <spi.h>
+#include <fdtdec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* COMMAND1 */
+#define SPI_CMD1_GO (1 << 31)
+#define SPI_CMD1_M_S (1 << 30)
+#define SPI_CMD1_MODE_MASK 0x3
+#define SPI_CMD1_MODE_SHIFT 28
+#define SPI_CMD1_CS_SEL_MASK 0x3
+#define SPI_CMD1_CS_SEL_SHIFT 26
+#define SPI_CMD1_CS_POL_INACTIVE3 (1 << 25)
+#define SPI_CMD1_CS_POL_INACTIVE2 (1 << 24)
+#define SPI_CMD1_CS_POL_INACTIVE1 (1 << 23)
+#define SPI_CMD1_CS_POL_INACTIVE0 (1 << 22)
+#define SPI_CMD1_CS_SW_HW (1 << 21)
+#define SPI_CMD1_CS_SW_VAL (1 << 20)
+#define SPI_CMD1_IDLE_SDA_MASK 0x3
+#define SPI_CMD1_IDLE_SDA_SHIFT 18
+#define SPI_CMD1_BIDIR (1 << 17)
+#define SPI_CMD1_LSBI_FE (1 << 16)
+#define SPI_CMD1_LSBY_FE (1 << 15)
+#define SPI_CMD1_BOTH_EN_BIT (1 << 14)
+#define SPI_CMD1_BOTH_EN_BYTE (1 << 13)
+#define SPI_CMD1_RX_EN (1 << 12)
+#define SPI_CMD1_TX_EN (1 << 11)
+#define SPI_CMD1_PACKED (1 << 5)
+#define SPI_CMD1_BIT_LEN_MASK 0x1F
+#define SPI_CMD1_BIT_LEN_SHIFT 0
+
+/* COMMAND2 */
+#define SPI_CMD2_TX_CLK_TAP_DELAY (1 << 6)
+#define SPI_CMD2_TX_CLK_TAP_DELAY_MASK (0x3F << 6)
+#define SPI_CMD2_RX_CLK_TAP_DELAY (1 << 0)
+#define SPI_CMD2_RX_CLK_TAP_DELAY_MASK (0x3F << 0)
+
+/* TRANSFER STATUS */
+#define SPI_XFER_STS_RDY (1 << 30)
+
+/* FIFO STATUS */
+#define SPI_FIFO_STS_CS_INACTIVE (1 << 31)
+#define SPI_FIFO_STS_FRAME_END (1 << 30)
+#define SPI_FIFO_STS_RX_FIFO_FLUSH (1 << 15)
+#define SPI_FIFO_STS_TX_FIFO_FLUSH (1 << 14)
+#define SPI_FIFO_STS_ERR (1 << 8)
+#define SPI_FIFO_STS_TX_FIFO_OVF (1 << 7)
+#define SPI_FIFO_STS_TX_FIFO_UNR (1 << 6)
+#define SPI_FIFO_STS_RX_FIFO_OVF (1 << 5)
+#define SPI_FIFO_STS_RX_FIFO_UNR (1 << 4)
+#define SPI_FIFO_STS_TX_FIFO_FULL (1 << 3)
+#define SPI_FIFO_STS_TX_FIFO_EMPTY (1 << 2)
+#define SPI_FIFO_STS_RX_FIFO_FULL (1 << 1)
+#define SPI_FIFO_STS_RX_FIFO_EMPTY (1 << 0)
+
+#define SPI_TIMEOUT 1000
+#define TEGRA_SPI_MAX_FREQ 52000000
+
+struct spi_regs {
+ u32 command1; /* 000:SPI_COMMAND1 register */
+ u32 command2; /* 004:SPI_COMMAND2 register */
+ u32 timing1; /* 008:SPI_CS_TIM1 register */
+ u32 timing2; /* 00c:SPI_CS_TIM2 register */
+ u32 xfer_status;/* 010:SPI_TRANS_STATUS register */
+ u32 fifo_status;/* 014:SPI_FIFO_STATUS register */
+ u32 tx_data; /* 018:SPI_TX_DATA register */
+ u32 rx_data; /* 01c:SPI_RX_DATA register */
+ u32 dma_ctl; /* 020:SPI_DMA_CTL register */
+ u32 dma_blk; /* 024:SPI_DMA_BLK register */
+ u32 rsvd[56]; /* 028-107 reserved */
+ u32 tx_fifo; /* 108:SPI_FIFO1 register */
+ u32 rsvd2[31]; /* 10c-187 reserved */
+ u32 rx_fifo; /* 188:SPI_FIFO2 register */
+ u32 spare_ctl; /* 18c:SPI_SPARE_CTRL register */
+};
+
+struct tegra_spi_ctrl {
+ struct spi_regs *regs;
+ unsigned int freq;
+ unsigned int mode;
+ int periph_id;
+ int valid;
+};
+
+struct tegra_spi_slave {
+ struct spi_slave slave;
+ struct tegra_spi_ctrl *ctrl;
+};
+
+static struct tegra_spi_ctrl spi_ctrls[CONFIG_TEGRA114_SPI_CTRLS];
+
+static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave)
+{
+ return container_of(slave, struct tegra_spi_slave, slave);
+}
+
+int tegra114_spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ if (bus >= CONFIG_TEGRA114_SPI_CTRLS || cs > 3 || !spi_ctrls[bus].valid)
+ return 0;
+ else
+ return 1;
+}
+
+struct spi_slave *tegra114_spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct tegra_spi_slave *spi;
+
+ debug("%s: bus: %u, cs: %u, max_hz: %u, mode: %u\n", __func__,
+ bus, cs, max_hz, mode);
+
+ if (!spi_cs_is_valid(bus, cs)) {
+ printf("SPI error: unsupported bus %d / chip select %d\n",
+ bus, cs);
+ return NULL;
+ }
+
+ if (max_hz > TEGRA_SPI_MAX_FREQ) {
+ printf("SPI error: unsupported frequency %d Hz. Max frequency"
+ " is %d Hz\n", max_hz, TEGRA_SPI_MAX_FREQ);
+ return NULL;
+ }
+
+ spi = spi_alloc_slave(struct tegra_spi_slave, bus, cs);
+ if (!spi) {
+ printf("SPI error: malloc of SPI structure failed\n");
+ return NULL;
+ }
+ spi->ctrl = &spi_ctrls[bus];
+ if (!spi->ctrl) {
+ printf("SPI error: could not find controller for bus %d\n",
+ bus);
+ return NULL;
+ }
+
+ if (max_hz < spi->ctrl->freq) {
+ debug("%s: limiting frequency from %u to %u\n", __func__,
+ spi->ctrl->freq, max_hz);
+ spi->ctrl->freq = max_hz;
+ }
+ spi->ctrl->mode = mode;
+
+ return &spi->slave;
+}
+
+void tegra114_spi_free_slave(struct spi_slave *slave)
+{
+ struct tegra_spi_slave *spi = to_tegra_spi(slave);
+
+ free(spi);
+}
+
+int tegra114_spi_init(int *node_list, int count)
+{
+ struct tegra_spi_ctrl *ctrl;
+ int i;
+ int node = 0;
+ int found = 0;
+
+ for (i = 0; i < count; i++) {
+ ctrl = &spi_ctrls[i];
+ node = node_list[i];
+
+ ctrl->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob,
+ node, "reg");
+ if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) {
+ debug("%s: no spi register found\n", __func__);
+ continue;
+ }
+ ctrl->freq = fdtdec_get_int(gd->fdt_blob, node,
+ "spi-max-frequency", 0);
+ if (!ctrl->freq) {
+ debug("%s: no spi max frequency found\n", __func__);
+ continue;
+ }
+
+ ctrl->periph_id = clock_decode_periph_id(gd->fdt_blob, node);
+ if (ctrl->periph_id == PERIPH_ID_NONE) {
+ debug("%s: could not decode periph id\n", __func__);
+ continue;
+ }
+ ctrl->valid = 1;
+ found = 1;
+
+ debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
+ __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
+ }
+
+ return !found;
+}
+
+int tegra114_spi_claim_bus(struct spi_slave *slave)
+{
+ struct tegra_spi_slave *spi = to_tegra_spi(slave);
+ struct spi_regs *regs = spi->ctrl->regs;
+
+ /* Change SPI clock to correct frequency, PLLP_OUT0 source */
+ clock_start_periph_pll(spi->ctrl->periph_id, CLOCK_ID_PERIPH,
+ spi->ctrl->freq);
+
+ /* Clear stale status here */
+ setbits_le32(&regs->fifo_status,
+ SPI_FIFO_STS_ERR |
+ SPI_FIFO_STS_TX_FIFO_OVF |
+ SPI_FIFO_STS_TX_FIFO_UNR |
+ SPI_FIFO_STS_RX_FIFO_OVF |
+ SPI_FIFO_STS_RX_FIFO_UNR |
+ SPI_FIFO_STS_TX_FIFO_FULL |
+ SPI_FIFO_STS_TX_FIFO_EMPTY |
+ SPI_FIFO_STS_RX_FIFO_FULL |
+ SPI_FIFO_STS_RX_FIFO_EMPTY);
+ debug("%s: FIFO STATUS = %08x\n", __func__, readl(&regs->fifo_status));
+
+ /* Set master mode and sw controlled CS */
+ setbits_le32(&regs->command1, SPI_CMD1_M_S | SPI_CMD1_CS_SW_HW |
+ (spi->ctrl->mode << SPI_CMD1_MODE_SHIFT));
+ debug("%s: COMMAND1 = %08x\n", __func__, readl(&regs->command1));
+
+ return 0;
+}
+
+void tegra114_spi_cs_activate(struct spi_slave *slave)
+{
+ struct tegra_spi_slave *spi = to_tegra_spi(slave);
+ struct spi_regs *regs = spi->ctrl->regs;
+
+ clrbits_le32(&regs->command1, SPI_CMD1_CS_SW_VAL);
+}
+
+void tegra114_spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct tegra_spi_slave *spi = to_tegra_spi(slave);
+ struct spi_regs *regs = spi->ctrl->regs;
+
+ setbits_le32(&regs->command1, SPI_CMD1_CS_SW_VAL);
+}
+
+int tegra114_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+ const void *data_out, void *data_in, unsigned long flags)
+{
+ struct tegra_spi_slave *spi = to_tegra_spi(slave);
+ struct spi_regs *regs = spi->ctrl->regs;
+ u32 reg, tmpdout, tmpdin = 0;
+ const u8 *dout = data_out;
+ u8 *din = data_in;
+ int num_bytes;
+ int ret;
+
+ debug("%s: slave %u:%u dout %p din %p bitlen %u\n",
+ __func__, slave->bus, slave->cs, dout, din, bitlen);
+ if (bitlen % 8)
+ return -1;
+ num_bytes = bitlen / 8;
+
+ ret = 0;
+
+ /* clear all error status bits */
+ reg = readl(&regs->fifo_status);
+ writel(reg, &regs->fifo_status);
+
+ clrsetbits_le32(&regs->command1, SPI_CMD1_CS_SW_VAL,
+ SPI_CMD1_RX_EN | SPI_CMD1_TX_EN | SPI_CMD1_LSBY_FE |
+ (slave->cs << SPI_CMD1_CS_SEL_SHIFT));
+
+ /* set xfer size to 1 block (32 bits) */
+ writel(0, &regs->dma_blk);
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ /* handle data in 32-bit chunks */
+ while (num_bytes > 0) {
+ int bytes;
+ int tm, i;
+
+ tmpdout = 0;
+ bytes = (num_bytes > 4) ? 4 : num_bytes;
+
+ if (dout != NULL) {
+ for (i = 0; i < bytes; ++i)
+ tmpdout = (tmpdout << 8) | dout[i];
+ dout += bytes;
+ }
+
+ num_bytes -= bytes;
+
+ /* clear ready bit */
+ setbits_le32(&regs->xfer_status, SPI_XFER_STS_RDY);
+
+ clrsetbits_le32(&regs->command1,
+ SPI_CMD1_BIT_LEN_MASK << SPI_CMD1_BIT_LEN_SHIFT,
+ (bytes * 8 - 1) << SPI_CMD1_BIT_LEN_SHIFT);
+ writel(tmpdout, &regs->tx_fifo);
+ setbits_le32(&regs->command1, SPI_CMD1_GO);
+
+ /*
+ * Wait for SPI transmit FIFO to empty, or to time out.
+ * The RX FIFO status will be read and cleared last
+ */
+ for (tm = 0; tm < SPI_TIMEOUT; ++tm) {
+ u32 fifo_status, xfer_status;
+
+ xfer_status = readl(&regs->xfer_status);
+ if (!(xfer_status & SPI_XFER_STS_RDY))
+ continue;
+
+ fifo_status = readl(&regs->fifo_status);
+ if (fifo_status & SPI_FIFO_STS_ERR) {
+ debug("%s: got a fifo error: ", __func__);
+ if (fifo_status & SPI_FIFO_STS_TX_FIFO_OVF)
+ debug("tx FIFO overflow ");
+ if (fifo_status & SPI_FIFO_STS_TX_FIFO_UNR)
+ debug("tx FIFO underrun ");
+ if (fifo_status & SPI_FIFO_STS_RX_FIFO_OVF)
+ debug("rx FIFO overflow ");
+ if (fifo_status & SPI_FIFO_STS_RX_FIFO_UNR)
+ debug("rx FIFO underrun ");
+ if (fifo_status & SPI_FIFO_STS_TX_FIFO_FULL)
+ debug("tx FIFO full ");
+ if (fifo_status & SPI_FIFO_STS_TX_FIFO_EMPTY)
+ debug("tx FIFO empty ");
+ if (fifo_status & SPI_FIFO_STS_RX_FIFO_FULL)
+ debug("rx FIFO full ");
+ if (fifo_status & SPI_FIFO_STS_RX_FIFO_EMPTY)
+ debug("rx FIFO empty ");
+ debug("\n");
+ break;
+ }
+
+ if (!(fifo_status & SPI_FIFO_STS_RX_FIFO_EMPTY)) {
+ tmpdin = readl(&regs->rx_fifo);
+
+ /* swap bytes read in */
+ if (din != NULL) {
+ for (i = bytes - 1; i >= 0; --i) {
+ din[i] = tmpdin & 0xff;
+ tmpdin >>= 8;
+ }
+ din += bytes;
+ }
+
+ /* We can exit when we've had both RX and TX */
+ break;
+ }
+ }
+
+ if (tm >= SPI_TIMEOUT)
+ ret = tm;
+
+ /* clear ACK RDY, etc. bits */
+ writel(readl(&regs->fifo_status), &regs->fifo_status);
+ }
+
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ debug("%s: transfer ended. Value=%08x, fifo_status = %08x\n",
+ __func__, tmpdin, readl(&regs->fifo_status));
+
+ if (ret) {
+ printf("%s: timeout during SPI transfer, tm %d\n",
+ __func__, ret);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/tegra20_sflash.c b/qemu/roms/u-boot/drivers/spi/tegra20_sflash.c
new file mode 100644
index 000000000..b5d561be3
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/tegra20_sflash.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (c) 2010-2013 NVIDIA Corporation
+ * With help from the mpc8xxx SPI driver
+ * With more help from omap3_spi SPI driver
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/pinmux.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra20/tegra20_sflash.h>
+#include <spi.h>
+#include <fdtdec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define SPI_CMD_GO (1 << 30)
+#define SPI_CMD_ACTIVE_SCLK_SHIFT 26
+#define SPI_CMD_ACTIVE_SCLK_MASK (3 << SPI_CMD_ACTIVE_SCLK_SHIFT)
+#define SPI_CMD_CK_SDA (1 << 21)
+#define SPI_CMD_ACTIVE_SDA_SHIFT 18
+#define SPI_CMD_ACTIVE_SDA_MASK (3 << SPI_CMD_ACTIVE_SDA_SHIFT)
+#define SPI_CMD_CS_POL (1 << 16)
+#define SPI_CMD_TXEN (1 << 15)
+#define SPI_CMD_RXEN (1 << 14)
+#define SPI_CMD_CS_VAL (1 << 13)
+#define SPI_CMD_CS_SOFT (1 << 12)
+#define SPI_CMD_CS_DELAY (1 << 9)
+#define SPI_CMD_CS3_EN (1 << 8)
+#define SPI_CMD_CS2_EN (1 << 7)
+#define SPI_CMD_CS1_EN (1 << 6)
+#define SPI_CMD_CS0_EN (1 << 5)
+#define SPI_CMD_BIT_LENGTH (1 << 4)
+#define SPI_CMD_BIT_LENGTH_MASK 0x0000001F
+
+#define SPI_STAT_BSY (1 << 31)
+#define SPI_STAT_RDY (1 << 30)
+#define SPI_STAT_RXF_FLUSH (1 << 29)
+#define SPI_STAT_TXF_FLUSH (1 << 28)
+#define SPI_STAT_RXF_UNR (1 << 27)
+#define SPI_STAT_TXF_OVF (1 << 26)
+#define SPI_STAT_RXF_EMPTY (1 << 25)
+#define SPI_STAT_RXF_FULL (1 << 24)
+#define SPI_STAT_TXF_EMPTY (1 << 23)
+#define SPI_STAT_TXF_FULL (1 << 22)
+#define SPI_STAT_SEL_TXRX_N (1 << 16)
+#define SPI_STAT_CUR_BLKCNT (1 << 15)
+
+#define SPI_TIMEOUT 1000
+#define TEGRA_SPI_MAX_FREQ 52000000
+
+struct spi_regs {
+ u32 command; /* SPI_COMMAND_0 register */
+ u32 status; /* SPI_STATUS_0 register */
+ u32 rx_cmp; /* SPI_RX_CMP_0 register */
+ u32 dma_ctl; /* SPI_DMA_CTL_0 register */
+ u32 tx_fifo; /* SPI_TX_FIFO_0 register */
+ u32 rsvd[3]; /* offsets 0x14 to 0x1F reserved */
+ u32 rx_fifo; /* SPI_RX_FIFO_0 register */
+};
+
+struct tegra_spi_ctrl {
+ struct spi_regs *regs;
+ unsigned int freq;
+ unsigned int mode;
+ int periph_id;
+ int valid;
+};
+
+struct tegra_spi_slave {
+ struct spi_slave slave;
+ struct tegra_spi_ctrl *ctrl;
+};
+
+/* tegra20 only supports one SFLASH controller */
+static struct tegra_spi_ctrl spi_ctrls[1];
+
+static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave)
+{
+ return container_of(slave, struct tegra_spi_slave, slave);
+}
+
+int tegra20_spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ /* Tegra20 SPI-Flash - only 1 device ('bus/cs') */
+ if (bus != 0 || cs != 0)
+ return 0;
+ else
+ return 1;
+}
+
+struct spi_slave *tegra20_spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct tegra_spi_slave *spi;
+
+ if (!spi_cs_is_valid(bus, cs)) {
+ printf("SPI error: unsupported bus %d / chip select %d\n",
+ bus, cs);
+ return NULL;
+ }
+
+ if (max_hz > TEGRA_SPI_MAX_FREQ) {
+ printf("SPI error: unsupported frequency %d Hz. Max frequency"
+ " is %d Hz\n", max_hz, TEGRA_SPI_MAX_FREQ);
+ return NULL;
+ }
+
+ spi = spi_alloc_slave(struct tegra_spi_slave, bus, cs);
+ if (!spi) {
+ printf("SPI error: malloc of SPI structure failed\n");
+ return NULL;
+ }
+ spi->ctrl = &spi_ctrls[bus];
+ if (!spi->ctrl) {
+ printf("SPI error: could not find controller for bus %d\n",
+ bus);
+ return NULL;
+ }
+
+ if (max_hz < spi->ctrl->freq) {
+ debug("%s: limiting frequency from %u to %u\n", __func__,
+ spi->ctrl->freq, max_hz);
+ spi->ctrl->freq = max_hz;
+ }
+ spi->ctrl->mode = mode;
+
+ return &spi->slave;
+}
+
+void tegra20_spi_free_slave(struct spi_slave *slave)
+{
+ struct tegra_spi_slave *spi = to_tegra_spi(slave);
+
+ free(spi);
+}
+
+int tegra20_spi_init(int *node_list, int count)
+{
+ struct tegra_spi_ctrl *ctrl;
+ int i;
+ int node = 0;
+ int found = 0;
+
+ for (i = 0; i < count; i++) {
+ ctrl = &spi_ctrls[i];
+ node = node_list[i];
+
+ ctrl->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob,
+ node, "reg");
+ if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) {
+ debug("%s: no slink register found\n", __func__);
+ continue;
+ }
+ ctrl->freq = fdtdec_get_int(gd->fdt_blob, node,
+ "spi-max-frequency", 0);
+ if (!ctrl->freq) {
+ debug("%s: no slink max frequency found\n", __func__);
+ continue;
+ }
+
+ ctrl->periph_id = clock_decode_periph_id(gd->fdt_blob, node);
+ if (ctrl->periph_id == PERIPH_ID_NONE) {
+ debug("%s: could not decode periph id\n", __func__);
+ continue;
+ }
+ ctrl->valid = 1;
+ found = 1;
+
+ debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
+ __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
+ }
+ return !found;
+}
+
+int tegra20_spi_claim_bus(struct spi_slave *slave)
+{
+ struct tegra_spi_slave *spi = to_tegra_spi(slave);
+ struct spi_regs *regs = spi->ctrl->regs;
+ u32 reg;
+
+ /* Change SPI clock to correct frequency, PLLP_OUT0 source */
+ clock_start_periph_pll(spi->ctrl->periph_id, CLOCK_ID_PERIPH,
+ spi->ctrl->freq);
+
+ /* Clear stale status here */
+ reg = SPI_STAT_RDY | SPI_STAT_RXF_FLUSH | SPI_STAT_TXF_FLUSH | \
+ SPI_STAT_RXF_UNR | SPI_STAT_TXF_OVF;
+ writel(reg, &regs->status);
+ debug("%s: STATUS = %08x\n", __func__, readl(&regs->status));
+
+ /*
+ * Use sw-controlled CS, so we can clock in data after ReadID, etc.
+ */
+ reg = (spi->ctrl->mode & 1) << SPI_CMD_ACTIVE_SDA_SHIFT;
+ if (spi->ctrl->mode & 2)
+ reg |= 1 << SPI_CMD_ACTIVE_SCLK_SHIFT;
+ clrsetbits_le32(&regs->command, SPI_CMD_ACTIVE_SCLK_MASK |
+ SPI_CMD_ACTIVE_SDA_MASK, SPI_CMD_CS_SOFT | reg);
+ debug("%s: COMMAND = %08x\n", __func__, readl(&regs->command));
+
+ /*
+ * SPI pins on Tegra20 are muxed - change pinmux later due to UART
+ * issue.
+ */
+ pinmux_set_func(PMUX_PINGRP_GMD, PMUX_FUNC_SFLASH);
+ pinmux_tristate_disable(PMUX_PINGRP_LSPI);
+ pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_SFLASH);
+
+ return 0;
+}
+
+void tegra20_spi_cs_activate(struct spi_slave *slave)
+{
+ struct tegra_spi_slave *spi = to_tegra_spi(slave);
+ struct spi_regs *regs = spi->ctrl->regs;
+
+ /* CS is negated on Tegra, so drive a 1 to get a 0 */
+ setbits_le32(&regs->command, SPI_CMD_CS_VAL);
+}
+
+void tegra20_spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct tegra_spi_slave *spi = to_tegra_spi(slave);
+ struct spi_regs *regs = spi->ctrl->regs;
+
+ /* CS is negated on Tegra, so drive a 0 to get a 1 */
+ clrbits_le32(&regs->command, SPI_CMD_CS_VAL);
+}
+
+int tegra20_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+ const void *data_out, void *data_in, unsigned long flags)
+{
+ struct tegra_spi_slave *spi = to_tegra_spi(slave);
+ struct spi_regs *regs = spi->ctrl->regs;
+ u32 reg, tmpdout, tmpdin = 0;
+ const u8 *dout = data_out;
+ u8 *din = data_in;
+ int num_bytes;
+ int ret;
+
+ debug("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
+ slave->bus, slave->cs, *(u8 *)dout, *(u8 *)din, bitlen);
+ if (bitlen % 8)
+ return -1;
+ num_bytes = bitlen / 8;
+
+ ret = 0;
+
+ reg = readl(&regs->status);
+ writel(reg, &regs->status); /* Clear all SPI events via R/W */
+ debug("spi_xfer entry: STATUS = %08x\n", reg);
+
+ reg = readl(&regs->command);
+ reg |= SPI_CMD_TXEN | SPI_CMD_RXEN;
+ writel(reg, &regs->command);
+ debug("spi_xfer: COMMAND = %08x\n", readl(&regs->command));
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ /* handle data in 32-bit chunks */
+ while (num_bytes > 0) {
+ int bytes;
+ int is_read = 0;
+ int tm, i;
+
+ tmpdout = 0;
+ bytes = (num_bytes > 4) ? 4 : num_bytes;
+
+ if (dout != NULL) {
+ for (i = 0; i < bytes; ++i)
+ tmpdout = (tmpdout << 8) | dout[i];
+ }
+
+ num_bytes -= bytes;
+ if (dout)
+ dout += bytes;
+
+ clrsetbits_le32(&regs->command, SPI_CMD_BIT_LENGTH_MASK,
+ bytes * 8 - 1);
+ writel(tmpdout, &regs->tx_fifo);
+ setbits_le32(&regs->command, SPI_CMD_GO);
+
+ /*
+ * Wait for SPI transmit FIFO to empty, or to time out.
+ * The RX FIFO status will be read and cleared last
+ */
+ for (tm = 0, is_read = 0; tm < SPI_TIMEOUT; ++tm) {
+ u32 status;
+
+ status = readl(&regs->status);
+
+ /* We can exit when we've had both RX and TX activity */
+ if (is_read && (status & SPI_STAT_TXF_EMPTY))
+ break;
+
+ if ((status & (SPI_STAT_BSY | SPI_STAT_RDY)) !=
+ SPI_STAT_RDY)
+ tm++;
+
+ else if (!(status & SPI_STAT_RXF_EMPTY)) {
+ tmpdin = readl(&regs->rx_fifo);
+ is_read = 1;
+
+ /* swap bytes read in */
+ if (din != NULL) {
+ for (i = bytes - 1; i >= 0; --i) {
+ din[i] = tmpdin & 0xff;
+ tmpdin >>= 8;
+ }
+ din += bytes;
+ }
+ }
+ }
+
+ if (tm >= SPI_TIMEOUT)
+ ret = tm;
+
+ /* clear ACK RDY, etc. bits */
+ writel(readl(&regs->status), &regs->status);
+ }
+
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ debug("spi_xfer: transfer ended. Value=%08x, status = %08x\n",
+ tmpdin, readl(&regs->status));
+
+ if (ret) {
+ printf("spi_xfer: timeout during SPI transfer, tm %d\n", ret);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/tegra20_slink.c b/qemu/roms/u-boot/drivers/spi/tegra20_slink.c
new file mode 100644
index 000000000..664de6e91
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/tegra20_slink.c
@@ -0,0 +1,359 @@
+/*
+ * NVIDIA Tegra SPI-SLINK controller
+ *
+ * Copyright (c) 2010-2013 NVIDIA Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <asm/arch/clock.h>
+#include <asm/arch-tegra/clk_rst.h>
+#include <asm/arch-tegra20/tegra20_slink.h>
+#include <spi.h>
+#include <fdtdec.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* COMMAND */
+#define SLINK_CMD_ENB (1 << 31)
+#define SLINK_CMD_GO (1 << 30)
+#define SLINK_CMD_M_S (1 << 28)
+#define SLINK_CMD_CK_SDA (1 << 21)
+#define SLINK_CMD_CS_POL (1 << 13)
+#define SLINK_CMD_CS_VAL (1 << 12)
+#define SLINK_CMD_CS_SOFT (1 << 11)
+#define SLINK_CMD_BIT_LENGTH (1 << 4)
+#define SLINK_CMD_BIT_LENGTH_MASK 0x0000001F
+/* COMMAND2 */
+#define SLINK_CMD2_TXEN (1 << 30)
+#define SLINK_CMD2_RXEN (1 << 31)
+#define SLINK_CMD2_SS_EN (1 << 18)
+#define SLINK_CMD2_SS_EN_SHIFT 18
+#define SLINK_CMD2_SS_EN_MASK 0x000C0000
+#define SLINK_CMD2_CS_ACTIVE_BETWEEN (1 << 17)
+/* STATUS */
+#define SLINK_STAT_BSY (1 << 31)
+#define SLINK_STAT_RDY (1 << 30)
+#define SLINK_STAT_ERR (1 << 29)
+#define SLINK_STAT_RXF_FLUSH (1 << 27)
+#define SLINK_STAT_TXF_FLUSH (1 << 26)
+#define SLINK_STAT_RXF_OVF (1 << 25)
+#define SLINK_STAT_TXF_UNR (1 << 24)
+#define SLINK_STAT_RXF_EMPTY (1 << 23)
+#define SLINK_STAT_RXF_FULL (1 << 22)
+#define SLINK_STAT_TXF_EMPTY (1 << 21)
+#define SLINK_STAT_TXF_FULL (1 << 20)
+#define SLINK_STAT_TXF_OVF (1 << 19)
+#define SLINK_STAT_RXF_UNR (1 << 18)
+#define SLINK_STAT_CUR_BLKCNT (1 << 15)
+/* STATUS2 */
+#define SLINK_STAT2_RXF_FULL_CNT (1 << 16)
+#define SLINK_STAT2_TXF_FULL_CNT (1 << 0)
+
+#define SPI_TIMEOUT 1000
+#define TEGRA_SPI_MAX_FREQ 52000000
+
+struct spi_regs {
+ u32 command; /* SLINK_COMMAND_0 register */
+ u32 command2; /* SLINK_COMMAND2_0 reg */
+ u32 status; /* SLINK_STATUS_0 register */
+ u32 reserved; /* Reserved offset 0C */
+ u32 mas_data; /* SLINK_MAS_DATA_0 reg */
+ u32 slav_data; /* SLINK_SLAVE_DATA_0 reg */
+ u32 dma_ctl; /* SLINK_DMA_CTL_0 register */
+ u32 status2; /* SLINK_STATUS2_0 reg */
+ u32 rsvd[56]; /* 0x20 to 0xFF reserved */
+ u32 tx_fifo; /* SLINK_TX_FIFO_0 reg off 100h */
+ u32 rsvd2[31]; /* 0x104 to 0x17F reserved */
+ u32 rx_fifo; /* SLINK_RX_FIFO_0 reg off 180h */
+};
+
+struct tegra_spi_ctrl {
+ struct spi_regs *regs;
+ unsigned int freq;
+ unsigned int mode;
+ int periph_id;
+ int valid;
+};
+
+struct tegra_spi_slave {
+ struct spi_slave slave;
+ struct tegra_spi_ctrl *ctrl;
+};
+
+static struct tegra_spi_ctrl spi_ctrls[CONFIG_TEGRA_SLINK_CTRLS];
+
+static inline struct tegra_spi_slave *to_tegra_spi(struct spi_slave *slave)
+{
+ return container_of(slave, struct tegra_spi_slave, slave);
+}
+
+int tegra30_spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ if (bus >= CONFIG_TEGRA_SLINK_CTRLS || cs > 3 || !spi_ctrls[bus].valid)
+ return 0;
+ else
+ return 1;
+}
+
+struct spi_slave *tegra30_spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct tegra_spi_slave *spi;
+
+ debug("%s: bus: %u, cs: %u, max_hz: %u, mode: %u\n", __func__,
+ bus, cs, max_hz, mode);
+
+ if (!spi_cs_is_valid(bus, cs)) {
+ printf("SPI error: unsupported bus %d / chip select %d\n",
+ bus, cs);
+ return NULL;
+ }
+
+ if (max_hz > TEGRA_SPI_MAX_FREQ) {
+ printf("SPI error: unsupported frequency %d Hz. Max frequency"
+ " is %d Hz\n", max_hz, TEGRA_SPI_MAX_FREQ);
+ return NULL;
+ }
+
+ spi = spi_alloc_slave(struct tegra_spi_slave, bus, cs);
+ if (!spi) {
+ printf("SPI error: malloc of SPI structure failed\n");
+ return NULL;
+ }
+ spi->ctrl = &spi_ctrls[bus];
+ if (!spi->ctrl) {
+ printf("SPI error: could not find controller for bus %d\n",
+ bus);
+ return NULL;
+ }
+
+ if (max_hz < spi->ctrl->freq) {
+ debug("%s: limiting frequency from %u to %u\n", __func__,
+ spi->ctrl->freq, max_hz);
+ spi->ctrl->freq = max_hz;
+ }
+ spi->ctrl->mode = mode;
+
+ return &spi->slave;
+}
+
+void tegra30_spi_free_slave(struct spi_slave *slave)
+{
+ struct tegra_spi_slave *spi = to_tegra_spi(slave);
+
+ free(spi);
+}
+
+int tegra30_spi_init(int *node_list, int count)
+{
+ struct tegra_spi_ctrl *ctrl;
+ int i;
+ int node = 0;
+ int found = 0;
+
+ for (i = 0; i < count; i++) {
+ ctrl = &spi_ctrls[i];
+ node = node_list[i];
+
+ ctrl->regs = (struct spi_regs *)fdtdec_get_addr(gd->fdt_blob,
+ node, "reg");
+ if ((fdt_addr_t)ctrl->regs == FDT_ADDR_T_NONE) {
+ debug("%s: no slink register found\n", __func__);
+ continue;
+ }
+ ctrl->freq = fdtdec_get_int(gd->fdt_blob, node,
+ "spi-max-frequency", 0);
+ if (!ctrl->freq) {
+ debug("%s: no slink max frequency found\n", __func__);
+ continue;
+ }
+
+ ctrl->periph_id = clock_decode_periph_id(gd->fdt_blob, node);
+ if (ctrl->periph_id == PERIPH_ID_NONE) {
+ debug("%s: could not decode periph id\n", __func__);
+ continue;
+ }
+ ctrl->valid = 1;
+ found = 1;
+
+ debug("%s: found controller at %p, freq = %u, periph_id = %d\n",
+ __func__, ctrl->regs, ctrl->freq, ctrl->periph_id);
+ }
+ return !found;
+}
+
+int tegra30_spi_claim_bus(struct spi_slave *slave)
+{
+ struct tegra_spi_slave *spi = to_tegra_spi(slave);
+ struct spi_regs *regs = spi->ctrl->regs;
+ u32 reg;
+
+ /* Change SPI clock to correct frequency, PLLP_OUT0 source */
+ clock_start_periph_pll(spi->ctrl->periph_id, CLOCK_ID_PERIPH,
+ spi->ctrl->freq);
+
+ /* Clear stale status here */
+ reg = SLINK_STAT_RDY | SLINK_STAT_RXF_FLUSH | SLINK_STAT_TXF_FLUSH | \
+ SLINK_STAT_RXF_UNR | SLINK_STAT_TXF_OVF;
+ writel(reg, &regs->status);
+ debug("%s: STATUS = %08x\n", __func__, readl(&regs->status));
+
+ /* Set master mode and sw controlled CS */
+ reg = readl(&regs->command);
+ reg |= SLINK_CMD_M_S | SLINK_CMD_CS_SOFT;
+ writel(reg, &regs->command);
+ debug("%s: COMMAND = %08x\n", __func__, readl(&regs->command));
+
+ return 0;
+}
+
+void tegra30_spi_cs_activate(struct spi_slave *slave)
+{
+ struct tegra_spi_slave *spi = to_tegra_spi(slave);
+ struct spi_regs *regs = spi->ctrl->regs;
+
+ /* CS is negated on Tegra, so drive a 1 to get a 0 */
+ setbits_le32(&regs->command, SLINK_CMD_CS_VAL);
+}
+
+void tegra30_spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct tegra_spi_slave *spi = to_tegra_spi(slave);
+ struct spi_regs *regs = spi->ctrl->regs;
+
+ /* CS is negated on Tegra, so drive a 0 to get a 1 */
+ clrbits_le32(&regs->command, SLINK_CMD_CS_VAL);
+}
+
+int tegra30_spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+ const void *data_out, void *data_in, unsigned long flags)
+{
+ struct tegra_spi_slave *spi = to_tegra_spi(slave);
+ struct spi_regs *regs = spi->ctrl->regs;
+ u32 reg, tmpdout, tmpdin = 0;
+ const u8 *dout = data_out;
+ u8 *din = data_in;
+ int num_bytes;
+ int ret;
+
+ debug("%s: slave %u:%u dout %p din %p bitlen %u\n",
+ __func__, slave->bus, slave->cs, dout, din, bitlen);
+ if (bitlen % 8)
+ return -1;
+ num_bytes = bitlen / 8;
+
+ ret = 0;
+
+ reg = readl(&regs->status);
+ writel(reg, &regs->status); /* Clear all SPI events via R/W */
+ debug("%s entry: STATUS = %08x\n", __func__, reg);
+
+ reg = readl(&regs->status2);
+ writel(reg, &regs->status2); /* Clear all STATUS2 events via R/W */
+ debug("%s entry: STATUS2 = %08x\n", __func__, reg);
+
+ debug("%s entry: COMMAND = %08x\n", __func__, readl(&regs->command));
+
+ clrsetbits_le32(&regs->command2, SLINK_CMD2_SS_EN_MASK,
+ SLINK_CMD2_TXEN | SLINK_CMD2_RXEN |
+ (slave->cs << SLINK_CMD2_SS_EN_SHIFT));
+ debug("%s entry: COMMAND2 = %08x\n", __func__, readl(&regs->command2));
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ /* handle data in 32-bit chunks */
+ while (num_bytes > 0) {
+ int bytes;
+ int is_read = 0;
+ int tm, i;
+
+ tmpdout = 0;
+ bytes = (num_bytes > 4) ? 4 : num_bytes;
+
+ if (dout != NULL) {
+ for (i = 0; i < bytes; ++i)
+ tmpdout = (tmpdout << 8) | dout[i];
+ dout += bytes;
+ }
+
+ num_bytes -= bytes;
+
+ clrsetbits_le32(&regs->command, SLINK_CMD_BIT_LENGTH_MASK,
+ bytes * 8 - 1);
+ writel(tmpdout, &regs->tx_fifo);
+ setbits_le32(&regs->command, SLINK_CMD_GO);
+
+ /*
+ * Wait for SPI transmit FIFO to empty, or to time out.
+ * The RX FIFO status will be read and cleared last
+ */
+ for (tm = 0, is_read = 0; tm < SPI_TIMEOUT; ++tm) {
+ u32 status;
+
+ status = readl(&regs->status);
+
+ /* We can exit when we've had both RX and TX activity */
+ if (is_read && (status & SLINK_STAT_TXF_EMPTY))
+ break;
+
+ if ((status & (SLINK_STAT_BSY | SLINK_STAT_RDY)) !=
+ SLINK_STAT_RDY)
+ tm++;
+
+ else if (!(status & SLINK_STAT_RXF_EMPTY)) {
+ tmpdin = readl(&regs->rx_fifo);
+ is_read = 1;
+
+ /* swap bytes read in */
+ if (din != NULL) {
+ for (i = bytes - 1; i >= 0; --i) {
+ din[i] = tmpdin & 0xff;
+ tmpdin >>= 8;
+ }
+ din += bytes;
+ }
+ }
+ }
+
+ if (tm >= SPI_TIMEOUT)
+ ret = tm;
+
+ /* clear ACK RDY, etc. bits */
+ writel(readl(&regs->status), &regs->status);
+ }
+
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ debug("%s: transfer ended. Value=%08x, status = %08x\n",
+ __func__, tmpdin, readl(&regs->status));
+
+ if (ret) {
+ printf("%s: timeout during SPI transfer, tm %d\n",
+ __func__, ret);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/ti_qspi.c b/qemu/roms/u-boot/drivers/spi/ti_qspi.c
new file mode 100644
index 000000000..c5d2245e4
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/ti_qspi.c
@@ -0,0 +1,341 @@
+/*
+ * TI QSPI driver
+ *
+ * Copyright (C) 2013, Texas Instruments, Incorporated
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/omap.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/gpio.h>
+#include <asm/omap_gpio.h>
+
+/* ti qpsi register bit masks */
+#define QSPI_TIMEOUT 2000000
+#define QSPI_FCLK 192000000
+/* clock control */
+#define QSPI_CLK_EN (1 << 31)
+#define QSPI_CLK_DIV_MAX 0xffff
+/* command */
+#define QSPI_EN_CS(n) (n << 28)
+#define QSPI_WLEN(n) ((n-1) << 19)
+#define QSPI_3_PIN (1 << 18)
+#define QSPI_RD_SNGL (1 << 16)
+#define QSPI_WR_SNGL (2 << 16)
+#define QSPI_INVAL (4 << 16)
+#define QSPI_RD_QUAD (7 << 16)
+/* device control */
+#define QSPI_DD(m, n) (m << (3 + n*8))
+#define QSPI_CKPHA(n) (1 << (2 + n*8))
+#define QSPI_CSPOL(n) (1 << (1 + n*8))
+#define QSPI_CKPOL(n) (1 << (n*8))
+/* status */
+#define QSPI_WC (1 << 1)
+#define QSPI_BUSY (1 << 0)
+#define QSPI_WC_BUSY (QSPI_WC | QSPI_BUSY)
+#define QSPI_XFER_DONE QSPI_WC
+#define MM_SWITCH 0x01
+#define MEM_CS 0x100
+#define MEM_CS_UNSELECT 0xfffff0ff
+#define MMAP_START_ADDR_DRA 0x5c000000
+#define MMAP_START_ADDR_AM43x 0x30000000
+#define CORE_CTRL_IO 0x4a002558
+
+#define QSPI_CMD_READ (0x3 << 0)
+#define QSPI_CMD_READ_QUAD (0x6b << 0)
+#define QSPI_CMD_READ_FAST (0x0b << 0)
+#define QSPI_SETUP0_NUM_A_BYTES (0x2 << 8)
+#define QSPI_SETUP0_NUM_D_BYTES_NO_BITS (0x0 << 10)
+#define QSPI_SETUP0_NUM_D_BYTES_8_BITS (0x1 << 10)
+#define QSPI_SETUP0_READ_NORMAL (0x0 << 12)
+#define QSPI_SETUP0_READ_QUAD (0x3 << 12)
+#define QSPI_CMD_WRITE (0x2 << 16)
+#define QSPI_NUM_DUMMY_BITS (0x0 << 24)
+
+/* ti qspi register set */
+struct ti_qspi_regs {
+ u32 pid;
+ u32 pad0[3];
+ u32 sysconfig;
+ u32 pad1[3];
+ u32 int_stat_raw;
+ u32 int_stat_en;
+ u32 int_en_set;
+ u32 int_en_ctlr;
+ u32 intc_eoi;
+ u32 pad2[3];
+ u32 clk_ctrl;
+ u32 dc;
+ u32 cmd;
+ u32 status;
+ u32 data;
+ u32 setup0;
+ u32 setup1;
+ u32 setup2;
+ u32 setup3;
+ u32 memswitch;
+ u32 data1;
+ u32 data2;
+ u32 data3;
+};
+
+/* ti qspi slave */
+struct ti_qspi_slave {
+ struct spi_slave slave;
+ struct ti_qspi_regs *base;
+ unsigned int mode;
+ u32 cmd;
+ u32 dc;
+};
+
+static inline struct ti_qspi_slave *to_ti_qspi_slave(struct spi_slave *slave)
+{
+ return container_of(slave, struct ti_qspi_slave, slave);
+}
+
+static void ti_spi_setup_spi_register(struct ti_qspi_slave *qslave)
+{
+ struct spi_slave *slave = &qslave->slave;
+ u32 memval = 0;
+
+#ifdef CONFIG_DRA7XX
+ slave->memory_map = (void *)MMAP_START_ADDR_DRA;
+#else
+ slave->memory_map = (void *)MMAP_START_ADDR_AM43x;
+#endif
+
+ memval |= QSPI_CMD_READ | QSPI_SETUP0_NUM_A_BYTES |
+ QSPI_SETUP0_NUM_D_BYTES_NO_BITS |
+ QSPI_SETUP0_READ_NORMAL | QSPI_CMD_WRITE |
+ QSPI_NUM_DUMMY_BITS;
+
+ writel(memval, &qslave->base->setup0);
+}
+
+static void ti_spi_set_speed(struct spi_slave *slave, uint hz)
+{
+ struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+ uint clk_div;
+
+ debug("ti_spi_set_speed: hz: %d, clock divider %d\n", hz, clk_div);
+
+ if (!hz)
+ clk_div = 0;
+ else
+ clk_div = (QSPI_FCLK / hz) - 1;
+
+ /* disable SCLK */
+ writel(readl(&qslave->base->clk_ctrl) & ~QSPI_CLK_EN,
+ &qslave->base->clk_ctrl);
+
+ /* assign clk_div values */
+ if (clk_div < 0)
+ clk_div = 0;
+ else if (clk_div > QSPI_CLK_DIV_MAX)
+ clk_div = QSPI_CLK_DIV_MAX;
+
+ /* enable SCLK */
+ writel(QSPI_CLK_EN | clk_div, &qslave->base->clk_ctrl);
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ return 1;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ /* CS handled in xfer */
+ return;
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+
+ debug("spi_cs_deactivate: 0x%08x\n", (u32)slave);
+
+ writel(qslave->cmd | QSPI_INVAL, &qslave->base->cmd);
+}
+
+void spi_init(void)
+{
+ /* nothing to do */
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct ti_qspi_slave *qslave;
+
+#ifdef CONFIG_AM43XX
+ gpio_request(CONFIG_QSPI_SEL_GPIO, "qspi_gpio");
+ gpio_direction_output(CONFIG_QSPI_SEL_GPIO, 1);
+#endif
+
+ qslave = spi_alloc_slave(struct ti_qspi_slave, bus, cs);
+ if (!qslave) {
+ printf("SPI_error: Fail to allocate ti_qspi_slave\n");
+ return NULL;
+ }
+
+ qslave->base = (struct ti_qspi_regs *)QSPI_BASE;
+ qslave->mode = mode;
+
+ ti_spi_set_speed(&qslave->slave, max_hz);
+
+#ifdef CONFIG_TI_SPI_MMAP
+ ti_spi_setup_spi_register(qslave);
+#endif
+
+ return &qslave->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+ free(qslave);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+
+ debug("spi_claim_bus: bus:%i cs:%i\n", slave->bus, slave->cs);
+
+ qslave->dc = 0;
+ if (qslave->mode & SPI_CPHA)
+ qslave->dc |= QSPI_CKPHA(slave->cs);
+ if (qslave->mode & SPI_CPOL)
+ qslave->dc |= QSPI_CKPOL(slave->cs);
+ if (qslave->mode & SPI_CS_HIGH)
+ qslave->dc |= QSPI_CSPOL(slave->cs);
+
+ writel(qslave->dc, &qslave->base->dc);
+ writel(0, &qslave->base->cmd);
+ writel(0, &qslave->base->data);
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+
+ debug("spi_release_bus: bus:%i cs:%i\n", slave->bus, slave->cs);
+
+ writel(0, &qslave->base->dc);
+ writel(0, &qslave->base->cmd);
+ writel(0, &qslave->base->data);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct ti_qspi_slave *qslave = to_ti_qspi_slave(slave);
+ uint words = bitlen >> 3; /* fixed 8-bit word length */
+ const uchar *txp = dout;
+ uchar *rxp = din;
+ uint status;
+ int timeout;
+
+#ifdef CONFIG_DRA7XX
+ int val;
+#endif
+
+ debug("spi_xfer: bus:%i cs:%i bitlen:%i words:%i flags:%lx\n",
+ slave->bus, slave->cs, bitlen, words, flags);
+
+ /* Setup mmap flags */
+ if (flags & SPI_XFER_MMAP) {
+ writel(MM_SWITCH, &qslave->base->memswitch);
+#ifdef CONFIG_DRA7XX
+ val = readl(CORE_CTRL_IO);
+ val |= MEM_CS;
+ writel(val, CORE_CTRL_IO);
+#endif
+ return 0;
+ } else if (flags & SPI_XFER_MMAP_END) {
+ writel(~MM_SWITCH, &qslave->base->memswitch);
+#ifdef CONFIG_DRA7XX
+ val = readl(CORE_CTRL_IO);
+ val &= MEM_CS_UNSELECT;
+ writel(val, CORE_CTRL_IO);
+#endif
+ return 0;
+ }
+
+ if (bitlen == 0)
+ return -1;
+
+ if (bitlen % 8) {
+ debug("spi_xfer: Non byte aligned SPI transfer\n");
+ return -1;
+ }
+
+ /* Setup command reg */
+ qslave->cmd = 0;
+ qslave->cmd |= QSPI_WLEN(8);
+ qslave->cmd |= QSPI_EN_CS(slave->cs);
+ if (flags & SPI_3WIRE)
+ qslave->cmd |= QSPI_3_PIN;
+ qslave->cmd |= 0xfff;
+
+/* FIXME: This delay is required for successfull
+ * completion of read/write/erase. Once its root
+ * caused, it will be remove from the driver.
+ */
+#ifdef CONFIG_AM43XX
+ udelay(100);
+#endif
+ while (words--) {
+ if (txp) {
+ debug("tx cmd %08x dc %08x data %02x\n",
+ qslave->cmd | QSPI_WR_SNGL, qslave->dc, *txp);
+ writel(*txp++, &qslave->base->data);
+ writel(qslave->cmd | QSPI_WR_SNGL,
+ &qslave->base->cmd);
+ status = readl(&qslave->base->status);
+ timeout = QSPI_TIMEOUT;
+ while ((status & QSPI_WC_BUSY) != QSPI_XFER_DONE) {
+ if (--timeout < 0) {
+ printf("spi_xfer: TX timeout!\n");
+ return -1;
+ }
+ status = readl(&qslave->base->status);
+ }
+ debug("tx done, status %08x\n", status);
+ }
+ if (rxp) {
+ qslave->cmd |= QSPI_RD_SNGL;
+ debug("rx cmd %08x dc %08x\n",
+ qslave->cmd, qslave->dc);
+ #ifdef CONFIG_DRA7XX
+ udelay(500);
+ #endif
+ writel(qslave->cmd, &qslave->base->cmd);
+ status = readl(&qslave->base->status);
+ timeout = QSPI_TIMEOUT;
+ while ((status & QSPI_WC_BUSY) != QSPI_XFER_DONE) {
+ if (--timeout < 0) {
+ printf("spi_xfer: RX timeout!\n");
+ return -1;
+ }
+ status = readl(&qslave->base->status);
+ }
+ *rxp++ = readl(&qslave->base->data);
+ debug("rx done, status %08x, read %02x\n",
+ status, *(rxp-1));
+ }
+ }
+
+ /* Terminate frame */
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/xilinx_spi.c b/qemu/roms/u-boot/drivers/spi/xilinx_spi.c
new file mode 100644
index 000000000..56d99d17c
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/xilinx_spi.c
@@ -0,0 +1,215 @@
+/*
+ * Xilinx SPI driver
+ *
+ * supports 8 bit SPI transfers only, with or w/o FIFO
+ *
+ * based on bfin_spi.c, by way of altera_spi.c
+ * Copyright (c) 2005-2008 Analog Devices Inc.
+ * Copyright (c) 2010 Thomas Chou <thomas@wytron.com.tw>
+ * Copyright (c) 2010 Graeme Smecher <graeme.smecher@mail.mcgill.ca>
+ * Copyright (c) 2012 Stephan Linz <linz@li-pro.net>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [S]: [0]/ip_documentation/xps_spi.pdf
+ * [0]/ip_documentation/axi_spi_ds742.pdf
+ */
+#include <config.h>
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+
+#include "xilinx_spi.h"
+
+#ifndef CONFIG_SYS_XILINX_SPI_LIST
+#define CONFIG_SYS_XILINX_SPI_LIST { CONFIG_SYS_SPI_BASE }
+#endif
+
+#ifndef CONFIG_XILINX_SPI_IDLE_VAL
+#define CONFIG_XILINX_SPI_IDLE_VAL 0xff
+#endif
+
+#define XILSPI_SPICR_DFLT_ON (SPICR_MANUAL_SS | \
+ SPICR_MASTER_MODE | \
+ SPICR_SPE)
+
+#define XILSPI_SPICR_DFLT_OFF (SPICR_MASTER_INHIBIT | \
+ SPICR_MANUAL_SS)
+
+#define XILSPI_MAX_XFER_BITS 8
+
+static unsigned long xilinx_spi_base_list[] = CONFIG_SYS_XILINX_SPI_LIST;
+
+__attribute__((weak))
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ return bus < ARRAY_SIZE(xilinx_spi_base_list) && cs < 32;
+}
+
+__attribute__((weak))
+void spi_cs_activate(struct spi_slave *slave)
+{
+ struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
+
+ writel(SPISSR_ACT(slave->cs), &xilspi->regs->spissr);
+}
+
+__attribute__((weak))
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
+
+ writel(SPISSR_OFF, &xilspi->regs->spissr);
+}
+
+void spi_init(void)
+{
+ /* do nothing */
+}
+
+void spi_set_speed(struct spi_slave *slave, uint hz)
+{
+ /* xilinx spi core does not support programmable speed */
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct xilinx_spi_slave *xilspi;
+
+ if (!spi_cs_is_valid(bus, cs)) {
+ printf("XILSPI error: %s: unsupported bus %d / cs %d\n",
+ __func__, bus, cs);
+ return NULL;
+ }
+
+ xilspi = spi_alloc_slave(struct xilinx_spi_slave, bus, cs);
+ if (!xilspi) {
+ printf("XILSPI error: %s: malloc of SPI structure failed\n",
+ __func__);
+ return NULL;
+ }
+ xilspi->regs = (struct xilinx_spi_reg *)xilinx_spi_base_list[bus];
+ xilspi->freq = max_hz;
+ xilspi->mode = mode;
+ debug("%s: bus:%i cs:%i base:%p mode:%x max_hz:%d\n", __func__,
+ bus, cs, xilspi->regs, xilspi->mode, xilspi->freq);
+
+ writel(SPISSR_RESET_VALUE, &xilspi->regs->srr);
+
+ return &xilspi->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
+
+ free(xilspi);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
+ u32 spicr;
+
+ debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
+ writel(SPISSR_OFF, &xilspi->regs->spissr);
+
+ spicr = XILSPI_SPICR_DFLT_ON;
+ if (xilspi->mode & SPI_LSB_FIRST)
+ spicr |= SPICR_LSB_FIRST;
+ if (xilspi->mode & SPI_CPHA)
+ spicr |= SPICR_CPHA;
+ if (xilspi->mode & SPI_CPOL)
+ spicr |= SPICR_CPOL;
+ if (xilspi->mode & SPI_LOOP)
+ spicr |= SPICR_LOOP;
+
+ writel(spicr, &xilspi->regs->spicr);
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
+
+ debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
+ writel(SPISSR_OFF, &xilspi->regs->spissr);
+ writel(XILSPI_SPICR_DFLT_OFF, &xilspi->regs->spicr);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct xilinx_spi_slave *xilspi = to_xilinx_spi_slave(slave);
+ /* assume spi core configured to do 8 bit transfers */
+ unsigned int bytes = bitlen / XILSPI_MAX_XFER_BITS;
+ const unsigned char *txp = dout;
+ unsigned char *rxp = din;
+ unsigned rxecount = 17; /* max. 16 elements in FIFO, leftover 1 */
+ unsigned global_timeout;
+
+ debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__,
+ slave->bus, slave->cs, bitlen, bytes, flags);
+ if (bitlen == 0)
+ goto done;
+
+ if (bitlen % XILSPI_MAX_XFER_BITS) {
+ printf("XILSPI warning: %s: Not a multiple of %d bits\n",
+ __func__, XILSPI_MAX_XFER_BITS);
+ flags |= SPI_XFER_END;
+ goto done;
+ }
+
+ /* empty read buffer */
+ while (rxecount && !(readl(&xilspi->regs->spisr) & SPISR_RX_EMPTY)) {
+ readl(&xilspi->regs->spidrr);
+ rxecount--;
+ }
+
+ if (!rxecount) {
+ printf("XILSPI error: %s: Rx buffer not empty\n", __func__);
+ return -1;
+ }
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ /* at least 1usec or greater, leftover 1 */
+ global_timeout = xilspi->freq > XILSPI_MAX_XFER_BITS * 1000000 ? 2 :
+ (XILSPI_MAX_XFER_BITS * 1000000 / xilspi->freq) + 1;
+
+ while (bytes--) {
+ unsigned timeout = global_timeout;
+ /* get Tx element from data out buffer and count up */
+ unsigned char d = txp ? *txp++ : CONFIG_XILINX_SPI_IDLE_VAL;
+ debug("%s: tx:%x ", __func__, d);
+
+ /* write out and wait for processing (receive data) */
+ writel(d & SPIDTR_8BIT_MASK, &xilspi->regs->spidtr);
+ while (timeout && readl(&xilspi->regs->spisr)
+ & SPISR_RX_EMPTY) {
+ timeout--;
+ udelay(1);
+ }
+
+ if (!timeout) {
+ printf("XILSPI error: %s: Xfer timeout\n", __func__);
+ return -1;
+ }
+
+ /* read Rx element and push into data in buffer */
+ d = readl(&xilspi->regs->spidrr) & SPIDRR_8BIT_MASK;
+ if (rxp)
+ *rxp++ = d;
+ debug("rx:%x\n", d);
+ }
+
+ done:
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ return 0;
+}
diff --git a/qemu/roms/u-boot/drivers/spi/xilinx_spi.h b/qemu/roms/u-boot/drivers/spi/xilinx_spi.h
new file mode 100644
index 000000000..ce7d82c39
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/xilinx_spi.h
@@ -0,0 +1,138 @@
+/*
+ * Xilinx SPI driver
+ *
+ * XPS/AXI bus interface
+ *
+ * based on bfin_spi.c, by way of altera_spi.c
+ * Copyright (c) 2005-2008 Analog Devices Inc.
+ * Copyright (c) 2010 Thomas Chou <thomas@wytron.com.tw>
+ * Copyright (c) 2010 Graeme Smecher <graeme.smecher@mail.mcgill.ca>
+ * Copyright (c) 2012 Stephan Linz <linz@li-pro.net>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * [0]: http://www.xilinx.com/support/documentation
+ *
+ * [S]: [0]/ip_documentation/xps_spi.pdf
+ * [0]/ip_documentation/axi_spi_ds742.pdf
+ */
+#ifndef _XILINX_SPI_
+#define _XILINX_SPI_
+
+#include <asm/types.h>
+#include <asm/io.h>
+
+/*
+ * Xilinx SPI Register Definition
+ *
+ * [1]: [0]/ip_documentation/xps_spi.pdf
+ * page 8, Register Descriptions
+ * [2]: [0]/ip_documentation/axi_spi_ds742.pdf
+ * page 7, Register Overview Table
+ */
+struct xilinx_spi_reg {
+ u32 __space0__[7];
+ u32 dgier; /* Device Global Interrupt Enable Register (DGIER) */
+ u32 ipisr; /* IP Interrupt Status Register (IPISR) */
+ u32 __space1__;
+ u32 ipier; /* IP Interrupt Enable Register (IPIER) */
+ u32 __space2__[5];
+ u32 srr; /* Softare Reset Register (SRR) */
+ u32 __space3__[7];
+ u32 spicr; /* SPI Control Register (SPICR) */
+ u32 spisr; /* SPI Status Register (SPISR) */
+ u32 spidtr; /* SPI Data Transmit Register (SPIDTR) */
+ u32 spidrr; /* SPI Data Receive Register (SPIDRR) */
+ u32 spissr; /* SPI Slave Select Register (SPISSR) */
+ u32 spitfor; /* SPI Transmit FIFO Occupancy Register (SPITFOR) */
+ u32 spirfor; /* SPI Receive FIFO Occupancy Register (SPIRFOR) */
+};
+
+/* Device Global Interrupt Enable Register (dgier), [1] p15, [2] p15 */
+#define DGIER_GIE (1 << 31)
+
+/* IP Interrupt Status Register (ipisr), [1] p15, [2] p15 */
+#define IPISR_DRR_NOT_EMPTY (1 << 8)
+#define IPISR_SLAVE_SELECT (1 << 7)
+#define IPISR_TXF_HALF_EMPTY (1 << 6)
+#define IPISR_DRR_OVERRUN (1 << 5)
+#define IPISR_DRR_FULL (1 << 4)
+#define IPISR_DTR_UNDERRUN (1 << 3)
+#define IPISR_DTR_EMPTY (1 << 2)
+#define IPISR_SLAVE_MODF (1 << 1)
+#define IPISR_MODF (1 << 0)
+
+/* IP Interrupt Enable Register (ipier), [1] p17, [2] p18 */
+#define IPIER_DRR_NOT_EMPTY (1 << 8)
+#define IPIER_SLAVE_SELECT (1 << 7)
+#define IPIER_TXF_HALF_EMPTY (1 << 6)
+#define IPIER_DRR_OVERRUN (1 << 5)
+#define IPIER_DRR_FULL (1 << 4)
+#define IPIER_DTR_UNDERRUN (1 << 3)
+#define IPIER_DTR_EMPTY (1 << 2)
+#define IPIER_SLAVE_MODF (1 << 1)
+#define IPIER_MODF (1 << 0)
+
+/* Softare Reset Register (srr), [1] p9, [2] p8 */
+#define SRR_RESET_CODE 0x0000000A
+
+/* SPI Control Register (spicr), [1] p9, [2] p8 */
+#define SPICR_LSB_FIRST (1 << 9)
+#define SPICR_MASTER_INHIBIT (1 << 8)
+#define SPICR_MANUAL_SS (1 << 7)
+#define SPICR_RXFIFO_RESEST (1 << 6)
+#define SPICR_TXFIFO_RESEST (1 << 5)
+#define SPICR_CPHA (1 << 4)
+#define SPICR_CPOL (1 << 3)
+#define SPICR_MASTER_MODE (1 << 2)
+#define SPICR_SPE (1 << 1)
+#define SPICR_LOOP (1 << 0)
+
+/* SPI Status Register (spisr), [1] p11, [2] p10 */
+#define SPISR_SLAVE_MODE_SELECT (1 << 5)
+#define SPISR_MODF (1 << 4)
+#define SPISR_TX_FULL (1 << 3)
+#define SPISR_TX_EMPTY (1 << 2)
+#define SPISR_RX_FULL (1 << 1)
+#define SPISR_RX_EMPTY (1 << 0)
+
+/* SPI Data Transmit Register (spidtr), [1] p12, [2] p12 */
+#define SPIDTR_8BIT_MASK (0xff << 0)
+#define SPIDTR_16BIT_MASK (0xffff << 0)
+#define SPIDTR_32BIT_MASK (0xffffffff << 0)
+
+/* SPI Data Receive Register (spidrr), [1] p12, [2] p12 */
+#define SPIDRR_8BIT_MASK (0xff << 0)
+#define SPIDRR_16BIT_MASK (0xffff << 0)
+#define SPIDRR_32BIT_MASK (0xffffffff << 0)
+
+/* SPI Slave Select Register (spissr), [1] p13, [2] p13 */
+#define SPISSR_MASK(cs) (1 << (cs))
+#define SPISSR_ACT(cs) ~SPISSR_MASK(cs)
+#define SPISSR_OFF ~0UL
+
+/* SPI Transmit FIFO Occupancy Register (spitfor), [1] p13, [2] p14 */
+#define SPITFOR_OCYVAL_POS 0
+#define SPITFOR_OCYVAL_MASK (0xf << SPITFOR_OCYVAL_POS)
+
+/* SPI Receive FIFO Occupancy Register (spirfor), [1] p14, [2] p14 */
+#define SPIRFOR_OCYVAL_POS 0
+#define SPIRFOR_OCYVAL_MASK (0xf << SPIRFOR_OCYVAL_POS)
+
+/* SPI Software Reset Register (ssr) */
+#define SPISSR_RESET_VALUE 0x0a
+
+struct xilinx_spi_slave {
+ struct spi_slave slave;
+ struct xilinx_spi_reg *regs;
+ unsigned int freq;
+ unsigned int mode;
+};
+
+static inline struct xilinx_spi_slave *to_xilinx_spi_slave(
+ struct spi_slave *slave)
+{
+ return container_of(slave, struct xilinx_spi_slave, slave);
+}
+
+#endif /* _XILINX_SPI_ */
diff --git a/qemu/roms/u-boot/drivers/spi/zynq_spi.c b/qemu/roms/u-boot/drivers/spi/zynq_spi.c
new file mode 100644
index 000000000..5da87591c
--- /dev/null
+++ b/qemu/roms/u-boot/drivers/spi/zynq_spi.c
@@ -0,0 +1,280 @@
+/*
+ * (C) Copyright 2013 Inc.
+ *
+ * Xilinx Zynq PS SPI controller driver (master mode only)
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <malloc.h>
+#include <spi.h>
+#include <asm/io.h>
+#include <asm/arch/hardware.h>
+
+/* zynq spi register bit masks ZYNQ_SPI_<REG>_<BIT>_MASK */
+#define ZYNQ_SPI_CR_MSA_MASK (1 << 15) /* Manual start enb */
+#define ZYNQ_SPI_CR_MCS_MASK (1 << 14) /* Manual chip select */
+#define ZYNQ_SPI_CR_CS_MASK (0xF << 10) /* Chip select */
+#define ZYNQ_SPI_CR_BRD_MASK (0x7 << 3) /* Baud rate div */
+#define ZYNQ_SPI_CR_CPHA_MASK (1 << 2) /* Clock phase */
+#define ZYNQ_SPI_CR_CPOL_MASK (1 << 1) /* Clock polarity */
+#define ZYNQ_SPI_CR_MSTREN_MASK (1 << 0) /* Mode select */
+#define ZYNQ_SPI_IXR_RXNEMPTY_MASK (1 << 4) /* RX_FIFO_not_empty */
+#define ZYNQ_SPI_IXR_TXOW_MASK (1 << 2) /* TX_FIFO_not_full */
+#define ZYNQ_SPI_IXR_ALL_MASK 0x7F /* All IXR bits */
+#define ZYNQ_SPI_ENR_SPI_EN_MASK (1 << 0) /* SPI Enable */
+
+#define ZYNQ_SPI_FIFO_DEPTH 128
+#ifndef CONFIG_SYS_ZYNQ_SPI_WAIT
+#define CONFIG_SYS_ZYNQ_SPI_WAIT (CONFIG_SYS_HZ/100) /* 10 ms */
+#endif
+
+/* zynq spi register set */
+struct zynq_spi_regs {
+ u32 cr; /* 0x00 */
+ u32 isr; /* 0x04 */
+ u32 ier; /* 0x08 */
+ u32 idr; /* 0x0C */
+ u32 imr; /* 0x10 */
+ u32 enr; /* 0x14 */
+ u32 dr; /* 0x18 */
+ u32 txdr; /* 0x1C */
+ u32 rxdr; /* 0x20 */
+};
+
+/* zynq spi slave */
+struct zynq_spi_slave {
+ struct spi_slave slave;
+ struct zynq_spi_regs *base;
+ u8 mode;
+ u8 fifo_depth;
+ u32 speed_hz;
+ u32 input_hz;
+ u32 req_hz;
+};
+
+static inline struct zynq_spi_slave *to_zynq_spi_slave(struct spi_slave *slave)
+{
+ return container_of(slave, struct zynq_spi_slave, slave);
+}
+
+static inline struct zynq_spi_regs *get_zynq_spi_base(int dev)
+{
+ if (dev)
+ return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR1;
+ else
+ return (struct zynq_spi_regs *)ZYNQ_SPI_BASEADDR0;
+}
+
+static void zynq_spi_init_hw(struct zynq_spi_slave *zslave)
+{
+ u32 confr;
+
+ /* Disable SPI */
+ writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
+
+ /* Disable Interrupts */
+ writel(ZYNQ_SPI_IXR_ALL_MASK, &zslave->base->idr);
+
+ /* Clear RX FIFO */
+ while (readl(&zslave->base->isr) &
+ ZYNQ_SPI_IXR_RXNEMPTY_MASK)
+ readl(&zslave->base->rxdr);
+
+ /* Clear Interrupts */
+ writel(ZYNQ_SPI_IXR_ALL_MASK, &zslave->base->isr);
+
+ /* Manual slave select and Auto start */
+ confr = ZYNQ_SPI_CR_MCS_MASK | ZYNQ_SPI_CR_CS_MASK |
+ ZYNQ_SPI_CR_MSTREN_MASK;
+ confr &= ~ZYNQ_SPI_CR_MSA_MASK;
+ writel(confr, &zslave->base->cr);
+
+ /* Enable SPI */
+ writel(ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
+}
+
+int spi_cs_is_valid(unsigned int bus, unsigned int cs)
+{
+ /* 2 bus with 3 chipselect */
+ return bus < 2 && cs < 3;
+}
+
+void spi_cs_activate(struct spi_slave *slave)
+{
+ struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
+ u32 cr;
+
+ debug("spi_cs_activate: 0x%08x\n", (u32)slave);
+
+ clrbits_le32(&zslave->base->cr, ZYNQ_SPI_CR_CS_MASK);
+ cr = readl(&zslave->base->cr);
+ /*
+ * CS cal logic: CS[13:10]
+ * xxx0 - cs0
+ * xx01 - cs1
+ * x011 - cs2
+ */
+ cr |= (~(0x1 << slave->cs) << 10) & ZYNQ_SPI_CR_CS_MASK;
+ writel(cr, &zslave->base->cr);
+}
+
+void spi_cs_deactivate(struct spi_slave *slave)
+{
+ struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
+
+ debug("spi_cs_deactivate: 0x%08x\n", (u32)slave);
+
+ setbits_le32(&zslave->base->cr, ZYNQ_SPI_CR_CS_MASK);
+}
+
+void spi_init()
+{
+ /* nothing to do */
+}
+
+struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
+ unsigned int max_hz, unsigned int mode)
+{
+ struct zynq_spi_slave *zslave;
+
+ if (!spi_cs_is_valid(bus, cs))
+ return NULL;
+
+ zslave = spi_alloc_slave(struct zynq_spi_slave, bus, cs);
+ if (!zslave) {
+ printf("SPI_error: Fail to allocate zynq_spi_slave\n");
+ return NULL;
+ }
+
+ zslave->base = get_zynq_spi_base(bus);
+ zslave->mode = mode;
+ zslave->fifo_depth = ZYNQ_SPI_FIFO_DEPTH;
+ zslave->input_hz = 166666700;
+ zslave->speed_hz = zslave->input_hz / 2;
+ zslave->req_hz = max_hz;
+
+ /* init the zynq spi hw */
+ zynq_spi_init_hw(zslave);
+
+ return &zslave->slave;
+}
+
+void spi_free_slave(struct spi_slave *slave)
+{
+ struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
+
+ debug("spi_free_slave: 0x%08x\n", (u32)slave);
+ free(zslave);
+}
+
+int spi_claim_bus(struct spi_slave *slave)
+{
+ struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
+ u32 confr = 0;
+ u8 baud_rate_val = 0;
+
+ writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
+
+ /* Set the SPI Clock phase and polarities */
+ confr = readl(&zslave->base->cr);
+ confr &= ~(ZYNQ_SPI_CR_CPHA_MASK | ZYNQ_SPI_CR_CPOL_MASK);
+ if (zslave->mode & SPI_CPHA)
+ confr |= ZYNQ_SPI_CR_CPHA_MASK;
+ if (zslave->mode & SPI_CPOL)
+ confr |= ZYNQ_SPI_CR_CPOL_MASK;
+
+ /* Set the clock frequency */
+ if (zslave->req_hz == 0) {
+ /* Set baudrate x8, if the req_hz is 0 */
+ baud_rate_val = 0x2;
+ } else if (zslave->speed_hz != zslave->req_hz) {
+ while ((baud_rate_val < 8) &&
+ ((zslave->input_hz /
+ (2 << baud_rate_val)) > zslave->req_hz))
+ baud_rate_val++;
+ zslave->speed_hz = zslave->req_hz / (2 << baud_rate_val);
+ }
+ confr &= ~ZYNQ_SPI_CR_BRD_MASK;
+ confr |= (baud_rate_val << 3);
+ writel(confr, &zslave->base->cr);
+
+ writel(ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
+
+ return 0;
+}
+
+void spi_release_bus(struct spi_slave *slave)
+{
+ struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
+
+ debug("spi_release_bus: 0x%08x\n", (u32)slave);
+ writel(~ZYNQ_SPI_ENR_SPI_EN_MASK, &zslave->base->enr);
+}
+
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
+ void *din, unsigned long flags)
+{
+ struct zynq_spi_slave *zslave = to_zynq_spi_slave(slave);
+ u32 len = bitlen / 8;
+ u32 tx_len = len, rx_len = len, tx_tvl;
+ const u8 *tx_buf = dout;
+ u8 *rx_buf = din, buf;
+ u32 ts, status;
+
+ debug("spi_xfer: bus:%i cs:%i bitlen:%i len:%i flags:%lx\n",
+ slave->bus, slave->cs, bitlen, len, flags);
+
+ if (bitlen == 0)
+ return -1;
+
+ if (bitlen % 8) {
+ debug("spi_xfer: Non byte aligned SPI transfer\n");
+ return -1;
+ }
+
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(slave);
+
+ while (rx_len > 0) {
+ /* Write the data into TX FIFO - tx threshold is fifo_depth */
+ tx_tvl = 0;
+ while ((tx_tvl < zslave->fifo_depth) && tx_len) {
+ if (tx_buf)
+ buf = *tx_buf++;
+ else
+ buf = 0;
+ writel(buf, &zslave->base->txdr);
+ tx_len--;
+ tx_tvl++;
+ }
+
+ /* Check TX FIFO completion */
+ ts = get_timer(0);
+ status = readl(&zslave->base->isr);
+ while (!(status & ZYNQ_SPI_IXR_TXOW_MASK)) {
+ if (get_timer(ts) > CONFIG_SYS_ZYNQ_SPI_WAIT) {
+ printf("spi_xfer: Timeout! TX FIFO not full\n");
+ return -1;
+ }
+ status = readl(&zslave->base->isr);
+ }
+
+ /* Read the data from RX FIFO */
+ status = readl(&zslave->base->isr);
+ while (status & ZYNQ_SPI_IXR_RXNEMPTY_MASK) {
+ buf = readl(&zslave->base->rxdr);
+ if (rx_buf)
+ *rx_buf++ = buf;
+ status = readl(&zslave->base->isr);
+ rx_len--;
+ }
+ }
+
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(slave);
+
+ return 0;
+}