summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/block/dwc_ahsata.c2
-rw-r--r--drivers/crypto/rsa_mod_exp/mod_exp_sw.c1
-rw-r--r--drivers/gpio/intel_broadwell_gpio.c7
-rw-r--r--drivers/gpio/intel_ich6_gpio.c5
-rw-r--r--drivers/i2c/i2c_core.c5
-rw-r--r--drivers/i2c/mxc_i2c.c27
-rw-r--r--drivers/misc/mxc_ocotp.c4
-rw-r--r--drivers/mtd/nand/mxs_nand.c2
-rw-r--r--drivers/net/fec_mxc.c2
-rw-r--r--drivers/spi/Kconfig8
-rw-r--r--drivers/spi/Makefile1
-rw-r--r--drivers/spi/pic32_spi.c448
-rw-r--r--drivers/usb/musb-new/sunxi.c7
14 files changed, 503 insertions, 17 deletions
diff --git a/drivers/Makefile b/drivers/Makefile
index f6295d285e..db5317c9c7 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_$(SPL_)RAM) += ram/
ifdef CONFIG_SPL_BUILD
+obj-$(CONFIG_SPL_CRYPTO_SUPPORT) += crypto/
obj-$(CONFIG_SPL_I2C_SUPPORT) += i2c/
obj-$(CONFIG_SPL_GPIO_SUPPORT) += gpio/
obj-$(CONFIG_SPL_MMC_SUPPORT) += mmc/
diff --git a/drivers/block/dwc_ahsata.c b/drivers/block/dwc_ahsata.c
index 6ec52a9114..6056fe5dfd 100644
--- a/drivers/block/dwc_ahsata.c
+++ b/drivers/block/dwc_ahsata.c
@@ -563,7 +563,7 @@ int init_sata(int dev)
struct ahci_probe_ent *probe_ent = NULL;
#if defined(CONFIG_MX6)
- if (!is_cpu_type(MXC_CPU_MX6Q) && !is_cpu_type(MXC_CPU_MX6D))
+ if (!is_mx6dq() && !is_mx6dqp())
return 1;
#endif
if (dev < 0 || dev > (CONFIG_SYS_SATA_MAX_DEVICE - 1)) {
diff --git a/drivers/crypto/rsa_mod_exp/mod_exp_sw.c b/drivers/crypto/rsa_mod_exp/mod_exp_sw.c
index dc6c064b4e..3817fb3e47 100644
--- a/drivers/crypto/rsa_mod_exp/mod_exp_sw.c
+++ b/drivers/crypto/rsa_mod_exp/mod_exp_sw.c
@@ -32,6 +32,7 @@ U_BOOT_DRIVER(mod_exp_sw) = {
.name = "mod_exp_sw",
.id = UCLASS_MOD_EXP,
.ops = &mod_exp_ops_sw,
+ .flags = DM_FLAG_PRE_RELOC,
};
U_BOOT_DEVICE(mod_exp_sw) = {
diff --git a/drivers/gpio/intel_broadwell_gpio.c b/drivers/gpio/intel_broadwell_gpio.c
index 81ce446e1a..8b50900f9f 100644
--- a/drivers/gpio/intel_broadwell_gpio.c
+++ b/drivers/gpio/intel_broadwell_gpio.c
@@ -9,7 +9,6 @@
#include <fdtdec.h>
#include <pch.h>
#include <pci.h>
-#include <syscon.h>
#include <asm/cpu.h>
#include <asm/gpio.h>
#include <asm/io.h>
@@ -119,12 +118,6 @@ static int broadwell_gpio_probe(struct udevice *dev)
struct broadwell_bank_platdata *plat = dev_get_platdata(dev);
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
struct broadwell_bank_priv *priv = dev_get_priv(dev);
- struct udevice *pinctrl;
- int ret;
-
- /* Set up pin control if available */
- ret = syscon_get_by_driver_data(X86_SYSCON_PINCONF, &pinctrl);
- debug("%s, pinctrl=%p, ret=%d\n", __func__, pinctrl, ret);
uc_priv->gpio_count = GPIO_PER_BANK;
uc_priv->bank_name = plat->bank_name;
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c
index b7e379ab97..fd6181fa5a 100644
--- a/drivers/gpio/intel_ich6_gpio.c
+++ b/drivers/gpio/intel_ich6_gpio.c
@@ -32,7 +32,6 @@
#include <fdtdec.h>
#include <pch.h>
#include <pci.h>
-#include <syscon.h>
#include <asm/cpu.h>
#include <asm/gpio.h>
#include <asm/io.h>
@@ -113,10 +112,6 @@ static int ich6_gpio_probe(struct udevice *dev)
struct ich6_bank_platdata *plat = dev_get_platdata(dev);
struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
struct ich6_bank_priv *bank = dev_get_priv(dev);
- struct udevice *pinctrl;
-
- /* Set up pin control if available */
- syscon_get_by_driver_data(X86_SYSCON_PINCONF, &pinctrl);
uc_priv->gpio_count = GPIO_PER_BANK;
uc_priv->bank_name = plat->bank_name;
diff --git a/drivers/i2c/i2c_core.c b/drivers/i2c/i2c_core.c
index 41cc3b8fa4..16b1aba32a 100644
--- a/drivers/i2c/i2c_core.c
+++ b/drivers/i2c/i2c_core.c
@@ -233,6 +233,11 @@ __weak void i2c_init_board(void)
{
}
+/* implement possible for i2c specific early i2c init */
+__weak void i2c_early_init_f(void)
+{
+}
+
/*
* i2c_init_all():
*
diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c
index 445fa21082..f3402089a8 100644
--- a/drivers/i2c/mxc_i2c.c
+++ b/drivers/i2c/mxc_i2c.c
@@ -32,6 +32,14 @@ DECLARE_GLOBAL_DATA_PTR;
#define IMX_I2C_REGSHIFT 2
#define VF610_I2C_REGSHIFT 0
+
+#define I2C_EARLY_INIT_INDEX 0
+#ifdef CONFIG_SYS_I2C_IFDR_DIV
+#define I2C_IFDR_DIV_CONSERVATIVE CONFIG_SYS_I2C_IFDR_DIV
+#else
+#define I2C_IFDR_DIV_CONSERVATIVE 0x7e
+#endif
+
/* Register index */
#define IADR 0
#define IFDR 1
@@ -660,6 +668,25 @@ void bus_i2c_init(int index, int speed, int unused,
}
/*
+ * Early init I2C for prepare read the clk through I2C.
+ */
+void i2c_early_init_f(void)
+{
+ ulong base = mxc_i2c_buses[I2C_EARLY_INIT_INDEX].base;
+ bool quirk = mxc_i2c_buses[I2C_EARLY_INIT_INDEX].driver_data
+ & I2C_QUIRK_FLAG ? true : false;
+ int reg_shift = quirk ? VF610_I2C_REGSHIFT : IMX_I2C_REGSHIFT;
+
+ /* Set I2C divider value */
+ writeb(I2C_IFDR_DIV_CONSERVATIVE, base + (IFDR << reg_shift));
+ /* Reset module */
+ writeb(I2CR_IDIS, base + (I2CR << reg_shift));
+ writeb(0, base + (I2SR << reg_shift));
+ /* Enable I2C */
+ writeb(I2CR_IEN, base + (I2CR << reg_shift));
+}
+
+/*
* Init I2C Bus
*/
static void mxc_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
diff --git a/drivers/misc/mxc_ocotp.c b/drivers/misc/mxc_ocotp.c
index 65ff8158e5..38344e8090 100644
--- a/drivers/misc/mxc_ocotp.c
+++ b/drivers/misc/mxc_ocotp.c
@@ -95,9 +95,9 @@ u32 fuse_bank_physical(int index)
{
u32 phy_index;
- if (is_cpu_type(MXC_CPU_MX6SL)) {
+ if (is_mx6sl()) {
phy_index = index;
- } else if (is_cpu_type(MXC_CPU_MX6UL)) {
+ } else if (is_mx6ul()) {
if (index >= 6)
phy_index = fuse_bank_physical(5) + (index - 6) + 3;
else
diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c
index 7be1f86bc2..c90a3a7bd2 100644
--- a/drivers/mtd/nand/mxs_nand.c
+++ b/drivers/mtd/nand/mxs_nand.c
@@ -152,7 +152,7 @@ static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
int max_ecc_strength_supported;
/* Refer to Chapter 17 for i.MX6DQ, Chapter 18 for i.MX6SX */
- if (is_cpu_type(MXC_CPU_MX6SX) || is_soc_type(MXC_SOC_MX7))
+ if (is_mx6sx() || is_mx7())
max_ecc_strength_supported = 62;
else
max_ecc_strength_supported = 40;
diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 3340dd256f..360f8e44d1 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -566,7 +566,7 @@ static int fec_init(struct eth_device *dev, bd_t* bd)
/* Do not access reserved register for i.MX6UL */
- if (!is_cpu_type(MXC_CPU_MX6UL)) {
+ if (!is_mx6ul()) {
/* clear MIB RAM */
for (i = mib_ptr; i <= mib_ptr + 0xfc; i += 4)
writel(0, i);
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index b7fd8e53a2..aca385d5e5 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -75,6 +75,14 @@ config ICH_SPI
access the SPI NOR flash on platforms embedding this Intel
ICH IP core.
+config PIC32_SPI
+ bool "Microchip PIC32 SPI driver"
+ depends on MACH_PIC32
+ help
+ Enable the Microchip PIC32 SPI driver. This driver can be used
+ to access the SPI NOR flash, MMC-over-SPI on platforms based on
+ Microchip PIC32 family devices.
+
config ROCKCHIP_SPI
bool "Rockchip SPI driver"
help
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 7fb2926e78..b1d9e2075e 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
obj-$(CONFIG_MXC_SPI) += mxc_spi.o
obj-$(CONFIG_MXS_SPI) += mxs_spi.o
obj-$(CONFIG_OMAP3_SPI) += omap3_spi.o
+obj-$(CONFIG_PIC32_SPI) += pic32_spi.o
obj-$(CONFIG_ROCKCHIP_SPI) += rk_spi.o
obj-$(CONFIG_SANDBOX_SPI) += sandbox_spi.o
obj-$(CONFIG_SH_SPI) += sh_spi.o
diff --git a/drivers/spi/pic32_spi.c b/drivers/spi/pic32_spi.c
new file mode 100644
index 0000000000..25ca1f3e1b
--- /dev/null
+++ b/drivers/spi/pic32_spi.c
@@ -0,0 +1,448 @@
+/*
+ * Microchip PIC32 SPI controller driver.
+ *
+ * Copyright (c) 2015, Microchip Technology Inc.
+ * Purna Chandra Mandal <purna.mandal@microchip.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <linux/compat.h>
+#include <malloc.h>
+#include <spi.h>
+
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+#include <dt-bindings/clock/microchip,clock.h>
+#include <mach/pic32.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* PIC32 SPI controller registers */
+struct pic32_reg_spi {
+ struct pic32_reg_atomic ctrl;
+ struct pic32_reg_atomic status;
+ struct pic32_reg_atomic buf;
+ struct pic32_reg_atomic baud;
+ struct pic32_reg_atomic ctrl2;
+};
+
+/* Bit fields in SPI Control Register */
+#define PIC32_SPI_CTRL_MSTEN BIT(5) /* Enable SPI Master */
+#define PIC32_SPI_CTRL_CKP BIT(6) /* active low */
+#define PIC32_SPI_CTRL_CKE BIT(8) /* Tx on falling edge */
+#define PIC32_SPI_CTRL_SMP BIT(9) /* Rx at middle or end of tx */
+#define PIC32_SPI_CTRL_BPW_MASK 0x03 /* Bits per word */
+#define PIC32_SPI_CTRL_BPW_8 0x0
+#define PIC32_SPI_CTRL_BPW_16 0x1
+#define PIC32_SPI_CTRL_BPW_32 0x2
+#define PIC32_SPI_CTRL_BPW_SHIFT 10
+#define PIC32_SPI_CTRL_ON BIT(15) /* Macro enable */
+#define PIC32_SPI_CTRL_ENHBUF BIT(16) /* Enable enhanced buffering */
+#define PIC32_SPI_CTRL_MCLKSEL BIT(23) /* Select SPI Clock src */
+#define PIC32_SPI_CTRL_MSSEN BIT(28) /* SPI macro will drive SS */
+#define PIC32_SPI_CTRL_FRMEN BIT(31) /* Enable framing mode */
+
+/* Bit fields in SPI Status Register */
+#define PIC32_SPI_STAT_RX_OV BIT(6) /* err, s/w needs to clear */
+#define PIC32_SPI_STAT_TF_LVL_MASK 0x1f
+#define PIC32_SPI_STAT_TF_LVL_SHIFT 16
+#define PIC32_SPI_STAT_RF_LVL_MASK 0x1f
+#define PIC32_SPI_STAT_RF_LVL_SHIFT 24
+
+/* Bit fields in SPI Baud Register */
+#define PIC32_SPI_BAUD_MASK 0x1ff
+
+struct pic32_spi_priv {
+ struct pic32_reg_spi *regs;
+ u32 fifo_depth; /* FIFO depth in bytes */
+ u32 fifo_n_word; /* FIFO depth in words */
+ struct gpio_desc cs_gpio;
+
+ /* Current SPI slave specific */
+ ulong clk_rate;
+ u32 speed_hz; /* spi-clk rate */
+ int mode;
+
+ /* Current message/transfer state */
+ const void *tx;
+ const void *tx_end;
+ const void *rx;
+ const void *rx_end;
+ u32 len;
+
+ /* SPI FiFo accessor */
+ void (*rx_fifo)(struct pic32_spi_priv *);
+ void (*tx_fifo)(struct pic32_spi_priv *);
+};
+
+static inline void pic32_spi_enable(struct pic32_spi_priv *priv)
+{
+ writel(PIC32_SPI_CTRL_ON, &priv->regs->ctrl.set);
+}
+
+static inline void pic32_spi_disable(struct pic32_spi_priv *priv)
+{
+ writel(PIC32_SPI_CTRL_ON, &priv->regs->ctrl.clr);
+}
+
+static inline u32 pic32_spi_rx_fifo_level(struct pic32_spi_priv *priv)
+{
+ u32 sr = readl(&priv->regs->status.raw);
+
+ return (sr >> PIC32_SPI_STAT_RF_LVL_SHIFT) & PIC32_SPI_STAT_RF_LVL_MASK;
+}
+
+static inline u32 pic32_spi_tx_fifo_level(struct pic32_spi_priv *priv)
+{
+ u32 sr = readl(&priv->regs->status.raw);
+
+ return (sr >> PIC32_SPI_STAT_TF_LVL_SHIFT) & PIC32_SPI_STAT_TF_LVL_MASK;
+}
+
+/* Return the max entries we can fill into tx fifo */
+static u32 pic32_tx_max(struct pic32_spi_priv *priv, int n_bytes)
+{
+ u32 tx_left, tx_room, rxtx_gap;
+
+ tx_left = (priv->tx_end - priv->tx) / n_bytes;
+ tx_room = priv->fifo_n_word - pic32_spi_tx_fifo_level(priv);
+
+ rxtx_gap = (priv->rx_end - priv->rx) - (priv->tx_end - priv->tx);
+ rxtx_gap /= n_bytes;
+ return min3(tx_left, tx_room, (u32)(priv->fifo_n_word - rxtx_gap));
+}
+
+/* Return the max entries we should read out of rx fifo */
+static u32 pic32_rx_max(struct pic32_spi_priv *priv, int n_bytes)
+{
+ u32 rx_left = (priv->rx_end - priv->rx) / n_bytes;
+
+ return min_t(u32, rx_left, pic32_spi_rx_fifo_level(priv));
+}
+
+#define BUILD_SPI_FIFO_RW(__name, __type, __bwl) \
+static void pic32_spi_rx_##__name(struct pic32_spi_priv *priv) \
+{ \
+ __type val; \
+ u32 mx = pic32_rx_max(priv, sizeof(__type)); \
+ \
+ for (; mx; mx--) { \
+ val = read##__bwl(&priv->regs->buf.raw); \
+ if (priv->rx_end - priv->len) \
+ *(__type *)(priv->rx) = val; \
+ priv->rx += sizeof(__type); \
+ } \
+} \
+ \
+static void pic32_spi_tx_##__name(struct pic32_spi_priv *priv) \
+{ \
+ __type val; \
+ u32 mx = pic32_tx_max(priv, sizeof(__type)); \
+ \
+ for (; mx ; mx--) { \
+ val = (__type) ~0U; \
+ if (priv->tx_end - priv->len) \
+ val = *(__type *)(priv->tx); \
+ write##__bwl(val, &priv->regs->buf.raw); \
+ priv->tx += sizeof(__type); \
+ } \
+}
+BUILD_SPI_FIFO_RW(byte, u8, b);
+BUILD_SPI_FIFO_RW(word, u16, w);
+BUILD_SPI_FIFO_RW(dword, u32, l);
+
+static int pic32_spi_set_word_size(struct pic32_spi_priv *priv,
+ unsigned int wordlen)
+{
+ u32 bits_per_word;
+ u32 val;
+
+ switch (wordlen) {
+ case 8:
+ priv->rx_fifo = pic32_spi_rx_byte;
+ priv->tx_fifo = pic32_spi_tx_byte;
+ bits_per_word = PIC32_SPI_CTRL_BPW_8;
+ break;
+ case 16:
+ priv->rx_fifo = pic32_spi_rx_word;
+ priv->tx_fifo = pic32_spi_tx_word;
+ bits_per_word = PIC32_SPI_CTRL_BPW_16;
+ break;
+ case 32:
+ priv->rx_fifo = pic32_spi_rx_dword;
+ priv->tx_fifo = pic32_spi_tx_dword;
+ bits_per_word = PIC32_SPI_CTRL_BPW_32;
+ break;
+ default:
+ printf("pic32-spi: unsupported wordlen\n");
+ return -EINVAL;
+ }
+
+ /* set bits-per-word */
+ val = readl(&priv->regs->ctrl.raw);
+ val &= ~(PIC32_SPI_CTRL_BPW_MASK << PIC32_SPI_CTRL_BPW_SHIFT);
+ val |= bits_per_word << PIC32_SPI_CTRL_BPW_SHIFT;
+ writel(val, &priv->regs->ctrl.raw);
+
+ /* calculate maximum number of words fifo can hold */
+ priv->fifo_n_word = DIV_ROUND_UP(priv->fifo_depth, wordlen / 8);
+
+ return 0;
+}
+
+static int pic32_spi_claim_bus(struct udevice *slave)
+{
+ struct pic32_spi_priv *priv = dev_get_priv(slave->parent);
+
+ /* enable chip */
+ pic32_spi_enable(priv);
+
+ return 0;
+}
+
+static int pic32_spi_release_bus(struct udevice *slave)
+{
+ struct pic32_spi_priv *priv = dev_get_priv(slave->parent);
+
+ /* disable chip */
+ pic32_spi_disable(priv);
+
+ return 0;
+}
+
+static void spi_cs_activate(struct pic32_spi_priv *priv)
+{
+ if (!dm_gpio_is_valid(&priv->cs_gpio))
+ return;
+
+ dm_gpio_set_value(&priv->cs_gpio, 1);
+}
+
+static void spi_cs_deactivate(struct pic32_spi_priv *priv)
+{
+ if (!dm_gpio_is_valid(&priv->cs_gpio))
+ return;
+
+ dm_gpio_set_value(&priv->cs_gpio, 0);
+}
+
+static int pic32_spi_xfer(struct udevice *slave, unsigned int bitlen,
+ const void *tx_buf, void *rx_buf,
+ unsigned long flags)
+{
+ struct dm_spi_slave_platdata *slave_plat;
+ struct udevice *bus = slave->parent;
+ struct pic32_spi_priv *priv;
+ int len = bitlen / 8;
+ int ret = 0;
+ ulong tbase;
+
+ priv = dev_get_priv(bus);
+ slave_plat = dev_get_parent_platdata(slave);
+
+ debug("spi_xfer: bus:%i cs:%i flags:%lx\n",
+ bus->seq, slave_plat->cs, flags);
+ debug("msg tx %p, rx %p submitted of %d byte(s)\n",
+ tx_buf, rx_buf, len);
+
+ /* assert cs */
+ if (flags & SPI_XFER_BEGIN)
+ spi_cs_activate(priv);
+
+ /* set current transfer information */
+ priv->tx = tx_buf;
+ priv->rx = rx_buf;
+ priv->tx_end = priv->tx + len;
+ priv->rx_end = priv->rx + len;
+ priv->len = len;
+
+ /* transact by polling */
+ tbase = get_timer(0);
+ for (;;) {
+ priv->tx_fifo(priv);
+ priv->rx_fifo(priv);
+
+ /* received sufficient data */
+ if (priv->rx >= priv->rx_end) {
+ ret = 0;
+ break;
+ }
+
+ if (get_timer(tbase) > 5 * CONFIG_SYS_HZ) {
+ printf("pic32_spi: error, xfer timedout.\n");
+ flags |= SPI_XFER_END;
+ ret = -ETIMEDOUT;
+ break;
+ }
+ }
+
+ /* deassert cs */
+ if (flags & SPI_XFER_END)
+ spi_cs_deactivate(priv);
+
+ return ret;
+}
+
+static int pic32_spi_set_speed(struct udevice *bus, uint speed)
+{
+ struct pic32_spi_priv *priv = dev_get_priv(bus);
+ u32 div;
+
+ debug("%s: %s, speed %u\n", __func__, bus->name, speed);
+
+ /* div = [clk_in / (2 * spi_clk)] - 1 */
+ div = (priv->clk_rate / 2 / speed) - 1;
+ div &= PIC32_SPI_BAUD_MASK;
+ writel(div, &priv->regs->baud.raw);
+
+ priv->speed_hz = speed;
+
+ return 0;
+}
+
+static int pic32_spi_set_mode(struct udevice *bus, uint mode)
+{
+ struct pic32_spi_priv *priv = dev_get_priv(bus);
+ u32 val;
+
+ debug("%s: %s, mode %d\n", __func__, bus->name, mode);
+
+ /* set spi-clk mode */
+ val = readl(&priv->regs->ctrl.raw);
+ /* HIGH when idle */
+ if (mode & SPI_CPOL)
+ val |= PIC32_SPI_CTRL_CKP;
+ else
+ val &= ~PIC32_SPI_CTRL_CKP;
+
+ /* TX at idle-to-active clk transition */
+ if (mode & SPI_CPHA)
+ val &= ~PIC32_SPI_CTRL_CKE;
+ else
+ val |= PIC32_SPI_CTRL_CKE;
+
+ /* RX at end of tx */
+ val |= PIC32_SPI_CTRL_SMP;
+ writel(val, &priv->regs->ctrl.raw);
+
+ priv->mode = mode;
+
+ return 0;
+}
+
+static int pic32_spi_set_wordlen(struct udevice *slave, unsigned int wordlen)
+{
+ struct pic32_spi_priv *priv = dev_get_priv(slave->parent);
+
+ return pic32_spi_set_word_size(priv, wordlen);
+}
+
+static void pic32_spi_hw_init(struct pic32_spi_priv *priv)
+{
+ u32 val;
+
+ /* disable module */
+ pic32_spi_disable(priv);
+
+ val = readl(&priv->regs->ctrl);
+
+ /* enable enhanced fifo of 128bit deep */
+ val |= PIC32_SPI_CTRL_ENHBUF;
+ priv->fifo_depth = 16;
+
+ /* disable framing mode */
+ val &= ~PIC32_SPI_CTRL_FRMEN;
+
+ /* enable master mode */
+ val |= PIC32_SPI_CTRL_MSTEN;
+
+ /* select clk source */
+ val &= ~PIC32_SPI_CTRL_MCLKSEL;
+
+ /* set manual /CS mode */
+ val &= ~PIC32_SPI_CTRL_MSSEN;
+
+ writel(val, &priv->regs->ctrl);
+
+ /* clear rx overflow indicator */
+ writel(PIC32_SPI_STAT_RX_OV, &priv->regs->status.clr);
+}
+
+static int pic32_spi_probe(struct udevice *bus)
+{
+ struct pic32_spi_priv *priv = dev_get_priv(bus);
+ struct dm_spi_bus *dm_spi = dev_get_uclass_priv(bus);
+ struct udevice *clkdev;
+ fdt_addr_t addr;
+ fdt_size_t size;
+ int ret;
+
+ debug("%s: %d, bus: %i\n", __func__, __LINE__, bus->seq);
+ addr = fdtdec_get_addr_size(gd->fdt_blob, bus->of_offset, "reg", &size);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ priv->regs = ioremap(addr, size);
+ if (!priv->regs)
+ return -EINVAL;
+
+ dm_spi->max_hz = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
+ "spi-max-frequency", 250000000);
+ /* get clock rate */
+ ret = clk_get_by_index(bus, 0, &clkdev);
+ if (ret < 0) {
+ printf("pic32-spi: error, clk not found\n");
+ return ret;
+ }
+ priv->clk_rate = clk_get_periph_rate(clkdev, ret);
+
+ /* initialize HW */
+ pic32_spi_hw_init(priv);
+
+ /* set word len */
+ pic32_spi_set_word_size(priv, SPI_DEFAULT_WORDLEN);
+
+ /* PIC32 SPI controller can automatically drive /CS during transfer
+ * depending on fifo fill-level. /CS will stay asserted as long as
+ * TX fifo is non-empty, else will be deasserted confirming completion
+ * of the ongoing transfer. To avoid this sort of error we will drive
+ * /CS manually by toggling cs-gpio pins.
+ */
+ ret = gpio_request_by_name_nodev(gd->fdt_blob, bus->of_offset,
+ "cs-gpios", 0,
+ &priv->cs_gpio, GPIOD_IS_OUT);
+ if (ret) {
+ printf("pic32-spi: error, cs-gpios not found\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct dm_spi_ops pic32_spi_ops = {
+ .claim_bus = pic32_spi_claim_bus,
+ .release_bus = pic32_spi_release_bus,
+ .xfer = pic32_spi_xfer,
+ .set_speed = pic32_spi_set_speed,
+ .set_mode = pic32_spi_set_mode,
+ .set_wordlen = pic32_spi_set_wordlen,
+};
+
+static const struct udevice_id pic32_spi_ids[] = {
+ { .compatible = "microchip,pic32mzda-spi" },
+ { }
+};
+
+U_BOOT_DRIVER(pic32_spi) = {
+ .name = "pic32_spi",
+ .id = UCLASS_SPI,
+ .of_match = pic32_spi_ids,
+ .ops = &pic32_spi_ops,
+ .priv_auto_alloc_size = sizeof(struct pic32_spi_priv),
+ .probe = pic32_spi_probe,
+};
diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c
index 3081afca0e..c016a0bb54 100644
--- a/drivers/usb/musb-new/sunxi.c
+++ b/drivers/usb/musb-new/sunxi.c
@@ -340,9 +340,16 @@ int musb_usb_probe(struct udevice *dev)
int musb_usb_remove(struct udevice *dev)
{
struct musb_host_data *host = dev_get_priv(dev);
+ struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
musb_stop(host->host);
+ sunxi_usb_phy_exit(0);
+#ifdef CONFIG_SUNXI_GEN_SUN6I
+ clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0);
+#endif
+ clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0);
+
return 0;
}
OpenPOWER on IntegriCloud