diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-13 08:34:11 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-13 08:34:11 -0800 |
commit | 5233c331cfb41433bc167fc7c70ea67c1133ffec (patch) | |
tree | 1ab0da40a3069c54e41a2aed8a0ada8ddb325e46 /drivers/soc/fsl | |
parent | 58f253d26254b7ec0faa0a67d70912facd6687e4 (diff) | |
parent | ff6af28faff53a7389230026b83e543385f7b21d (diff) |
Merge tag 'mmc-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC updates from Ulf Hansson:
"It's been an busy period for mmc. Quite some changes in the mmc core,
two new mmc host drivers, some existing drivers being extended to
support new IP versions and lots of other updates.
MMC core:
- Delete eMMC packed command support
- Introduce mmc_abort_tuning() to enable eMMC tuning to fail
gracefully
- Introduce mmc_can_retune() to see if a host can be retuned
- Re-work and improve the sequence when sending a CMD6 for mmc
- Enable CDM13 polling when switching to HS and HS DDR mode for mmc
- Relax checking for CMD6 errors after switch to HS200
- Re-factoring the code dealing with the mmc block queue
- Recognize whether the eMMC card supports CMDQ
- Fix 4K native sector check
- Don't power off the card when starting the host
- Increase MMC_IOC_MAX_BYTES to support bigger firmware binaries
- Improve error handling and drop meaningless BUG_ONs()
- Lots of clean-ups and changes to improve the quality of the code
MMC host:
- sdhci: Fix tuning sequence and clean-up the related code
- sdhci: Add support to via DT override broken SDHCI cap register
bits
- sdhci-cadence: Add new driver for Cadence SD4HC SDHCI variant
- sdhci-msm: Update clock management
- sdhci-msm: Add support for eMMC HS400 mode
- sdhci-msm: Deploy runtime/system PM support
- sdhci-iproc: Extend driver support to newer IP versions
- sdhci-pci: Add support for Intel GLK
- sdhci-pci: Add support for Intel NI byt sdio
- sdhci-acpi: Add support for 80860F14 UID 2 SDIO bus
- sdhci: Lots of various small improvements and clean-ups
- tmio: Add support for tuning
- sh_mobile_sdhi: Add support for tuning
- sh_mobile_sdhi: Extend driver to support SDHI IP on R7S72100 SoC
- sh_mobile_sdhi: remove support for sh7372
- davinci: Use mmc_of_parse() to enable generic mmc DT bindings
- meson: Add new driver to support GX platforms
- dw_mmc: Deploy generic runtime/system PM support
- dw_mmc: Lots of various small improvements
As a part of the mmc changes this time, I have also pulled in an
immutable branch/tag (soc-device-match-tag1) hosted by Geert
Uytterhoeven, to share the implementation of the new
soc_device_match() interface. This is needed by these mmc related
changes:
- mmc: sdhci-of-esdhc: Get correct IP version for T4240-R1.0-R2.0
- soc: fsl: add GUTS driver for QorIQ platforms"
* tag 'mmc-v4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (136 commits)
mmc: sdhci-cadence: add Cadence SD4HC support
mmc: sdhci: export sdhci_execute_tuning()
mmc: sdhci: Tidy tuning loop
mmc: sdhci: Simplify tuning block size logic
mmc: sdhci: Factor out tuning helper functions
mmc: sdhci: Use mmc_abort_tuning()
mmc: mmc: Introduce mmc_abort_tuning()
mmc: sdhci: Always allow tuning to fall back to fixed sampling
mmc: sdhci: Fix tuning reset after exhausting the maximum number of loops
mmc: sdhci: Fix recovery from tuning timeout
Revert "mmc: sdhci: Reset cmd and data circuits after tuning failure"
mmc: mmc: Relax checking for switch errors after HS200 switch
mmc: sdhci-acpi: support 80860F14 UID 2 SDIO bus
mmc: sdhci-of-at91: remove bogus MMC_SDHCI_IO_ACCESSORS select
mmc: sdhci-pci: Use ACPI to get max frequency for Intel NI byt sdio
mmc: sdhci-pci: Add PCI ID for Intel NI byt sdio
mmc: sdhci-s3c: add spin_unlock_irq() before calling clk_round_rate
mmc: dw_mmc: display the clock message only one time when card is polling
mmc: dw_mmc: add the debug message for polling and non-removable
mmc: dw_mmc: check the "present" variable before checking flags
...
Diffstat (limited to 'drivers/soc/fsl')
-rw-r--r-- | drivers/soc/fsl/Kconfig | 18 | ||||
-rw-r--r-- | drivers/soc/fsl/Makefile | 1 | ||||
-rw-r--r-- | drivers/soc/fsl/guts.c | 239 |
3 files changed, 258 insertions, 0 deletions
diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig new file mode 100644 index 000000000000..7a9fb9baa66d --- /dev/null +++ b/drivers/soc/fsl/Kconfig @@ -0,0 +1,18 @@ +# +# Freescale SOC drivers +# + +source "drivers/soc/fsl/qbman/Kconfig" +source "drivers/soc/fsl/qe/Kconfig" + +config FSL_GUTS + bool + select SOC_BUS + help + The global utilities block controls power management, I/O device + enabling, power-onreset(POR) configuration monitoring, alternate + function selection for multiplexed signals,and clock control. + This driver is to manage and access global utilities block. + Initially only reading SVR and registering soc device are supported. + Other guts accesses, such as reading RCW, should eventually be moved + into this driver as well. diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile index 75e1f5334821..44b3bebef24a 100644 --- a/drivers/soc/fsl/Makefile +++ b/drivers/soc/fsl/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_FSL_DPAA) += qbman/ obj-$(CONFIG_QUICC_ENGINE) += qe/ obj-$(CONFIG_CPM) += qe/ +obj-$(CONFIG_FSL_GUTS) += guts.o diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c new file mode 100644 index 000000000000..6af7a11f09a5 --- /dev/null +++ b/drivers/soc/fsl/guts.c @@ -0,0 +1,239 @@ +/* + * Freescale QorIQ Platforms GUTS Driver + * + * Copyright (C) 2016 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. + */ + +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/of_fdt.h> +#include <linux/sys_soc.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <linux/fsl/guts.h> + +struct guts { + struct ccsr_guts __iomem *regs; + bool little_endian; +}; + +struct fsl_soc_die_attr { + char *die; + u32 svr; + u32 mask; +}; + +static struct guts *guts; +static struct soc_device_attribute soc_dev_attr; +static struct soc_device *soc_dev; + + +/* SoC die attribute definition for QorIQ platform */ +static const struct fsl_soc_die_attr fsl_soc_die[] = { + /* + * Power Architecture-based SoCs T Series + */ + + /* Die: T4240, SoC: T4240/T4160/T4080 */ + { .die = "T4240", + .svr = 0x82400000, + .mask = 0xfff00000, + }, + /* Die: T1040, SoC: T1040/T1020/T1042/T1022 */ + { .die = "T1040", + .svr = 0x85200000, + .mask = 0xfff00000, + }, + /* Die: T2080, SoC: T2080/T2081 */ + { .die = "T2080", + .svr = 0x85300000, + .mask = 0xfff00000, + }, + /* Die: T1024, SoC: T1024/T1014/T1023/T1013 */ + { .die = "T1024", + .svr = 0x85400000, + .mask = 0xfff00000, + }, + + /* + * ARM-based SoCs LS Series + */ + + /* Die: LS1043A, SoC: LS1043A/LS1023A */ + { .die = "LS1043A", + .svr = 0x87920000, + .mask = 0xffff0000, + }, + /* Die: LS2080A, SoC: LS2080A/LS2040A/LS2085A */ + { .die = "LS2080A", + .svr = 0x87010000, + .mask = 0xff3f0000, + }, + /* Die: LS1088A, SoC: LS1088A/LS1048A/LS1084A/LS1044A */ + { .die = "LS1088A", + .svr = 0x87030000, + .mask = 0xff3f0000, + }, + /* Die: LS1012A, SoC: LS1012A */ + { .die = "LS1012A", + .svr = 0x87040000, + .mask = 0xffff0000, + }, + /* Die: LS1046A, SoC: LS1046A/LS1026A */ + { .die = "LS1046A", + .svr = 0x87070000, + .mask = 0xffff0000, + }, + /* Die: LS2088A, SoC: LS2088A/LS2048A/LS2084A/LS2044A */ + { .die = "LS2088A", + .svr = 0x87090000, + .mask = 0xff3f0000, + }, + /* Die: LS1021A, SoC: LS1021A/LS1020A/LS1022A */ + { .die = "LS1021A", + .svr = 0x87000000, + .mask = 0xfff70000, + }, + { }, +}; + +static const struct fsl_soc_die_attr *fsl_soc_die_match( + u32 svr, const struct fsl_soc_die_attr *matches) +{ + while (matches->svr) { + if (matches->svr == (svr & matches->mask)) + return matches; + matches++; + }; + return NULL; +} + +u32 fsl_guts_get_svr(void) +{ + u32 svr = 0; + + if (!guts || !guts->regs) + return svr; + + if (guts->little_endian) + svr = ioread32(&guts->regs->svr); + else + svr = ioread32be(&guts->regs->svr); + + return svr; +} +EXPORT_SYMBOL(fsl_guts_get_svr); + +static int fsl_guts_probe(struct platform_device *pdev) +{ + struct device_node *root, *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct resource *res; + const struct fsl_soc_die_attr *soc_die; + const char *machine; + u32 svr; + + /* Initialize guts */ + guts = devm_kzalloc(dev, sizeof(*guts), GFP_KERNEL); + if (!guts) + return -ENOMEM; + + guts->little_endian = of_property_read_bool(np, "little-endian"); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + guts->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(guts->regs)) + return PTR_ERR(guts->regs); + + /* Register soc device */ + root = of_find_node_by_path("/"); + if (of_property_read_string(root, "model", &machine)) + of_property_read_string_index(root, "compatible", 0, &machine); + of_node_put(root); + if (machine) + soc_dev_attr.machine = devm_kstrdup(dev, machine, GFP_KERNEL); + + svr = fsl_guts_get_svr(); + soc_die = fsl_soc_die_match(svr, fsl_soc_die); + if (soc_die) { + soc_dev_attr.family = devm_kasprintf(dev, GFP_KERNEL, + "QorIQ %s", soc_die->die); + } else { + soc_dev_attr.family = devm_kasprintf(dev, GFP_KERNEL, "QorIQ"); + } + soc_dev_attr.soc_id = devm_kasprintf(dev, GFP_KERNEL, + "svr:0x%08x", svr); + soc_dev_attr.revision = devm_kasprintf(dev, GFP_KERNEL, "%d.%d", + (svr >> 4) & 0xf, svr & 0xf); + + soc_dev = soc_device_register(&soc_dev_attr); + if (IS_ERR(soc_dev)) + return PTR_ERR(soc_dev); + + pr_info("Machine: %s\n", soc_dev_attr.machine); + pr_info("SoC family: %s\n", soc_dev_attr.family); + pr_info("SoC ID: %s, Revision: %s\n", + soc_dev_attr.soc_id, soc_dev_attr.revision); + return 0; +} + +static int fsl_guts_remove(struct platform_device *dev) +{ + soc_device_unregister(soc_dev); + return 0; +} + +/* + * Table for matching compatible strings, for device tree + * guts node, for Freescale QorIQ SOCs. + */ +static const struct of_device_id fsl_guts_of_match[] = { + { .compatible = "fsl,qoriq-device-config-1.0", }, + { .compatible = "fsl,qoriq-device-config-2.0", }, + { .compatible = "fsl,p1010-guts", }, + { .compatible = "fsl,p1020-guts", }, + { .compatible = "fsl,p1021-guts", }, + { .compatible = "fsl,p1022-guts", }, + { .compatible = "fsl,p1023-guts", }, + { .compatible = "fsl,p2020-guts", }, + { .compatible = "fsl,bsc9131-guts", }, + { .compatible = "fsl,bsc9132-guts", }, + { .compatible = "fsl,mpc8536-guts", }, + { .compatible = "fsl,mpc8544-guts", }, + { .compatible = "fsl,mpc8548-guts", }, + { .compatible = "fsl,mpc8568-guts", }, + { .compatible = "fsl,mpc8569-guts", }, + { .compatible = "fsl,mpc8572-guts", }, + { .compatible = "fsl,ls1021a-dcfg", }, + { .compatible = "fsl,ls1043a-dcfg", }, + { .compatible = "fsl,ls2080a-dcfg", }, + {} +}; +MODULE_DEVICE_TABLE(of, fsl_guts_of_match); + +static struct platform_driver fsl_guts_driver = { + .driver = { + .name = "fsl-guts", + .of_match_table = fsl_guts_of_match, + }, + .probe = fsl_guts_probe, + .remove = fsl_guts_remove, +}; + +static int __init fsl_guts_init(void) +{ + return platform_driver_register(&fsl_guts_driver); +} +core_initcall(fsl_guts_init); + +static void __exit fsl_guts_exit(void) +{ + platform_driver_unregister(&fsl_guts_driver); +} +module_exit(fsl_guts_exit); |