* [PATCH 0/5] Add fsl-dspi driver support @ 2020-03-25 8:36 Sascha Hauer 2020-03-25 8:36 ` [PATCH 1/5] regmap-mmio: Add missing pieces for 64bit support Sascha Hauer ` (4 more replies) 0 siblings, 5 replies; 8+ messages in thread From: Sascha Hauer @ 2020-03-25 8:36 UTC (permalink / raw) To: Barebox List The fsl-dspi is a SPI core that is found on Freescale Layerscape SoCs. This series adds support for it. It uses regmap to access registers and it's connected in big-endian, so we need some regmap patches to support such maps. Sascha Hauer (5): regmap-mmio: Add missing pieces for 64bit support regmap-mmio: Add big endian support spi: validate spi messages spi: Add fsl-dspi driver mtd: spi-nor: Add support for cy15x104q drivers/base/regmap/internal.h | 4 + drivers/base/regmap/regmap-mmio.c | 94 ++++- drivers/base/regmap/regmap.c | 44 ++ drivers/mtd/spi-nor/spi-nor.c | 3 + drivers/spi/Kconfig | 7 + drivers/spi/Makefile | 1 + drivers/spi/spi-fsl-dspi.c | 655 ++++++++++++++++++++++++++++++ drivers/spi/spi.c | 46 +++ include/regmap.h | 13 + include/spi/spi.h | 4 + 10 files changed, 857 insertions(+), 14 deletions(-) create mode 100644 drivers/spi/spi-fsl-dspi.c -- 2.26.0.rc2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/5] regmap-mmio: Add missing pieces for 64bit support 2020-03-25 8:36 [PATCH 0/5] Add fsl-dspi driver support Sascha Hauer @ 2020-03-25 8:36 ` Sascha Hauer 2020-03-25 8:36 ` [PATCH 2/5] regmap-mmio: Add big endian support Sascha Hauer ` (3 subsequent siblings) 4 siblings, 0 replies; 8+ messages in thread From: Sascha Hauer @ 2020-03-25 8:36 UTC (permalink / raw) To: Barebox List The 64bit accessor functions are present, but unused. Hook them up when needed. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/base/regmap/regmap-mmio.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index f8d2cda843..ef6a7db6fd 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c @@ -197,6 +197,12 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs, ctx->reg_read = regmap_mmio_read32le; ctx->reg_write = regmap_mmio_write32le; break; +#ifdef CONFIG_64BIT + case 64: + ctx->reg_read = regmap_mmio_read64le; + ctx->reg_write = regmap_mmio_write64le; + break; +#endif default: ret = -EINVAL; goto err_free; -- 2.26.0.rc2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/5] regmap-mmio: Add big endian support 2020-03-25 8:36 [PATCH 0/5] Add fsl-dspi driver support Sascha Hauer 2020-03-25 8:36 ` [PATCH 1/5] regmap-mmio: Add missing pieces for 64bit support Sascha Hauer @ 2020-03-25 8:36 ` Sascha Hauer 2020-03-25 8:36 ` [PATCH 3/5] spi: validate spi messages Sascha Hauer ` (2 subsequent siblings) 4 siblings, 0 replies; 8+ messages in thread From: Sascha Hauer @ 2020-03-25 8:36 UTC (permalink / raw) To: Barebox List Add support for parsing the big-endian device tree property. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/base/regmap/internal.h | 4 ++ drivers/base/regmap/regmap-mmio.c | 98 +++++++++++++++++++++++++------ drivers/base/regmap/regmap.c | 44 ++++++++++++++ include/regmap.h | 13 ++++ 4 files changed, 140 insertions(+), 19 deletions(-) diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 5b19459828..4c7460fa4c 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -22,4 +22,8 @@ struct regmap { struct cdev cdev; }; +enum regmap_endian regmap_get_val_endian(struct device_d *dev, + const struct regmap_bus *bus, + const struct regmap_config *config); + #endif diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index ef6a7db6fd..492dd16ff5 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c @@ -86,6 +86,20 @@ static void regmap_mmio_write32le(struct regmap_mmio_context *ctx, writel(val, ctx->regs + reg); } +static void regmap_mmio_write16be(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + iowrite16be(val, ctx->regs + reg); +} + +static void regmap_mmio_write32be(struct regmap_mmio_context *ctx, + unsigned int reg, + unsigned int val) +{ + iowrite32be(val, ctx->regs + reg); +} + #ifdef CONFIG_64BIT static void regmap_mmio_write64le(struct regmap_mmio_context *ctx, unsigned int reg, @@ -137,6 +151,18 @@ static unsigned int regmap_mmio_read64le(struct regmap_mmio_context *ctx, } #endif +static unsigned int regmap_mmio_read16be(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return ioread16be(ctx->regs + reg); +} + +static unsigned int regmap_mmio_read32be(struct regmap_mmio_context *ctx, + unsigned int reg) +{ + return ioread32be(ctx->regs + reg); +} + static int regmap_mmio_read(void *context, unsigned int reg, unsigned int *val) { struct regmap_mmio_context *ctx = context; @@ -158,7 +184,8 @@ static const struct regmap_bus regmap_mmio = { .reg_read = regmap_mmio_read, }; -static struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs, +static struct regmap_mmio_context *regmap_mmio_gen_context(struct device_d *dev, + void __iomem *regs, const struct regmap_config *config) { struct regmap_mmio_context *ctx; @@ -184,25 +211,58 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs, ctx->regs = regs; ctx->val_bytes = config->val_bits / 8; - switch (config->val_bits) { - case 8: - ctx->reg_read = regmap_mmio_read8; - ctx->reg_write = regmap_mmio_write8; - break; - case 16: - ctx->reg_read = regmap_mmio_read16le; - ctx->reg_write = regmap_mmio_write16le; - break; - case 32: - ctx->reg_read = regmap_mmio_read32le; - ctx->reg_write = regmap_mmio_write32le; - break; + switch (regmap_get_val_endian(dev, ®map_mmio, config)) { + case REGMAP_ENDIAN_DEFAULT: + case REGMAP_ENDIAN_LITTLE: +#ifdef __LITTLE_ENDIAN + case REGMAP_ENDIAN_NATIVE: +#endif + switch (config->val_bits) { + case 8: + ctx->reg_read = regmap_mmio_read8; + ctx->reg_write = regmap_mmio_write8; + break; + case 16: + ctx->reg_read = regmap_mmio_read16le; + ctx->reg_write = regmap_mmio_write16le; + break; + case 32: + ctx->reg_read = regmap_mmio_read32le; + ctx->reg_write = regmap_mmio_write32le; + break; #ifdef CONFIG_64BIT - case 64: - ctx->reg_read = regmap_mmio_read64le; - ctx->reg_write = regmap_mmio_write64le; + case 64: + ctx->reg_read = regmap_mmio_read64le; + ctx->reg_write = regmap_mmio_write64le; + break; +#endif + default: + ret = -EINVAL; + goto err_free; + } break; + case REGMAP_ENDIAN_BIG: +#ifdef __BIG_ENDIAN + case REGMAP_ENDIAN_NATIVE: #endif + switch (config->val_bits) { + case 8: + ctx->reg_read = regmap_mmio_read8; + ctx->reg_write = regmap_mmio_write8; + break; + case 16: + ctx->reg_read = regmap_mmio_read16be; + ctx->reg_write = regmap_mmio_write16be; + break; + case 32: + ctx->reg_read = regmap_mmio_read32be; + ctx->reg_write = regmap_mmio_write32be; + break; + default: + ret = -EINVAL; + goto err_free; + } + break; default: ret = -EINVAL; goto err_free; @@ -223,7 +283,7 @@ struct regmap *regmap_init_mmio_clk(struct device_d *dev, { struct regmap_mmio_context *ctx; - ctx = regmap_mmio_gen_context(regs, config); + ctx = regmap_mmio_gen_context(dev, regs, config); if (IS_ERR(ctx)) return ERR_CAST(ctx); @@ -245,7 +305,7 @@ struct regmap *of_regmap_init_mmio_clk(struct device_node *np, { struct regmap_mmio_context *ctx; - ctx = regmap_mmio_gen_context(regs, config); + ctx = regmap_mmio_gen_context(NULL, regs, config); if (IS_ERR(ctx)) return ERR_CAST(ctx); diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index dc7b4f276f..374d3ea3d6 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -28,6 +28,50 @@ static LIST_HEAD(regmaps); +enum regmap_endian regmap_get_val_endian(struct device_d *dev, + const struct regmap_bus *bus, + const struct regmap_config *config) +{ + struct device_node *np; + enum regmap_endian endian; + + /* Retrieve the endianness specification from the regmap config */ + endian = config->val_format_endian; + + /* If the regmap config specified a non-default value, use that */ + if (endian != REGMAP_ENDIAN_DEFAULT) + return endian; + + /* If the dev and dev->device_node exist try to get endianness from DT */ + if (dev && dev->device_node) { + np = dev->device_node; + + /* Parse the device's DT node for an endianness specification */ + if (of_property_read_bool(np, "big-endian")) + endian = REGMAP_ENDIAN_BIG; + else if (of_property_read_bool(np, "little-endian")) + endian = REGMAP_ENDIAN_LITTLE; + else if (of_property_read_bool(np, "native-endian")) + endian = REGMAP_ENDIAN_NATIVE; + + /* If the endianness was specified in DT, use that */ + if (endian != REGMAP_ENDIAN_DEFAULT) + return endian; + } + + /* Retrieve the endianness specification from the bus config */ + if (bus && bus->val_format_endian_default) + endian = bus->val_format_endian_default; + + /* If the bus specified a non-default value, use that */ + if (endian != REGMAP_ENDIAN_DEFAULT) + return endian; + + /* Use this if no other value was found */ + return REGMAP_ENDIAN_BIG; +} +EXPORT_SYMBOL_GPL(regmap_get_val_endian); + /* * regmap_init - initialize and register a regmap * diff --git a/include/regmap.h b/include/regmap.h index 3bcd9fe038..139ac33ec3 100644 --- a/include/regmap.h +++ b/include/regmap.h @@ -2,6 +2,14 @@ #ifndef __REGMAP_H #define __REGMAP_H +enum regmap_endian { + /* Unspecified -> 0 -> Backwards compatible default */ + REGMAP_ENDIAN_DEFAULT = 0, + REGMAP_ENDIAN_BIG, + REGMAP_ENDIAN_LITTLE, + REGMAP_ENDIAN_NATIVE, +}; + /** * Configuration for the register map of a device. * @@ -26,6 +34,9 @@ struct regmap_config { int val_bits; unsigned int max_register; + + enum regmap_endian reg_format_endian; + enum regmap_endian val_format_endian; }; typedef int (*regmap_hw_reg_read)(void *context, unsigned int reg, @@ -36,6 +47,8 @@ typedef int (*regmap_hw_reg_write)(void *context, unsigned int reg, struct regmap_bus { regmap_hw_reg_write reg_write; regmap_hw_reg_read reg_read; + enum regmap_endian reg_format_endian_default; + enum regmap_endian val_format_endian_default; }; struct device_d; -- 2.26.0.rc2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 3/5] spi: validate spi messages 2020-03-25 8:36 [PATCH 0/5] Add fsl-dspi driver support Sascha Hauer 2020-03-25 8:36 ` [PATCH 1/5] regmap-mmio: Add missing pieces for 64bit support Sascha Hauer 2020-03-25 8:36 ` [PATCH 2/5] regmap-mmio: Add big endian support Sascha Hauer @ 2020-03-25 8:36 ` Sascha Hauer 2020-03-25 8:36 ` [PATCH 4/5] spi: Add fsl-dspi driver Sascha Hauer 2020-03-25 8:36 ` [PATCH 5/5] mtd: spi-nor: Add support for cy15x104q Sascha Hauer 4 siblings, 0 replies; 8+ messages in thread From: Sascha Hauer @ 2020-03-25 8:36 UTC (permalink / raw) To: Barebox List This adds __spi_validate() to validate spi messages. This function is a stripped down version from the Kernel. The motivation for adding this was to fill in xfer->bits_per_word from spi->bits_per_word so that a spi bus driver can use the former. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/spi/spi.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ include/spi/spi.h | 4 ++++ 2 files changed, 50 insertions(+) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index bd615b4e99..0694f14c39 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -297,8 +297,54 @@ struct spi_controller *spi_get_controller(int bus) return NULL; } +static int __spi_validate(struct spi_device *spi, struct spi_message *message) +{ + struct spi_controller *ctlr = spi->controller; + struct spi_transfer *xfer; + int w_size; + + if (list_empty(&message->transfers)) + return -EINVAL; + + list_for_each_entry(xfer, &message->transfers, transfer_list) { + if (!xfer->bits_per_word) + xfer->bits_per_word = spi->bits_per_word; + + if (!xfer->speed_hz) + xfer->speed_hz = spi->max_speed_hz; + + if (ctlr->max_speed_hz && xfer->speed_hz > ctlr->max_speed_hz) + xfer->speed_hz = ctlr->max_speed_hz; + + /* + * SPI transfer length should be multiple of SPI word size + * where SPI word size should be power-of-two multiple + */ + if (xfer->bits_per_word <= 8) + w_size = 1; + else if (xfer->bits_per_word <= 16) + w_size = 2; + else + w_size = 4; + + /* No partial transfers accepted */ + if (xfer->len % w_size) + return -EINVAL; + } + + message->status = -EINPROGRESS; + + return 0; +} + int spi_sync(struct spi_device *spi, struct spi_message *message) { + int status; + + status = __spi_validate(spi, message); + if (status != 0) + return status; + return spi->controller->transfer(spi, message); } diff --git a/include/spi/spi.h b/include/spi/spi.h index 48a90bcca7..66e0500d04 100644 --- a/include/spi/spi.h +++ b/include/spi/spi.h @@ -126,6 +126,7 @@ struct spi_message; * SPI slaves, and are numbered from zero to num_chipselects. * each slave has a chipselect signal, but it's common that not * every chipselect is connected to a slave. + * @max_speed_hz: Highest supported transfer speed * @setup: updates the device mode and clocking records used by a * device's SPI controller; protocol code may call this. This * must fail if an unrecognized or unsupported mode is requested. @@ -171,6 +172,9 @@ struct spi_controller { */ u16 num_chipselect; + /* limits on transfer speed */ + u32 max_speed_hz; + /* setup mode and clock, etc (spi driver may call many times) */ int (*setup)(struct spi_device *spi); -- 2.26.0.rc2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 4/5] spi: Add fsl-dspi driver 2020-03-25 8:36 [PATCH 0/5] Add fsl-dspi driver support Sascha Hauer ` (2 preceding siblings ...) 2020-03-25 8:36 ` [PATCH 3/5] spi: validate spi messages Sascha Hauer @ 2020-03-25 8:36 ` Sascha Hauer 2020-04-04 19:14 ` Andrey Smirnov 2020-03-25 8:36 ` [PATCH 5/5] mtd: spi-nor: Add support for cy15x104q Sascha Hauer 4 siblings, 1 reply; 8+ messages in thread From: Sascha Hauer @ 2020-03-25 8:36 UTC (permalink / raw) To: Barebox List The fsl-dspi is found on Freescale Vybrid, Coldfire and Layerscape SoCs. This adds the driver based on the Linux driver as of v5.5. Coldfire support has been dropped as it's rather obsolete. Vybrid support has been dropped because it needs the DMA engine support we do not have in barebox. What's left is support for Layerscape where this driver has been tested on. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/spi/Kconfig | 7 + drivers/spi/Makefile | 1 + drivers/spi/spi-fsl-dspi.c | 655 +++++++++++++++++++++++++++++++++++++ 3 files changed, 663 insertions(+) create mode 100644 drivers/spi/spi-fsl-dspi.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 3758a0fad9..96235a1be2 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -44,6 +44,13 @@ config DRIVER_SPI_FSL_QUADSPI This controller does not support generic SPI messages. It only supports the high-level SPI memory interface. +config SPI_FSL_DSPI + bool "Freescale DSPI controller" + depends on ARCH_LAYERSCAPE + help + This enables support for the Freescale DSPI controller in master + mode. VF610, LS1021A and ColdFire platforms uses the controller. + config DRIVER_SPI_GPIO bool "GPIO SPI Master driver" depends on GPIOLIB diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 75a89ef38e..908d514a01 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_DRIVER_SPI_MVEBU) += mvebu_spi.o obj-$(CONFIG_DRIVER_SPI_MXS) += mxs_spi.o obj-$(CONFIG_DRIVER_SPI_ALTERA) += altera_spi.o obj-$(CONFIG_DRIVER_SPI_ATMEL) += atmel_spi.o +obj-$(CONFIG_SPI_FSL_DSPI) += spi-fsl-dspi.o obj-$(CONFIG_SPI_ATMEL_QUADSPI) += atmel-quadspi.o obj-$(CONFIG_DRIVER_SPI_OMAP3) += omap3_spi.o obj-$(CONFIG_DRIVER_SPI_DSPI) += dspi_spi.o diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c new file mode 100644 index 0000000000..a7ceb854e9 --- /dev/null +++ b/drivers/spi/spi-fsl-dspi.c @@ -0,0 +1,655 @@ +// SPDX-License-Identifier: GPL-2.0+ +// +// Copyright 2013 Freescale Semiconductor, Inc. +// +// Freescale DSPI driver +// This file contains a driver for the Freescale DSPI + +#include <common.h> +#include <driver.h> +#include <errno.h> +#include <init.h> +#include <io.h> +#include <regmap.h> +#include <spi/spi.h> +#include <linux/clk.h> +#include <linux/math64.h> + +#define DRIVER_NAME "fsl-dspi" + +#define DSPI_FIFO_SIZE 4 +#define DSPI_DMA_BUFSIZE (DSPI_FIFO_SIZE * 1024) + +#define SPI_MCR 0x00 +#define SPI_MCR_MASTER BIT(31) +#define SPI_MCR_PCSIS (0x3F << 16) +#define SPI_MCR_CLR_TXF BIT(11) +#define SPI_MCR_CLR_RXF BIT(10) +#define SPI_MCR_XSPI BIT(3) + +#define SPI_TCR 0x08 +#define SPI_TCR_GET_TCNT(x) (((x) & GENMASK(31, 16)) >> 16) + +#define SPI_CTAR(x) (0x0c + (((x) & GENMASK(1, 0)) * 4)) +#define SPI_CTAR_FMSZ(x) (((x) << 27) & GENMASK(30, 27)) +#define SPI_CTAR_CPOL BIT(26) +#define SPI_CTAR_CPHA BIT(25) +#define SPI_CTAR_LSBFE BIT(24) +#define SPI_CTAR_PCSSCK(x) (((x) << 22) & GENMASK(23, 22)) +#define SPI_CTAR_PASC(x) (((x) << 20) & GENMASK(21, 20)) +#define SPI_CTAR_PDT(x) (((x) << 18) & GENMASK(19, 18)) +#define SPI_CTAR_PBR(x) (((x) << 16) & GENMASK(17, 16)) +#define SPI_CTAR_CSSCK(x) (((x) << 12) & GENMASK(15, 12)) +#define SPI_CTAR_ASC(x) (((x) << 8) & GENMASK(11, 8)) +#define SPI_CTAR_DT(x) (((x) << 4) & GENMASK(7, 4)) +#define SPI_CTAR_BR(x) ((x) & GENMASK(3, 0)) +#define SPI_CTAR_SCALE_BITS 0xf + +#define SPI_CTAR0_SLAVE 0x0c + +#define SPI_SR 0x2c +#define SPI_SR_TCFQF BIT(31) +#define SPI_SR_EOQF BIT(28) +#define SPI_SR_TFUF BIT(27) +#define SPI_SR_TFFF BIT(25) +#define SPI_SR_CMDTCF BIT(23) +#define SPI_SR_SPEF BIT(21) +#define SPI_SR_RFOF BIT(19) +#define SPI_SR_TFIWF BIT(18) +#define SPI_SR_RFDF BIT(17) +#define SPI_SR_CMDFFF BIT(16) +#define SPI_SR_CLEAR (SPI_SR_TCFQF | SPI_SR_EOQF | \ + SPI_SR_TFUF | SPI_SR_TFFF | \ + SPI_SR_CMDTCF | SPI_SR_SPEF | \ + SPI_SR_RFOF | SPI_SR_TFIWF | \ + SPI_SR_RFDF | SPI_SR_CMDFFF) + +#define SPI_RSER_TFFFE BIT(25) +#define SPI_RSER_TFFFD BIT(24) +#define SPI_RSER_RFDFE BIT(17) +#define SPI_RSER_RFDFD BIT(16) + +#define SPI_RSER 0x30 +#define SPI_RSER_TCFQE BIT(31) +#define SPI_RSER_EOQFE BIT(28) + +#define SPI_PUSHR 0x34 +#define SPI_PUSHR_CMD_CONT BIT(15) +#define SPI_PUSHR_CMD_CTAS(x) (((x) << 12 & GENMASK(14, 12))) +#define SPI_PUSHR_CMD_EOQ BIT(11) +#define SPI_PUSHR_CMD_CTCNT BIT(10) +#define SPI_PUSHR_CMD_PCS(x) (BIT(x) & GENMASK(5, 0)) + +#define SPI_PUSHR_SLAVE 0x34 + +#define SPI_POPR 0x38 + +#define SPI_TXFR0 0x3c +#define SPI_TXFR1 0x40 +#define SPI_TXFR2 0x44 +#define SPI_TXFR3 0x48 +#define SPI_RXFR0 0x7c +#define SPI_RXFR1 0x80 +#define SPI_RXFR2 0x84 +#define SPI_RXFR3 0x88 + +#define SPI_CTARE(x) (0x11c + (((x) & GENMASK(1, 0)) * 4)) +#define SPI_CTARE_FMSZE(x) (((x) & 0x1) << 16) +#define SPI_CTARE_DTCP(x) ((x) & 0x7ff) + +#define SPI_SREX 0x13c + +#define SPI_FRAME_BITS(bits) SPI_CTAR_FMSZ((bits) - 1) +#define SPI_FRAME_EBITS(bits) SPI_CTARE_FMSZE(((bits) - 1) >> 4) + +/* Register offsets for regmap_pushr */ +#define PUSHR_CMD 0x0 +#define PUSHR_TX 0x2 + +#define DMA_COMPLETION_TIMEOUT msecs_to_jiffies(3000) + +struct chip_data { + u32 ctar_val; + u16 void_write_data; +}; + +struct fsl_dspi_devtype_data { + u8 max_clock_factor; + bool ptp_sts_supported; + bool xspi_mode; +}; + +static const struct fsl_dspi_devtype_data ls1021a_v1_data = { + .max_clock_factor = 8, + .ptp_sts_supported = true, + .xspi_mode = true, +}; + +static const struct fsl_dspi_devtype_data ls2085a_data = { + .max_clock_factor = 8, + .ptp_sts_supported = true, +}; + +struct fsl_dspi { + struct spi_controller ctlr; + struct device_d *dev; + + struct regmap *regmap; + struct regmap *regmap_pushr; + int irq; + struct clk *clk; + + struct spi_transfer *cur_transfer; + struct spi_message *cur_msg; + struct chip_data *cur_chip; + size_t progress; + size_t len; + const void *tx; + void *rx; + void *rx_end; + u16 void_write_data; + u16 tx_cmd; + u8 bits_per_word; + u8 bytes_per_word; + const struct fsl_dspi_devtype_data *devtype_data; +}; + +static u32 dspi_pop_tx(struct fsl_dspi *dspi) +{ + u32 txdata = 0; + + if (dspi->tx) { + if (dspi->bytes_per_word == 1) + txdata = *(u8 *)dspi->tx; + else if (dspi->bytes_per_word == 2) + txdata = *(u16 *)dspi->tx; + else /* dspi->bytes_per_word == 4 */ + txdata = *(u32 *)dspi->tx; + dspi->tx += dspi->bytes_per_word; + } + dspi->len -= dspi->bytes_per_word; + return txdata; +} + +static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi) +{ + u16 cmd = dspi->tx_cmd, data = dspi_pop_tx(dspi); + + if (dspi->len > 0) + cmd |= SPI_PUSHR_CMD_CONT; + return cmd << 16 | data; +} + +static void dspi_push_rx(struct fsl_dspi *dspi, u32 rxdata) +{ + if (!dspi->rx) + return; + + /* Mask off undefined bits */ + rxdata &= (1 << dspi->bits_per_word) - 1; + + if (dspi->bytes_per_word == 1) + *(u8 *)dspi->rx = rxdata; + else if (dspi->bytes_per_word == 2) + *(u16 *)dspi->rx = rxdata; + else /* dspi->bytes_per_word == 4 */ + *(u32 *)dspi->rx = rxdata; + dspi->rx += dspi->bytes_per_word; +} + +static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, + unsigned long clkrate) +{ + /* Valid baud rate pre-scaler values */ + int pbr_tbl[4] = {2, 3, 5, 7}; + int brs[16] = { 2, 4, 6, 8, + 16, 32, 64, 128, + 256, 512, 1024, 2048, + 4096, 8192, 16384, 32768 }; + int scale_needed, scale, minscale = INT_MAX; + int i, j; + + scale_needed = clkrate / speed_hz; + if (clkrate % speed_hz) + scale_needed++; + + for (i = 0; i < ARRAY_SIZE(brs); i++) + for (j = 0; j < ARRAY_SIZE(pbr_tbl); j++) { + scale = brs[i] * pbr_tbl[j]; + if (scale >= scale_needed) { + if (scale < minscale) { + minscale = scale; + *br = i; + *pbr = j; + } + break; + } + } + + if (minscale == INT_MAX) { + pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld, we use the max prescaler value.\n", + speed_hz, clkrate); + *pbr = ARRAY_SIZE(pbr_tbl) - 1; + *br = ARRAY_SIZE(brs) - 1; + } +} + +static void ns_delay_scale(char *psc, char *sc, int delay_ns, + unsigned long clkrate) +{ + int scale_needed, scale, minscale = INT_MAX; + int pscale_tbl[4] = {1, 3, 5, 7}; + u32 remainder; + int i, j; + + scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC, + &remainder); + if (remainder) + scale_needed++; + + for (i = 0; i < ARRAY_SIZE(pscale_tbl); i++) + for (j = 0; j <= SPI_CTAR_SCALE_BITS; j++) { + scale = pscale_tbl[i] * (2 << j); + if (scale >= scale_needed) { + if (scale < minscale) { + minscale = scale; + *psc = i; + *sc = j; + } + break; + } + } + + if (minscale == INT_MAX) { + pr_warn("Cannot find correct scale values for %dns delay at clkrate %ld, using max prescaler value", + delay_ns, clkrate); + *psc = ARRAY_SIZE(pscale_tbl) - 1; + *sc = SPI_CTAR_SCALE_BITS; + } +} + +static void fifo_write(struct fsl_dspi *dspi) +{ + regmap_write(dspi->regmap, SPI_PUSHR, dspi_pop_tx_pushr(dspi)); +} + +static void cmd_fifo_write(struct fsl_dspi *dspi) +{ + u16 cmd = dspi->tx_cmd; + + if (dspi->len > 0) + cmd |= SPI_PUSHR_CMD_CONT; + regmap_write(dspi->regmap_pushr, PUSHR_CMD, cmd); +} + +static void tx_fifo_write(struct fsl_dspi *dspi, u16 txdata) +{ + regmap_write(dspi->regmap_pushr, PUSHR_TX, txdata); +} + +static void dspi_tcfq_write(struct fsl_dspi *dspi) +{ + /* Clear transfer count */ + dspi->tx_cmd |= SPI_PUSHR_CMD_CTCNT; + + if (dspi->devtype_data->xspi_mode && dspi->bits_per_word > 16) { + /* Write the CMD FIFO entry first, and then the two + * corresponding TX FIFO entries. + */ + u32 data = dspi_pop_tx(dspi); + + cmd_fifo_write(dspi); + tx_fifo_write(dspi, data & 0xFFFF); + tx_fifo_write(dspi, data >> 16); + } else { + /* Write one entry to both TX FIFO and CMD FIFO + * simultaneously. + */ + fifo_write(dspi); + } +} + +static u32 fifo_read(struct fsl_dspi *dspi) +{ + u32 rxdata = 0; + + regmap_read(dspi->regmap, SPI_POPR, &rxdata); + return rxdata; +} + +static void dspi_tcfq_read(struct fsl_dspi *dspi) +{ + dspi_push_rx(dspi, fifo_read(dspi)); +} + +static int dspi_rxtx(struct fsl_dspi *dspi) +{ + struct spi_message *msg = dspi->cur_msg; + u16 spi_tcnt; + u32 spi_tcr; + + /* Get transfer counter (in number of SPI transfers). It was + * reset to 0 when transfer(s) were started. + */ + regmap_read(dspi->regmap, SPI_TCR, &spi_tcr); + spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr); + /* Update total number of bytes that were transferred */ + msg->actual_length += spi_tcnt * dspi->bytes_per_word; + dspi->progress += spi_tcnt; + + dspi_tcfq_read(dspi); + if (!dspi->len) + /* Success! */ + return 0; + + dspi_tcfq_write(dspi); + + return -EINPROGRESS; +} + +static int dspi_poll(struct fsl_dspi *dspi) +{ + int tries = 1000; + u32 spi_sr; + + do { + regmap_read(dspi->regmap, SPI_SR, &spi_sr); + regmap_write(dspi->regmap, SPI_SR, spi_sr); + + if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF)) + break; + udelay(1); + } while (--tries); + + if (!tries) + return -ETIMEDOUT; + + return dspi_rxtx(dspi); +} + +static int dspi_transfer_one_message(struct spi_device *spi, + struct spi_message *message) +{ + struct fsl_dspi *dspi = container_of(spi->master, struct fsl_dspi, ctlr); + struct spi_transfer *transfer; + int status = 0; + + message->actual_length = 0; + + list_for_each_entry(transfer, &message->transfers, transfer_list) { + dspi->cur_transfer = transfer; + dspi->cur_msg = message; + dspi->cur_chip = spi->controller_data; + /* Prepare command word for CMD FIFO */ + dspi->tx_cmd = SPI_PUSHR_CMD_CTAS(0) | + SPI_PUSHR_CMD_PCS(spi->chip_select); + if (list_is_last(&dspi->cur_transfer->transfer_list, + &dspi->cur_msg->transfers)) { + /* Leave PCS activated after last transfer when + * cs_change is set. + */ + if (transfer->cs_change) + dspi->tx_cmd |= SPI_PUSHR_CMD_CONT; + } else { + /* Keep PCS active between transfers in same message + * when cs_change is not set, and de-activate PCS + * between transfers in the same message when + * cs_change is set. + */ + if (!transfer->cs_change) + dspi->tx_cmd |= SPI_PUSHR_CMD_CONT; + } + + dspi->void_write_data = dspi->cur_chip->void_write_data; + + dspi->tx = transfer->tx_buf; + dspi->rx = transfer->rx_buf; + dspi->rx_end = dspi->rx + transfer->len; + dspi->len = transfer->len; + dspi->progress = 0; + /* Validated transfer specific frame size (defaults applied) */ + dspi->bits_per_word = transfer->bits_per_word; + + if (transfer->bits_per_word <= 8) + dspi->bytes_per_word = 1; + else if (transfer->bits_per_word <= 16) + dspi->bytes_per_word = 2; + else + dspi->bytes_per_word = 4; + + regmap_update_bits(dspi->regmap, SPI_MCR, + SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF, + SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF); + regmap_write(dspi->regmap, SPI_CTAR(0), + dspi->cur_chip->ctar_val | + SPI_FRAME_BITS(transfer->bits_per_word)); + if (dspi->devtype_data->xspi_mode) + regmap_write(dspi->regmap, SPI_CTARE(0), + SPI_FRAME_EBITS(transfer->bits_per_word) | + SPI_CTARE_DTCP(1)); + + regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_TCFQE); + dspi_tcfq_write(dspi); + + do { + status = dspi_poll(dspi); + } while (status == -EINPROGRESS); + + if (status) + dev_err(dspi->dev, + "Waiting for transfer to complete failed!\n"); + } + + message->status = status; + + return status; +} + +static int dspi_setup(struct spi_device *spi) +{ + struct fsl_dspi *dspi = container_of(spi->master, struct fsl_dspi, ctlr); + unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0; + u32 cs_sck_delay = 0, sck_cs_delay = 0; + unsigned char pasc = 0, asc = 0; + struct chip_data *chip; + unsigned long clkrate; + + /* Only alloc on first setup */ + chip = spi->controller_data; + if (chip == NULL) { + chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); + if (!chip) + return -ENOMEM; + } + + of_property_read_u32(spi->dev.device_node, "fsl,spi-cs-sck-delay", + &cs_sck_delay); + + of_property_read_u32(spi->dev.device_node, "fsl,spi-sck-cs-delay", + &sck_cs_delay); + + chip->void_write_data = 0; + + clkrate = clk_get_rate(dspi->clk); + hz_to_spi_baud(&pbr, &br, spi->max_speed_hz, clkrate); + + /* Set PCS to SCK delay scale values */ + ns_delay_scale(&pcssck, &cssck, cs_sck_delay, clkrate); + + /* Set After SCK delay scale values */ + ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate); + + chip->ctar_val = 0; + if (spi->mode & SPI_CPOL) + chip->ctar_val |= SPI_CTAR_CPOL; + if (spi->mode & SPI_CPHA) + chip->ctar_val |= SPI_CTAR_CPHA; + + chip->ctar_val |= SPI_CTAR_PCSSCK(pcssck) | + SPI_CTAR_CSSCK(cssck) | + SPI_CTAR_PASC(pasc) | + SPI_CTAR_ASC(asc) | + SPI_CTAR_PBR(pbr) | + SPI_CTAR_BR(br); + + if (spi->mode & SPI_LSB_FIRST) + chip->ctar_val |= SPI_CTAR_LSBFE; + + spi->controller_data = chip; + + return 0; +} + +static void dspi_cleanup(struct spi_device *spi) +{ + struct chip_data *chip = spi->controller_data; + + dev_dbg(&spi->dev, "spi_device %u.%u cleanup\n", + spi->controller->bus_num, spi->chip_select); + + kfree(chip); +} + +static const struct of_device_id fsl_dspi_dt_ids[] = { + { .compatible = "fsl,ls1021a-v1.0-dspi", .data = &ls1021a_v1_data, }, + { .compatible = "fsl,ls2085a-dspi", .data = &ls2085a_data, }, + { /* sentinel */ } +}; + +static const struct regmap_config dspi_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x88, +}; + +static const struct regmap_config dspi_xspi_regmap_config[] = { + { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0x13c, + }, { + .name = "pushr", + .reg_bits = 16, + .val_bits = 16, + .reg_stride = 2, + .max_register = 0x2, + }, +}; + +static void dspi_init(struct fsl_dspi *dspi) +{ + unsigned int mcr = SPI_MCR_PCSIS; + + if (dspi->devtype_data->xspi_mode) + mcr |= SPI_MCR_XSPI; + mcr |= SPI_MCR_MASTER; + + regmap_write(dspi->regmap, SPI_MCR, mcr); + regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR); + if (dspi->devtype_data->xspi_mode) + regmap_write(dspi->regmap, SPI_CTARE(0), + SPI_CTARE_FMSZE(0) | SPI_CTARE_DTCP(1)); +} + +static int dspi_probe(struct device_d *dev) +{ + struct device_node *np = dev->device_node; + const struct regmap_config *regmap_config; + struct spi_master *master; + int ret, cs_num, bus_num = -1; + struct fsl_dspi *dspi; + struct resource *res; + void __iomem *base; + + dspi = xzalloc(sizeof(*dspi)); + + dspi->dev = dev; + master = &dspi->ctlr; + + master->dev = dev; + master->setup = dspi_setup; + master->transfer = dspi_transfer_one_message; + + master->cleanup = dspi_cleanup; + + ret = of_property_read_u32(np, "spi-num-chipselects", &cs_num); + if (ret < 0) { + dev_err(dev, "can't get spi-num-chipselects\n"); + goto out_ctlr_put; + } + master->num_chipselect = cs_num; + + of_property_read_u32(np, "bus-num", &bus_num); + master->bus_num = bus_num; + + ret = dev_get_drvdata(dev, (const void **)&dspi->devtype_data); + if (ret) + return -ENODEV; + + res = dev_request_mem_resource(dev, 0); + if (IS_ERR(res)) + return PTR_ERR(res); + + base = IOMEM(res->start); + + if (dspi->devtype_data->xspi_mode) + regmap_config = &dspi_xspi_regmap_config[0]; + else + regmap_config = &dspi_regmap_config; + + dspi->regmap = regmap_init_mmio(dev, base, regmap_config); + if (IS_ERR(dspi->regmap)) { + dev_err(dev, "failed to init regmap: %ld\n", + PTR_ERR(dspi->regmap)); + ret = PTR_ERR(dspi->regmap); + goto out_ctlr_put; + } + + if (dspi->devtype_data->xspi_mode) { + dspi->regmap_pushr = regmap_init_mmio( + dev, base + SPI_PUSHR, + &dspi_xspi_regmap_config[1]); + if (IS_ERR(dspi->regmap_pushr)) { + dev_err(dev, + "failed to init pushr regmap: %ld\n", + PTR_ERR(dspi->regmap_pushr)); + ret = PTR_ERR(dspi->regmap_pushr); + goto out_ctlr_put; + } + } + + dspi->clk = clk_get(dev, "dspi"); + if (IS_ERR(dspi->clk)) { + ret = PTR_ERR(dspi->clk); + dev_err(dev, "unable to get clock\n"); + goto out_ctlr_put; + } + ret = clk_enable(dspi->clk); + if (ret) + goto out_ctlr_put; + + dspi_init(dspi); + + ret = spi_register_master(master); + if (ret != 0) { + dev_err(dev, "Problem registering DSPI ctlr\n"); + goto out_clk_put; + } + + return ret; + +out_clk_put: + clk_disable(dspi->clk); +out_ctlr_put: + + return ret; +} + +static struct driver_d fsl_dspi_driver = { + .name = "fsl-dspi", + .probe = dspi_probe, + .of_compatible = DRV_OF_COMPAT(fsl_dspi_dt_ids), +}; +coredevice_platform_driver(fsl_dspi_driver); -- 2.26.0.rc2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 4/5] spi: Add fsl-dspi driver 2020-03-25 8:36 ` [PATCH 4/5] spi: Add fsl-dspi driver Sascha Hauer @ 2020-04-04 19:14 ` Andrey Smirnov 2020-04-14 10:30 ` Sascha Hauer 0 siblings, 1 reply; 8+ messages in thread From: Andrey Smirnov @ 2020-04-04 19:14 UTC (permalink / raw) To: Sascha Hauer; +Cc: Barebox List On Wed, Mar 25, 2020 at 1:36 AM Sascha Hauer <s.hauer@pengutronix.de> wrote: > > The fsl-dspi is found on Freescale Vybrid, Coldfire and Layerscape SoCs. > This adds the driver based on the Linux driver as of v5.5. Coldfire > support has been dropped as it's rather obsolete. Vybrid support has > been dropped because it needs the DMA engine support we do not have in > barebox. What's left is support for Layerscape where this driver has > been tested on. > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > --- > drivers/spi/Kconfig | 7 + > drivers/spi/Makefile | 1 + > drivers/spi/spi-fsl-dspi.c | 655 +++++++++++++++++++++++++++++++++++++ > 3 files changed, 663 insertions(+) > create mode 100644 drivers/spi/spi-fsl-dspi.c > > diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig > index 3758a0fad9..96235a1be2 100644 > --- a/drivers/spi/Kconfig > +++ b/drivers/spi/Kconfig > @@ -44,6 +44,13 @@ config DRIVER_SPI_FSL_QUADSPI > This controller does not support generic SPI messages. It only > supports the high-level SPI memory interface. > > +config SPI_FSL_DSPI > + bool "Freescale DSPI controller" > + depends on ARCH_LAYERSCAPE > + help > + This enables support for the Freescale DSPI controller in master > + mode. VF610, LS1021A and ColdFire platforms uses the controller. Sorry I didn't notice this patch earlier. Maybe we should drop the wording about VF610 here since there a separate DSPI driver for Vybrid as well: https://git.pengutronix.de/cgit/barebox/tree/drivers/spi/Kconfig?h=next#n90 > + > config DRIVER_SPI_GPIO > bool "GPIO SPI Master driver" > depends on GPIOLIB > diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile > index 75a89ef38e..908d514a01 100644 > --- a/drivers/spi/Makefile > +++ b/drivers/spi/Makefile > @@ -8,6 +8,7 @@ obj-$(CONFIG_DRIVER_SPI_MVEBU) += mvebu_spi.o > obj-$(CONFIG_DRIVER_SPI_MXS) += mxs_spi.o > obj-$(CONFIG_DRIVER_SPI_ALTERA) += altera_spi.o > obj-$(CONFIG_DRIVER_SPI_ATMEL) += atmel_spi.o > +obj-$(CONFIG_SPI_FSL_DSPI) += spi-fsl-dspi.o > obj-$(CONFIG_SPI_ATMEL_QUADSPI) += atmel-quadspi.o > obj-$(CONFIG_DRIVER_SPI_OMAP3) += omap3_spi.o > obj-$(CONFIG_DRIVER_SPI_DSPI) += dspi_spi.o > diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c > new file mode 100644 > index 0000000000..a7ceb854e9 > --- /dev/null > +++ b/drivers/spi/spi-fsl-dspi.c > @@ -0,0 +1,655 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +// > +// Copyright 2013 Freescale Semiconductor, Inc. > +// > +// Freescale DSPI driver > +// This file contains a driver for the Freescale DSPI > + > +#include <common.h> > +#include <driver.h> > +#include <errno.h> > +#include <init.h> > +#include <io.h> > +#include <regmap.h> > +#include <spi/spi.h> > +#include <linux/clk.h> > +#include <linux/math64.h> > + > +#define DRIVER_NAME "fsl-dspi" > + > +#define DSPI_FIFO_SIZE 4 > +#define DSPI_DMA_BUFSIZE (DSPI_FIFO_SIZE * 1024) > + > +#define SPI_MCR 0x00 > +#define SPI_MCR_MASTER BIT(31) > +#define SPI_MCR_PCSIS (0x3F << 16) > +#define SPI_MCR_CLR_TXF BIT(11) > +#define SPI_MCR_CLR_RXF BIT(10) > +#define SPI_MCR_XSPI BIT(3) > + > +#define SPI_TCR 0x08 > +#define SPI_TCR_GET_TCNT(x) (((x) & GENMASK(31, 16)) >> 16) > + > +#define SPI_CTAR(x) (0x0c + (((x) & GENMASK(1, 0)) * 4)) > +#define SPI_CTAR_FMSZ(x) (((x) << 27) & GENMASK(30, 27)) > +#define SPI_CTAR_CPOL BIT(26) > +#define SPI_CTAR_CPHA BIT(25) > +#define SPI_CTAR_LSBFE BIT(24) > +#define SPI_CTAR_PCSSCK(x) (((x) << 22) & GENMASK(23, 22)) > +#define SPI_CTAR_PASC(x) (((x) << 20) & GENMASK(21, 20)) > +#define SPI_CTAR_PDT(x) (((x) << 18) & GENMASK(19, 18)) > +#define SPI_CTAR_PBR(x) (((x) << 16) & GENMASK(17, 16)) > +#define SPI_CTAR_CSSCK(x) (((x) << 12) & GENMASK(15, 12)) > +#define SPI_CTAR_ASC(x) (((x) << 8) & GENMASK(11, 8)) > +#define SPI_CTAR_DT(x) (((x) << 4) & GENMASK(7, 4)) > +#define SPI_CTAR_BR(x) ((x) & GENMASK(3, 0)) > +#define SPI_CTAR_SCALE_BITS 0xf > + > +#define SPI_CTAR0_SLAVE 0x0c > + > +#define SPI_SR 0x2c > +#define SPI_SR_TCFQF BIT(31) > +#define SPI_SR_EOQF BIT(28) > +#define SPI_SR_TFUF BIT(27) > +#define SPI_SR_TFFF BIT(25) > +#define SPI_SR_CMDTCF BIT(23) > +#define SPI_SR_SPEF BIT(21) > +#define SPI_SR_RFOF BIT(19) > +#define SPI_SR_TFIWF BIT(18) > +#define SPI_SR_RFDF BIT(17) > +#define SPI_SR_CMDFFF BIT(16) > +#define SPI_SR_CLEAR (SPI_SR_TCFQF | SPI_SR_EOQF | \ > + SPI_SR_TFUF | SPI_SR_TFFF | \ > + SPI_SR_CMDTCF | SPI_SR_SPEF | \ > + SPI_SR_RFOF | SPI_SR_TFIWF | \ > + SPI_SR_RFDF | SPI_SR_CMDFFF) > + > +#define SPI_RSER_TFFFE BIT(25) > +#define SPI_RSER_TFFFD BIT(24) > +#define SPI_RSER_RFDFE BIT(17) > +#define SPI_RSER_RFDFD BIT(16) > + > +#define SPI_RSER 0x30 > +#define SPI_RSER_TCFQE BIT(31) > +#define SPI_RSER_EOQFE BIT(28) > + > +#define SPI_PUSHR 0x34 > +#define SPI_PUSHR_CMD_CONT BIT(15) > +#define SPI_PUSHR_CMD_CTAS(x) (((x) << 12 & GENMASK(14, 12))) > +#define SPI_PUSHR_CMD_EOQ BIT(11) > +#define SPI_PUSHR_CMD_CTCNT BIT(10) > +#define SPI_PUSHR_CMD_PCS(x) (BIT(x) & GENMASK(5, 0)) > + > +#define SPI_PUSHR_SLAVE 0x34 > + > +#define SPI_POPR 0x38 > + > +#define SPI_TXFR0 0x3c > +#define SPI_TXFR1 0x40 > +#define SPI_TXFR2 0x44 > +#define SPI_TXFR3 0x48 > +#define SPI_RXFR0 0x7c > +#define SPI_RXFR1 0x80 > +#define SPI_RXFR2 0x84 > +#define SPI_RXFR3 0x88 > + > +#define SPI_CTARE(x) (0x11c + (((x) & GENMASK(1, 0)) * 4)) > +#define SPI_CTARE_FMSZE(x) (((x) & 0x1) << 16) > +#define SPI_CTARE_DTCP(x) ((x) & 0x7ff) > + > +#define SPI_SREX 0x13c > + > +#define SPI_FRAME_BITS(bits) SPI_CTAR_FMSZ((bits) - 1) > +#define SPI_FRAME_EBITS(bits) SPI_CTARE_FMSZE(((bits) - 1) >> 4) > + > +/* Register offsets for regmap_pushr */ > +#define PUSHR_CMD 0x0 > +#define PUSHR_TX 0x2 > + > +#define DMA_COMPLETION_TIMEOUT msecs_to_jiffies(3000) > + > +struct chip_data { > + u32 ctar_val; > + u16 void_write_data; > +}; > + > +struct fsl_dspi_devtype_data { > + u8 max_clock_factor; > + bool ptp_sts_supported; > + bool xspi_mode; > +}; > + > +static const struct fsl_dspi_devtype_data ls1021a_v1_data = { > + .max_clock_factor = 8, > + .ptp_sts_supported = true, > + .xspi_mode = true, > +}; > + > +static const struct fsl_dspi_devtype_data ls2085a_data = { > + .max_clock_factor = 8, > + .ptp_sts_supported = true, > +}; > + > +struct fsl_dspi { > + struct spi_controller ctlr; > + struct device_d *dev; > + > + struct regmap *regmap; > + struct regmap *regmap_pushr; > + int irq; > + struct clk *clk; > + > + struct spi_transfer *cur_transfer; > + struct spi_message *cur_msg; > + struct chip_data *cur_chip; > + size_t progress; > + size_t len; > + const void *tx; > + void *rx; > + void *rx_end; > + u16 void_write_data; > + u16 tx_cmd; > + u8 bits_per_word; > + u8 bytes_per_word; > + const struct fsl_dspi_devtype_data *devtype_data; > +}; > + > +static u32 dspi_pop_tx(struct fsl_dspi *dspi) > +{ > + u32 txdata = 0; > + > + if (dspi->tx) { > + if (dspi->bytes_per_word == 1) > + txdata = *(u8 *)dspi->tx; > + else if (dspi->bytes_per_word == 2) > + txdata = *(u16 *)dspi->tx; > + else /* dspi->bytes_per_word == 4 */ > + txdata = *(u32 *)dspi->tx; > + dspi->tx += dspi->bytes_per_word; > + } > + dspi->len -= dspi->bytes_per_word; > + return txdata; > +} > + > +static u32 dspi_pop_tx_pushr(struct fsl_dspi *dspi) > +{ > + u16 cmd = dspi->tx_cmd, data = dspi_pop_tx(dspi); > + > + if (dspi->len > 0) > + cmd |= SPI_PUSHR_CMD_CONT; > + return cmd << 16 | data; > +} > + > +static void dspi_push_rx(struct fsl_dspi *dspi, u32 rxdata) > +{ > + if (!dspi->rx) > + return; > + > + /* Mask off undefined bits */ > + rxdata &= (1 << dspi->bits_per_word) - 1; > + > + if (dspi->bytes_per_word == 1) > + *(u8 *)dspi->rx = rxdata; > + else if (dspi->bytes_per_word == 2) > + *(u16 *)dspi->rx = rxdata; > + else /* dspi->bytes_per_word == 4 */ > + *(u32 *)dspi->rx = rxdata; > + dspi->rx += dspi->bytes_per_word; > +} > + > +static void hz_to_spi_baud(char *pbr, char *br, int speed_hz, > + unsigned long clkrate) > +{ > + /* Valid baud rate pre-scaler values */ > + int pbr_tbl[4] = {2, 3, 5, 7}; > + int brs[16] = { 2, 4, 6, 8, > + 16, 32, 64, 128, > + 256, 512, 1024, 2048, > + 4096, 8192, 16384, 32768 }; > + int scale_needed, scale, minscale = INT_MAX; > + int i, j; > + > + scale_needed = clkrate / speed_hz; > + if (clkrate % speed_hz) > + scale_needed++; > + > + for (i = 0; i < ARRAY_SIZE(brs); i++) > + for (j = 0; j < ARRAY_SIZE(pbr_tbl); j++) { > + scale = brs[i] * pbr_tbl[j]; > + if (scale >= scale_needed) { > + if (scale < minscale) { > + minscale = scale; > + *br = i; > + *pbr = j; > + } > + break; > + } > + } > + > + if (minscale == INT_MAX) { > + pr_warn("Can not find valid baud rate,speed_hz is %d,clkrate is %ld, we use the max prescaler value.\n", > + speed_hz, clkrate); > + *pbr = ARRAY_SIZE(pbr_tbl) - 1; > + *br = ARRAY_SIZE(brs) - 1; > + } > +} > + > +static void ns_delay_scale(char *psc, char *sc, int delay_ns, > + unsigned long clkrate) > +{ > + int scale_needed, scale, minscale = INT_MAX; > + int pscale_tbl[4] = {1, 3, 5, 7}; > + u32 remainder; > + int i, j; > + > + scale_needed = div_u64_rem((u64)delay_ns * clkrate, NSEC_PER_SEC, > + &remainder); > + if (remainder) > + scale_needed++; > + > + for (i = 0; i < ARRAY_SIZE(pscale_tbl); i++) > + for (j = 0; j <= SPI_CTAR_SCALE_BITS; j++) { > + scale = pscale_tbl[i] * (2 << j); > + if (scale >= scale_needed) { > + if (scale < minscale) { > + minscale = scale; > + *psc = i; > + *sc = j; > + } > + break; > + } > + } > + > + if (minscale == INT_MAX) { > + pr_warn("Cannot find correct scale values for %dns delay at clkrate %ld, using max prescaler value", > + delay_ns, clkrate); > + *psc = ARRAY_SIZE(pscale_tbl) - 1; > + *sc = SPI_CTAR_SCALE_BITS; > + } > +} > + > +static void fifo_write(struct fsl_dspi *dspi) > +{ > + regmap_write(dspi->regmap, SPI_PUSHR, dspi_pop_tx_pushr(dspi)); > +} > + > +static void cmd_fifo_write(struct fsl_dspi *dspi) > +{ > + u16 cmd = dspi->tx_cmd; > + > + if (dspi->len > 0) > + cmd |= SPI_PUSHR_CMD_CONT; > + regmap_write(dspi->regmap_pushr, PUSHR_CMD, cmd); > +} > + > +static void tx_fifo_write(struct fsl_dspi *dspi, u16 txdata) > +{ > + regmap_write(dspi->regmap_pushr, PUSHR_TX, txdata); > +} > + > +static void dspi_tcfq_write(struct fsl_dspi *dspi) > +{ > + /* Clear transfer count */ > + dspi->tx_cmd |= SPI_PUSHR_CMD_CTCNT; > + > + if (dspi->devtype_data->xspi_mode && dspi->bits_per_word > 16) { > + /* Write the CMD FIFO entry first, and then the two > + * corresponding TX FIFO entries. > + */ > + u32 data = dspi_pop_tx(dspi); > + > + cmd_fifo_write(dspi); > + tx_fifo_write(dspi, data & 0xFFFF); > + tx_fifo_write(dspi, data >> 16); > + } else { > + /* Write one entry to both TX FIFO and CMD FIFO > + * simultaneously. > + */ > + fifo_write(dspi); > + } > +} > + > +static u32 fifo_read(struct fsl_dspi *dspi) > +{ > + u32 rxdata = 0; > + > + regmap_read(dspi->regmap, SPI_POPR, &rxdata); > + return rxdata; > +} > + > +static void dspi_tcfq_read(struct fsl_dspi *dspi) > +{ > + dspi_push_rx(dspi, fifo_read(dspi)); > +} > + > +static int dspi_rxtx(struct fsl_dspi *dspi) > +{ > + struct spi_message *msg = dspi->cur_msg; > + u16 spi_tcnt; > + u32 spi_tcr; > + > + /* Get transfer counter (in number of SPI transfers). It was > + * reset to 0 when transfer(s) were started. > + */ > + regmap_read(dspi->regmap, SPI_TCR, &spi_tcr); > + spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr); > + /* Update total number of bytes that were transferred */ > + msg->actual_length += spi_tcnt * dspi->bytes_per_word; > + dspi->progress += spi_tcnt; > + > + dspi_tcfq_read(dspi); > + if (!dspi->len) > + /* Success! */ > + return 0; > + > + dspi_tcfq_write(dspi); > + > + return -EINPROGRESS; > +} > + > +static int dspi_poll(struct fsl_dspi *dspi) > +{ > + int tries = 1000; > + u32 spi_sr; > + > + do { > + regmap_read(dspi->regmap, SPI_SR, &spi_sr); > + regmap_write(dspi->regmap, SPI_SR, spi_sr); > + > + if (spi_sr & (SPI_SR_EOQF | SPI_SR_TCFQF)) > + break; > + udelay(1); > + } while (--tries); > + > + if (!tries) > + return -ETIMEDOUT; > + > + return dspi_rxtx(dspi); > +} > + > +static int dspi_transfer_one_message(struct spi_device *spi, > + struct spi_message *message) > +{ > + struct fsl_dspi *dspi = container_of(spi->master, struct fsl_dspi, ctlr); > + struct spi_transfer *transfer; > + int status = 0; > + > + message->actual_length = 0; > + > + list_for_each_entry(transfer, &message->transfers, transfer_list) { > + dspi->cur_transfer = transfer; > + dspi->cur_msg = message; > + dspi->cur_chip = spi->controller_data; > + /* Prepare command word for CMD FIFO */ > + dspi->tx_cmd = SPI_PUSHR_CMD_CTAS(0) | > + SPI_PUSHR_CMD_PCS(spi->chip_select); > + if (list_is_last(&dspi->cur_transfer->transfer_list, > + &dspi->cur_msg->transfers)) { > + /* Leave PCS activated after last transfer when > + * cs_change is set. > + */ > + if (transfer->cs_change) > + dspi->tx_cmd |= SPI_PUSHR_CMD_CONT; > + } else { > + /* Keep PCS active between transfers in same message > + * when cs_change is not set, and de-activate PCS > + * between transfers in the same message when > + * cs_change is set. > + */ > + if (!transfer->cs_change) > + dspi->tx_cmd |= SPI_PUSHR_CMD_CONT; > + } > + > + dspi->void_write_data = dspi->cur_chip->void_write_data; > + > + dspi->tx = transfer->tx_buf; > + dspi->rx = transfer->rx_buf; > + dspi->rx_end = dspi->rx + transfer->len; > + dspi->len = transfer->len; > + dspi->progress = 0; > + /* Validated transfer specific frame size (defaults applied) */ > + dspi->bits_per_word = transfer->bits_per_word; > + > + if (transfer->bits_per_word <= 8) > + dspi->bytes_per_word = 1; > + else if (transfer->bits_per_word <= 16) > + dspi->bytes_per_word = 2; > + else > + dspi->bytes_per_word = 4; > + > + regmap_update_bits(dspi->regmap, SPI_MCR, > + SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF, > + SPI_MCR_CLR_TXF | SPI_MCR_CLR_RXF); > + regmap_write(dspi->regmap, SPI_CTAR(0), > + dspi->cur_chip->ctar_val | > + SPI_FRAME_BITS(transfer->bits_per_word)); > + if (dspi->devtype_data->xspi_mode) > + regmap_write(dspi->regmap, SPI_CTARE(0), > + SPI_FRAME_EBITS(transfer->bits_per_word) | > + SPI_CTARE_DTCP(1)); > + > + regmap_write(dspi->regmap, SPI_RSER, SPI_RSER_TCFQE); > + dspi_tcfq_write(dspi); > + > + do { > + status = dspi_poll(dspi); > + } while (status == -EINPROGRESS); > + > + if (status) > + dev_err(dspi->dev, > + "Waiting for transfer to complete failed!\n"); > + } > + > + message->status = status; > + > + return status; > +} > + > +static int dspi_setup(struct spi_device *spi) > +{ > + struct fsl_dspi *dspi = container_of(spi->master, struct fsl_dspi, ctlr); > + unsigned char br = 0, pbr = 0, pcssck = 0, cssck = 0; > + u32 cs_sck_delay = 0, sck_cs_delay = 0; > + unsigned char pasc = 0, asc = 0; > + struct chip_data *chip; > + unsigned long clkrate; > + > + /* Only alloc on first setup */ > + chip = spi->controller_data; > + if (chip == NULL) { > + chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); > + if (!chip) > + return -ENOMEM; > + } > + > + of_property_read_u32(spi->dev.device_node, "fsl,spi-cs-sck-delay", > + &cs_sck_delay); > + > + of_property_read_u32(spi->dev.device_node, "fsl,spi-sck-cs-delay", > + &sck_cs_delay); > + > + chip->void_write_data = 0; > + > + clkrate = clk_get_rate(dspi->clk); > + hz_to_spi_baud(&pbr, &br, spi->max_speed_hz, clkrate); > + > + /* Set PCS to SCK delay scale values */ > + ns_delay_scale(&pcssck, &cssck, cs_sck_delay, clkrate); > + > + /* Set After SCK delay scale values */ > + ns_delay_scale(&pasc, &asc, sck_cs_delay, clkrate); > + > + chip->ctar_val = 0; > + if (spi->mode & SPI_CPOL) > + chip->ctar_val |= SPI_CTAR_CPOL; > + if (spi->mode & SPI_CPHA) > + chip->ctar_val |= SPI_CTAR_CPHA; > + > + chip->ctar_val |= SPI_CTAR_PCSSCK(pcssck) | > + SPI_CTAR_CSSCK(cssck) | > + SPI_CTAR_PASC(pasc) | > + SPI_CTAR_ASC(asc) | > + SPI_CTAR_PBR(pbr) | > + SPI_CTAR_BR(br); > + > + if (spi->mode & SPI_LSB_FIRST) > + chip->ctar_val |= SPI_CTAR_LSBFE; > + > + spi->controller_data = chip; > + > + return 0; > +} > + > +static void dspi_cleanup(struct spi_device *spi) > +{ > + struct chip_data *chip = spi->controller_data; > + > + dev_dbg(&spi->dev, "spi_device %u.%u cleanup\n", > + spi->controller->bus_num, spi->chip_select); > + > + kfree(chip); > +} > + > +static const struct of_device_id fsl_dspi_dt_ids[] = { > + { .compatible = "fsl,ls1021a-v1.0-dspi", .data = &ls1021a_v1_data, }, > + { .compatible = "fsl,ls2085a-dspi", .data = &ls2085a_data, }, > + { /* sentinel */ } > +}; > + > +static const struct regmap_config dspi_regmap_config = { > + .reg_bits = 32, > + .val_bits = 32, > + .reg_stride = 4, > + .max_register = 0x88, > +}; > + > +static const struct regmap_config dspi_xspi_regmap_config[] = { > + { > + .reg_bits = 32, > + .val_bits = 32, > + .reg_stride = 4, > + .max_register = 0x13c, > + }, { > + .name = "pushr", > + .reg_bits = 16, > + .val_bits = 16, > + .reg_stride = 2, > + .max_register = 0x2, > + }, > +}; > + > +static void dspi_init(struct fsl_dspi *dspi) > +{ > + unsigned int mcr = SPI_MCR_PCSIS; > + > + if (dspi->devtype_data->xspi_mode) > + mcr |= SPI_MCR_XSPI; > + mcr |= SPI_MCR_MASTER; > + > + regmap_write(dspi->regmap, SPI_MCR, mcr); > + regmap_write(dspi->regmap, SPI_SR, SPI_SR_CLEAR); > + if (dspi->devtype_data->xspi_mode) > + regmap_write(dspi->regmap, SPI_CTARE(0), > + SPI_CTARE_FMSZE(0) | SPI_CTARE_DTCP(1)); > +} > + > +static int dspi_probe(struct device_d *dev) > +{ > + struct device_node *np = dev->device_node; > + const struct regmap_config *regmap_config; > + struct spi_master *master; > + int ret, cs_num, bus_num = -1; > + struct fsl_dspi *dspi; > + struct resource *res; > + void __iomem *base; > + > + dspi = xzalloc(sizeof(*dspi)); > + > + dspi->dev = dev; > + master = &dspi->ctlr; > + > + master->dev = dev; > + master->setup = dspi_setup; > + master->transfer = dspi_transfer_one_message; > + > + master->cleanup = dspi_cleanup; > + > + ret = of_property_read_u32(np, "spi-num-chipselects", &cs_num); > + if (ret < 0) { > + dev_err(dev, "can't get spi-num-chipselects\n"); > + goto out_ctlr_put; > + } > + master->num_chipselect = cs_num; > + > + of_property_read_u32(np, "bus-num", &bus_num); > + master->bus_num = bus_num; > + > + ret = dev_get_drvdata(dev, (const void **)&dspi->devtype_data); > + if (ret) > + return -ENODEV; > + > + res = dev_request_mem_resource(dev, 0); > + if (IS_ERR(res)) > + return PTR_ERR(res); > + > + base = IOMEM(res->start); > + > + if (dspi->devtype_data->xspi_mode) > + regmap_config = &dspi_xspi_regmap_config[0]; > + else > + regmap_config = &dspi_regmap_config; > + > + dspi->regmap = regmap_init_mmio(dev, base, regmap_config); > + if (IS_ERR(dspi->regmap)) { > + dev_err(dev, "failed to init regmap: %ld\n", > + PTR_ERR(dspi->regmap)); > + ret = PTR_ERR(dspi->regmap); > + goto out_ctlr_put; > + } > + > + if (dspi->devtype_data->xspi_mode) { > + dspi->regmap_pushr = regmap_init_mmio( > + dev, base + SPI_PUSHR, > + &dspi_xspi_regmap_config[1]); > + if (IS_ERR(dspi->regmap_pushr)) { > + dev_err(dev, > + "failed to init pushr regmap: %ld\n", > + PTR_ERR(dspi->regmap_pushr)); > + ret = PTR_ERR(dspi->regmap_pushr); > + goto out_ctlr_put; > + } > + } > + > + dspi->clk = clk_get(dev, "dspi"); > + if (IS_ERR(dspi->clk)) { > + ret = PTR_ERR(dspi->clk); > + dev_err(dev, "unable to get clock\n"); > + goto out_ctlr_put; > + } > + ret = clk_enable(dspi->clk); > + if (ret) > + goto out_ctlr_put; > + > + dspi_init(dspi); > + > + ret = spi_register_master(master); > + if (ret != 0) { > + dev_err(dev, "Problem registering DSPI ctlr\n"); > + goto out_clk_put; > + } > + > + return ret; > + > +out_clk_put: > + clk_disable(dspi->clk); > +out_ctlr_put: > + > + return ret; > +} > + > +static struct driver_d fsl_dspi_driver = { > + .name = "fsl-dspi", > + .probe = dspi_probe, > + .of_compatible = DRV_OF_COMPAT(fsl_dspi_dt_ids), > +}; > +coredevice_platform_driver(fsl_dspi_driver); > -- > 2.26.0.rc2 > > > _______________________________________________ > barebox mailing list > barebox@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/barebox _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 4/5] spi: Add fsl-dspi driver 2020-04-04 19:14 ` Andrey Smirnov @ 2020-04-14 10:30 ` Sascha Hauer 0 siblings, 0 replies; 8+ messages in thread From: Sascha Hauer @ 2020-04-14 10:30 UTC (permalink / raw) To: Andrey Smirnov; +Cc: Barebox List On Sat, Apr 04, 2020 at 12:14:33PM -0700, Andrey Smirnov wrote: > On Wed, Mar 25, 2020 at 1:36 AM Sascha Hauer <s.hauer@pengutronix.de> wrote: > > > > The fsl-dspi is found on Freescale Vybrid, Coldfire and Layerscape SoCs. > > This adds the driver based on the Linux driver as of v5.5. Coldfire > > support has been dropped as it's rather obsolete. Vybrid support has > > been dropped because it needs the DMA engine support we do not have in > > barebox. What's left is support for Layerscape where this driver has > > been tested on. > > > > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > > --- > > drivers/spi/Kconfig | 7 + > > drivers/spi/Makefile | 1 + > > drivers/spi/spi-fsl-dspi.c | 655 +++++++++++++++++++++++++++++++++++++ > > 3 files changed, 663 insertions(+) > > create mode 100644 drivers/spi/spi-fsl-dspi.c > > > > diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig > > index 3758a0fad9..96235a1be2 100644 > > --- a/drivers/spi/Kconfig > > +++ b/drivers/spi/Kconfig > > @@ -44,6 +44,13 @@ config DRIVER_SPI_FSL_QUADSPI > > This controller does not support generic SPI messages. It only > > supports the high-level SPI memory interface. > > > > +config SPI_FSL_DSPI > > + bool "Freescale DSPI controller" > > + depends on ARCH_LAYERSCAPE > > + help > > + This enables support for the Freescale DSPI controller in master > > + mode. VF610, LS1021A and ColdFire platforms uses the controller. > > Sorry I didn't notice this patch earlier. Maybe we should drop the > wording about VF610 here since there a separate DSPI driver for Vybrid > as well: https://git.pengutronix.de/cgit/barebox/tree/drivers/spi/Kconfig?h=next#n90 So there already is a driver for this hardware in barebox. I missed that :( I dropped the wording about VF610 for now, but the real solution should be to use the existing driver or at least merge them. I'll see when and if I can find time for this. Sascha -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 5/5] mtd: spi-nor: Add support for cy15x104q 2020-03-25 8:36 [PATCH 0/5] Add fsl-dspi driver support Sascha Hauer ` (3 preceding siblings ...) 2020-03-25 8:36 ` [PATCH 4/5] spi: Add fsl-dspi driver Sascha Hauer @ 2020-03-25 8:36 ` Sascha Hauer 4 siblings, 0 replies; 8+ messages in thread From: Sascha Hauer @ 2020-03-25 8:36 UTC (permalink / raw) To: Barebox List The Cypress cy15b104q and cy15v104q are 4Mbit serial SPI F-RAM devices. Add support for them to the spi-nor driver. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- drivers/mtd/spi-nor/spi-nor.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 038d7072aa..5cc4573178 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -640,6 +640,9 @@ static const struct spi_device_id spi_nor_ids[] = { { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) }, + /* Cypress */ + { "cy15x104q", INFO6(0x042cc2, 0x7f7f7f, 512 * 1024, 1, SPI_NOR_NO_ERASE) }, + /* EON -- en25xxx */ { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) }, { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) }, -- 2.26.0.rc2 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2020-04-14 10:30 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-03-25 8:36 [PATCH 0/5] Add fsl-dspi driver support Sascha Hauer 2020-03-25 8:36 ` [PATCH 1/5] regmap-mmio: Add missing pieces for 64bit support Sascha Hauer 2020-03-25 8:36 ` [PATCH 2/5] regmap-mmio: Add big endian support Sascha Hauer 2020-03-25 8:36 ` [PATCH 3/5] spi: validate spi messages Sascha Hauer 2020-03-25 8:36 ` [PATCH 4/5] spi: Add fsl-dspi driver Sascha Hauer 2020-04-04 19:14 ` Andrey Smirnov 2020-04-14 10:30 ` Sascha Hauer 2020-03-25 8:36 ` [PATCH 5/5] mtd: spi-nor: Add support for cy15x104q Sascha Hauer
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox