diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2016-09-13 14:56:04 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2016-09-13 14:56:04 +0200 |
commit | b2c398f44031efc3c6ab2bec19f56df0c05ad3de (patch) | |
tree | f64b1bb976f832daa0160e1a67cfcd669822ae58 /drivers | |
parent | 0a12c7156890eae6c74732f69a6b731135b0bb27 (diff) | |
parent | b12f38097bce1f12e4b7e420c2c11bea281b4daa (diff) | |
download | barebox-b2c398f44031efc3c6ab2bec19f56df0c05ad3de.tar.gz barebox-b2c398f44031efc3c6ab2bec19f56df0c05ad3de.tar.xz |
Merge branch 'for-next/imx'
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mci/imx-esdhc.c | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/Makefile | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_imx.c | 72 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_timings.c | 251 | ||||
-rw-r--r-- | drivers/spi/Kconfig | 4 | ||||
-rw-r--r-- | drivers/usb/imx/chipidea-imx.c | 28 | ||||
-rw-r--r-- | drivers/usb/imx/imx-usb-misc.c | 6 |
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", |