diff options
Diffstat (limited to 'drivers/spi/altera_spi.c')
-rw-r--r-- | drivers/spi/altera_spi.c | 197 |
1 files changed, 111 insertions, 86 deletions
diff --git a/drivers/spi/altera_spi.c b/drivers/spi/altera_spi.c index a4d03d9..ff3512a 100644 --- a/drivers/spi/altera_spi.c +++ b/drivers/spi/altera_spi.c @@ -8,18 +8,19 @@ * SPDX-License-Identifier: GPL-2.0+ */ #include <common.h> -#include <asm/io.h> +#include <dm.h> +#include <errno.h> #include <malloc.h> #include <spi.h> +#include <fdtdec.h> +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; #ifndef CONFIG_ALTERA_SPI_IDLE_VAL #define CONFIG_ALTERA_SPI_IDLE_VAL 0xff #endif -#ifndef CONFIG_SYS_ALTERA_SPI_LIST -#define CONFIG_SYS_ALTERA_SPI_LIST { CONFIG_SYS_SPI_BASE } -#endif - struct altera_spi_regs { u32 rxdata; u32 txdata; @@ -29,102 +30,68 @@ struct altera_spi_regs { u32 slave_sel; }; -#define ALTERA_SPI_STATUS_ROE_MSK (1 << 3) -#define ALTERA_SPI_STATUS_TOE_MSK (1 << 4) -#define ALTERA_SPI_STATUS_TMT_MSK (1 << 5) -#define ALTERA_SPI_STATUS_TRDY_MSK (1 << 6) -#define ALTERA_SPI_STATUS_RRDY_MSK (1 << 7) -#define ALTERA_SPI_STATUS_E_MSK (1 << 8) - -#define ALTERA_SPI_CONTROL_IROE_MSK (1 << 3) -#define ALTERA_SPI_CONTROL_ITOE_MSK (1 << 4) -#define ALTERA_SPI_CONTROL_ITRDY_MSK (1 << 6) -#define ALTERA_SPI_CONTROL_IRRDY_MSK (1 << 7) -#define ALTERA_SPI_CONTROL_IE_MSK (1 << 8) -#define ALTERA_SPI_CONTROL_SSO_MSK (1 << 10) - -static ulong altera_spi_base_list[] = CONFIG_SYS_ALTERA_SPI_LIST; +struct altera_spi_platdata { + struct altera_spi_regs *regs; +}; -struct altera_spi_slave { - struct spi_slave slave; - struct altera_spi_regs *regs; +struct altera_spi_priv { + struct altera_spi_regs *regs; }; -#define to_altera_spi_slave(s) container_of(s, struct altera_spi_slave, slave) -__weak int spi_cs_is_valid(unsigned int bus, unsigned int cs) -{ - return bus < ARRAY_SIZE(altera_spi_base_list) && cs < 32; -} +#define ALTERA_SPI_STATUS_RRDY_MSK (1 << 7) +#define ALTERA_SPI_CONTROL_SSO_MSK (1 << 10) -__weak void spi_cs_activate(struct spi_slave *slave) +static void spi_cs_activate(struct udevice *dev, uint cs) { - struct altera_spi_slave *altspi = to_altera_spi_slave(slave); - writel(1 << slave->cs, &altspi->regs->slave_sel); - writel(ALTERA_SPI_CONTROL_SSO_MSK, &altspi->regs->control); -} + struct udevice *bus = dev->parent; + struct altera_spi_priv *priv = dev_get_priv(bus); + struct altera_spi_regs *const regs = priv->regs; -__weak void spi_cs_deactivate(struct spi_slave *slave) -{ - struct altera_spi_slave *altspi = to_altera_spi_slave(slave); - writel(0, &altspi->regs->control); - writel(0, &altspi->regs->slave_sel); + writel(1 << cs, ®s->slave_sel); + writel(ALTERA_SPI_CONTROL_SSO_MSK, ®s->control); } -void spi_init(void) +static void spi_cs_deactivate(struct udevice *dev) { -} + struct udevice *bus = dev->parent; + struct altera_spi_priv *priv = dev_get_priv(bus); + struct altera_spi_regs *const regs = priv->regs; -void spi_set_speed(struct spi_slave *slave, uint hz) -{ - /* altera spi core does not support programmable speed */ + writel(0, ®s->control); + writel(0, ®s->slave_sel); } -struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, - unsigned int max_hz, unsigned int mode) +static int altera_spi_claim_bus(struct udevice *dev) { - 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; + struct udevice *bus = dev->parent; + struct altera_spi_priv *priv = dev_get_priv(bus); + struct altera_spi_regs *const regs = priv->regs; - altspi->regs = (struct altera_spi_regs *)altera_spi_base_list[bus]; - debug("%s: bus:%i cs:%i base:%p\n", __func__, bus, cs, altspi->regs); + writel(0, ®s->control); + writel(0, ®s->slave_sel); - return &altspi->slave; + return 0; } -void spi_free_slave(struct spi_slave *slave) +static int altera_spi_release_bus(struct udevice *dev) { - struct altera_spi_slave *altspi = to_altera_spi_slave(slave); - free(altspi); -} + struct udevice *bus = dev->parent; + struct altera_spi_priv *priv = dev_get_priv(bus); + struct altera_spi_regs *const regs = priv->regs; -int spi_claim_bus(struct spi_slave *slave) -{ - struct altera_spi_slave *altspi = to_altera_spi_slave(slave); + writel(0, ®s->slave_sel); - debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs); - writel(0, &altspi->regs->control); - writel(0, &altspi->regs->slave_sel); return 0; } -void spi_release_bus(struct spi_slave *slave) +static int altera_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) { - struct altera_spi_slave *altspi = to_altera_spi_slave(slave); + struct udevice *bus = dev->parent; + struct altera_spi_priv *priv = dev_get_priv(bus); + struct altera_spi_regs *const regs = priv->regs; + struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); - debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs); - writel(0, &altspi->regs->slave_sel); -} - -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 */ unsigned int bytes = bitlen / 8; const unsigned char *txp = dout; @@ -132,7 +99,7 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, uint32_t reg, data, start; debug("%s: bus:%i cs:%i bitlen:%i bytes:%i flags:%lx\n", __func__, - slave->bus, slave->cs, bitlen, bytes, flags); + bus->seq, slave_plat->cs, bitlen, bytes, flags); if (bitlen == 0) goto done; @@ -143,11 +110,11 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, } /* empty read buffer */ - if (readl(&altspi->regs->status) & ALTERA_SPI_STATUS_RRDY_MSK) - readl(&altspi->regs->rxdata); + if (readl(®s->status) & ALTERA_SPI_STATUS_RRDY_MSK) + readl(®s->rxdata); if (flags & SPI_XFER_BEGIN) - spi_cs_activate(slave); + spi_cs_activate(dev, slave_plat->cs); while (bytes--) { if (txp) @@ -156,20 +123,20 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, data = CONFIG_ALTERA_SPI_IDLE_VAL; debug("%s: tx:%x ", __func__, data); - writel(data, &altspi->regs->txdata); + writel(data, ®s->txdata); start = get_timer(0); while (1) { - reg = readl(&altspi->regs->status); + reg = readl(®s->status); if (reg & ALTERA_SPI_STATUS_RRDY_MSK) break; if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) { - printf("%s: Transmission timed out!\n", __func__); - goto done; + debug("%s: Transmission timed out!\n", __func__); + return -1; } } - data = readl(&altspi->regs->rxdata); + data = readl(®s->rxdata); if (rxp) *rxp++ = data & 0xff; @@ -178,7 +145,65 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout, done: if (flags & SPI_XFER_END) - spi_cs_deactivate(slave); + spi_cs_deactivate(dev); return 0; } + +static int altera_spi_set_speed(struct udevice *bus, uint speed) +{ + return 0; +} + +static int altera_spi_set_mode(struct udevice *bus, uint mode) +{ + return 0; +} + +static int altera_spi_probe(struct udevice *bus) +{ + struct altera_spi_platdata *plat = dev_get_platdata(bus); + struct altera_spi_priv *priv = dev_get_priv(bus); + + priv->regs = plat->regs; + + return 0; +} + +static int altera_spi_ofdata_to_platdata(struct udevice *bus) +{ + struct altera_spi_platdata *plat = dev_get_platdata(bus); + + plat->regs = ioremap(dev_get_addr(bus), + sizeof(struct altera_spi_regs)); + + return 0; +} + +static const struct dm_spi_ops altera_spi_ops = { + .claim_bus = altera_spi_claim_bus, + .release_bus = altera_spi_release_bus, + .xfer = altera_spi_xfer, + .set_speed = altera_spi_set_speed, + .set_mode = altera_spi_set_mode, + /* + * cs_info is not needed, since we require all chip selects to be + * in the device tree explicitly + */ +}; + +static const struct udevice_id altera_spi_ids[] = { + { .compatible = "altr,spi-1.0", }, + { } +}; + +U_BOOT_DRIVER(altera_spi) = { + .name = "altera_spi", + .id = UCLASS_SPI, + .of_match = altera_spi_ids, + .ops = &altera_spi_ops, + .ofdata_to_platdata = altera_spi_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct altera_spi_platdata), + .priv_auto_alloc_size = sizeof(struct altera_spi_priv), + .probe = altera_spi_probe, +}; |