diff options
author | Paul Fertser <fercerpav@gmail.com> | 2011-08-30 10:30:51 +0400 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2011-09-21 09:43:44 +0200 |
commit | 8c1f388d88c78b260e881c93ad21b4fe894300c6 (patch) | |
tree | 56cfcc27b767ca62990e8788cd52b56587c75d5e /drivers | |
parent | b360d7ed5b34a7a04dcc83c6ad6022b1537f4024 (diff) | |
download | barebox-8c1f388d88c78b260e881c93ad21b4fe894300c6.tar.gz barebox-8c1f388d88c78b260e881c93ad21b4fe894300c6.tar.xz |
imx25: imx_spi: support CSPI v0.7 as found on i.MX25
Based on the Linux driver. Tested with m25p80 with CS in GPIO mode.
Clock setting support is ad-hoc as the corresponding mach is not using
the generic clock infrastructure.
Signed-off-by: Paul Fertser <fercerpav@gmail.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/spi/Kconfig | 5 | ||||
-rw-r--r-- | drivers/spi/imx_spi.c | 111 |
2 files changed, 116 insertions, 0 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 9864d84ba6..609bafd07f 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -14,6 +14,11 @@ config DRIVER_SPI_IMX_0_0 depends on ARCH_IMX27 default y +config DRIVER_SPI_IMX_0_7 + bool + depends on ARCH_IMX25 + default y + config DRIVER_SPI_IMX_2_3 bool depends on ARCH_IMX51 || ARCH_IMX53 diff --git a/drivers/spi/imx_spi.c b/drivers/spi/imx_spi.c index 0d21fb3da1..bc84e19337 100644 --- a/drivers/spi/imx_spi.c +++ b/drivers/spi/imx_spi.c @@ -27,6 +27,7 @@ #include <gpio.h> #include <mach/spi.h> #include <mach/generic.h> +#include <mach/clock.h> #define CSPI_0_0_RXDATA 0x00 #define CSPI_0_0_TXDATA 0x04 @@ -65,6 +66,22 @@ #define CSPI_0_0_TEST_LBC (1 << 14) +#define CSPI_0_7_RXDATA 0x00 +#define CSPI_0_7_TXDATA 0x04 +#define CSPI_0_7_CTRL 0x08 +#define CSPI_0_7_CTRL_ENABLE (1 << 0) +#define CSPI_0_7_CTRL_MASTER (1 << 1) +#define CSPI_0_7_CTRL_XCH (1 << 2) +#define CSPI_0_7_CTRL_POL (1 << 4) +#define CSPI_0_7_CTRL_PHA (1 << 5) +#define CSPI_0_7_CTRL_SSCTL (1 << 6) +#define CSPI_0_7_CTRL_SSPOL (1 << 7) +#define CSPI_0_7_CTRL_CS_SHIFT 12 +#define CSPI_0_7_CTRL_DR_SHIFT 16 +#define CSPI_0_7_CTRL_BL_SHIFT 20 +#define CSPI_0_7_STAT 0x14 +#define CSPI_0_7_STAT_RR (1 << 3) + #define CSPI_2_3_RXDATA 0x00 #define CSPI_2_3_TXDATA 0x04 #define CSPI_2_3_CTRL 0x08 @@ -206,6 +223,89 @@ static void cspi_0_0_init(struct imx_spi *imx) } #endif +#ifdef CONFIG_DRIVER_SPI_IMX_0_7 +static unsigned int cspi_0_7_xchg_single(struct imx_spi *imx, unsigned int data) +{ + void __iomem *base = imx->regs; + + unsigned int cfg_reg = readl(base + CSPI_0_7_CTRL); + + writel(data, base + CSPI_0_7_TXDATA); + + cfg_reg |= CSPI_0_7_CTRL_XCH; + + writel(cfg_reg, base + CSPI_0_7_CTRL); + + while (!(readl(base + CSPI_0_7_STAT) & CSPI_0_7_STAT_RR)) + ; + + return readl(base + CSPI_0_7_RXDATA); +} + +/* MX1, MX31, MX35, MX51 CSPI */ +static unsigned int spi_imx_clkdiv_2(unsigned int fin, + unsigned int fspi) +{ + int i, div = 4; + + for (i = 0; i < 7; i++) { + if (fspi * div >= fin) + return i; + div <<= 1; + } + + return 7; +} + +static void cspi_0_7_chipselect(struct spi_device *spi, int is_active) +{ + struct spi_master *master = spi->master; + struct imx_spi *imx = container_of(master, struct imx_spi, master); + void __iomem *base = imx->regs; + unsigned int cs = 0; + int gpio = imx->cs_array[spi->chip_select]; + unsigned int reg = CSPI_0_7_CTRL_ENABLE | CSPI_0_7_CTRL_MASTER; + + if (spi->mode & SPI_CS_HIGH) + cs = 1; + + if (!is_active) { + if (gpio >= 0) + gpio_set_value(gpio, !cs); + return; + } + + reg |= spi_imx_clkdiv_2(imx_get_cspiclk(), spi->max_speed_hz) << + CSPI_0_7_CTRL_DR_SHIFT; + + reg |= (spi->bits_per_word - 1) << CSPI_0_7_CTRL_BL_SHIFT; + reg |= CSPI_0_7_CTRL_SSCTL; + + if (spi->mode & SPI_CPHA) + reg |= CSPI_0_7_CTRL_PHA; + if (spi->mode & SPI_CPOL) + reg |= CSPI_0_7_CTRL_POL; + if (spi->mode & SPI_CS_HIGH) + reg |= CSPI_0_7_CTRL_SSPOL; + if (gpio < 0) + reg |= (gpio + 32) << CSPI_0_7_CTRL_CS_SHIFT; + + writel(reg, base + CSPI_0_7_CTRL); + + if (gpio >= 0) + gpio_set_value(gpio, cs); +} + +static void cspi_0_7_init(struct imx_spi *imx) +{ + void __iomem *base = imx->regs; + + /* drain receive buffer */ + while (readl(base + CSPI_0_7_STAT) & CSPI_0_7_STAT_RR) + readl(base + CSPI_0_7_RXDATA); +} +#endif + #ifdef CONFIG_DRIVER_SPI_IMX_2_3 static unsigned int cspi_2_3_xchg_single(struct imx_spi *imx, unsigned int data) { @@ -375,6 +475,13 @@ static struct spi_imx_devtype_data spi_imx_devtype_data[] = { .init = cspi_0_0_init, }, #endif +#ifdef CONFIG_DRIVER_SPI_IMX_0_7 + [SPI_IMX_VER_0_7] = { + .chipselect = cspi_0_7_chipselect, + .xchg_single = cspi_0_7_xchg_single, + .init = cspi_0_7_init, + }, +#endif #ifdef CONFIG_DRIVER_SPI_IMX_2_3 [SPI_IMX_VER_2_3] = { .chipselect = cspi_2_3_chipselect, @@ -405,6 +512,10 @@ static int imx_spi_probe(struct device_d *dev) if (cpu_is_mx27()) version = SPI_IMX_VER_0_0; #endif +#ifdef CONFIG_DRIVER_SPI_IMX_0_7 + if (cpu_is_mx25()) + version = SPI_IMX_VER_0_7; +#endif #ifdef CONFIG_DRIVER_SPI_IMX_2_3 if (cpu_is_mx51() || cpu_is_mx53()) version = SPI_IMX_VER_2_3; |