summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2010-10-12 21:31:38 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2010-10-12 21:31:38 +0200
commit23e13992c8dd993a69794952fdf4f1c11e3da6e4 (patch)
treeef8e13e993ad0553e45a3f182248d7f17b5ad502 /drivers
parent6af0fb083442de041012f4438b1f66cc24bf3c8f (diff)
parent869baba6581723842729bd3e83f1167431b0c317 (diff)
downloadbarebox-23e13992c8dd993a69794952fdf4f1c11e3da6e4.tar.gz
barebox-23e13992c8dd993a69794952fdf4f1c11e3da6e4.tar.xz
Merge branch 'mx51' into next
Conflicts: arch/arm/Makefile Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/Kconfig1
-rw-r--r--drivers/Makefile1
-rw-r--r--drivers/i2c/Kconfig16
-rw-r--r--drivers/i2c/Makefile6
-rw-r--r--drivers/i2c/mc13892.c164
-rw-r--r--drivers/mci/Kconfig13
-rw-r--r--drivers/mci/Makefile1
-rw-r--r--drivers/mci/imx-esdhc.c512
-rw-r--r--drivers/mci/imx-esdhc.h164
-rw-r--r--drivers/mci/mci-core.c47
-rw-r--r--drivers/mfd/Kconfig28
-rw-r--r--drivers/mfd/Makefile6
-rw-r--r--drivers/mfd/lp3972.c (renamed from drivers/i2c/lp3972.c)0
-rw-r--r--drivers/mfd/mc13783.c (renamed from drivers/spi/mc13783.c)0
-rw-r--r--drivers/mfd/mc13892.c327
-rw-r--r--drivers/mfd/mc34704.c (renamed from drivers/i2c/mc34704.c)2
-rw-r--r--drivers/mfd/mc9sdz60.c (renamed from drivers/i2c/mc9sdz60.c)2
-rw-r--r--drivers/mfd/twl4030.c (renamed from drivers/i2c/twl4030.c)2
-rw-r--r--drivers/serial/serial_imx.c3
-rw-r--r--drivers/spi/Kconfig12
-rw-r--r--drivers/spi/Makefile2
-rw-r--r--drivers/spi/imx_spi.c347
-rw-r--r--drivers/usb/host/ehci-omap.c2
-rw-r--r--drivers/usb/otg/twl4030.c2
24 files changed, 1370 insertions, 290 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 13235f35f5..d94017bfc1 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -11,5 +11,6 @@ source "drivers/usb/Kconfig"
source "drivers/video/Kconfig"
source "drivers/mci/Kconfig"
source "drivers/clk/Kconfig"
+source "drivers/mfd/Kconfig"
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index 71d34f969b..242a564dd7 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_I2C) += i2c/
obj-$(CONFIG_MCI) += mci/
obj-$(CONFIG_VIDEO) += video/
obj-y += clk/
+obj-y += mfd/
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 9ce16558c4..c2af818393 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -5,20 +5,4 @@ if I2C
source drivers/i2c/busses/Kconfig
-config I2C_MC13892
- bool "MC13892 a.k.a. PMIC driver"
-
-config I2C_MC34704
- bool "MC34704 PMIC driver"
-
-config I2C_MC9SDZ60
- bool "MC9SDZ60 driver"
-
-config I2C_LP3972
- bool "LP3972 driver"
-
-config I2C_TWL4030
- bool "TWL4030 driver"
- select GPIO
-
endif
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 0584b5589d..42e22c01b0 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -1,7 +1 @@
obj-$(CONFIG_I2C) += i2c.o busses/
-
-obj-$(CONFIG_I2C_MC13892) += mc13892.o
-obj-$(CONFIG_I2C_MC34704) += mc34704.o
-obj-$(CONFIG_I2C_MC9SDZ60) += mc9sdz60.o
-obj-$(CONFIG_I2C_LP3972) += lp3972.o
-obj-$(CONFIG_I2C_TWL4030) += twl4030.o
diff --git a/drivers/i2c/mc13892.c b/drivers/i2c/mc13892.c
deleted file mode 100644
index 67d4232a23..0000000000
--- a/drivers/i2c/mc13892.c
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2007 Sascha Hauer, Pengutronix
- * 2009 Marc Kleine-Budde <mkl@pengutronix.de>
- *
- * 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 <xfuncs.h>
-#include <errno.h>
-
-#include <i2c/i2c.h>
-#include <i2c/mc13892.h>
-
-#define DRIVERNAME "mc13892"
-
-#define to_mc13892(a) container_of(a, struct mc13892, cdev)
-
-static struct mc13892 *mc_dev;
-
-struct mc13892 *mc13892_get(void)
-{
- if (!mc_dev)
- return NULL;
-
- return mc_dev;
-}
-EXPORT_SYMBOL(mc13892_get);
-
-int mc13892_reg_read(struct mc13892 *mc13892, enum mc13892_reg reg, u32 *val)
-{
- u8 buf[3];
- int ret;
-
- ret = i2c_read_reg(mc13892->client, reg, buf, 3);
- *val = buf[0] << 16 | buf[1] << 8 | buf[2] << 0;
-
- return ret == 3 ? 0 : ret;
-}
-EXPORT_SYMBOL(mc13892_reg_read)
-
-int mc13892_reg_write(struct mc13892 *mc13892, enum mc13892_reg reg, u32 val)
-{
- u8 buf[] = {
- val >> 16,
- val >> 8,
- val >> 0,
- };
- int ret;
-
- ret = i2c_write_reg(mc13892->client, reg, buf, 3);
-
- return ret == 3 ? 0 : ret;
-}
-EXPORT_SYMBOL(mc13892_reg_write)
-
-int mc13892_set_bits(struct mc13892 *mc13892, enum mc13892_reg reg, u32 mask, u32 val)
-{
- u32 tmp;
- int err;
-
- err = mc13892_reg_read(mc13892, reg, &tmp);
- tmp = (tmp & ~mask) | val;
-
- if (!err)
- err = mc13892_reg_write(mc13892, reg, tmp);
-
- return err;
-}
-EXPORT_SYMBOL(mc13892_set_bits);
-
-static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags)
-{
- struct mc13892 *priv = to_mc13892(cdev);
- u32 *buf = _buf;
- size_t i = count >> 2;
- int err;
-
- offset >>= 2;
-
- while (i) {
- err = mc13892_reg_read(priv, offset, buf);
- if (err)
- return (ssize_t)err;
- buf++;
- i--;
- offset++;
- }
-
- return count;
-}
-
-static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, ulong offset, ulong flags)
-{
- struct mc13892 *mc13892 = to_mc13892(cdev);
- const u32 *buf = _buf;
- size_t i = count >> 2;
- int err;
-
- offset >>= 2;
-
- while (i) {
- err = mc13892_reg_write(mc13892, offset, *buf);
- if (err)
- return (ssize_t)err;
- buf++;
- i--;
- offset++;
- }
-
- return count;
-}
-
-static struct file_operations mc_fops = {
- .lseek = dev_lseek_default,
- .read = mc_read,
- .write = mc_write,
-};
-
-static int mc_probe(struct device_d *dev)
-{
- if (mc_dev)
- return -EBUSY;
-
- mc_dev = xzalloc(sizeof(struct mc13892));
- mc_dev->cdev.name = DRIVERNAME;
- mc_dev->client = to_i2c_client(dev);
- mc_dev->cdev.size = 256;
- mc_dev->cdev.dev = dev;
- mc_dev->cdev.ops = &mc_fops;
-
- devfs_create(&mc_dev->cdev);
-
- return 0;
-}
-
-static struct driver_d mc_driver = {
- .name = DRIVERNAME,
- .probe = mc_probe,
-};
-
-static int mc_init(void)
-{
- register_driver(&mc_driver);
- return 0;
-}
-
-device_initcall(mc_init);
diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig
index 0bc4254acb..b1f2773354 100644
--- a/drivers/mci/Kconfig
+++ b/drivers/mci/Kconfig
@@ -48,4 +48,17 @@ config MCI_IMX
Enable this entry to add support to read and write SD cards on a
Freescale i.MX based system.
+config MCI_IMX_ESDHC
+ bool "i.MX esdhc"
+ depends on ARCH_IMX25 || ARCH_IMX35 || ARCH_IMX51
+ help
+ Enable this entry to add support to read and write SD cards on a
+ Freescale i.MX25/35/51 based system.
+
+config MCI_IMX_ESDHC_PIO
+ bool "use PIO mode"
+ depends on MCI_IMX_ESDHC
+ help
+ mostly useful for debugging. Normally you should use DMA.
+
endif
diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile
index f393e93b33..a10cb47960 100644
--- a/drivers/mci/Makefile
+++ b/drivers/mci/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_MCI) += mci-core.o
obj-$(CONFIG_MCI_STM378X) += stm378x.o
obj-$(CONFIG_MCI_S3C) += s3c.o
obj-$(CONFIG_MCI_IMX) += imx.o
+obj-$(CONFIG_MCI_IMX_ESDHC) += imx-esdhc.o
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
new file mode 100644
index 0000000000..63cd059f6d
--- /dev/null
+++ b/drivers/mci/imx-esdhc.c
@@ -0,0 +1,512 @@
+/*
+ * Copyright 2007,2010 Freescale Semiconductor, Inc
+ * Andy Fleming
+ *
+ * Based vaguely on the pxa mmc code:
+ * (C) Copyright 2003
+ * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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 <config.h>
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <malloc.h>
+#include <mci.h>
+#include <clock.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <mach/clock.h>
+
+#include "imx-esdhc.h"
+
+struct fsl_esdhc {
+ u32 dsaddr;
+ u32 blkattr;
+ u32 cmdarg;
+ u32 xfertyp;
+ u32 cmdrsp0;
+ u32 cmdrsp1;
+ u32 cmdrsp2;
+ u32 cmdrsp3;
+ u32 datport;
+ u32 prsstat;
+ u32 proctl;
+ u32 sysctl;
+ u32 irqstat;
+ u32 irqstaten;
+ u32 irqsigen;
+ u32 autoc12err;
+ u32 hostcapblt;
+ u32 wml;
+ char reserved1[8];
+ u32 fevt;
+ char reserved2[168];
+ u32 hostver;
+ char reserved3[780];
+ u32 scr;
+};
+
+struct fsl_esdhc_host {
+ struct mci_host mci;
+ struct fsl_esdhc *regs;
+ u32 no_snoop;
+ unsigned long cur_clock;
+ struct device_d *dev;
+};
+
+#define to_fsl_esdhc(mci) container_of(mci, struct fsl_esdhc_host, mci)
+
+/* Return the XFERTYP flags for a given command and data packet */
+u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data)
+{
+ u32 xfertyp = 0;
+
+ if (data) {
+ xfertyp |= XFERTYP_DPSEL;
+#ifndef CONFIG_MCI_IMX_ESDHC_PIO
+ xfertyp |= XFERTYP_DMAEN;
+#endif
+ if (data->blocks > 1) {
+ xfertyp |= XFERTYP_MSBSEL;
+ xfertyp |= XFERTYP_BCEN;
+ }
+
+ if (data->flags & MMC_DATA_READ)
+ xfertyp |= XFERTYP_DTDSEL;
+ }
+
+ if (cmd->resp_type & MMC_RSP_CRC)
+ xfertyp |= XFERTYP_CCCEN;
+ if (cmd->resp_type & MMC_RSP_OPCODE)
+ xfertyp |= XFERTYP_CICEN;
+ if (cmd->resp_type & MMC_RSP_136)
+ xfertyp |= XFERTYP_RSPTYP_136;
+ else if (cmd->resp_type & MMC_RSP_BUSY)
+ xfertyp |= XFERTYP_RSPTYP_48_BUSY;
+ else if (cmd->resp_type & MMC_RSP_PRESENT)
+ xfertyp |= XFERTYP_RSPTYP_48;
+
+ return XFERTYP_CMD(cmd->cmdidx) | xfertyp;
+}
+
+#ifdef CONFIG_MCI_IMX_ESDHC_PIO
+/*
+ * PIO Read/Write Mode reduce the performace as DMA is not used in this mode.
+ */
+static void
+esdhc_pio_read_write(struct mci_host *mci, struct mci_data *data)
+{
+ struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
+ struct fsl_esdhc *regs = host->regs;
+ u32 blocks;
+ char *buffer;
+ u32 databuf;
+ u32 size;
+ u32 irqstat;
+ u32 timeout;
+
+ if (data->flags & MMC_DATA_READ) {
+ blocks = data->blocks;
+ buffer = data->dest;
+ while (blocks) {
+ timeout = PIO_TIMEOUT;
+ size = data->blocksize;
+ irqstat = esdhc_read32(&regs->irqstat);
+ while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_BREN)
+ && --timeout);
+ if (timeout <= 0) {
+ printf("\nData Read Failed in PIO Mode.");
+ return;
+ }
+ while (size && (!(irqstat & IRQSTAT_TC))) {
+ udelay(100); /* Wait before last byte transfer complete */
+ irqstat = esdhc_read32(&regs->irqstat);
+ databuf = esdhc_read32(&regs->datport);
+ *((u32 *)buffer) = databuf;
+ buffer += 4;
+ size -= 4;
+ }
+ blocks--;
+ }
+ } else {
+ blocks = data->blocks;
+ buffer = (char *)data->src;
+ while (blocks) {
+ timeout = PIO_TIMEOUT;
+ size = data->blocksize;
+ irqstat = esdhc_read32(&regs->irqstat);
+ while (!(esdhc_read32(&regs->prsstat) & PRSSTAT_BWEN)
+ && --timeout);
+ if (timeout <= 0) {
+ printf("\nData Write Failed in PIO Mode.");
+ return;
+ }
+ while (size && (!(irqstat & IRQSTAT_TC))) {
+ udelay(100); /* Wait before last byte transfer complete */
+ databuf = *((u32 *)buffer);
+ buffer += 4;
+ size -= 4;
+ irqstat = esdhc_read32(&regs->irqstat);
+ esdhc_write32(&regs->datport, databuf);
+ }
+ blocks--;
+ }
+ }
+}
+#endif
+
+static int esdhc_setup_data(struct mci_host *mci, struct mci_data *data)
+{
+ struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
+ struct fsl_esdhc *regs = host->regs;
+#ifndef CONFIG_MCI_IMX_ESDHC_PIO
+ u32 wml_value;
+
+ wml_value = data->blocksize/4;
+
+ if (data->flags & MMC_DATA_READ) {
+ if (wml_value > 0x10)
+ wml_value = 0x10;
+
+ esdhc_clrsetbits32(&regs->wml, WML_RD_WML_MASK, wml_value);
+ esdhc_write32(&regs->dsaddr, (u32)data->dest);
+ } else {
+ if (wml_value > 0x80)
+ wml_value = 0x80;
+ if ((esdhc_read32(&regs->prsstat) & PRSSTAT_WPSPL) == 0) {
+ printf("\nThe SD card is locked. Can not write to a locked card.\n\n");
+ return -ETIMEDOUT;
+ }
+
+ esdhc_clrsetbits32(&regs->wml, WML_WR_WML_MASK,
+ wml_value << 16);
+ esdhc_write32(&regs->dsaddr, (u32)data->src);
+ }
+#else /* CONFIG_MCI_IMX_ESDHC_PIO */
+ if (!(data->flags & MMC_DATA_READ)) {
+ if ((esdhc_read32(&regs->prsstat) & PRSSTAT_WPSPL) == 0) {
+ printf("\nThe SD card is locked. "
+ "Can not write to a locked card.\n\n");
+ return -ETIMEDOUT;
+ }
+ esdhc_write32(&regs->dsaddr, (u32)data->src);
+ } else
+ esdhc_write32(&regs->dsaddr, (u32)data->dest);
+#endif /* CONFIG_MCI_IMX_ESDHC_PIO */
+
+ esdhc_write32(&regs->blkattr, data->blocks << 16 | data->blocksize);
+
+ return 0;
+}
+
+
+/*
+ * Sends a command out on the bus. Takes the mci pointer,
+ * a command pointer, and an optional data pointer.
+ */
+static int
+esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
+{
+ u32 xfertyp;
+ u32 irqstat;
+ struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
+ struct fsl_esdhc *regs = host->regs;
+
+ esdhc_write32(&regs->irqstat, -1);
+
+ /* Wait for the bus to be idle */
+ while ((esdhc_read32(&regs->prsstat) & PRSSTAT_CICHB) ||
+ (esdhc_read32(&regs->prsstat) & PRSSTAT_CIDHB))
+ ;
+
+ while (esdhc_read32(&regs->prsstat) & PRSSTAT_DLA)
+ ;
+
+ /* Wait at least 8 SD clock cycles before the next command */
+ /*
+ * Note: This is way more than 8 cycles, but 1ms seems to
+ * resolve timing issues with some cards
+ */
+ udelay(1000);
+
+ /* Set up for a data transfer if we have one */
+ if (data) {
+ int err;
+
+ err = esdhc_setup_data(mci, data);
+ if(err)
+ return err;
+ if (data->flags & MMC_DATA_WRITE) {
+ dma_flush_range((unsigned long)data->src,
+ (unsigned long)(data->src + 512));
+ } else
+ dma_clean_range((unsigned long)data->src,
+ (unsigned long)(data->src + 512));
+
+ }
+
+ /* Figure out the transfer arguments */
+ xfertyp = esdhc_xfertyp(cmd, data);
+
+ /* Send the command */
+ esdhc_write32(&regs->cmdarg, cmd->cmdarg);
+ esdhc_write32(&regs->xfertyp, xfertyp);
+
+ /* Wait for the command to complete */
+ while (!(esdhc_read32(&regs->irqstat) & IRQSTAT_CC))
+ ;
+
+ irqstat = esdhc_read32(&regs->irqstat);
+ esdhc_write32(&regs->irqstat, irqstat);
+
+ if (irqstat & CMD_ERR)
+ return -EIO;
+
+ if (irqstat & IRQSTAT_CTOE)
+ return -ETIMEDOUT;
+
+ /* Copy the response to the response buffer */
+ if (cmd->resp_type & MMC_RSP_136) {
+ u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0;
+
+ cmdrsp3 = esdhc_read32(&regs->cmdrsp3);
+ cmdrsp2 = esdhc_read32(&regs->cmdrsp2);
+ cmdrsp1 = esdhc_read32(&regs->cmdrsp1);
+ cmdrsp0 = esdhc_read32(&regs->cmdrsp0);
+ cmd->response[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24);
+ cmd->response[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24);
+ cmd->response[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24);
+ cmd->response[3] = (cmdrsp0 << 8);
+ } else
+ cmd->response[0] = esdhc_read32(&regs->cmdrsp0);
+
+ /* Wait until all of the blocks are transferred */
+ if (data) {
+#ifdef CONFIG_MCI_IMX_ESDHC_PIO
+ esdhc_pio_read_write(mci, data);
+#else
+ do {
+ irqstat = esdhc_read32(&regs->irqstat);
+
+ if (irqstat & DATA_ERR)
+ return -EIO;
+
+ if (irqstat & IRQSTAT_DTOE)
+ return -ETIMEDOUT;
+ } while (!(irqstat & IRQSTAT_TC) &&
+ (esdhc_read32(&regs->prsstat) & PRSSTAT_DLA));
+
+ if (data->flags & MMC_DATA_READ) {
+ dma_inv_range((unsigned long)data->dest,
+ (unsigned long)(data->dest + 512));
+ }
+#endif
+ }
+
+ esdhc_write32(&regs->irqstat, -1);
+
+ return 0;
+}
+
+void set_sysctl(struct mci_host *mci, u32 clock)
+{
+ int div, pre_div;
+ struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
+ struct fsl_esdhc *regs = host->regs;
+ int sdhc_clk = imx_get_mmcclk();
+ u32 clk;
+
+ if (clock < mci->f_min)
+ clock = mci->f_min;
+
+ pre_div = 0;
+
+ for (pre_div = 1; pre_div < 256; pre_div <<= 1) {
+ if (sdhc_clk / pre_div < clock * 16)
+ break;
+ };
+
+ div = sdhc_clk / pre_div / clock;
+
+ if (sdhc_clk / pre_div / div > clock)
+ div++;
+
+ host->cur_clock = sdhc_clk / pre_div / div;
+
+ div -= 1;
+ pre_div >>= 1;
+
+ dev_dbg(host->dev, "set clock: wanted: %d got: %d\n", clock, host->cur_clock);
+ dev_dbg(host->dev, "pre_div: %d div: %d\n", pre_div, div);
+
+ clk = (pre_div << 8) | (div << 4);
+
+ esdhc_clrbits32(&regs->sysctl, SYSCTL_CKEN);
+
+ esdhc_clrsetbits32(&regs->sysctl, SYSCTL_CLOCK_MASK, clk);
+
+ udelay(10000);
+
+ clk = SYSCTL_PEREN | SYSCTL_CKEN;
+
+ esdhc_setbits32(&regs->sysctl, clk);
+}
+
+static void esdhc_set_ios(struct mci_host *mci, struct device_d *dev,
+ unsigned bus_width, unsigned clock)
+{
+ struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
+ struct fsl_esdhc *regs = host->regs;
+
+ /* Set the clock speed */
+ set_sysctl(mci, clock);
+
+ /* Set the bus width */
+ esdhc_clrbits32(&regs->proctl, PROCTL_DTW_4 | PROCTL_DTW_8);
+
+ if (bus_width == 4)
+ esdhc_setbits32(&regs->proctl, PROCTL_DTW_4);
+ else if (bus_width == 8)
+ esdhc_setbits32(&regs->proctl, PROCTL_DTW_8);
+
+}
+
+static int esdhc_init(struct mci_host *mci, struct device_d *dev)
+{
+ struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
+ struct fsl_esdhc *regs = host->regs;
+ int timeout = 1000;
+ int ret = 0;
+
+ /* Enable cache snooping */
+ if (host && !host->no_snoop)
+ esdhc_write32(&regs->scr, 0x00000040);
+
+ /* Reset the entire host controller */
+ esdhc_write32(&regs->sysctl, SYSCTL_RSTA);
+
+ /* Wait until the controller is available */
+ while ((esdhc_read32(&regs->sysctl) & SYSCTL_RSTA) && --timeout)
+ udelay(1000);
+
+ esdhc_write32(&regs->sysctl, SYSCTL_HCKEN | SYSCTL_IPGEN);
+
+ /* Set the initial clock speed */
+ set_sysctl(mci, 400000);
+
+ /* Disable the BRR and BWR bits in IRQSTAT */
+ esdhc_clrbits32(&regs->irqstaten, IRQSTATEN_BRR | IRQSTATEN_BWR);
+
+ /* Put the PROCTL reg back to the default */
+ esdhc_write32(&regs->proctl, PROCTL_INIT);
+
+ /* Set timout to the maximum value */
+ esdhc_clrsetbits32(&regs->sysctl, SYSCTL_TIMEOUT_MASK, 14 << 16);
+
+ return ret;
+}
+
+static int esdhc_reset(struct fsl_esdhc *regs)
+{
+ uint64_t start;
+
+ /* reset the controller */
+ esdhc_write32(&regs->sysctl, SYSCTL_RSTA);
+
+ start = get_time_ns();
+ /* hardware clears the bit when it is done */
+ while (1) {
+ if (!(esdhc_read32(&regs->sysctl) & SYSCTL_RSTA))
+ break;
+ if (is_timeout(start, 100 * MSECOND)) {
+ printf("MMC/SD: Reset never completed.\n");
+ return -EIO;
+ }
+ }
+
+ return 0;
+}
+
+static int fsl_esdhc_probe(struct device_d *dev)
+{
+ struct fsl_esdhc_host *host;
+ struct mci_host *mci;
+ u32 caps;
+ int ret;
+
+ host = xzalloc(sizeof(*host));
+ mci = &host->mci;
+
+ host->dev = dev;
+ host->regs = (struct fsl_esdhc *)dev->map_base;
+
+ /* First reset the eSDHC controller */
+ ret = esdhc_reset(host->regs);
+ if (ret) {
+ free(host);
+ return ret;
+ }
+
+ caps = esdhc_read32(&host->regs->hostcapblt);
+
+ if (caps & ESDHC_HOSTCAPBLT_VS18)
+ mci->voltages |= MMC_VDD_165_195;
+ if (caps & ESDHC_HOSTCAPBLT_VS30)
+ mci->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
+ if (caps & ESDHC_HOSTCAPBLT_VS33)
+ mci->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
+
+ mci->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT;
+
+ if (caps & ESDHC_HOSTCAPBLT_HSS)
+ mci->host_caps |= MMC_MODE_HS_52MHz | MMC_MODE_HS;
+
+ host->mci.send_cmd = esdhc_send_cmd;
+ host->mci.set_ios = esdhc_set_ios;
+ host->mci.init = esdhc_init;
+ host->mci.host_caps = MMC_MODE_4BIT;
+
+ host->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+ host->mci.f_min = imx_get_mmcclk() >> 12;
+ if (host->mci.f_min < 200000)
+ host->mci.f_min = 200000;
+ host->mci.f_max = imx_get_mmcclk();
+
+ mci_register(&host->mci);
+
+ return 0;
+}
+
+static struct driver_d fsl_esdhc_driver = {
+ .name = "imx-esdhc",
+ .probe = fsl_esdhc_probe,
+};
+
+static int fsl_esdhc_init_driver(void)
+{
+ register_driver(&fsl_esdhc_driver);
+ return 0;
+}
+
+device_initcall(fsl_esdhc_init_driver);
+
diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h
new file mode 100644
index 0000000000..19fed5aebf
--- /dev/null
+++ b/drivers/mci/imx-esdhc.h
@@ -0,0 +1,164 @@
+/*
+ * FSL SD/MMC Defines
+ *-------------------------------------------------------------------
+ *
+ * Copyright 2007-2008,2010 Freescale Semiconductor, Inc
+ *
+ * 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
+ *
+ *-------------------------------------------------------------------
+ *
+ */
+
+#ifndef __FSL_ESDHC_H__
+#define __FSL_ESDHC_H__
+
+#include <errno.h>
+#include <asm/byteorder.h>
+
+/* FSL eSDHC-specific constants */
+#define SYSCTL 0x0002e02c
+#define SYSCTL_INITA 0x08000000
+#define SYSCTL_TIMEOUT_MASK 0x000f0000
+#define SYSCTL_CLOCK_MASK 0x0000fff0
+#define SYSCTL_RSTA 0x01000000
+#define SYSCTL_CKEN 0x00000008
+#define SYSCTL_PEREN 0x00000004
+#define SYSCTL_HCKEN 0x00000002
+#define SYSCTL_IPGEN 0x00000001
+#define SYSCTL_RSTA 0x01000000
+
+#define IRQSTAT 0x0002e030
+#define IRQSTAT_DMAE (0x10000000)
+#define IRQSTAT_AC12E (0x01000000)
+#define IRQSTAT_DEBE (0x00400000)
+#define IRQSTAT_DCE (0x00200000)
+#define IRQSTAT_DTOE (0x00100000)
+#define IRQSTAT_CIE (0x00080000)
+#define IRQSTAT_CEBE (0x00040000)
+#define IRQSTAT_CCE (0x00020000)
+#define IRQSTAT_CTOE (0x00010000)
+#define IRQSTAT_CINT (0x00000100)
+#define IRQSTAT_CRM (0x00000080)
+#define IRQSTAT_CINS (0x00000040)
+#define IRQSTAT_BRR (0x00000020)
+#define IRQSTAT_BWR (0x00000010)
+#define IRQSTAT_DINT (0x00000008)
+#define IRQSTAT_BGE (0x00000004)
+#define IRQSTAT_TC (0x00000002)
+#define IRQSTAT_CC (0x00000001)
+
+#define CMD_ERR (IRQSTAT_CIE | IRQSTAT_CEBE | IRQSTAT_CCE)
+#define DATA_ERR (IRQSTAT_DEBE | IRQSTAT_DCE | IRQSTAT_DTOE)
+
+#define IRQSTATEN 0x0002e034
+#define IRQSTATEN_DMAE (0x10000000)
+#define IRQSTATEN_AC12E (0x01000000)
+#define IRQSTATEN_DEBE (0x00400000)
+#define IRQSTATEN_DCE (0x00200000)
+#define IRQSTATEN_DTOE (0x00100000)
+#define IRQSTATEN_CIE (0x00080000)
+#define IRQSTATEN_CEBE (0x00040000)
+#define IRQSTATEN_CCE (0x00020000)
+#define IRQSTATEN_CTOE (0x00010000)
+#define IRQSTATEN_CINT (0x00000100)
+#define IRQSTATEN_CRM (0x00000080)
+#define IRQSTATEN_CINS (0x00000040)
+#define IRQSTATEN_BRR (0x00000020)
+#define IRQSTATEN_BWR (0x00000010)
+#define IRQSTATEN_DINT (0x00000008)
+#define IRQSTATEN_BGE (0x00000004)
+#define IRQSTATEN_TC (0x00000002)
+#define IRQSTATEN_CC (0x00000001)
+
+#define PRSSTAT 0x0002e024
+#define PRSSTAT_CLSL (0x00800000)
+#define PRSSTAT_WPSPL (0x00080000)
+#define PRSSTAT_CDPL (0x00040000)
+#define PRSSTAT_CINS (0x00010000)
+#define PRSSTAT_BREN (0x00000800)
+#define PRSSTAT_BWEN (0x00000400)
+#define PRSSTAT_DLA (0x00000004)
+#define PRSSTAT_CICHB (0x00000002)
+#define PRSSTAT_CIDHB (0x00000001)
+
+#define PROCTL 0x0002e028
+#define PROCTL_INIT 0x00000020
+#define PROCTL_DTW_4 0x00000002
+#define PROCTL_DTW_8 0x00000004
+
+#define CMDARG 0x0002e008
+
+#define XFERTYP 0x0002e00c
+#define XFERTYP_CMD(x) ((x & 0x3f) << 24)
+#define XFERTYP_CMDTYP_NORMAL 0x0
+#define XFERTYP_CMDTYP_SUSPEND 0x00400000
+#define XFERTYP_CMDTYP_RESUME 0x00800000
+#define XFERTYP_CMDTYP_ABORT 0x00c00000
+#define XFERTYP_DPSEL 0x00200000
+#define XFERTYP_CICEN 0x00100000
+#define XFERTYP_CCCEN 0x00080000
+#define XFERTYP_RSPTYP_NONE 0
+#define XFERTYP_RSPTYP_136 0x00010000
+#define XFERTYP_RSPTYP_48 0x00020000
+#define XFERTYP_RSPTYP_48_BUSY 0x00030000
+#define XFERTYP_MSBSEL 0x00000020
+#define XFERTYP_DTDSEL 0x00000010
+#define XFERTYP_AC12EN 0x00000004
+#define XFERTYP_BCEN 0x00000002
+#define XFERTYP_DMAEN 0x00000001
+
+#define CINS_TIMEOUT 1000
+#define PIO_TIMEOUT 100000
+
+#define DSADDR 0x2e004
+
+#define CMDRSP0 0x2e010
+#define CMDRSP1 0x2e014
+#define CMDRSP2 0x2e018
+#define CMDRSP3 0x2e01c
+
+#define DATPORT 0x2e020
+
+#define WML 0x2e044
+#define WML_WRITE 0x00010000
+#define WML_RD_WML_MASK 0xff
+#define WML_WR_WML_MASK 0xff0000
+
+#define BLKATTR 0x2e004
+#define BLKATTR_CNT(x) ((x & 0xffff) << 16)
+#define BLKATTR_SIZE(x) (x & 0x1fff)
+#define MAX_BLK_CNT 0x7fff /* so malloc will have enough room with 32M */
+
+#define ESDHC_HOSTCAPBLT_VS18 0x04000000
+#define ESDHC_HOSTCAPBLT_VS30 0x02000000
+#define ESDHC_HOSTCAPBLT_VS33 0x01000000
+#define ESDHC_HOSTCAPBLT_SRS 0x00800000
+#define ESDHC_HOSTCAPBLT_DMAS 0x00400000
+#define ESDHC_HOSTCAPBLT_HSS 0x00200000
+
+struct fsl_esdhc_cfg {
+ u32 esdhc_base;
+ u32 no_snoop;
+};
+
+#define esdhc_read32(a) readl(a)
+#define esdhc_write32(a, v) writel(v,a)
+#define esdhc_clrsetbits32(a, c, s) writel((readl(a) & ~(c)) | (s), (a))
+#define esdhc_clrbits32(a, c) writel(readl(a) & ~(c), (a))
+#define esdhc_setbits32(a, s) writel(readl(a) | (s), (a))
+
+#endif /* __FSL_ESDHC_H__ */
diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c
index f961e46848..ea2706234a 100644
--- a/drivers/mci/mci-core.c
+++ b/drivers/mci/mci-core.c
@@ -45,7 +45,7 @@
* @brief Memory Card framework
*
* Checked with the following cards:
- * - old Canon SD 16 MiB, does not like the 0x08 command (SD_CMD_SEND_IF_COND) -> failed
+ * - Canon MMC 16 MiB
* - Kingston 512 MiB
* - SanDisk 512 MiB
* - Transcend SD Ultra, 1 GiB (Industrial)
@@ -94,6 +94,8 @@ static int mci_set_blocklen(struct device_d *mci_dev, unsigned len)
return mci_send_cmd(mci_dev, &cmd, NULL);
}
+static void *sector_buf;
+
/**
* Write one block of data to the card
* @param mci_dev MCI instance
@@ -106,13 +108,21 @@ static int mci_block_write(struct device_d *mci_dev, const void *src, unsigned b
struct mci *mci = GET_MCI_DATA(mci_dev);
struct mci_cmd cmd;
struct mci_data data;
+ const void *buf;
+
+ if ((unsigned long)src & 0x3) {
+ memcpy(sector_buf, src, 512);
+ buf = sector_buf;
+ } else {
+ buf = src;
+ }
mci_setup_cmd(&cmd,
MMC_CMD_WRITE_SINGLE_BLOCK,
mci->high_capacity != 0 ? blocknum : blocknum * mci->write_bl_len,
MMC_RSP_R1);
- data.src = src;
+ data.src = buf;
data.blocks = 1;
data.blocksize = mci->write_bl_len;
data.flags = MMC_DATA_WRITE;
@@ -927,7 +937,7 @@ static int mci_sd_write(struct device_d *disk_dev, uint64_t sector_start,
}
rc = mci_block_write(mci_dev, buffer, sector_start);
if (rc != 0) {
- pr_err("Writing block %u failed\n", (unsigned)sector_start);
+ pr_err("Writing block %u failed with %d\n", (unsigned)sector_start, rc);
return rc;
}
sector_count--;
@@ -973,7 +983,7 @@ static int mci_sd_read(struct device_d *disk_dev, uint64_t sector_start,
}
rc = mci_read_block(mci_dev, buffer, (unsigned)sector_start);
if (rc != 0) {
- pr_err("Reading block %lu failed\n", (unsigned)sector_start);
+ pr_err("Reading block %lu failed with %d\n", (unsigned)sector_start, rc);
return rc;
}
sector_count--;
@@ -1148,27 +1158,16 @@ static int mci_card_probe(struct device_d *mci_dev)
/* Check if this card can handle the "SD Card Physical Layer Specification 2.0" */
rc = sd_send_if_cond(mci_dev);
- if (rc) {
+ rc = sd_send_op_cond(mci_dev);
+ if (rc && rc == -ETIMEDOUT) {
/* If the command timed out, we check for an MMC card */
- if (rc == -ETIMEDOUT) {
- pr_debug("Card seems to be a MultiMediaCard\n");
- rc = mmc_send_op_cond(mci_dev);
- if (rc) {
- pr_err("MultiMediaCard did not respond to voltage select!\n");
- rc = -ENODEV;
- goto on_error;
- }
- } else
- goto on_error;
- } else {
- /* Its a 2.xx card. Setup operation conditions */
- rc = sd_send_op_cond(mci_dev);
- if (rc) {
- pr_debug("Cannot setup SD card's operation condition\n");
- goto on_error;
- }
+ pr_debug("Card seems to be a MultiMediaCard\n");
+ rc = mmc_send_op_cond(mci_dev);
}
+ if (rc)
+ goto on_error;
+
rc = mci_startup(mci_dev);
if (rc) {
printf("Card's startup fails with %d\n", rc);
@@ -1310,6 +1309,10 @@ static struct driver_d mci_driver = {
static int mci_init(void)
{
+ sector_buf = memalign(32, 512);
+ if (!sector_buf)
+ return -ENOMEM;
+
return register_driver(&mci_driver);
}
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
new file mode 100644
index 0000000000..96440d852f
--- /dev/null
+++ b/drivers/mfd/Kconfig
@@ -0,0 +1,28 @@
+menu MFD
+
+config I2C_MC13892
+ depends on I2C || SPI
+ bool "MC13892 a.k.a. PMIC driver"
+
+config I2C_MC34704
+ depends on I2C
+ bool "MC34704 PMIC driver"
+
+config I2C_MC9SDZ60
+ depends on I2C
+ bool "MC9SDZ60 driver"
+
+config I2C_LP3972
+ depends on I2C
+ bool "LP3972 driver"
+
+config I2C_TWL4030
+ depends on I2C
+ bool "TWL4030 driver"
+ select GPIO
+
+config DRIVER_SPI_MC13783
+ depends on SPI
+ bool "MC13783 a.k.a. PMIC driver"
+
+endmenu
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
new file mode 100644
index 0000000000..d411f23b69
--- /dev/null
+++ b/drivers/mfd/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_I2C_MC13892) += mc13892.o
+obj-$(CONFIG_I2C_MC34704) += mc34704.o
+obj-$(CONFIG_I2C_MC9SDZ60) += mc9sdz60.o
+obj-$(CONFIG_I2C_LP3972) += lp3972.o
+obj-$(CONFIG_I2C_TWL4030) += twl4030.o
+obj-$(CONFIG_DRIVER_SPI_MC13783) += mc13783.o
diff --git a/drivers/i2c/lp3972.c b/drivers/mfd/lp3972.c
index 98266990dc..98266990dc 100644
--- a/drivers/i2c/lp3972.c
+++ b/drivers/mfd/lp3972.c
diff --git a/drivers/spi/mc13783.c b/drivers/mfd/mc13783.c
index 19e2780920..19e2780920 100644
--- a/drivers/spi/mc13783.c
+++ b/drivers/mfd/mc13783.c
diff --git a/drivers/mfd/mc13892.c b/drivers/mfd/mc13892.c
new file mode 100644
index 0000000000..08a439b4c7
--- /dev/null
+++ b/drivers/mfd/mc13892.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2007 Sascha Hauer, Pengutronix
+ * 2009 Marc Kleine-Budde <mkl@pengutronix.de>
+ *
+ * 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 <xfuncs.h>
+#include <errno.h>
+#include <spi/spi.h>
+#include <malloc.h>
+
+#include <i2c/i2c.h>
+#include <mfd/mc13892.h>
+
+#define DRIVERNAME "mc13892"
+
+#define to_mc13892(a) container_of(a, struct mc13892, cdev)
+
+static struct mc13892 *mc_dev;
+
+struct mc13892 *mc13892_get(void)
+{
+ if (!mc_dev)
+ return NULL;
+
+ return mc_dev;
+}
+EXPORT_SYMBOL(mc13892_get);
+
+#ifdef CONFIG_SPI
+static int spi_rw(struct spi_device *spi, void * buf, size_t len)
+{
+ int ret;
+
+ struct spi_transfer t = {
+ .tx_buf = (const void *)buf,
+ .rx_buf = buf,
+ .len = len,
+ .cs_change = 0,
+ .delay_usecs = 0,
+ };
+ struct spi_message m;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+
+ if ((ret = spi_sync(spi, &m)))
+ return ret;
+ return 0;
+}
+
+#define MXC_PMIC_REG_NUM(reg) (((reg) & 0x3f) << 25)
+#define MXC_PMIC_WRITE (1 << 31)
+
+static int mc13892_spi_reg_read(struct mc13892 *mc13892, enum mc13892_reg reg, u32 *val)
+{
+ uint32_t buf;
+
+ buf = MXC_PMIC_REG_NUM(reg);
+
+ spi_rw(mc13892->spi, &buf, 4);
+
+ *val = buf;
+
+ return 0;
+}
+
+static int mc13892_spi_reg_write(struct mc13892 *mc13892, enum mc13892_reg reg, u32 val)
+{
+ uint32_t buf = MXC_PMIC_REG_NUM(reg) | MXC_PMIC_WRITE | (val & 0xffffff);
+
+ spi_rw(mc13892->spi, &buf, 4);
+
+ return 0;
+}
+#endif
+
+#ifdef CONFIG_I2C
+static int mc13892_i2c_reg_read(struct mc13892 *mc13892, enum mc13892_reg reg, u32 *val)
+{
+ u8 buf[3];
+ int ret;
+
+ ret = i2c_read_reg(mc13892->client, reg, buf, 3);
+ *val = buf[0] << 16 | buf[1] << 8 | buf[2] << 0;
+
+ return ret == 3 ? 0 : ret;
+}
+
+static int mc13892_i2c_reg_write(struct mc13892 *mc13892, enum mc13892_reg reg, u32 val)
+{
+ u8 buf[] = {
+ val >> 16,
+ val >> 8,
+ val >> 0,
+ };
+ int ret;
+
+ ret = i2c_write_reg(mc13892->client, reg, buf, 3);
+
+ return ret == 3 ? 0 : ret;
+}
+#endif
+
+int mc13892_reg_write(struct mc13892 *mc13892, enum mc13892_reg reg, u32 val)
+{
+#ifdef CONFIG_I2C
+ if (mc13892->mode == MC13892_MODE_I2C)
+ return mc13892_i2c_reg_write(mc13892, reg, val);
+#endif
+#ifdef CONFIG_SPI
+ if (mc13892->mode == MC13892_MODE_SPI)
+ return mc13892_spi_reg_write(mc13892, reg, val);
+#endif
+ return -EINVAL;
+}
+EXPORT_SYMBOL(mc13892_reg_write)
+
+int mc13892_reg_read(struct mc13892 *mc13892, enum mc13892_reg reg, u32 *val)
+{
+#ifdef CONFIG_I2C
+ if (mc13892->mode == MC13892_MODE_I2C)
+ return mc13892_i2c_reg_read(mc13892, reg, val);
+#endif
+#ifdef CONFIG_SPI
+ if (mc13892->mode == MC13892_MODE_SPI)
+ return mc13892_spi_reg_read(mc13892, reg, val);
+#endif
+ return -EINVAL;
+}
+EXPORT_SYMBOL(mc13892_reg_read)
+
+int mc13892_set_bits(struct mc13892 *mc13892, enum mc13892_reg reg, u32 mask, u32 val)
+{
+ u32 tmp;
+ int err;
+
+ err = mc13892_reg_read(mc13892, reg, &tmp);
+ tmp = (tmp & ~mask) | val;
+
+ if (!err)
+ err = mc13892_reg_write(mc13892, reg, tmp);
+
+ return err;
+}
+EXPORT_SYMBOL(mc13892_set_bits);
+
+static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags)
+{
+ struct mc13892 *priv = to_mc13892(cdev);
+ u32 *buf = _buf;
+ size_t i = count >> 2;
+ int err;
+
+ offset >>= 2;
+
+ while (i) {
+ err = mc13892_reg_read(priv, offset, buf);
+ if (err)
+ return (ssize_t)err;
+ buf++;
+ i--;
+ offset++;
+ }
+
+ return count;
+}
+
+static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, ulong offset, ulong flags)
+{
+ struct mc13892 *mc13892 = to_mc13892(cdev);
+ const u32 *buf = _buf;
+ size_t i = count >> 2;
+ int err;
+
+ offset >>= 2;
+
+ while (i) {
+ err = mc13892_reg_write(mc13892, offset, *buf);
+ if (err)
+ return (ssize_t)err;
+ buf++;
+ i--;
+ offset++;
+ }
+
+ return count;
+}
+
+static struct file_operations mc_fops = {
+ .lseek = dev_lseek_default,
+ .read = mc_read,
+ .write = mc_write,
+};
+
+struct mc13892_rev {
+ u16 rev_id;
+ enum mc13892_revision rev;
+ char *revstr;
+};
+
+static struct mc13892_rev mc13892_revisions[] = {
+ { 0x01, MC13892_REVISION_1_0, "1.0" },
+ { 0x09, MC13892_REVISION_1_1, "1.1" },
+ { 0x0a, MC13892_REVISION_1_2, "1.2" },
+ { 0x10, MC13892_REVISION_2_0, "2.0" },
+ { 0x11, MC13892_REVISION_2_1, "2.1" },
+ { 0x18, MC13892_REVISION_3_0, "3.0" },
+ { 0x19, MC13892_REVISION_3_1, "3.1" },
+ { 0x1a, MC13892_REVISION_3_2, "3.2" },
+ { 0x02, MC13892_REVISION_3_2a, "3.2a" },
+ { 0x1b, MC13892_REVISION_3_3, "3.3" },
+ { 0x1d, MC13892_REVISION_3_5, "3.5" },
+};
+
+static int mc13893_query_revision(struct mc13892 *mc13892)
+{
+ unsigned int rev_id;
+ char *revstr;
+ int rev, i;
+
+ mc13892_reg_read(mc13892, 7, &rev_id);
+
+ for (i = 0; i < ARRAY_SIZE(mc13892_revisions); i++)
+ if ((rev_id & 0x1f) == mc13892_revisions[i].rev_id)
+ break;
+
+ if (i == ARRAY_SIZE(mc13892_revisions))
+ return -EINVAL;
+
+ rev = mc13892_revisions[i].rev;
+ revstr = mc13892_revisions[i].revstr;
+
+ if (rev == MC13892_REVISION_2_0) {
+ if ((rev_id >> 9) & 0x3) {
+ rev = MC13892_REVISION_2_0a;
+ revstr = "2.0a";
+ }
+ }
+
+ dev_info(mc_dev->cdev.dev, "PMIC ID: 0x%08x [Rev: %s]\n",
+ rev_id, revstr);
+
+ mc13892->revision = rev;
+
+ return rev;
+}
+
+static int mc_probe(struct device_d *dev, enum mc13892_mode mode)
+{
+ int rev;
+
+ if (mc_dev)
+ return -EBUSY;
+
+ mc_dev = xzalloc(sizeof(struct mc13892));
+ mc_dev->mode = mode;
+ mc_dev->cdev.name = DRIVERNAME;
+ if (mode == MC13892_MODE_I2C) {
+ mc_dev->client = to_i2c_client(dev);
+ }
+ if (mode == MC13892_MODE_SPI) {
+ mc_dev->spi = dev->type_data;
+ mc_dev->spi->mode = SPI_MODE_0 | SPI_CS_HIGH;
+ mc_dev->spi->bits_per_word = 32;
+ }
+ mc_dev->cdev.size = 256;
+ mc_dev->cdev.dev = dev;
+ mc_dev->cdev.ops = &mc_fops;
+
+ rev = mc13893_query_revision(mc_dev);
+ if (rev < 0) {
+ free(mc_dev);
+ return -EINVAL;
+ }
+
+ devfs_create(&mc_dev->cdev);
+
+ return 0;
+}
+
+static int mc_i2c_probe(struct device_d *dev)
+{
+ return mc_probe(dev, MC13892_MODE_I2C);
+}
+
+static int mc_spi_probe(struct device_d *dev)
+{
+ return mc_probe(dev, MC13892_MODE_SPI);
+}
+
+static struct driver_d mc_i2c_driver = {
+ .name = "mc13892-i2c",
+ .probe = mc_i2c_probe,
+};
+
+static struct driver_d mc_spi_driver = {
+ .name = "mc13892-spi",
+ .probe = mc_spi_probe,
+};
+
+static int mc_init(void)
+{
+ register_driver(&mc_i2c_driver);
+ register_driver(&mc_spi_driver);
+ return 0;
+}
+
+device_initcall(mc_init);
diff --git a/drivers/i2c/mc34704.c b/drivers/mfd/mc34704.c
index 51a8737209..a2171b35d1 100644
--- a/drivers/i2c/mc34704.c
+++ b/drivers/mfd/mc34704.c
@@ -27,7 +27,7 @@
#include <errno.h>
#include <i2c/i2c.h>
-#include <i2c/mc34704.h>
+#include <mfd/mc34704.h>
#define DRIVERNAME "mc34704"
diff --git a/drivers/i2c/mc9sdz60.c b/drivers/mfd/mc9sdz60.c
index 3580af8852..db208ec2db 100644
--- a/drivers/i2c/mc9sdz60.c
+++ b/drivers/mfd/mc9sdz60.c
@@ -26,7 +26,7 @@
#include <errno.h>
#include <i2c/i2c.h>
-#include <i2c/mc9sdz60.h>
+#include <mfd/mc9sdz60.h>
#define DRIVERNAME "mc9sdz60"
diff --git a/drivers/i2c/twl4030.c b/drivers/mfd/twl4030.c
index 5305ec67e3..81bf48bbb7 100644
--- a/drivers/i2c/twl4030.c
+++ b/drivers/mfd/twl4030.c
@@ -12,7 +12,7 @@
#include <errno.h>
#include <i2c/i2c.h>
-#include <i2c/twl4030.h>
+#include <mfd/twl4030.h>
#define DRIVERNAME "twl4030"
diff --git a/drivers/serial/serial_imx.c b/drivers/serial/serial_imx.c
index 801004e186..25e6a0c6fc 100644
--- a/drivers/serial/serial_imx.c
+++ b/drivers/serial/serial_imx.c
@@ -160,7 +160,8 @@
# define UCR3_VAL (0x700 | UCR3_RXDMUXSEL)
# define UCR4_VAL UCR4_CTSTL_32
#endif
-#if defined CONFIG_ARCH_IMX31 || defined CONFIG_ARCH_IMX35 || defined CONFIG_ARCH_IMX25
+#if defined CONFIG_ARCH_IMX31 || defined CONFIG_ARCH_IMX35 || \
+ defined CONFIG_ARCH_IMX25 || defined CONFIG_ARCH_IMX51
# define UCR1_VAL (0)
# define UCR3_VAL (0x700 | UCR3_RXDMUXSEL)
# define UCR4_VAL UCR4_CTSTL_32
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 3eebd08983..a88e179e5a 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -9,8 +9,14 @@ config DRIVER_SPI_IMX
depends on ARCH_IMX
depends on SPI
-config DRIVER_SPI_MC13783
- bool "MC13783 a.k.a. PMIC driver"
- depends on SPI
+config DRIVER_SPI_IMX_0_0
+ bool
+ depends on ARCH_IMX27
+ default y
+
+config DRIVER_SPI_IMX_2_3
+ bool
+ depends on ARCH_IMX51
+ default y
endmenu
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 81f2c6bc62..b2b2f6788f 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -1,4 +1,2 @@
obj-$(CONFIG_SPI) += spi.o
obj-$(CONFIG_DRIVER_SPI_IMX) += imx_spi.o
-
-obj-$(CONFIG_DRIVER_SPI_MC13783) += mc13783.o
diff --git a/drivers/spi/imx_spi.c b/drivers/spi/imx_spi.c
index 5c9791978a..2ad1bfa499 100644
--- a/drivers/spi/imx_spi.c
+++ b/drivers/spi/imx_spi.c
@@ -26,47 +26,104 @@
#include <asm/io.h>
#include <gpio.h>
#include <mach/spi.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 << 4)
-#define MXC_CSPISTAT_RH (1 << 5)
-#define MXC_CSPISTAT_RF (1 << 6)
-#define MXC_CSPISTAT_RO (1 << 7)
-
-#define MXC_CSPIPERIOD_32KHZ (1 << 15)
-
-#define MXC_CSPITEST_LBC (1 << 14)
+#include <mach/generic.h>
+
+#define CSPI_0_0_RXDATA 0x00
+#define CSPI_0_0_TXDATA 0x04
+#define CSPI_0_0_CTRL 0x08
+#define CSPI_0_0_INT 0x0C
+#define CSPI_0_0_DMA 0x18
+#define CSPI_0_0_STAT 0x0C
+#define CSPI_0_0_PERIOD 0x14
+#define CSPI_0_0_TEST 0x10
+#define CSPI_0_0_RESET 0x1C
+
+#define CSPI_0_0_CTRL_ENABLE (1 << 10)
+#define CSPI_0_0_CTRL_MASTER (1 << 11)
+#define CSPI_0_0_CTRL_XCH (1 << 9)
+#define CSPI_0_0_CTRL_LOWPOL (1 << 5)
+#define CSPI_0_0_CTRL_PHA (1 << 6)
+#define CSPI_0_0_CTRL_SSCTL (1 << 7)
+#define CSPI_0_0_CTRL_HIGHSSPOL (1 << 8)
+#define CSPI_0_0_CTRL_CS(x) (((x) & 0x3) << 19)
+#define CSPI_0_0_CTRL_BITCOUNT(x) (((x) & 0x1f) << 0)
+#define CSPI_0_0_CTRL_DATARATE(x) (((x) & 0x7) << 14)
+
+#define CSPI_0_0_CTRL_MAXDATRATE 0x10
+#define CSPI_0_0_CTRL_DATAMASK 0x1F
+#define CSPI_0_0_CTRL_DATASHIFT 14
+
+#define CSPI_0_0_STAT_TE (1 << 0)
+#define CSPI_0_0_STAT_TH (1 << 1)
+#define CSPI_0_0_STAT_TF (1 << 2)
+#define CSPI_0_0_STAT_RR (1 << 4)
+#define CSPI_0_0_STAT_RH (1 << 5)
+#define CSPI_0_0_STAT_RF (1 << 6)
+#define CSPI_0_0_STAT_RO (1 << 7)
+
+#define CSPI_0_0_PERIOD_32KHZ (1 << 15)
+
+#define CSPI_0_0_TEST_LBC (1 << 14)
+
+#define CSPI_2_3_RXDATA 0x00
+#define CSPI_2_3_TXDATA 0x04
+#define CSPI_2_3_CTRL 0x08
+#define CSPI_2_3_CTRL_ENABLE (1 << 0)
+#define CSPI_2_3_CTRL_XCH (1 << 2)
+#define CSPI_2_3_CTRL_MODE(cs) (1 << ((cs) + 4))
+#define CSPI_2_3_CTRL_POSTDIV_OFFSET 8
+#define CSPI_2_3_CTRL_PREDIV_OFFSET 12
+#define CSPI_2_3_CTRL_CS(cs) ((cs) << 18)
+#define CSPI_2_3_CTRL_BL_OFFSET 20
+
+#define CSPI_2_3_CONFIG 0x0c
+#define CSPI_2_3_CONFIG_SCLKPHA(cs) (1 << ((cs) + 0))
+#define CSPI_2_3_CONFIG_SCLKPOL(cs) (1 << ((cs) + 4))
+#define CSPI_2_3_CONFIG_SBBCTRL(cs) (1 << ((cs) + 8))
+#define CSPI_2_3_CONFIG_SSBPOL(cs) (1 << ((cs) + 12))
+
+#define CSPI_2_3_INT 0x10
+#define CSPI_2_3_INT_TEEN (1 << 0)
+#define CSPI_2_3_INT_RREN (1 << 3)
+
+#define CSPI_2_3_STAT 0x18
+#define CSPI_2_3_STAT_RR (1 << 3)
+
+enum imx_spi_devtype {
+#ifdef CONFIG_DRIVER_SPI_IMX1
+ SPI_IMX_VER_IMX1,
+#endif
+#ifdef CONFIG_DRIVER_SPI_IMX_0_0
+ SPI_IMX_VER_0_0,
+#endif
+#ifdef CONFIG_DRIVER_SPI_IMX_0_4
+ SPI_IMX_VER_0_4,
+#endif
+#ifdef CONFIG_DRIVER_SPI_IMX_0_5
+ SPI_IMX_VER_0_5,
+#endif
+#ifdef CONFIG_DRIVER_SPI_IMX_0_7
+ SPI_IMX_VER_0_7,
+#endif
+#ifdef CONFIG_DRIVER_SPI_IMX_2_3
+ SPI_IMX_VER_2_3,
+#endif
+};
struct imx_spi {
- struct spi_master master;
- int *chipselect;
+ struct spi_master master;
+ int *cs_array;
+ void __iomem *regs;
+
+ unsigned int (*xchg_single)(struct imx_spi *imx, u32 data);
+ void (*chipselect)(struct spi_device *spi, int active);
+ void (*init)(struct imx_spi *imx);
+};
+
+struct spi_imx_devtype_data {
+ unsigned int (*xchg_single)(struct imx_spi *imx, u32 data);
+ void (*chipselect)(struct spi_device *spi, int active);
+ void (*init)(struct imx_spi *imx);
};
static int imx_spi_setup(struct spi_device *spi)
@@ -77,29 +134,31 @@ static int imx_spi_setup(struct spi_device *spi)
return 0;
}
-static unsigned int spi_xchg_single(ulong base, unsigned int data)
+#ifdef CONFIG_DRIVER_SPI_IMX_0_0
+static unsigned int cspi_0_0_xchg_single(struct imx_spi *imx, unsigned int data)
{
+ void __iomem *base = imx->regs;
- unsigned int cfg_reg = readl(base + MXC_CSPICTRL);
+ unsigned int cfg_reg = readl(base + CSPI_0_0_CTRL);
- writel(data, base + MXC_CSPITXDATA);
+ writel(data, base + CSPI_0_0_TXDATA);
- cfg_reg |= MXC_CSPICTRL_XCH;
+ cfg_reg |= CSPI_0_0_CTRL_XCH;
- writel(cfg_reg, base + MXC_CSPICTRL);
+ writel(cfg_reg, base + CSPI_0_0_CTRL);
- while (!(readl(base + MXC_CSPIINT) & MXC_CSPISTAT_RR));
+ while (!(readl(base + CSPI_0_0_INT) & CSPI_0_0_STAT_RR));
- return readl(base + MXC_CSPIRXDATA);
+ return readl(base + CSPI_0_0_RXDATA);
}
-static void mxc_spi_chipselect(struct spi_device *spi, int is_active)
+static void cspi_0_0_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);
- ulong base = master->dev->map_base;
+ void __iomem *base = imx->regs;
unsigned int cs = 0;
- int gpio = imx->chipselect[spi->chip_select];
+ int gpio = imx->cs_array[spi->chip_select];
u32 ctrl_reg;
if (spi->mode & SPI_CS_HIGH)
@@ -111,35 +170,156 @@ static void mxc_spi_chipselect(struct spi_device *spi, int is_active)
return;
}
- ctrl_reg = MXC_CSPICTRL_BITCOUNT(spi->bits_per_word - 1)
- | MXC_CSPICTRL_DATARATE(7) /* FIXME: calculate data rate */
- | MXC_CSPICTRL_ENABLE
- | MXC_CSPICTRL_MASTER;
+ ctrl_reg = CSPI_0_0_CTRL_BITCOUNT(spi->bits_per_word - 1)
+ | CSPI_0_0_CTRL_DATARATE(7) /* FIXME: calculate data rate */
+ | CSPI_0_0_CTRL_ENABLE
+ | CSPI_0_0_CTRL_MASTER;
if (gpio < 0) {
- ctrl_reg |= MXC_CSPICTRL_CS(gpio + 32);
+ ctrl_reg |= CSPI_0_0_CTRL_CS(gpio + 32);
}
if (spi->mode & SPI_CPHA)
- ctrl_reg |= MXC_CSPICTRL_PHA;
+ ctrl_reg |= CSPI_0_0_CTRL_PHA;
if (spi->mode & SPI_CPOL)
- ctrl_reg |= MXC_CSPICTRL_LOWPOL;
+ ctrl_reg |= CSPI_0_0_CTRL_LOWPOL;
if (spi->mode & SPI_CS_HIGH)
- ctrl_reg |= MXC_CSPICTRL_HIGHSSPOL;
+ ctrl_reg |= CSPI_0_0_CTRL_HIGHSSPOL;
- writel(ctrl_reg, base + MXC_CSPICTRL);
+ writel(ctrl_reg, base + CSPI_0_0_CTRL);
if (gpio >= 0)
gpio_set_value(gpio, cs);
}
+static void cspi_0_0_init(struct imx_spi *imx)
+{
+ void __iomem *base = imx->regs;
+
+ writel(CSPI_0_0_CTRL_ENABLE | CSPI_0_0_CTRL_MASTER,
+ base + CSPI_0_0_CTRL);
+ writel(CSPI_0_0_PERIOD_32KHZ,
+ base + CSPI_0_0_PERIOD);
+ while (readl(base + CSPI_0_0_INT) & CSPI_0_0_STAT_RR)
+ readl(base + CSPI_0_0_RXDATA);
+ writel(0, base + CSPI_0_0_INT);
+}
+#endif
+
+#ifdef CONFIG_DRIVER_SPI_IMX_2_3
+static unsigned int cspi_2_3_xchg_single(struct imx_spi *imx, unsigned int data)
+{
+ void __iomem *base = imx->regs;
+
+ unsigned int cfg_reg = readl(base + CSPI_2_3_CTRL);
+
+ writel(data, base + CSPI_2_3_TXDATA);
+
+ cfg_reg |= CSPI_2_3_CTRL_XCH;
+
+ writel(cfg_reg, base + CSPI_2_3_CTRL);
+
+ while (!(readl(base + CSPI_2_3_STAT) & CSPI_2_3_STAT_RR));
+
+ return readl(base + CSPI_2_3_RXDATA);
+}
+
+/* FIXME: include/linux/kernel.h */
+#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
+
+static unsigned int cspi_2_3_clkdiv(unsigned int fin, unsigned int fspi)
+{
+ /*
+ * there are two 4-bit dividers, the pre-divider divides by
+ * $pre, the post-divider by 2^$post
+ */
+ unsigned int pre, post;
+
+ if (unlikely(fspi > fin))
+ return 0;
+
+ post = fls(fin) - fls(fspi);
+ if (fin > fspi << post)
+ post++;
+
+ /* now we have: (fin <= fspi << post) with post being minimal */
+
+ post = max(4U, post) - 4;
+ if (unlikely(post > 0xf)) {
+ pr_err("%s: cannot set clock freq: %u (base freq: %u)\n",
+ __func__, fspi, fin);
+ return 0xff;
+ }
+
+ pre = DIV_ROUND_UP(fin, fspi << post) - 1;
+
+ pr_debug("%s: fin: %u, fspi: %u, post: %u, pre: %u\n",
+ __func__, fin, fspi, post, pre);
+ return (pre << CSPI_2_3_CTRL_PREDIV_OFFSET) |
+ (post << CSPI_2_3_CTRL_POSTDIV_OFFSET);
+}
+
+static void cspi_2_3_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 = spi->chip_select, gpio_cs = 0;
+ int gpio = imx->cs_array[spi->chip_select];
+ u32 ctrl, cfg = 0;
+
+ if (spi->mode & SPI_CS_HIGH)
+ gpio_cs = 1;
+
+ if (!is_active) {
+ if (gpio >= 0)
+ gpio_set_value(gpio, !gpio_cs);
+ return;
+ }
+
+ ctrl = CSPI_2_3_CTRL_ENABLE;
+
+ /* set master mode */
+ ctrl |= CSPI_2_3_CTRL_MODE(cs);
+
+ /* set clock speed */
+ ctrl |= cspi_2_3_clkdiv(166000000, spi->max_speed_hz);
+
+ /* set chip select to use */
+ ctrl |= CSPI_2_3_CTRL_CS(cs);
+
+ ctrl |= (spi->bits_per_word - 1) << CSPI_2_3_CTRL_BL_OFFSET;
+
+ cfg |= CSPI_2_3_CONFIG_SBBCTRL(cs);
+
+ if (spi->mode & SPI_CPHA)
+ cfg |= CSPI_2_3_CONFIG_SCLKPHA(cs);
+
+ if (spi->mode & SPI_CPOL)
+ cfg |= CSPI_2_3_CONFIG_SCLKPOL(cs);
+
+ if (spi->mode & SPI_CS_HIGH)
+ cfg |= CSPI_2_3_CONFIG_SSBPOL(cs);
+
+ writel(ctrl, base + CSPI_2_3_CTRL);
+ writel(cfg, base + CSPI_2_3_CONFIG);
+
+ if (gpio >= 0)
+ gpio_set_value(gpio, gpio_cs);
+}
+
+static void cspi_2_3_init(struct imx_spi *imx)
+{
+}
+#endif
+
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 imx_spi *imx = container_of(master, struct imx_spi, master);
struct spi_transfer *t = NULL;
- mxc_spi_chipselect(spi, 1);
+ imx->chipselect(spi, 1);
list_for_each_entry (t, &mesg->transfers, transfer_list) {
const u32 *txbuf = t->tx_buf;
@@ -147,21 +327,39 @@ static int imx_spi_transfer(struct spi_device *spi, struct spi_message *mesg)
int i = 0;
while(i < t->len >> 2) {
- rxbuf[i] = spi_xchg_single(base, txbuf[i]);
+ rxbuf[i] = imx->xchg_single(imx, txbuf[i]);
i++;
}
}
- mxc_spi_chipselect(spi, 0);
+ imx->chipselect(spi, 0);
return 0;
}
+static struct spi_imx_devtype_data spi_imx_devtype_data[] = {
+#ifdef CONFIG_DRIVER_SPI_IMX_0_0
+ [SPI_IMX_VER_0_0] = {
+ .chipselect = cspi_0_0_chipselect,
+ .xchg_single = cspi_0_0_xchg_single,
+ .init = cspi_0_0_init,
+ },
+#endif
+#ifdef CONFIG_DRIVER_SPI_IMX_2_3
+ [SPI_IMX_VER_2_3] = {
+ .chipselect = cspi_2_3_chipselect,
+ .xchg_single = cspi_2_3_xchg_single,
+ .init = cspi_2_3_init,
+ },
+#endif
+};
+
static int imx_spi_probe(struct device_d *dev)
{
struct spi_master *master;
struct imx_spi *imx;
struct spi_imx_master *pdata = dev->platform_data;
+ enum imx_spi_devtype version;
imx = xzalloc(sizeof(*imx));
@@ -171,15 +369,22 @@ static int imx_spi_probe(struct device_d *dev)
master->setup = imx_spi_setup;
master->transfer = imx_spi_transfer;
master->num_chipselect = pdata->num_chipselect;
- imx->chipselect = pdata->chipselect;
-
- writel(MXC_CSPICTRL_ENABLE | MXC_CSPICTRL_MASTER,
- dev->map_base + MXC_CSPICTRL);
- writel(MXC_CSPIPERIOD_32KHZ,
- dev->map_base + MXC_CSPIPERIOD);
- while (readl(dev->map_base + MXC_CSPIINT) & MXC_CSPISTAT_RR)
- readl(dev->map_base + MXC_CSPIRXDATA);
- writel(0, dev->map_base + MXC_CSPIINT);
+ imx->cs_array = pdata->chipselect;
+
+#ifdef CONFIG_DRIVER_SPI_IMX_0_0
+ if (cpu_is_mx27())
+ version = SPI_IMX_VER_0_0;
+#endif
+#ifdef CONFIG_DRIVER_SPI_IMX_2_3
+ if (cpu_is_mx51())
+ version = SPI_IMX_VER_2_3;
+#endif
+ imx->chipselect = spi_imx_devtype_data[version].chipselect;
+ imx->xchg_single = spi_imx_devtype_data[version].xchg_single;
+ imx->init = spi_imx_devtype_data[version].init;
+ imx->regs = (void __iomem *)dev->map_base;
+
+ imx->init(imx);
spi_register_master(master);
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 0c30c52fc9..05f1628fab 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -11,7 +11,7 @@
/*-------------------------------------------------------------------------*/
-#include <i2c/twl4030.h>
+#include <mfd/twl4030.h>
#include <usb/twl4030.h>
#include <mach/ehci.h>
#include <common.h>
diff --git a/drivers/usb/otg/twl4030.c b/drivers/usb/otg/twl4030.c
index 72edf25843..40771699ea 100644
--- a/drivers/usb/otg/twl4030.c
+++ b/drivers/usb/otg/twl4030.c
@@ -37,7 +37,7 @@
* MA 02111-1307 USA
*/
-#include <i2c/twl4030.h>
+#include <mfd/twl4030.h>
#include <usb/twl4030.h>
#include <clock.h>