uboot/drivers/spi/lpc32xx_ssp.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * LPC32xx SSP interface (SPI mode)
   4 *
   5 * (C) Copyright 2014  DENX Software Engineering GmbH
   6 * Written-by: Albert ARIBAUD <albert.aribaud@3adev.fr>
   7 */
   8
   9#include <common.h>
  10#include <linux/compat.h>
  11#include <asm/io.h>
  12#include <malloc.h>
  13#include <spi.h>
  14#include <asm/arch/clk.h>
  15
  16/* SSP chip registers */
  17struct ssp_regs {
  18        u32 cr0;
  19        u32 cr1;
  20        u32 data;
  21        u32 sr;
  22        u32 cpsr;
  23        u32 imsc;
  24        u32 ris;
  25        u32 mis;
  26        u32 icr;
  27        u32 dmacr;
  28};
  29
  30/* CR1 register defines  */
  31#define SSP_CR1_SSP_ENABLE 0x0002
  32
  33/* SR register defines  */
  34#define SSP_SR_TNF 0x0002
  35/* SSP status RX FIFO not empty bit */
  36#define SSP_SR_RNE 0x0004
  37
  38/* lpc32xx spi slave */
  39struct lpc32xx_spi_slave {
  40        struct spi_slave slave;
  41        struct ssp_regs *regs;
  42};
  43
  44static inline struct lpc32xx_spi_slave *to_lpc32xx_spi_slave(
  45        struct spi_slave *slave)
  46{
  47        return container_of(slave, struct lpc32xx_spi_slave, slave);
  48}
  49
  50/* the following is called in sequence by do_spi_xfer() */
  51
  52struct spi_slave *spi_setup_slave(uint bus, uint cs, uint max_hz, uint mode)
  53{
  54        struct lpc32xx_spi_slave *lslave;
  55
  56        /* we only set up SSP0 for now, so ignore bus */
  57
  58        if (mode & SPI_3WIRE) {
  59                pr_err("3-wire mode not supported");
  60                return NULL;
  61        }
  62
  63        if (mode & SPI_SLAVE) {
  64                pr_err("slave mode not supported\n");
  65                return NULL;
  66        }
  67
  68        if (mode & SPI_PREAMBLE) {
  69                pr_err("preamble byte skipping not supported\n");
  70                return NULL;
  71        }
  72
  73        lslave = spi_alloc_slave(struct lpc32xx_spi_slave, bus, cs);
  74        if (!lslave) {
  75                printf("SPI_error: Fail to allocate lpc32xx_spi_slave\n");
  76                return NULL;
  77        }
  78
  79        lslave->regs = (struct ssp_regs *)SSP0_BASE;
  80
  81        /*
  82         * 8 bit frame, SPI fmt, 500kbps -> clock divider is 26.
  83         * Set SCR to 0 and CPSDVSR to 26.
  84         */
  85
  86        writel(0x7, &lslave->regs->cr0); /* 8-bit chunks, SPI, 1 clk/bit */
  87        writel(26, &lslave->regs->cpsr); /* SSP clock = HCLK/26 = 500kbps */
  88        writel(0, &lslave->regs->imsc); /* do not raise any interrupts */
  89        writel(0, &lslave->regs->icr); /* clear any pending interrupt */
  90        writel(0, &lslave->regs->dmacr); /* do not do DMAs */
  91        writel(SSP_CR1_SSP_ENABLE, &lslave->regs->cr1); /* enable SSP0 */
  92        return &lslave->slave;
  93}
  94
  95void spi_free_slave(struct spi_slave *slave)
  96{
  97        struct lpc32xx_spi_slave *lslave = to_lpc32xx_spi_slave(slave);
  98
  99        debug("(lpc32xx) spi_free_slave: 0x%08x\n", (u32)lslave);
 100        free(lslave);
 101}
 102
 103int spi_claim_bus(struct spi_slave *slave)
 104{
 105        /* only one bus and slave so far, always available */
 106        return 0;
 107}
 108
 109int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 110        const void *dout, void *din, unsigned long flags)
 111{
 112        struct lpc32xx_spi_slave *lslave = to_lpc32xx_spi_slave(slave);
 113        int bytelen = bitlen >> 3;
 114        int idx_out = 0;
 115        int idx_in = 0;
 116        int start_time;
 117
 118        start_time = get_timer(0);
 119        while ((idx_out < bytelen) || (idx_in < bytelen)) {
 120                int status = readl(&lslave->regs->sr);
 121                if ((idx_out < bytelen) && (status & SSP_SR_TNF))
 122                        writel(((u8 *)dout)[idx_out++], &lslave->regs->data);
 123                if ((idx_in < bytelen) && (status & SSP_SR_RNE))
 124                        ((u8 *)din)[idx_in++] = readl(&lslave->regs->data);
 125                if (get_timer(start_time) >= CONFIG_LPC32XX_SSP_TIMEOUT)
 126                        return -1;
 127        }
 128        return 0;
 129}
 130
 131void spi_release_bus(struct spi_slave *slave)
 132{
 133        /* do nothing */
 134}
 135