diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2008-03-14 12:59:55 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2008-03-14 12:59:55 +0100 |
commit | a14a5c02f0063e0cf7aae85aace499a080b790c1 (patch) | |
tree | 8fdd107ec20cc9093c12d2baa85b054b14ff1d01 /drivers/spi/imx_spi.c | |
parent | 906eea397a2f4378c4cab841fb832211e0414ce9 (diff) | |
download | barebox-a14a5c02f0063e0cf7aae85aace499a080b790c1.tar.gz barebox-a14a5c02f0063e0cf7aae85aace499a080b790c1.tar.xz |
first (partly) running spi support
Diffstat (limited to 'drivers/spi/imx_spi.c')
-rw-r--r-- | drivers/spi/imx_spi.c | 154 |
1 files changed, 151 insertions, 3 deletions
diff --git a/drivers/spi/imx_spi.c b/drivers/spi/imx_spi.c index 641e635e29..1410f355d8 100644 --- a/drivers/spi/imx_spi.c +++ b/drivers/spi/imx_spi.c @@ -1,14 +1,162 @@ +/* + * Copyright (C) 2008 Sascha Hauer, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + #include <common.h> #include <init.h> #include <driver.h> #include <spi/spi.h> #include <xfuncs.h> +#include <asm/io.h> + +#define MXC_CSPIRXDATA 0x00 +#define MXC_CSPITXDATA 0x04 +#define MXC_CSPICTRL 0x08 +#define MXC_CSPIINT 0x0C +#define MXC_CSPIDMA 0x18 +#define MXC_CSPISTAT 0x0C +#define MXC_CSPIPERIOD 0x14 +#define MXC_CSPITEST 0x10 +#define MXC_CSPIRESET 0x1C + +#define MXC_CSPICTRL_ENABLE (1 << 10) +#define MXC_CSPICTRL_MASTER (1 << 11) +#define MXC_CSPICTRL_XCH (1 << 9) +#define MXC_CSPICTRL_LOWPOL (1 << 5) +#define MXC_CSPICTRL_PHA (1 << 6) +#define MXC_CSPICTRL_SSCTL (1 << 7) +#define MXC_CSPICTRL_HIGHSSPOL (1 << 8) +#define MXC_CSPICTRL_CS(x) (((x) & 0x3) << 19) +#define MXC_CSPICTRL_BITCOUNT(x) (((x) & 0x1f) << 0) +#define MXC_CSPICTRL_DATARATE(x) (((x) & 0x7) << 14) + +#define MXC_CSPICTRL_MAXDATRATE 0x10 +#define MXC_CSPICTRL_DATAMASK 0x1F +#define MXC_CSPICTRL_DATASHIFT 14 + +#define MXC_CSPISTAT_TE (1 << 0) +#define MXC_CSPISTAT_TH (1 << 1) +#define MXC_CSPISTAT_TF (1 << 2) +#define MXC_CSPISTAT_RR (1 << 3) +#define MXC_CSPISTAT_RH (1 << 4) +#define MXC_CSPISTAT_RF (1 << 5) +#define MXC_CSPISTAT_RO (1 << 6) +#define MXC_CSPISTAT_TC_0_7 (1 << 7) +#define MXC_CSPISTAT_TC_0_5 (1 << 8) +#define MXC_CSPISTAT_TC_0_4 (1 << 8) +#define MXC_CSPISTAT_TC_0_0 (1 << 3) +#define MXC_CSPISTAT_BO_0_7 0 +#define MXC_CSPISTAT_BO_0_5 (1 << 7) +#define MXC_CSPISTAT_BO_0_4 (1 << 7) +#define MXC_CSPISTAT_BO_0_0 (1 << 8) + +#define MXC_CSPIPERIOD_32KHZ (1 << 15) + +#define MXC_CSPITEST_LBC (1 << 14) + +static int imx_spi_setup(struct spi_device *spi) +{ + debug("%s mode 0x%08x bits_per_word: %d speed: %d\n", + __FUNCTION__, spi->mode, spi->bits_per_word, + spi->max_speed_hz); + return 0; +} + +unsigned int spi_xchg_single(ulong base, unsigned int data) +{ + + unsigned int cfg_reg = readl(base + MXC_CSPICTRL); + + writel(data, base + MXC_CSPITXDATA); + + cfg_reg |= MXC_CSPICTRL_XCH; + + writel(cfg_reg, base + MXC_CSPICTRL); + + while (readl(base + MXC_CSPICTRL) & MXC_CSPICTRL_XCH); + + return readl(base + MXC_CSPIRXDATA); +} + +static void mxc_spi_chipselect(struct spi_device *spi, int is_active) +{ + struct spi_master *master = spi->master; + ulong base = master->dev->map_base; + u32 ctrl_reg; + + ctrl_reg = MXC_CSPICTRL_CS(spi->chip_select) + | MXC_CSPICTRL_BITCOUNT(spi->bits_per_word - 1) + | MXC_CSPICTRL_DATARATE(7) /* FIXME: calculate data rate */ + | MXC_CSPICTRL_ENABLE + | MXC_CSPICTRL_MASTER; + + if (spi->mode & SPI_CPHA) + ctrl_reg |= MXC_CSPICTRL_PHA; + if (!(spi->mode & SPI_CPOL)) + ctrl_reg |= MXC_CSPICTRL_LOWPOL; + if (spi->mode & SPI_CS_HIGH) + ctrl_reg |= MXC_CSPICTRL_HIGHSSPOL; + + writel(ctrl_reg, base + MXC_CSPICTRL); +} + +static int imx_spi_transfer(struct spi_device *spi, struct spi_message *mesg) +{ + struct spi_master *master = spi->master; + ulong base = master->dev->map_base; + struct spi_transfer *t = NULL; + + mxc_spi_chipselect(spi, 1); + + list_for_each_entry (t, &mesg->transfers, transfer_list) { + const u32 *txbuf = t->tx_buf; + u32 *rxbuf = t->rx_buf; + int i = 0; + + while(i < t->len >> 2) { + rxbuf[i] = spi_xchg_single(base, txbuf[i]); + i++; + } + } + return 0; +} static int imx_spi_probe(struct device_d *dev) { struct spi_master *master; - master = xmalloc(sizeof(struct spi_master)); + debug("%s\n", __FUNCTION__); + + master = xzalloc(sizeof(struct spi_master)); + debug("master: %p %d\n", master, sizeof(struct spi_master)); + + master->dev = dev; + + master->setup = imx_spi_setup; + master->transfer = imx_spi_transfer; + master->num_chipselect = 1; /* FIXME: Board dependent */ + + writel(MXC_CSPICTRL_ENABLE | MXC_CSPICTRL_MASTER, + dev->map_base + MXC_CSPICTRL); + writel(MXC_CSPIPERIOD_32KHZ, + dev->map_base + MXC_CSPIPERIOD); + writel(0, dev->map_base + MXC_CSPIINT); spi_register_master(master); @@ -22,8 +170,8 @@ static struct driver_d imx_spi_driver = { static int imx_spi_init(void) { - register_driver(&imx_spi_driver); - return 0; + register_driver(&imx_spi_driver); + return 0; } device_initcall(imx_spi_init); |