uboot/drivers/spi/soft_spi_legacy.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
   4 *
   5 * Influenced by code from:
   6 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
   7 *
   8 * SPDX-License-Identifier:     GPL-2.0+
   9 */
  10
  11#include <common.h>
  12#include <spi.h>
  13
  14#include <malloc.h>
  15
  16/*-----------------------------------------------------------------------
  17 * Definitions
  18 */
  19
  20#ifdef DEBUG_SPI
  21#define PRINTD(fmt,args...)     printf (fmt ,##args)
  22#else
  23#define PRINTD(fmt,args...)
  24#endif
  25
  26struct soft_spi_slave {
  27        struct spi_slave slave;
  28        unsigned int mode;
  29};
  30
  31static inline struct soft_spi_slave *to_soft_spi(struct spi_slave *slave)
  32{
  33        return container_of(slave, struct soft_spi_slave, slave);
  34}
  35
  36/*=====================================================================*/
  37/*                         Public Functions                            */
  38/*=====================================================================*/
  39
  40/*-----------------------------------------------------------------------
  41 * Initialization
  42 */
  43void spi_init (void)
  44{
  45}
  46
  47struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
  48                unsigned int max_hz, unsigned int mode)
  49{
  50        struct soft_spi_slave *ss;
  51
  52        if (!spi_cs_is_valid(bus, cs))
  53                return NULL;
  54
  55        ss = spi_alloc_slave(struct soft_spi_slave, bus, cs);
  56        if (!ss)
  57                return NULL;
  58
  59        ss->mode = mode;
  60
  61        /* TODO: Use max_hz to limit the SCK rate */
  62
  63        return &ss->slave;
  64}
  65
  66void spi_free_slave(struct spi_slave *slave)
  67{
  68        struct soft_spi_slave *ss = to_soft_spi(slave);
  69
  70        free(ss);
  71}
  72
  73int spi_claim_bus(struct spi_slave *slave)
  74{
  75#ifdef CONFIG_SYS_IMMR
  76        volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
  77#endif
  78        struct soft_spi_slave *ss = to_soft_spi(slave);
  79
  80        /*
  81         * Make sure the SPI clock is in idle state as defined for
  82         * this slave.
  83         */
  84        if (ss->mode & SPI_CPOL)
  85                SPI_SCL(1);
  86        else
  87                SPI_SCL(0);
  88
  89        return 0;
  90}
  91
  92void spi_release_bus(struct spi_slave *slave)
  93{
  94        /* Nothing to do */
  95}
  96
  97/*-----------------------------------------------------------------------
  98 * SPI transfer
  99 *
 100 * This writes "bitlen" bits out the SPI MOSI port and simultaneously clocks
 101 * "bitlen" bits in the SPI MISO port.  That's just the way SPI works.
 102 *
 103 * The source of the outgoing bits is the "dout" parameter and the
 104 * destination of the input bits is the "din" parameter.  Note that "dout"
 105 * and "din" can point to the same memory location, in which case the
 106 * input data overwrites the output data (since both are buffered by
 107 * temporary variables, this is OK).
 108 */
 109int  spi_xfer(struct spi_slave *slave, unsigned int bitlen,
 110                const void *dout, void *din, unsigned long flags)
 111{
 112#ifdef CONFIG_SYS_IMMR
 113        volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
 114#endif
 115        struct soft_spi_slave *ss = to_soft_spi(slave);
 116        uchar           tmpdin  = 0;
 117        uchar           tmpdout = 0;
 118        const u8        *txd = dout;
 119        u8              *rxd = din;
 120        int             cpol = ss->mode & SPI_CPOL;
 121        int             cpha = ss->mode & SPI_CPHA;
 122        unsigned int    j;
 123
 124        PRINTD("spi_xfer: slave %u:%u dout %08X din %08X bitlen %u\n",
 125                slave->bus, slave->cs, *(uint *)txd, *(uint *)rxd, bitlen);
 126
 127        if (flags & SPI_XFER_BEGIN)
 128                spi_cs_activate(slave);
 129
 130        for(j = 0; j < bitlen; j++) {
 131                /*
 132                 * Check if it is time to work on a new byte.
 133                 */
 134                if ((j % 8) == 0) {
 135                        if (txd)
 136                                tmpdout = *txd++;
 137                        else
 138                                tmpdout = 0;
 139                        if(j != 0) {
 140                                if (rxd)
 141                                        *rxd++ = tmpdin;
 142                        }
 143                        tmpdin  = 0;
 144                }
 145
 146                if (!cpha)
 147                        SPI_SCL(!cpol);
 148                SPI_SDA(tmpdout & 0x80);
 149                SPI_DELAY;
 150                if (cpha)
 151                        SPI_SCL(!cpol);
 152                else
 153                        SPI_SCL(cpol);
 154                tmpdin  <<= 1;
 155                tmpdin  |= SPI_READ;
 156                tmpdout <<= 1;
 157                SPI_DELAY;
 158                if (cpha)
 159                        SPI_SCL(cpol);
 160        }
 161        /*
 162         * If the number of bits isn't a multiple of 8, shift the last
 163         * bits over to left-justify them.  Then store the last byte
 164         * read in.
 165         */
 166        if (rxd) {
 167                if ((bitlen % 8) != 0)
 168                        tmpdin <<= 8 - (bitlen % 8);
 169                *rxd++ = tmpdin;
 170        }
 171
 172        if (flags & SPI_XFER_END)
 173                spi_cs_deactivate(slave);
 174
 175        return(0);
 176}
 177