diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/Makefile | 1 | ||||
-rw-r--r-- | drivers/block/dwc_ahsata.c | 2 | ||||
-rw-r--r-- | drivers/crypto/rsa_mod_exp/mod_exp_sw.c | 1 | ||||
-rw-r--r-- | drivers/gpio/intel_broadwell_gpio.c | 7 | ||||
-rw-r--r-- | drivers/gpio/intel_ich6_gpio.c | 5 | ||||
-rw-r--r-- | drivers/i2c/i2c_core.c | 5 | ||||
-rw-r--r-- | drivers/i2c/mxc_i2c.c | 27 | ||||
-rw-r--r-- | drivers/misc/mxc_ocotp.c | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/mxs_nand.c | 2 | ||||
-rw-r--r-- | drivers/net/fec_mxc.c | 2 | ||||
-rw-r--r-- | drivers/spi/Kconfig | 8 | ||||
-rw-r--r-- | drivers/spi/Makefile | 1 | ||||
-rw-r--r-- | drivers/spi/pic32_spi.c | 448 | ||||
-rw-r--r-- | drivers/usb/musb-new/sunxi.c | 7 |
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; } |