OpenCores
URL https://opencores.org/ocsvn/tiny_spi/tiny_spi/trunk

Subversion Repositories tiny_spi

[/] [tiny_spi/] [trunk/] [driver/] [u-boot/] [oc_tiny_spi.c] - Diff between revs 5 and 9

Show entire file | Details | Blame | View Log

Rev 5 Rev 9
Line 1... Line 1...
/*
/*
 * Opencore tiny_spi driver
 * Opencore tiny_spi driver
 *
 *
 
 * http://opencores.org/project,tiny_spi
 
 *
 * based on bfin_spi.c
 * based on bfin_spi.c
 * Copyright (c) 2005-2008 Analog Devices Inc.
 * Copyright (c) 2005-2008 Analog Devices Inc.
 * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
 * Copyright (C) 2010 Thomas Chou <thomas@wytron.com.tw>
 *
 *
 * Licensed under the GPL-2 or later.
 * Licensed under the GPL-2 or later.
 */
 */
 
 
#include <common.h>
#include <common.h>
#include <asm/io.h>
#include <asm/io.h>
#include <malloc.h>
#include <malloc.h>
#include <spi.h>
#include <spi.h>
#include <asm/gpio.h>
#include <asm/gpio.h>
 
 
#define TINY_SPI_RXDATA 0
#define TINY_SPI_RXDATA 0
#define TINY_SPI_TXDATA 4
#define TINY_SPI_TXDATA 4
#define TINY_SPI_STATUS 8
#define TINY_SPI_STATUS 8
#define TINY_SPI_CONTROL 12
#define TINY_SPI_CONTROL 12
#define TINY_SPI_BAUD 16
#define TINY_SPI_BAUD 16
Line 24... Line 28...
struct tiny_spi_host {
struct tiny_spi_host {
        ulong base;
        ulong base;
        uint freq;
        uint freq;
        uint baudwidth;
        uint baudwidth;
};
};
static struct tiny_spi_host tiny_spi_host_list[] = CONFIG_SYS_TINY_SPI_LIST;
static const struct tiny_spi_host tiny_spi_host_list[] =
 
        CONFIG_SYS_TINY_SPI_LIST;
 
 
struct tiny_spi_slave {
struct tiny_spi_slave {
        struct spi_slave slave;
        struct spi_slave slave;
        struct tiny_spi_host *host;
        const struct tiny_spi_host *host;
        uint mode;
        uint mode;
        uint baud;
        uint baud;
        uint flg;
        uint flg;
};
};
#define to_tiny_spi_slave(s) container_of(s, struct tiny_spi_slave, slave)
#define to_tiny_spi_slave(s) container_of(s, struct tiny_spi_slave, slave)
 
 
__attribute__((weak))
 
int spi_cs_is_valid(unsigned int bus, unsigned int cs)
int spi_cs_is_valid(unsigned int bus, unsigned int cs)
{
{
        return bus < ARRAY_SIZE(tiny_spi_host_list) && gpio_is_valid(cs);
        return bus < ARRAY_SIZE(tiny_spi_host_list) && gpio_is_valid(cs);
}
}
 
 
__attribute__((weak))
 
void spi_cs_activate(struct spi_slave *slave)
void spi_cs_activate(struct spi_slave *slave)
{
{
        struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
        struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
        unsigned int cs = slave->cs;
        unsigned int cs = slave->cs;
        gpio_set_value(cs, tiny_spi->flg);
        gpio_set_value(cs, tiny_spi->flg);
        debug("%s: SPI_CS_GPIO:%x\n", __func__, gpio_get_value(cs));
        debug("%s: SPI_CS_GPIO:%x\n", __func__, gpio_get_value(cs));
}
}
 
 
__attribute__((weak))
 
void spi_cs_deactivate(struct spi_slave *slave)
void spi_cs_deactivate(struct spi_slave *slave)
{
{
        struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
        struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
        unsigned int cs = slave->cs;
        unsigned int cs = slave->cs;
        gpio_set_value(cs, !tiny_spi->flg);
        gpio_set_value(cs, !tiny_spi->flg);
Line 62... Line 64...
}
}
 
 
void spi_set_speed(struct spi_slave *slave, uint hz)
void spi_set_speed(struct spi_slave *slave, uint hz)
{
{
        struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
        struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
        struct tiny_spi_host *host = tiny_spi->host;
        const struct tiny_spi_host *host = tiny_spi->host;
        tiny_spi->baud = DIV_ROUND_UP(host->freq, hz * 2) - 1;
        tiny_spi->baud = min(DIV_ROUND_UP(host->freq, hz * 2),
        if (tiny_spi->baud > (1 << host->baudwidth) - 1)
                             (1 << host->baudwidth)) - 1;
                tiny_spi->baud =(1 << host->baudwidth) - 1;
 
        debug("%s: speed %u actual %u\n", __func__, hz,
        debug("%s: speed %u actual %u\n", __func__, hz,
              host->freq / ((tiny_spi->baud + 1) * 2));
              host->freq / ((tiny_spi->baud + 1) * 2));
}
}
 
 
void spi_init(void)
void spi_init(void)
Line 109... Line 110...
}
}
 
 
int spi_claim_bus(struct spi_slave *slave)
int spi_claim_bus(struct spi_slave *slave)
{
{
        struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
        struct tiny_spi_slave *tiny_spi = to_tiny_spi_slave(slave);
        struct tiny_spi_host *host = tiny_spi->host;
        const struct tiny_spi_host *host = tiny_spi->host;
        debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
        debug("%s: bus:%i cs:%i\n", __func__, slave->bus, slave->cs);
        gpio_direction_output(slave->cs, !tiny_spi->flg);
        gpio_direction_output(slave->cs, !tiny_spi->flg);
        writel(tiny_spi->mode, host->base + TINY_SPI_CONTROL);
        writel(tiny_spi->mode, host->base + TINY_SPI_CONTROL);
        writel(tiny_spi->baud, host->base + TINY_SPI_BAUD);
        writel(tiny_spi->baud, host->base + TINY_SPI_BAUD);
        return 0;
        return 0;
Line 129... Line 130...
#endif
#endif
 
 
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
int spi_xfer(struct spi_slave *slave, unsigned int bitlen, const void *dout,
             void *din, unsigned long flags)
             void *din, unsigned long flags)
{
{
        struct tiny_spi_host *host = to_tiny_spi_slave(slave)->host;
        const struct tiny_spi_host *host = to_tiny_spi_slave(slave)->host;
        const u8 *txp = dout;
        const u8 *txp = dout;
        u8 *rxp = din;
        u8 *rxp = din;
        uint bytes = bitlen / 8;
        uint bytes = bitlen / 8;
        uint i;
        uint i;
 
 
Line 157... Line 158...
                if (bytes > 1) {
                if (bytes > 1) {
                        writeb(*txp++, host->base + TINY_SPI_TXDATA);
                        writeb(*txp++, host->base + TINY_SPI_TXDATA);
                        for (i = 2; i < bytes; i++) {
                        for (i = 2; i < bytes; i++) {
                                u8 rx, tx = *txp++;
                                u8 rx, tx = *txp++;
                                while (!(readb(host->base + TINY_SPI_STATUS) &
                                while (!(readb(host->base + TINY_SPI_STATUS) &
                                         TINY_SPI_STATUS_TXR));
                                         TINY_SPI_STATUS_TXR))
 
                                        ;
                                rx = readb(host->base + TINY_SPI_TXDATA);
                                rx = readb(host->base + TINY_SPI_TXDATA);
                                writeb(tx, host->base + TINY_SPI_TXDATA);
                                writeb(tx, host->base + TINY_SPI_TXDATA);
                                *rxp++ = rx;
                                *rxp++ = rx;
                        }
                        }
                        while (!(readb(host->base + TINY_SPI_STATUS) &
                        while (!(readb(host->base + TINY_SPI_STATUS) &
                                 TINY_SPI_STATUS_TXR));
                                 TINY_SPI_STATUS_TXR))
 
                                ;
                        *rxp++ = readb(host->base + TINY_SPI_TXDATA);
                        *rxp++ = readb(host->base + TINY_SPI_TXDATA);
                }
                }
                while (!(readb(host->base + TINY_SPI_STATUS) &
                while (!(readb(host->base + TINY_SPI_STATUS) &
                         TINY_SPI_STATUS_TXE));
                         TINY_SPI_STATUS_TXE))
 
                        ;
                *rxp++ = readb(host->base + TINY_SPI_RXDATA);
                *rxp++ = readb(host->base + TINY_SPI_RXDATA);
        } else if (rxp) {
        } else if (rxp) {
                writeb(CONFIG_TINY_SPI_IDLE_VAL, host->base + TINY_SPI_TXDATA);
                writeb(CONFIG_TINY_SPI_IDLE_VAL, host->base + TINY_SPI_TXDATA);
                if (bytes > 1) {
                if (bytes > 1) {
                        writeb(CONFIG_TINY_SPI_IDLE_VAL,
                        writeb(CONFIG_TINY_SPI_IDLE_VAL,
                               host->base + TINY_SPI_TXDATA);
                               host->base + TINY_SPI_TXDATA);
                        for (i = 2; i < bytes; i++) {
                        for (i = 2; i < bytes; i++) {
                                u8 rx;
                                u8 rx;
                                while (!(readb(host->base + TINY_SPI_STATUS) &
                                while (!(readb(host->base + TINY_SPI_STATUS) &
                                         TINY_SPI_STATUS_TXR));
                                         TINY_SPI_STATUS_TXR))
 
                                        ;
                                rx = readb(host->base + TINY_SPI_TXDATA);
                                rx = readb(host->base + TINY_SPI_TXDATA);
                                writeb(CONFIG_TINY_SPI_IDLE_VAL,
                                writeb(CONFIG_TINY_SPI_IDLE_VAL,
                                       host->base + TINY_SPI_TXDATA);
                                       host->base + TINY_SPI_TXDATA);
                                *rxp++ = rx;
                                *rxp++ = rx;
                        }
                        }
                        while (!(readb(host->base + TINY_SPI_STATUS) &
                        while (!(readb(host->base + TINY_SPI_STATUS) &
                                 TINY_SPI_STATUS_TXR));
                                 TINY_SPI_STATUS_TXR))
 
                                ;
                        *rxp++ = readb(host->base + TINY_SPI_TXDATA);
                        *rxp++ = readb(host->base + TINY_SPI_TXDATA);
                }
                }
                while (!(readb(host->base + TINY_SPI_STATUS) &
                while (!(readb(host->base + TINY_SPI_STATUS) &
                         TINY_SPI_STATUS_TXE));
                         TINY_SPI_STATUS_TXE))
 
                        ;
                *rxp++ = readb(host->base + TINY_SPI_RXDATA);
                *rxp++ = readb(host->base + TINY_SPI_RXDATA);
        } else if (txp) {
        } else if (txp) {
                writeb(*txp++, host->base + TINY_SPI_TXDATA);
                writeb(*txp++, host->base + TINY_SPI_TXDATA);
                if (bytes > 1) {
                if (bytes > 1) {
                        writeb(*txp++, host->base + TINY_SPI_TXDATA);
                        writeb(*txp++, host->base + TINY_SPI_TXDATA);
                        for (i = 2; i < bytes; i++) {
                        for (i = 2; i < bytes; i++) {
                                u8 tx = *txp++;
                                u8 tx = *txp++;
                                while (!(readb(host->base + TINY_SPI_STATUS) &
                                while (!(readb(host->base + TINY_SPI_STATUS) &
                                         TINY_SPI_STATUS_TXR));
                                         TINY_SPI_STATUS_TXR))
 
                                        ;
                                writeb(tx, host->base + TINY_SPI_TXDATA);
                                writeb(tx, host->base + TINY_SPI_TXDATA);
                        }
                        }
                }
                }
                while (!(readb(host->base + TINY_SPI_STATUS) &
                while (!(readb(host->base + TINY_SPI_STATUS) &
                         TINY_SPI_STATUS_TXE));
                         TINY_SPI_STATUS_TXE))
 
                        ;
        } else {
        } else {
                writeb(CONFIG_TINY_SPI_IDLE_VAL, host->base + TINY_SPI_TXDATA);
                writeb(CONFIG_TINY_SPI_IDLE_VAL, host->base + TINY_SPI_TXDATA);
                if (bytes > 1) {
                if (bytes > 1) {
                        writeb(CONFIG_TINY_SPI_IDLE_VAL,
                        writeb(CONFIG_TINY_SPI_IDLE_VAL,
                               host->base + TINY_SPI_TXDATA);
                               host->base + TINY_SPI_TXDATA);
                        for (i = 2; i < bytes; i++) {
                        for (i = 2; i < bytes; i++) {
                                while (!(readb(host->base + TINY_SPI_STATUS) &
                                while (!(readb(host->base + TINY_SPI_STATUS) &
                                         TINY_SPI_STATUS_TXR));
                                         TINY_SPI_STATUS_TXR))
 
                                        ;
                                writeb(CONFIG_TINY_SPI_IDLE_VAL,
                                writeb(CONFIG_TINY_SPI_IDLE_VAL,
                                       host->base + TINY_SPI_TXDATA);
                                       host->base + TINY_SPI_TXDATA);
                        }
                        }
                }
                }
                while (!(readb(host->base + TINY_SPI_STATUS) &
                while (!(readb(host->base + TINY_SPI_STATUS) &
                         TINY_SPI_STATUS_TXE));
                         TINY_SPI_STATUS_TXE))
 
                        ;
        }
        }
 
 
 done:
 done:
        if (flags & SPI_XFER_END)
        if (flags & SPI_XFER_END)
                spi_cs_deactivate(slave);
                spi_cs_deactivate(slave);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.