[U-Boot] [PATCH v1 1/1] spi: lpc32xx_ssp: DM conversion
Jagan Teki
jagan at amarulasolutions.com
Tue Sep 4 06:33:16 UTC 2018
On Wed, May 9, 2018 at 12:37 PM, Akash Gajjar <gajjar04akash at gmail.com> wrote:
> From: Akash Gajjar <gajjar04akash at gmail.com>
>
> This patch adds support for DM to the LPC32xx SSP SPI driver.
>
> Some TODOs are left over for later, These would be enhancements to the
> original functionality, and can come later. The legacy functionality is
> removed in this version.
>
> Signed-off-by: Akash Gajjar <akash at openedev.com>
> ---
> drivers/spi/Kconfig | 10 +-
> drivers/spi/lpc32xx_ssp.c | 145 +++++++++++++++--------------
> include/dm/platform_data/spi_lpc32xx_ssp.h | 15 +++
> 3 files changed, 93 insertions(+), 77 deletions(-)
> create mode 100644 include/dm/platform_data/spi_lpc32xx_ssp.h
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
> index ec92b84..2297d4a 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -99,6 +99,11 @@ config ICH_SPI
> access the SPI NOR flash on platforms embedding this Intel
> ICH IP core.
>
> +config LPC32XX_SSP
> + bool "LPC32XX SPI Driver"
> + help
> + Enable support for SPI on LPC32xx
> +
> config MVEBU_A3700_SPI
> bool "Marvell Armada 3700 SPI driver"
> help
> @@ -277,11 +282,6 @@ config KIRKWOOD_SPI
> Enable support for SPI on various Marvell SoCs, such as
> Kirkwood and Armada 375.
>
> -config LPC32XX_SSP
> - bool "LPC32XX SPI Driver"
> - help
> - Enable support for SPI on LPC32xx
> -
> config MPC8XX_SPI
> bool "MPC8XX SPI Driver"
> depends on MPC8xx
> diff --git a/drivers/spi/lpc32xx_ssp.c b/drivers/spi/lpc32xx_ssp.c
> index e2a593b..ae41b57 100644
> --- a/drivers/spi/lpc32xx_ssp.c
> +++ b/drivers/spi/lpc32xx_ssp.c
> @@ -4,6 +4,9 @@
> * (C) Copyright 2014 DENX Software Engineering GmbH
> * Written-by: Albert ARIBAUD <albert.aribaud at 3adev.fr>
> *
> + * Support for device model:
> + * Copyright (C) 2018 Akash Gajjar <akash at openedev.com>
> + *
> * SPDX-License-Identifier: GPL-2.0+
> */
>
> @@ -13,6 +16,8 @@
> #include <malloc.h>
> #include <spi.h>
> #include <asm/arch/clk.h>
> +#include <dm.h>
> +#include <dm/platform_data/spi_lpc32xx_ssp.h>
>
> /* SSP chip registers */
> struct ssp_regs {
> @@ -36,90 +41,36 @@ struct ssp_regs {
> /* SSP status RX FIFO not empty bit */
> #define SSP_SR_RNE 0x0004
>
> -/* lpc32xx spi slave */
> -struct lpc32xx_spi_slave {
> - struct spi_slave slave;
> +struct lpc32xx_ssp_spi_priv {
> struct ssp_regs *regs;
> };
>
> -static inline struct lpc32xx_spi_slave *to_lpc32xx_spi_slave(
> - struct spi_slave *slave)
> +static int lpc32xx_ssp_spi_claim_bus(struct udevice *dev)
> {
> - return container_of(slave, struct lpc32xx_spi_slave, slave);
> -}
> -
> -/* spi_init is called during boot when CONFIG_CMD_SPI is defined */
> -void spi_init(void)
> -{
> - /*
> - * nothing to do: clocking was enabled in lpc32xx_ssp_enable()
> - * and configuration will be done in spi_setup_slave()
> - */
> + return 0;
> }
>
> -/* the following is called in sequence by do_spi_xfer() */
> -
> -struct spi_slave *spi_setup_slave(uint bus, uint cs, uint max_hz, uint mode)
> +static int lpc32xx_ssp_spi_release_bus(struct udevice *dev)
> {
> - struct lpc32xx_spi_slave *lslave;
> -
> - /* we only set up SSP0 for now, so ignore bus */
> -
> - if (mode & SPI_3WIRE) {
> - pr_err("3-wire mode not supported");
> - return NULL;
> - }
> -
> - if (mode & SPI_SLAVE) {
> - pr_err("slave mode not supported\n");
> - return NULL;
> - }
> -
> - if (mode & SPI_PREAMBLE) {
> - pr_err("preamble byte skipping not supported\n");
> - return NULL;
> - }
> -
> - lslave = spi_alloc_slave(struct lpc32xx_spi_slave, bus, cs);
> - if (!lslave) {
> - printf("SPI_error: Fail to allocate lpc32xx_spi_slave\n");
> - return NULL;
> - }
> -
> - lslave->regs = (struct ssp_regs *)SSP0_BASE;
> -
> - /*
> - * 8 bit frame, SPI fmt, 500kbps -> clock divider is 26.
> - * Set SCR to 0 and CPSDVSR to 26.
> - */
> -
> - writel(0x7, &lslave->regs->cr0); /* 8-bit chunks, SPI, 1 clk/bit */
> - writel(26, &lslave->regs->cpsr); /* SSP clock = HCLK/26 = 500kbps */
> - writel(0, &lslave->regs->imsc); /* do not raise any interrupts */
> - writel(0, &lslave->regs->icr); /* clear any pending interrupt */
> - writel(0, &lslave->regs->dmacr); /* do not do DMAs */
> - writel(SSP_CR1_SSP_ENABLE, &lslave->regs->cr1); /* enable SSP0 */
> - return &lslave->slave;
> + return 0;
> }
>
> -void spi_free_slave(struct spi_slave *slave)
> +static int lpc32xx_ssp_spi_set_speed(struct udevice *bus, uint hz)
> {
> - struct lpc32xx_spi_slave *lslave = to_lpc32xx_spi_slave(slave);
> -
> - debug("(lpc32xx) spi_free_slave: 0x%08x\n", (u32)lslave);
> - free(lslave);
> + return 0;
> }
>
> -int spi_claim_bus(struct spi_slave *slave)
> +static int lpc32xx_ssp_spi_set_mode(struct udevice *bus, uint mode)
> {
> - /* only one bus and slave so far, always available */
> return 0;
> }
>
> -int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
> - const void *dout, void *din, unsigned long flags)
> +static int lpc32xx_ssp_spi_xfer(struct udevice *dev, uint bitlen,
> + const void *dout, void *din, ulong flags)
> {
> - struct lpc32xx_spi_slave *lslave = to_lpc32xx_spi_slave(slave);
> + struct udevice *bus = dev->parent;
> + struct lpc32xx_ssp_priv *priv = dev_get_priv(bus);
> + struct ssp_regs *regs = priv->regs;
> int bytelen = bitlen >> 3;
> int idx_out = 0;
> int idx_in = 0;
> @@ -127,18 +78,68 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
>
> start_time = get_timer(0);
> while ((idx_out < bytelen) || (idx_in < bytelen)) {
> - int status = readl(&lslave->regs->sr);
> + int status = readl(®s->sr);
> if ((idx_out < bytelen) && (status & SSP_SR_TNF))
> - writel(((u8 *)dout)[idx_out++], &lslave->regs->data);
> + writel(((u8 *)dout)[idx_out++], ®s->data);
> if ((idx_in < bytelen) && (status & status & SSP_SR_RNE))
> - ((u8 *)din)[idx_in++] = readl(&lslave->regs->data);
> + ((u8 *)din)[idx_in++] = readl(®s->data);
> if (get_timer(start_time) >= CONFIG_LPC32XX_SSP_TIMEOUT)
> return -1;
> }
> +
> + return 0;
> +}
> +
> +static int lpc32xx_ssp_spi_probe(struct udevice *bus)
> +{
> + struct lpc32xx_ssp_spi_platdata *plat = bus->platdata;
> + struct lpc32xx_ssp_spi_priv = dev_get_priv(bus);
> +
> + priv->regs = plat->regs;
> +
> return 0;
> }
>
> -void spi_release_bus(struct spi_slave *slave)
> +static const struct dm_spi_ops lpc32xx_ssp_spi_ops = {
> + .claim_bus = lpc32xx_ssp_spi_claim_bus,
> + .release_bus = lpc32xx_ssp_spi_release_bus,
> + .xfer = lpc32xx_ssp_spi_xfer,
> + .set_speed = lpc32xx_ssp_spi_set_speed,
> + .set_mode = lpc32xx_ssp_spi_set_mode,
> +};
> +
> +#if CONFIG_IS_ENABLED(OF_CONTROL)
> +static int lpc32xx_ssp_spi_ofdata_to_platadata(struct udevice *bus)
> {
> - /* do nothing */
> + struct lpc32xx_ssp_spi_platdata *plat = bus->platdata;
> + fdt_addr_t addr;
> +
> + addr = devfdt_get_addr(bus);
> + if (addr == FDT_ADDR_T_NONE)
> + return -EINVAL;
> +
> + plat->regs = (struct struct ssp_regs *)addr;
> +
> + return 0;
> }
> +
> +/* TODO: update compatibel device tree */
> +static const struct udevice_id lpc32xx_ssp_spi_ids[] = {
> + { .compatible = "" },
Don't we have DTS for this platform on Linux?
More information about the U-Boot
mailing list