summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2016-09-13 14:56:04 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2016-09-13 14:56:04 +0200
commitb2c398f44031efc3c6ab2bec19f56df0c05ad3de (patch)
treef64b1bb976f832daa0160e1a67cfcd669822ae58 /drivers
parent0a12c7156890eae6c74732f69a6b731135b0bb27 (diff)
parentb12f38097bce1f12e4b7e420c2c11bea281b4daa (diff)
downloadbarebox-b2c398f44031efc3c6ab2bec19f56df0c05ad3de.tar.gz
barebox-b2c398f44031efc3c6ab2bec19f56df0c05ad3de.tar.xz
Merge branch 'for-next/imx'
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mci/imx-esdhc.c4
-rw-r--r--drivers/mtd/nand/Makefile2
-rw-r--r--drivers/mtd/nand/nand_imx.c72
-rw-r--r--drivers/mtd/nand/nand_timings.c251
-rw-r--r--drivers/spi/Kconfig4
-rw-r--r--drivers/usb/imx/chipidea-imx.c28
-rw-r--r--drivers/usb/imx/imx-usb-misc.c6
7 files changed, 343 insertions, 24 deletions
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index 66786ffec7..262a904ace 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -85,7 +85,7 @@ static u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data)
xfertyp |= COMMAND_RSPTYP_48_BUSY;
else if (cmd->resp_type & MMC_RSP_PRESENT)
xfertyp |= COMMAND_RSPTYP_48;
- if ((cpu_is_mx51() || cpu_is_mx53()) &&
+ if ((cpu_is_mx50() || cpu_is_mx51() || cpu_is_mx53()) &&
cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)
xfertyp |= SDHCI_CMD_ABORTCMD;
@@ -638,6 +638,8 @@ static __maybe_unused struct of_device_id fsl_esdhc_compatible[] = {
{
.compatible = "fsl,imx25-esdhc",
}, {
+ .compatible = "fsl,imx50-esdhc",
+ }, {
.compatible = "fsl,imx51-esdhc",
}, {
.compatible = "fsl,imx53-esdhc",
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 8809238e54..6088512745 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -3,7 +3,7 @@
obj-$(CONFIG_NAND) += nand_ecc.o
obj-$(CONFIG_NAND_ECC_BCH) += nand_bch.o
obj-$(CONFIG_MTD_NAND_IDS) += nand_ids.o
-obj-$(CONFIG_NAND) += nand_base.o nand-bb.o
+obj-$(CONFIG_NAND) += nand_base.o nand-bb.o nand_timings.o
obj-$(CONFIG_NAND_BBT) += nand_bbt.o
obj-$(CONFIG_MTD_NAND_NOMADIK) += nomadik_nand.o
diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index f54fe21f7d..6f31c28ec6 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -24,6 +24,7 @@
#include <init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
+#include <linux/clk.h>
#include <mach/generic.h>
#include <mach/imx-nand.h>
#include <io.h>
@@ -784,16 +785,63 @@ static int get_eccsize(struct mtd_info *mtd)
return 8;
}
-static void preset_v1_v2(struct mtd_info *mtd)
+static void preset_v1(struct mtd_info *mtd)
{
struct nand_chip *nand_chip = mtd->priv;
struct imx_nand_host *host = nand_chip->priv;
uint16_t config1 = 0;
- if (nfc_is_v21())
- config1 |= NFC_V2_CONFIG1_FP_INT;
+ host->eccsize = 1;
+
+ writew(config1, host->regs + NFC_V1_V2_CONFIG1);
+ /* preset operation */
+
+ /* Unlock the internal RAM Buffer */
+ writew(0x2, host->regs + NFC_V1_V2_CONFIG);
+
+ /* Blocks to be unlocked */
+ writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR);
+ writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR);
+
+ /* Unlock Block Command for given address range */
+ writew(0x4, host->regs + NFC_V1_V2_WRPROT);
+}
- if (nfc_is_v21() && mtd->writesize) {
+static void preset_v2(struct mtd_info *mtd)
+{
+ struct nand_chip *nand_chip = mtd->priv;
+ struct imx_nand_host *host = nand_chip->priv;
+ uint16_t config1 = 0;
+ int mode;
+
+ mode = onfi_get_async_timing_mode(nand_chip);
+ if (mode != ONFI_TIMING_MODE_UNKNOWN && !IS_ERR(host->clk)) {
+ const struct nand_sdr_timings *timings;
+
+ mode = fls(mode) - 1;
+ if (mode < 0)
+ mode = 0;
+
+ timings = onfi_async_timing_mode_to_sdr_timings(mode);
+ if (!IS_ERR(timings)) {
+ unsigned long rate;
+ int tRC_min_ns = timings->tRC_min / 1000;
+
+ rate = 1000000000 / tRC_min_ns;
+ if (tRC_min_ns < 30)
+ /* If tRC is smaller than 30ns we have to use EDO timing */
+ config1 |= NFC_V1_V2_CONFIG1_ONE_CYCLE;
+ else
+ /* Otherwise we have two clock cycles per access */
+ rate *= 2;
+
+ clk_set_rate(host->clk, rate);
+ }
+ }
+
+ config1 |= NFC_V2_CONFIG1_FP_INT;
+
+ if (mtd->writesize) {
uint16_t pages_per_block = mtd->erasesize / mtd->writesize;
host->eccsize = get_eccsize(mtd);
@@ -812,14 +860,8 @@ static void preset_v1_v2(struct mtd_info *mtd)
writew(0x2, host->regs + NFC_V1_V2_CONFIG);
/* Blocks to be unlocked */
- if (nfc_is_v21()) {
- writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR);
- writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR);
- } else if (nfc_is_v1()) {
- writew(0x0, host->regs + NFC_V1_UNLOCKSTART_BLKADDR);
- writew(0x4000, host->regs + NFC_V1_UNLOCKEND_BLKADDR);
- } else
- BUG();
+ writew(0x0, host->regs + NFC_V21_UNLOCKSTART_BLKADDR);
+ writew(0xffff, host->regs + NFC_V21_UNLOCKEND_BLKADDR);
/* Unlock Block Command for given address range */
writew(0x4, host->regs + NFC_V1_V2_WRPROT);
@@ -1166,8 +1208,10 @@ static int __init imxnd_probe(struct device_d *dev)
host->data_buf = (uint8_t *)(host + 1);
+ /* No error check, not all SoCs provide a clk yet */
+ host->clk = clk_get(dev, NULL);
+
if (nfc_is_v1() || nfc_is_v21()) {
- host->preset = preset_v1_v2;
host->send_cmd = send_cmd_v1_v2;
host->send_addr = send_addr_v1_v2;
host->send_page = send_page_v1_v2;
@@ -1189,6 +1233,7 @@ static int __init imxnd_probe(struct device_d *dev)
oob_smallpage = &nandv2_hw_eccoob_smallpage;
oob_largepage = &nandv2_hw_eccoob_largepage;
oob_4kpage = &nandv2_hw_eccoob_4k; /* FIXME : to check */
+ host->preset = preset_v2;
} else if (nfc_is_v1()) {
iores = dev_request_mem_resource(dev, 0);
if (IS_ERR(iores))
@@ -1201,6 +1246,7 @@ static int __init imxnd_probe(struct device_d *dev)
oob_smallpage = &nandv1_hw_eccoob_smallpage;
oob_largepage = &nandv1_hw_eccoob_largepage;
oob_4kpage = &nandv1_hw_eccoob_smallpage; /* FIXME : to check */
+ host->preset = preset_v1;
} else if (nfc_is_v3_2()) {
iores = dev_request_mem_resource(dev, 0);
if (IS_ERR(iores))
diff --git a/drivers/mtd/nand/nand_timings.c b/drivers/mtd/nand/nand_timings.c
new file mode 100644
index 0000000000..7a939510b7
--- /dev/null
+++ b/drivers/mtd/nand/nand_timings.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2014 Free Electrons
+ *
+ * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/mtd/nand.h>
+
+static const struct nand_sdr_timings onfi_sdr_timings[] = {
+ /* Mode 0 */
+ {
+ .tADL_min = 200000,
+ .tALH_min = 20000,
+ .tALS_min = 50000,
+ .tAR_min = 25000,
+ .tCEA_max = 100000,
+ .tCEH_min = 20000,
+ .tCH_min = 20000,
+ .tCHZ_max = 100000,
+ .tCLH_min = 20000,
+ .tCLR_min = 20000,
+ .tCLS_min = 50000,
+ .tCOH_min = 0,
+ .tCS_min = 70000,
+ .tDH_min = 20000,
+ .tDS_min = 40000,
+ .tFEAT_max = 1000000,
+ .tIR_min = 10000,
+ .tITC_max = 1000000,
+ .tRC_min = 100000,
+ .tREA_max = 40000,
+ .tREH_min = 30000,
+ .tRHOH_min = 0,
+ .tRHW_min = 200000,
+ .tRHZ_max = 200000,
+ .tRLOH_min = 0,
+ .tRP_min = 50000,
+ .tRST_max = 250000000000,
+ .tWB_max = 200000,
+ .tRR_min = 40000,
+ .tWC_min = 100000,
+ .tWH_min = 30000,
+ .tWHR_min = 120000,
+ .tWP_min = 50000,
+ .tWW_min = 100000,
+ },
+ /* Mode 1 */
+ {
+ .tADL_min = 100000,
+ .tALH_min = 10000,
+ .tALS_min = 25000,
+ .tAR_min = 10000,
+ .tCEA_max = 45000,
+ .tCEH_min = 20000,
+ .tCH_min = 10000,
+ .tCHZ_max = 50000,
+ .tCLH_min = 10000,
+ .tCLR_min = 10000,
+ .tCLS_min = 25000,
+ .tCOH_min = 15000,
+ .tCS_min = 35000,
+ .tDH_min = 10000,
+ .tDS_min = 20000,
+ .tFEAT_max = 1000000,
+ .tIR_min = 0,
+ .tITC_max = 1000000,
+ .tRC_min = 50000,
+ .tREA_max = 30000,
+ .tREH_min = 15000,
+ .tRHOH_min = 15000,
+ .tRHW_min = 100000,
+ .tRHZ_max = 100000,
+ .tRLOH_min = 0,
+ .tRP_min = 25000,
+ .tRR_min = 20000,
+ .tRST_max = 500000000,
+ .tWB_max = 100000,
+ .tWC_min = 45000,
+ .tWH_min = 15000,
+ .tWHR_min = 80000,
+ .tWP_min = 25000,
+ .tWW_min = 100000,
+ },
+ /* Mode 2 */
+ {
+ .tADL_min = 100000,
+ .tALH_min = 10000,
+ .tALS_min = 15000,
+ .tAR_min = 10000,
+ .tCEA_max = 30000,
+ .tCEH_min = 20000,
+ .tCH_min = 10000,
+ .tCHZ_max = 50000,
+ .tCLH_min = 10000,
+ .tCLR_min = 10000,
+ .tCLS_min = 15000,
+ .tCOH_min = 15000,
+ .tCS_min = 25000,
+ .tDH_min = 5000,
+ .tDS_min = 15000,
+ .tFEAT_max = 1000000,
+ .tIR_min = 0,
+ .tITC_max = 1000000,
+ .tRC_min = 35000,
+ .tREA_max = 25000,
+ .tREH_min = 15000,
+ .tRHOH_min = 15000,
+ .tRHW_min = 100000,
+ .tRHZ_max = 100000,
+ .tRLOH_min = 0,
+ .tRR_min = 20000,
+ .tRST_max = 500000000,
+ .tWB_max = 100000,
+ .tRP_min = 17000,
+ .tWC_min = 35000,
+ .tWH_min = 15000,
+ .tWHR_min = 80000,
+ .tWP_min = 17000,
+ .tWW_min = 100000,
+ },
+ /* Mode 3 */
+ {
+ .tADL_min = 100000,
+ .tALH_min = 5000,
+ .tALS_min = 10000,
+ .tAR_min = 10000,
+ .tCEA_max = 25000,
+ .tCEH_min = 20000,
+ .tCH_min = 5000,
+ .tCHZ_max = 50000,
+ .tCLH_min = 5000,
+ .tCLR_min = 10000,
+ .tCLS_min = 10000,
+ .tCOH_min = 15000,
+ .tCS_min = 25000,
+ .tDH_min = 5000,
+ .tDS_min = 10000,
+ .tFEAT_max = 1000000,
+ .tIR_min = 0,
+ .tITC_max = 1000000,
+ .tRC_min = 30000,
+ .tREA_max = 20000,
+ .tREH_min = 10000,
+ .tRHOH_min = 15000,
+ .tRHW_min = 100000,
+ .tRHZ_max = 100000,
+ .tRLOH_min = 0,
+ .tRP_min = 15000,
+ .tRR_min = 20000,
+ .tRST_max = 500000000,
+ .tWB_max = 100000,
+ .tWC_min = 30000,
+ .tWH_min = 10000,
+ .tWHR_min = 80000,
+ .tWP_min = 15000,
+ .tWW_min = 100000,
+ },
+ /* Mode 4 */
+ {
+ .tADL_min = 70000,
+ .tALH_min = 5000,
+ .tALS_min = 10000,
+ .tAR_min = 10000,
+ .tCEA_max = 25000,
+ .tCEH_min = 20000,
+ .tCH_min = 5000,
+ .tCHZ_max = 30000,
+ .tCLH_min = 5000,
+ .tCLR_min = 10000,
+ .tCLS_min = 10000,
+ .tCOH_min = 15000,
+ .tCS_min = 20000,
+ .tDH_min = 5000,
+ .tDS_min = 10000,
+ .tFEAT_max = 1000000,
+ .tIR_min = 0,
+ .tITC_max = 1000000,
+ .tRC_min = 25000,
+ .tREA_max = 20000,
+ .tREH_min = 10000,
+ .tRHOH_min = 15000,
+ .tRHW_min = 100000,
+ .tRHZ_max = 100000,
+ .tRLOH_min = 5000,
+ .tRP_min = 12000,
+ .tRR_min = 20000,
+ .tRST_max = 500000000,
+ .tWB_max = 100000,
+ .tWC_min = 25000,
+ .tWH_min = 10000,
+ .tWHR_min = 80000,
+ .tWP_min = 12000,
+ .tWW_min = 100000,
+ },
+ /* Mode 5 */
+ {
+ .tADL_min = 70000,
+ .tALH_min = 5000,
+ .tALS_min = 10000,
+ .tAR_min = 10000,
+ .tCEA_max = 25000,
+ .tCEH_min = 20000,
+ .tCH_min = 5000,
+ .tCHZ_max = 30000,
+ .tCLH_min = 5000,
+ .tCLR_min = 10000,
+ .tCLS_min = 10000,
+ .tCOH_min = 15000,
+ .tCS_min = 15000,
+ .tDH_min = 5000,
+ .tDS_min = 7000,
+ .tFEAT_max = 1000000,
+ .tIR_min = 0,
+ .tITC_max = 1000000,
+ .tRC_min = 20000,
+ .tREA_max = 16000,
+ .tREH_min = 7000,
+ .tRHOH_min = 15000,
+ .tRHW_min = 100000,
+ .tRHZ_max = 100000,
+ .tRLOH_min = 5000,
+ .tRP_min = 10000,
+ .tRR_min = 20000,
+ .tRST_max = 500000000,
+ .tWB_max = 100000,
+ .tWC_min = 20000,
+ .tWH_min = 7000,
+ .tWHR_min = 80000,
+ .tWP_min = 10000,
+ .tWW_min = 100000,
+ },
+};
+
+/**
+ * onfi_async_timing_mode_to_sdr_timings - [NAND Interface] Retrieve NAND
+ * timings according to the given ONFI timing mode
+ * @mode: ONFI timing mode
+ */
+const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode)
+{
+ if (mode < 0 || mode >= ARRAY_SIZE(onfi_sdr_timings))
+ return ERR_PTR(-EINVAL);
+
+ return &onfi_sdr_timings[mode];
+}
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 9a71b3bc25..43ba8f49ec 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -33,12 +33,12 @@ config DRIVER_SPI_IMX_0_0
config DRIVER_SPI_IMX_0_7
bool
- depends on ARCH_IMX25 || ARCH_IMX31 || ARCH_IMX35 || ARCH_IMX53
+ depends on ARCH_IMX25 || ARCH_IMX31 || ARCH_IMX35 || ARCH_IMX50 || ARCH_IMX53
default y
config DRIVER_SPI_IMX_2_3
bool
- depends on ARCH_IMX51 || ARCH_IMX53 || ARCH_IMX6
+ depends on ARCH_IMX50 || ARCH_IMX51 || ARCH_IMX53 || ARCH_IMX6
default y
config DRIVER_SPI_MXS
diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c
index a799abe4ee..a6f59261c3 100644
--- a/drivers/usb/imx/chipidea-imx.c
+++ b/drivers/usb/imx/chipidea-imx.c
@@ -150,13 +150,23 @@ static int imx_chipidea_probe_dt(struct imx_chipidea *ci)
static int ci_register_role(struct imx_chipidea *ci)
{
- if (ci->role_registered)
+ int ret;
+
+ if (ci->role_registered != IMX_USB_MODE_OTG)
return -EBUSY;
if (ci->mode == IMX_USB_MODE_HOST) {
if (IS_ENABLED(CONFIG_USB_EHCI)) {
ci->role_registered = 1;
- return ehci_register(ci->dev, &ci->data);
+ ret = regulator_enable(ci->vbus);
+ if (ret)
+ return ret;
+
+ ret = ehci_register(ci->dev, &ci->data);
+ if (!ret)
+ return 0;
+
+ regulator_disable(ci->vbus);
} else {
dev_err(ci->dev, "Host support not available\n");
return -ENODEV;
@@ -180,8 +190,12 @@ static int ci_set_mode(struct param_d *param, void *priv)
{
struct imx_chipidea *ci = priv;
- if (ci->role_registered)
- return -EBUSY;
+ if (ci->role_registered != IMX_USB_MODE_OTG) {
+ if (ci->role_registered == ci->mode)
+ return 0;
+ else
+ return -EBUSY;
+ }
return ci_register_role(ci);
}
@@ -225,6 +239,7 @@ static int imx_chipidea_probe(struct device_d *dev)
ci = xzalloc(sizeof(*ci));
ci->dev = dev;
+ ci->role_registered = IMX_USB_MODE_OTG;
if (IS_ENABLED(CONFIG_OFDEVICE) && dev->device_node) {
ret = imx_chipidea_probe_dt(ci);
@@ -242,9 +257,8 @@ static int imx_chipidea_probe(struct device_d *dev)
}
ci->vbus = regulator_get(dev, "vbus");
-
- if (!IS_ERR(ci->vbus))
- regulator_enable(ci->vbus);
+ if (IS_ERR(ci->vbus))
+ ci->vbus = NULL;
iores = dev_request_mem_resource(dev, 0);
if (IS_ERR(iores))
diff --git a/drivers/usb/imx/imx-usb-misc.c b/drivers/usb/imx/imx-usb-misc.c
index d938a2cd87..7c18ca2a18 100644
--- a/drivers/usb/imx/imx-usb-misc.c
+++ b/drivers/usb/imx/imx-usb-misc.c
@@ -447,6 +447,12 @@ static struct platform_device_id imx_usbmisc_ids[] = {
.driver_data = (unsigned long)&mx35_data,
},
#endif
+#ifdef CONFIG_ARCH_IMX50
+ {
+ .name = "imx50-usb-misc",
+ .driver_data = (unsigned long)&mx5_data,
+ },
+#endif
#ifdef CONFIG_ARCH_IMX51
{
.name = "imx51-usb-misc",