9
0
Fork 0
barebox/drivers/spi/imx_spi.c

179 lines
4.6 KiB
C
Raw Normal View History

2008-03-14 11:59:55 +00:00
/*
* 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
*
*/
2008-03-11 21:13:06 +00:00
#include <common.h>
#include <init.h>
#include <driver.h>
#include <spi/spi.h>
#include <xfuncs.h>
2008-03-14 11:59:55 +00:00
#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;
}
static unsigned int spi_xchg_single(ulong base, unsigned int data)
2008-03-14 11:59:55 +00:00
{
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;
}
2008-03-11 21:13:06 +00:00
static int imx_spi_probe(struct device_d *dev)
{
struct spi_master *master;
2008-03-14 11:59:55 +00:00
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);
2008-03-11 21:13:06 +00:00
spi_register_master(master);
return 0;
}
static struct driver_d imx_spi_driver = {
.name = "imx_spi",
.probe = imx_spi_probe,
};
static int imx_spi_init(void)
{
2008-03-14 11:59:55 +00:00
register_driver(&imx_spi_driver);
return 0;
2008-03-11 21:13:06 +00:00
}
device_initcall(imx_spi_init);