All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jagan Teki <jagannadh.teki@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v2 5/8] lpc32xx: add LPC32xx SSP support (SPI mode)
Date: Tue, 17 Feb 2015 15:03:16 +0530	[thread overview]
Message-ID: <CAD6G_RRmB=kCK=JwSQNONbiUaNUbg252=i=Xy2t=z3A_25nYhA@mail.gmail.com> (raw)
In-Reply-To: <1423762636-18353-6-git-send-email-albert.aribaud@3adev.fr>

On 12 February 2015 at 23:07, Albert ARIBAUD (3ADEV)
<albert.aribaud@3adev.fr> wrote:
> Signed-off-by: Albert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
> ---
>
> Changes in v2:
> - added MUX setting for SSP0
>
>  arch/arm/cpu/arm926ejs/lpc32xx/devices.c      |  14 +++
>  arch/arm/include/asm/arch-lpc32xx/clk.h       |   3 +
>  arch/arm/include/asm/arch-lpc32xx/sys_proto.h |   1 +
>  drivers/spi/Makefile                          |   1 +
>  drivers/spi/lpc32xx_ssp.c                     | 132 ++++++++++++++++++++++++++
>  5 files changed, 151 insertions(+)
>  create mode 100644 drivers/spi/lpc32xx_ssp.c
>
> diff --git a/arch/arm/cpu/arm926ejs/lpc32xx/devices.c b/arch/arm/cpu/arm926ejs/lpc32xx/devices.c
> index a407098..5a453e3 100644
> --- a/arch/arm/cpu/arm926ejs/lpc32xx/devices.c
> +++ b/arch/arm/cpu/arm926ejs/lpc32xx/devices.c
> @@ -8,11 +8,13 @@
>  #include <asm/arch/cpu.h>
>  #include <asm/arch/clk.h>
>  #include <asm/arch/uart.h>
> +#include <asm/arch/mux.h>
>  #include <asm/io.h>
>  #include <dm.h>
>
>  static struct clk_pm_regs    *clk  = (struct clk_pm_regs *)CLK_PM_BASE;
>  static struct uart_ctrl_regs *ctrl = (struct uart_ctrl_regs *)UART_CTRL_BASE;
> +static struct mux_regs *mux = (struct mux_regs *)MUX_BASE;
>
>  void lpc32xx_uart_init(unsigned int uart_id)
>  {
> @@ -66,3 +68,15 @@ void lpc32xx_i2c_init(unsigned int devnum)
>  U_BOOT_DEVICE(lpc32xx_gpios) = {
>         .name = "gpio_lpc32xx"
>  };
> +
> +/* Mux for SCK0, MISO0, MOSI0. We do not use SSEL0. */
> +
> +#define P_MUX_SET_SSP0 0x1600
> +
> +void lpc32xx_ssp_init(void)
> +{
> +       /* Enable SSP0 interface */
> +       writel(CLK_SSP0_ENABLE_CLOCK, &clk->ssp_ctrl);
> +       /* Mux SSP0 pins */
> +       writel(P_MUX_SET_SSP0, &mux->p_mux_set);
> +}
> diff --git a/arch/arm/include/asm/arch-lpc32xx/clk.h b/arch/arm/include/asm/arch-lpc32xx/clk.h
> index 781ac07..2cb5703 100644
> --- a/arch/arm/include/asm/arch-lpc32xx/clk.h
> +++ b/arch/arm/include/asm/arch-lpc32xx/clk.h
> @@ -155,6 +155,9 @@ struct clk_pm_regs {
>  #define CLK_NAND_MLC                   (1 << 1)
>  #define CLK_NAND_MLC_INT               (1 << 5)
>
> +/* SSP Clock Control Register bits */
> +#define CLK_SSP0_ENABLE_CLOCK          (1 << 0)
> +
>  unsigned int get_sys_clk_rate(void);
>  unsigned int get_hclk_pll_rate(void);
>  unsigned int get_hclk_clk_div(void);
> diff --git a/arch/arm/include/asm/arch-lpc32xx/sys_proto.h b/arch/arm/include/asm/arch-lpc32xx/sys_proto.h
> index a4a05d1..86d5ee9 100644
> --- a/arch/arm/include/asm/arch-lpc32xx/sys_proto.h
> +++ b/arch/arm/include/asm/arch-lpc32xx/sys_proto.h
> @@ -11,5 +11,6 @@ void lpc32xx_uart_init(unsigned int uart_id);
>  void lpc32xx_mac_init(void);
>  void lpc32xx_mlc_nand_init(void);
>  void lpc32xx_i2c_init(unsigned int devnum);
> +void lpc32xx_ssp_init(void);
>
>  #endif /* _LPC32XX_SYS_PROTO_H */
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
> index edbd520..ce6f1cc 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -32,6 +32,7 @@ obj-$(CONFIG_EXYNOS_SPI) += exynos_spi.o
>  obj-$(CONFIG_FTSSP010_SPI) += ftssp010_spi.o
>  obj-$(CONFIG_ICH_SPI) +=  ich.o
>  obj-$(CONFIG_KIRKWOOD_SPI) += kirkwood_spi.o
> +obj-$(CONFIG_LPC32XX_SSP) += lpc32xx_ssp.o
>  obj-$(CONFIG_MPC52XX_SPI) += mpc52xx_spi.o
>  obj-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
>  obj-$(CONFIG_MXC_SPI) += mxc_spi.o
> diff --git a/drivers/spi/lpc32xx_ssp.c b/drivers/spi/lpc32xx_ssp.c
> new file mode 100644
> index 0000000..40270df
> --- /dev/null
> +++ b/drivers/spi/lpc32xx_ssp.c
> @@ -0,0 +1,132 @@
> +/*
> + * LPC32xx SSP interface (SPI mode)
> + *
> + * (C) Copyright 2014  DENX Software Engineering GmbH
> + * Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
> + *
> + * SPDX-License-Identifier:     GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <linux/compat.h>
> +#include <asm/io.h>
> +#include <malloc.h>
> +#include <spi.h>
> +#include <asm/arch/clk.h>
> +
> +/* SSP chip registers */
> +struct ssp_regs {
> +       u32 cr0;
> +       u32 cr1;
> +       u32 data;
> +       u32 sr;
> +       u32 cpsr;
> +       u32 imsc;
> +       u32 ris;
> +       u32 mis;
> +       u32 icr;
> +       u32 dmacr;
> +};
> +
> +/* CR1 register defines  */
> +#define SSP_CR1_SSP_ENABLE 0x0002
> +
> +/* SR register defines  */
> +#define SSP_SR_TNF 0x0002
> +/* SSP status RX FIFO not empty bit */
> +#define SSP_SR_RNE 0x0004
> +
> +static struct ssp_regs *ssp0_regs = (struct ssp_regs *)SSP0_BASE;

Pls- use static inline instead of direct macro assignment.

> +
> +static struct spi_slave ssp0_slave = {
> +       .bus = 0,
> +       .cs = 0,
> +       .op_mode_rx = 0,
> +       .op_mode_tx = 0,
> +       .wordlen = 8,
> +       .max_write_size = 1, /* this is for SPI FLASHes -- don't care */
> +       .memory_map = NULL, /* for SPI FLASHes too */
> +       .option = 0,
> +       .flags = 0
> +};

This wouldn't require - spi_alloc_slave() is a generic func to do all the stuff.
See comments below...

> +
> +/* 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()
> +       */
> +}
> +
> +/* 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)
> +{

Define spi_cs_is_valid() that wikk ensure the controlling bus and cs
options command prompt

use spi_alloc_slave() and members will be having reg_base and slave that's.
See drivers/spi/zynq_spi.c for more info.

Suggested code:
static struct ssp0_spi_slave {
     struct spi_slave slave;
     struct ssp_regs *base;
};

static inline struct ssp0_regs *get_ssp0_spi_base(void)
{
           return (struct ssp0_regs *) SSP0_BASE;
}

in spi_setup_slave()

{
    struct ssp0_spi_slave *ssp0;

    /* valid bus and cs */

    /* allocate */
    ssp0 = spi_alloc_slave(struct ssp0_spi_slave, bus, cs);

    ssp0->base = get_ssp0_spi_base();

}

> +       /* we only set up SSP0 for now, so ignore bus */
> +
> +       if (mode & SPI_3WIRE) {
> +               error("3-wire mode not supported");
> +               return NULL;
> +       }
> +
> +       if (mode & SPI_SLAVE) {
> +               error("slave mode not supported\n");
> +               return NULL;
> +       }
> +
> +       if (mode & SPI_PREAMBLE) {
> +               error("preamble byte skipping not supported\n");
> +               return NULL;
> +       }
> +
> +       /*
> +        * 8 bit frame, SPI fmt, 500kbps -> clock divider is 26.
> +        * Set SCR to 0 and CPSDVSR to 26.
> +        */
> +
> +       writel(0x7, &ssp0_regs->cr0); /* 8-bit chunks, SPI, 1 clk/bit */
> +       writel(26, &ssp0_regs->cpsr); /* SSP clock = HCLK/26 = 500kbps */
> +       writel(0, &ssp0_regs->imsc); /* do not raise any interrupts */
> +       writel(0, &ssp0_regs->icr); /* clear any pending interrupt */
> +       writel(0, &ssp0_regs->dmacr); /* do not do DMAs */
> +       writel(SSP_CR1_SSP_ENABLE, &ssp0_regs->cr1); /* enable SSP0 */
> +       return &ssp0_slave;
> +}
> +
> +int spi_claim_bus(struct spi_slave *slave)
> +{
> +       /* 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)
> +{
> +       int bytelen = bitlen >> 3;
> +       int idx_out = 0;
> +       int idx_in = 0;
> +       int start_time;
> +
> +       start_time = get_timer(0);
> +       while ((idx_out < bytelen) || (idx_in < bytelen)) {
> +               int status = readl(&ssp0_regs->sr);
> +               if ((idx_out < bytelen) && (status & SSP_SR_TNF))
> +                       writel(((u8 *)dout)[idx_out++], &ssp0_regs->data);
> +               if ((idx_in < bytelen) && (status & status & SSP_SR_RNE))
> +                       ((u8 *)din)[idx_in++] = readl(&ssp0_regs->data);
> +               if (get_timer(start_time) >= CONFIG_LPC32XX_SSP_TIMEOUT)
> +                       return -1;
> +       }
> +       return 0;
> +}
> +
> +void spi_release_bus(struct spi_slave *slave)
> +{
> +       /* do nothing */
> +}
> +
> +void spi_free_slave(struct spi_slave *slave)
> +{
> +       /* do nothing */
> +}
> --
> 2.1.0
>

thanks!
-- 
Jagan.

  parent reply	other threads:[~2015-02-17  9:33 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-02-12 17:36 [U-Boot] [PATCH v2 0/8] Extend LPC32xx functionality and add LPC32xx-based work_92015 board Albert ARIBAUD
2015-02-12 17:37 ` [U-Boot] [PATCH v2 1/8] lpc32xx: add Ethernet support Albert ARIBAUD
2015-02-12 17:37   ` [U-Boot] [PATCH v2 2/8] lpc32xx: mtd: nand: add MLC NAND controller Albert ARIBAUD
2015-02-12 17:37     ` [U-Boot] [PATCH v2 3/8] lpc32xx: i2c: add LPC32xx I2C interface support Albert ARIBAUD
2015-02-12 17:37       ` [U-Boot] [PATCH v2 4/8] lpc32xx: add GPIO support Albert ARIBAUD
2015-02-12 17:37         ` [U-Boot] [PATCH v2 5/8] lpc32xx: add LPC32xx SSP support (SPI mode) Albert ARIBAUD
2015-02-12 17:37           ` [U-Boot] [PATCH v2 6/8] dtt: add ds620 support Albert ARIBAUD
2015-02-12 17:37             ` [U-Boot] [PATCH v2 7/8] lpc32xx: add lpc32xx-spl.bin boot image target Albert ARIBAUD
2015-02-12 17:37               ` [U-Boot] [PATCH v2 8/8] lpc32xx: add support for board work_92105 Albert ARIBAUD
2015-02-13  9:36                 ` Stefan Roese
2015-02-13 11:08                   ` Albert ARIBAUD
2015-02-13 11:19                     ` Stefan Roese
2015-02-17  1:08                 ` [U-Boot] [U-Boot, v2, " Tom Rini
2015-02-17  7:06                   ` Albert ARIBAUD
2015-02-13  5:06               ` [U-Boot] [PATCH v2 7/8] lpc32xx: add lpc32xx-spl.bin boot image target Simon Glass
2015-02-17  9:33           ` Jagan Teki [this message]
2015-02-17  9:51             ` [U-Boot] [PATCH v2 5/8] lpc32xx: add LPC32xx SSP support (SPI mode) Albert ARIBAUD
2015-02-17 13:15               ` Jagan Teki
2015-02-13  5:06         ` [U-Boot] [PATCH v2 4/8] lpc32xx: add GPIO support Simon Glass
2015-02-13  6:30           ` Albert ARIBAUD
2015-02-13 14:33             ` Simon Glass
2015-02-13 10:48       ` [U-Boot] [PATCH v2 3/8] lpc32xx: i2c: add LPC32xx I2C interface support Heiko Schocher
2015-02-13 11:09         ` Albert ARIBAUD
2015-02-13 11:20           ` Heiko Schocher
2015-02-15 21:48             ` Simon Glass
2015-02-17 13:20 ` [U-Boot] [PATCH v2 0/8] Extend LPC32xx functionality and add LPC32xx-based work_92015 board Tom Rini
2015-02-17 13:26   ` Albert ARIBAUD
2015-02-17 16:10     ` Tom Rini
2015-03-30 12:07       ` Jagan Teki
2015-03-31  5:24         ` Albert ARIBAUD
2015-03-31  7:00           ` Jagan Teki
2015-03-31  9:26             ` Albert ARIBAUD

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAD6G_RRmB=kCK=JwSQNONbiUaNUbg252=i=Xy2t=z3A_25nYhA@mail.gmail.com' \
    --to=jagannadh.teki@gmail.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.