aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/Kconfig2
-rw-r--r--drivers/ata/ahci.c67
-rw-r--r--drivers/ata/ahci.h27
-rw-r--r--drivers/ata/ahci_brcmstb.c61
-rw-r--r--drivers/ata/ahci_qoriq.c31
-rw-r--r--drivers/ata/libahci.c46
-rw-r--r--drivers/ata/libata-core.c20
-rw-r--r--drivers/ata/sata_rcar.c19
-rw-r--r--drivers/ata/sata_sx4.c2
-rw-r--r--drivers/base/platform-msi.c256
-rw-r--r--drivers/base/platform.c20
-rw-r--r--drivers/base/regmap/regcache-flat.c2
-rw-r--r--drivers/base/regmap/regcache-lzo.c6
-rw-r--r--drivers/base/regmap/regcache-rbtree.c18
-rw-r--r--drivers/base/regmap/regcache.c41
-rw-r--r--drivers/base/regmap/regmap-debugfs.c69
-rw-r--r--drivers/base/regmap/regmap-irq.c113
-rw-r--r--drivers/base/regmap/regmap-mmio.c66
-rw-r--r--drivers/base/regmap/regmap.c118
-rw-r--r--drivers/char/hw_random/via-rng.c5
-rw-r--r--drivers/clocksource/Kconfig132
-rw-r--r--drivers/clocksource/Makefile2
-rw-r--r--drivers/clocksource/acpi_pm.c27
-rw-r--r--drivers/clocksource/arm_global_timer.c21
-rw-r--r--drivers/clocksource/dw_apb_timer.c46
-rw-r--r--drivers/clocksource/dw_apb_timer_of.c16
-rw-r--r--drivers/clocksource/h8300_timer16.c222
-rw-r--r--drivers/clocksource/h8300_timer8.c264
-rw-r--r--drivers/clocksource/h8300_tpu.c159
-rw-r--r--drivers/clocksource/mtk_timer.c20
-rw-r--r--drivers/clocksource/rockchip_timer.c23
-rw-r--r--drivers/clocksource/tango_xtal.c18
-rw-r--r--drivers/clocksource/tegra20_timer.c3
-rw-r--r--drivers/clocksource/time-lpc32xx.c4
-rw-r--r--drivers/clocksource/time-pistachio.c2
-rw-r--r--drivers/clocksource/timer-sun5i.c16
-rw-r--r--drivers/clocksource/vt8500_timer.c1
-rw-r--r--drivers/crypto/padlock-aes.c2
-rw-r--r--drivers/crypto/padlock-sha.c2
-rw-r--r--drivers/edac/Makefile2
-rw-r--r--drivers/edac/edac_device.c41
-rw-r--r--drivers/edac/edac_device_sysfs.c11
-rw-r--r--drivers/edac/edac_mc.c29
-rw-r--r--drivers/edac/edac_mc_sysfs.c37
-rw-r--r--drivers/edac/edac_module.c52
-rw-r--r--drivers/edac/edac_module.h10
-rw-r--r--drivers/edac/edac_pci.c70
-rw-r--r--drivers/edac/edac_pci_sysfs.c16
-rw-r--r--drivers/edac/edac_stub.c41
-rw-r--r--drivers/edac/i5100_edac.c4
-rw-r--r--drivers/edac/mpc85xx_edac.c54
-rw-r--r--drivers/edac/mv64x60_edac.c39
-rw-r--r--drivers/edac/sb_edac.c1071
-rw-r--r--drivers/edac/wq.c42
-rw-r--r--drivers/hwmon/Kconfig10
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/fam15h_power.c7
-rw-r--r--drivers/hwmon/htu21.c174
-rw-r--r--drivers/hwmon/ibmaem.c12
-rw-r--r--drivers/hwmon/nct6683.c89
-rw-r--r--drivers/hwmon/nct6775.c11
-rw-r--r--drivers/hwmon/pmbus/Kconfig10
-rw-r--r--drivers/hwmon/pmbus/Makefile1
-rw-r--r--drivers/hwmon/pmbus/ltc3815.c215
-rw-r--r--drivers/iommu/intel_irq_remapping.c2
-rw-r--r--drivers/irqchip/Kconfig19
-rw-r--r--drivers/irqchip/Makefile3
-rw-r--r--drivers/irqchip/irq-bcm2836.c55
-rw-r--r--drivers/irqchip/irq-gic-realview.c43
-rw-r--r--drivers/irqchip/irq-gic-v2m.c165
-rw-r--r--drivers/irqchip/irq-gic.c64
-rw-r--r--drivers/irqchip/irq-mbigen.c297
-rw-r--r--drivers/irqchip/irq-omap-intc.c28
-rw-r--r--drivers/irqchip/irq-renesas-h8300h.c8
-rw-r--r--drivers/irqchip/irq-renesas-intc-irqpin.c96
-rw-r--r--drivers/irqchip/irq-sunxi-nmi.c13
-rw-r--r--drivers/irqchip/irq-ts4800.c163
-rw-r--r--drivers/irqchip/irq-zevio.c3
-rw-r--r--drivers/leds/Kconfig2
-rw-r--r--drivers/leds/led-class-flash.c8
-rw-r--r--drivers/leds/led-class.c11
-rw-r--r--drivers/leds/led-core.c120
-rw-r--r--drivers/leds/led-triggers.c28
-rw-r--r--drivers/leds/leds-88pm860x.c23
-rw-r--r--drivers/leds/leds-aat1290.c59
-rw-r--r--drivers/leds/leds-adp5520.c26
-rw-r--r--drivers/leds/leds-bcm6328.c63
-rw-r--r--drivers/leds/leds-bcm6358.c37
-rw-r--r--drivers/leds/leds-bd2802.c39
-rw-r--r--drivers/leds/leds-blinkm.c87
-rw-r--r--drivers/leds/leds-da903x.c46
-rw-r--r--drivers/leds/leds-da9052.c39
-rw-r--r--drivers/leds/leds-dac124s085.c38
-rw-r--r--drivers/leds/leds-gpio.c62
-rw-r--r--drivers/leds/leds-ipaq-micro.c6
-rw-r--r--drivers/leds/leds-ktd2692.c50
-rw-r--r--drivers/leds/leds-lm3533.c30
-rw-r--r--drivers/leds/leds-lm355x.c85
-rw-r--r--drivers/leds/leds-lm3642.c73
-rw-r--r--drivers/leds/leds-lp3944.c32
-rw-r--r--drivers/leds/leds-lp5521.c11
-rw-r--r--drivers/leds/leds-lp5523.c10
-rw-r--r--drivers/leds/leds-lp5562.c11
-rw-r--r--drivers/leds/leds-lp55xx-common.c12
-rw-r--r--drivers/leds/leds-lp55xx-common.h6
-rw-r--r--drivers/leds/leds-lp8501.c11
-rw-r--r--drivers/leds/leds-lp8788.c48
-rw-r--r--drivers/leds/leds-lp8860.c27
-rw-r--r--drivers/leds/leds-lt3593.c33
-rw-r--r--drivers/leds/leds-max77693.c58
-rw-r--r--drivers/leds/leds-max8997.c1
-rw-r--r--drivers/leds/leds-mc13783.c35
-rw-r--r--drivers/leds/leds-ns2.c31
-rw-r--r--drivers/leds/leds-pca9532.c28
-rw-r--r--drivers/leds/leds-pca955x.c39
-rw-r--r--drivers/leds/leds-pca963x.c80
-rw-r--r--drivers/leds/leds-powernv.c18
-rw-r--r--drivers/leds/leds-pwm.c39
-rw-r--r--drivers/leds/leds-regulator.c46
-rw-r--r--drivers/leds/leds-sunfire.c23
-rw-r--r--drivers/leds/leds-syscon.c18
-rw-r--r--drivers/leds/leds-tlc591xx.c31
-rw-r--r--drivers/leds/leds-wm831x-status.c25
-rw-r--r--drivers/leds/leds-wm8350.c64
-rw-r--r--drivers/leds/leds.h27
-rw-r--r--drivers/leds/trigger/ledtrig-backlight.c8
-rw-r--r--drivers/leds/trigger/ledtrig-cpu.c26
-rw-r--r--drivers/leds/trigger/ledtrig-default-on.c2
-rw-r--r--drivers/leds/trigger/ledtrig-gpio.c6
-rw-r--r--drivers/leds/trigger/ledtrig-heartbeat.c4
-rw-r--r--drivers/leds/trigger/ledtrig-ide-disk.c14
-rw-r--r--drivers/leds/trigger/ledtrig-oneshot.c6
-rw-r--r--drivers/leds/trigger/ledtrig-transient.c10
-rw-r--r--drivers/media/v4l2-core/v4l2-flash-led-class.c8
-rw-r--r--drivers/mmc/card/block.c11
-rw-r--r--drivers/mmc/core/bus.c2
-rw-r--r--drivers/mmc/core/core.c85
-rw-r--r--drivers/mmc/core/core.h8
-rw-r--r--drivers/mmc/core/host.c11
-rw-r--r--drivers/mmc/core/mmc.c23
-rw-r--r--drivers/mmc/core/mmc_ops.c9
-rw-r--r--drivers/mmc/core/pwrseq.h2
-rw-r--r--drivers/mmc/core/pwrseq_emmc.c2
-rw-r--r--drivers/mmc/core/pwrseq_simple.c2
-rw-r--r--drivers/mmc/core/sd.c17
-rw-r--r--drivers/mmc/core/sdio.c2
-rw-r--r--drivers/mmc/core/sdio_bus.c1
-rw-r--r--drivers/mmc/host/Kconfig1
-rw-r--r--drivers/mmc/host/atmel-mci-regs.h171
-rw-r--r--drivers/mmc/host/atmel-mci.c165
-rw-r--r--drivers/mmc/host/cb710-mmc.h3
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.c2
-rw-r--r--drivers/mmc/host/dw_mmc-rockchip.c8
-rw-r--r--drivers/mmc/host/dw_mmc.c21
-rw-r--r--drivers/mmc/host/mtk-sd.c9
-rw-r--r--drivers/mmc/host/mvsdio.c58
-rw-r--r--drivers/mmc/host/of_mmc_spi.c4
-rw-r--r--drivers/mmc/host/omap_hsmmc.c6
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c7
-rw-r--r--drivers/mmc/host/sdhci-of-at91.c75
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c10
-rw-r--r--drivers/mmc/host/sdhci-pci-core.c6
-rw-r--r--drivers/mmc/host/sdhci-pltfm.c3
-rw-r--r--drivers/mmc/host/sdhci-tegra.c178
-rw-r--r--drivers/mmc/host/sdhci.c124
-rw-r--r--drivers/mmc/host/sdhci.h21
-rw-r--r--drivers/mmc/host/sh_mmcif.c84
-rw-r--r--drivers/mmc/host/usdhi6rol0.c3
-rw-r--r--drivers/pci/msi.c4
-rw-r--r--drivers/pci/pci-acpi.c42
-rw-r--r--drivers/pci/probe.c2
-rw-r--r--drivers/pinctrl/Kconfig3
-rw-r--r--drivers/pinctrl/Makefile7
-rw-r--r--drivers/pinctrl/bcm/Kconfig48
-rw-r--r--drivers/pinctrl/bcm/Makefile3
-rw-r--r--drivers/pinctrl/bcm/pinctrl-bcm2835.c2
-rw-r--r--drivers/pinctrl/bcm/pinctrl-iproc-gpio.c (renamed from drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c)358
-rw-r--r--drivers/pinctrl/bcm/pinctrl-nsp-gpio.c749
-rw-r--r--drivers/pinctrl/berlin/Makefile2
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt8127.c2
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt8135.c2
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt8173.c2
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mtk-common.c28
-rw-r--r--drivers/pinctrl/mvebu/Makefile2
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-mvebu.c29
-rw-r--r--drivers/pinctrl/pinconf-generic.c1
-rw-r--r--drivers/pinctrl/pinctrl-adi2.c24
-rw-r--r--drivers/pinctrl/pinctrl-at91-pio4.c17
-rw-r--r--drivers/pinctrl/pinctrl-at91.c14
-rw-r--r--drivers/pinctrl/pinctrl-lantiq.h8
-rw-r--r--drivers/pinctrl/pinctrl-rockchip.c58
-rw-r--r--drivers/pinctrl/pinctrl-single.c5
-rw-r--r--drivers/pinctrl/pinctrl-tegra-xusb.c4
-rw-r--r--drivers/pinctrl/pinctrl-tegra.c1
-rw-r--r--drivers/pinctrl/pinctrl-xway.c1187
-rw-r--r--drivers/pinctrl/pxa/Kconfig17
-rw-r--r--drivers/pinctrl/pxa/Makefile2
-rw-r--r--drivers/pinctrl/pxa/pinctrl-pxa27x.c566
-rw-r--r--drivers/pinctrl/pxa/pinctrl-pxa2xx.c436
-rw-r--r--drivers/pinctrl/pxa/pinctrl-pxa2xx.h92
-rw-r--r--drivers/pinctrl/qcom/Kconfig8
-rw-r--r--drivers/pinctrl/qcom/Makefile1
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm8996.c1942
-rw-r--r--drivers/pinctrl/qcom/pinctrl-qdf2xxx.c14
-rw-r--r--drivers/pinctrl/qcom/pinctrl-spmi-gpio.c15
-rw-r--r--drivers/pinctrl/qcom/pinctrl-spmi-mpp.c14
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c21
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c21
-rw-r--r--drivers/pinctrl/samsung/pinctrl-exynos.c103
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.c2
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.h1
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-emev2.c136
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7740.c2
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7778.c22
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7779.c62
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7790.c58
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7791.c167
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7794.c86
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-r8a7795.c1505
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh73a0.c548
-rw-r--r--drivers/pinctrl/sh-pfc/pfc-sh7734.c29
-rw-r--r--drivers/pinctrl/sh-pfc/pinctrl.c4
-rw-r--r--drivers/pinctrl/sh-pfc/sh_pfc.h74
-rw-r--r--drivers/pinctrl/sirf/pinctrl-atlas7.c134
-rw-r--r--drivers/pinctrl/sirf/pinctrl-sirf.c8
-rw-r--r--drivers/pinctrl/spear/Makefile2
-rw-r--r--drivers/pinctrl/sunxi/Kconfig9
-rw-r--r--drivers/pinctrl/sunxi/Makefile2
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c515
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun9i-a80-r.c181
-rw-r--r--drivers/pinctrl/uniphier/Kconfig23
-rw-r--r--drivers/staging/lustre/lustre/llite/symlink.c24
-rw-r--r--drivers/staging/lustre/lustre/llite/xattr.c4
-rw-r--r--drivers/tty/sysrq.c6
234 files changed, 13458 insertions, 3893 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 6aaa3f81755b..861643ea91b5 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -100,7 +100,7 @@ config SATA_AHCI_PLATFORM
config AHCI_BRCMSTB
tristate "Broadcom STB AHCI SATA support"
- depends on ARCH_BRCMSTB
+ depends on ARCH_BRCMSTB || BMIPS_GENERIC
help
This option enables support for the AHCI SATA3 controller found on
STB SoC's.
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index cdfbcc54821f..594fcabd22cd 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1306,15 +1306,13 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host)
#endif
/*
- * ahci_init_msix() only implements single MSI-X support, not multiple
- * MSI-X per-port interrupts. This is needed for host controllers that only
- * have MSI-X support implemented, but no MSI or intx.
+ * ahci_init_msix() - optionally enable per-port MSI-X otherwise defer
+ * to single msi.
*/
static int ahci_init_msix(struct pci_dev *pdev, unsigned int n_ports,
- struct ahci_host_priv *hpriv)
+ struct ahci_host_priv *hpriv, unsigned long flags)
{
- int rc, nvec;
- struct msix_entry entry = {};
+ int nvec, i, rc;
/* Do not init MSI-X if MSI is disabled for the device */
if (hpriv->flags & AHCI_HFLAG_NO_MSI)
@@ -1324,22 +1322,39 @@ static int ahci_init_msix(struct pci_dev *pdev, unsigned int n_ports,
if (nvec < 0)
return nvec;
- if (!nvec) {
+ /*
+ * Proper MSI-X implementations will have a vector per-port.
+ * Barring that, we prefer single-MSI over single-MSIX. If this
+ * check fails (not enough MSI-X vectors for all ports) we will
+ * be called again with the flag clear iff ahci_init_msi()
+ * fails.
+ */
+ if (flags & AHCI_HFLAG_MULTI_MSIX) {
+ if (nvec < n_ports)
+ return -ENODEV;
+ nvec = n_ports;
+ } else if (nvec) {
+ nvec = 1;
+ } else {
+ /*
+ * Emit dev_err() since this was the non-legacy irq
+ * method of last resort.
+ */
rc = -ENODEV;
goto fail;
}
- /*
- * There can be more than one vector (e.g. for error detection or
- * hdd hotplug). Only the first vector (entry.entry = 0) is used.
- */
- rc = pci_enable_msix_exact(pdev, &entry, 1);
+ for (i = 0; i < nvec; i++)
+ hpriv->msix[i].entry = i;
+ rc = pci_enable_msix_exact(pdev, hpriv->msix, nvec);
if (rc < 0)
goto fail;
- hpriv->irq = entry.vector;
+ if (nvec > 1)
+ hpriv->flags |= AHCI_HFLAG_MULTI_MSIX;
+ hpriv->irq = hpriv->msix[0].vector; /* for single msi-x */
- return 1;
+ return nvec;
fail:
dev_err(&pdev->dev,
"failed to enable MSI-X with error %d, # of vectors: %d\n",
@@ -1403,20 +1418,25 @@ static int ahci_init_interrupts(struct pci_dev *pdev, unsigned int n_ports,
{
int nvec;
+ /*
+ * Try to enable per-port MSI-X. If the host is not capable
+ * fall back to single MSI before finally attempting single
+ * MSI-X.
+ */
+ nvec = ahci_init_msix(pdev, n_ports, hpriv, AHCI_HFLAG_MULTI_MSIX);
+ if (nvec >= 0)
+ return nvec;
+
nvec = ahci_init_msi(pdev, n_ports, hpriv);
if (nvec >= 0)
return nvec;
- /*
- * Currently, MSI-X support only implements single IRQ mode and
- * exists for controllers which can't do other types of IRQ. Only
- * set it up if MSI fails.
- */
- nvec = ahci_init_msix(pdev, n_ports, hpriv);
+ /* try single-msix */
+ nvec = ahci_init_msix(pdev, n_ports, hpriv, 0);
if (nvec >= 0)
return nvec;
- /* lagacy intx interrupts */
+ /* legacy intx interrupts */
pci_intx(pdev, 1);
hpriv->irq = pdev->irq;
@@ -1578,7 +1598,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!host)
return -ENOMEM;
host->private_data = hpriv;
-
+ hpriv->msix = devm_kzalloc(&pdev->dev,
+ sizeof(struct msix_entry) * n_ports, GFP_KERNEL);
+ if (!hpriv->msix)
+ return -ENOMEM;
ahci_init_interrupts(pdev, n_ports, hpriv);
if (!(hpriv->cap & HOST_CAP_SSS) || ahci_ignore_sss)
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 45586c1dbbdc..a4faa438889c 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -35,6 +35,7 @@
#ifndef _AHCI_H
#define _AHCI_H
+#include <linux/pci.h>
#include <linux/clk.h>
#include <linux/libata.h>
#include <linux/phy/phy.h>
@@ -237,11 +238,18 @@ enum {
AHCI_HFLAG_DELAY_ENGINE = (1 << 15), /* do not start engine on
port start (wait until
error-handling stage) */
- AHCI_HFLAG_MULTI_MSI = (1 << 16), /* multiple PCI MSIs */
AHCI_HFLAG_NO_DEVSLP = (1 << 17), /* no device sleep */
AHCI_HFLAG_NO_FBS = (1 << 18), /* no FBS */
AHCI_HFLAG_EDGE_IRQ = (1 << 19), /* HOST_IRQ_STAT behaves as
Edge Triggered */
+#ifdef CONFIG_PCI_MSI
+ AHCI_HFLAG_MULTI_MSI = (1 << 20), /* multiple PCI MSIs */
+ AHCI_HFLAG_MULTI_MSIX = (1 << 21), /* per-port MSI-X */
+#else
+ /* compile out MSI infrastructure */
+ AHCI_HFLAG_MULTI_MSI = 0,
+ AHCI_HFLAG_MULTI_MSIX = 0,
+#endif
/* ap->flags bits */
@@ -308,7 +316,6 @@ struct ahci_port_priv {
unsigned int ncq_saw_d2h:1;
unsigned int ncq_saw_dmas:1;
unsigned int ncq_saw_sdb:1;
- atomic_t intr_status; /* interrupts to handle */
spinlock_t lock; /* protects parent ata_port */
u32 intr_mask; /* interrupts to enable */
bool fbs_supported; /* set iff FBS is supported */
@@ -343,6 +350,7 @@ struct ahci_host_priv {
* the PHY position in this array.
*/
struct phy **phys;
+ struct msix_entry *msix; /* Optional MSI-X support */
unsigned nports; /* Number of ports */
void *plat_data; /* Other platform data */
unsigned int irq; /* interrupt line */
@@ -354,6 +362,21 @@ struct ahci_host_priv {
void (*start_engine)(struct ata_port *ap);
};
+#ifdef CONFIG_PCI_MSI
+static inline int ahci_irq_vector(struct ahci_host_priv *hpriv, int port)
+{
+ if (hpriv->flags & AHCI_HFLAG_MULTI_MSIX)
+ return hpriv->msix[port].vector;
+ else
+ return hpriv->irq + port;
+}
+#else
+static inline int ahci_irq_vector(struct ahci_host_priv *hpriv, int port)
+{
+ return hpriv->irq;
+}
+#endif
+
extern int ahci_ignore_sss;
extern struct device_attribute *ahci_shost_attrs[];
diff --git a/drivers/ata/ahci_brcmstb.c b/drivers/ata/ahci_brcmstb.c
index 14b7305d2ba0..b36cae2fd04b 100644
--- a/drivers/ata/ahci_brcmstb.c
+++ b/drivers/ata/ahci_brcmstb.c
@@ -52,8 +52,10 @@
#define SATA_TOP_CTRL_2_PHY_GLOBAL_RESET BIT(14)
#define SATA_TOP_CTRL_PHY_OFFS 0x8
#define SATA_TOP_MAX_PHYS 2
-#define SATA_TOP_CTRL_SATA_TP_OUT 0x1c
-#define SATA_TOP_CTRL_CLIENT_INIT_CTRL 0x20
+
+#define SATA_FIRST_PORT_CTRL 0x700
+#define SATA_NEXT_PORT_CTRL_OFFSET 0x80
+#define SATA_PORT_PCTRL6(reg_base) (reg_base + 0x18)
/* On big-endian MIPS, buses are reversed to big endian, so switch them back */
#if defined(CONFIG_MIPS) && defined(__BIG_ENDIAN)
@@ -69,14 +71,21 @@
(DATA_ENDIAN << DMADESC_ENDIAN_SHIFT) | \
(MMIO_ENDIAN << MMIO_ENDIAN_SHIFT))
+enum brcm_ahci_quirks {
+ BRCM_AHCI_QUIRK_NO_NCQ = BIT(0),
+ BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE = BIT(1),
+};
+
struct brcm_ahci_priv {
struct device *dev;
void __iomem *top_ctrl;
u32 port_mask;
+ u32 quirks;
};
static const struct ata_port_info ahci_brcm_port_info = {
- .flags = AHCI_FLAG_COMMON,
+ .flags = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
+ .link_flags = ATA_LFLAG_NO_DB_DELAY,
.pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA6,
.port_ops = &ahci_platform_ops,
@@ -107,6 +116,34 @@ static inline void brcm_sata_writereg(u32 val, void __iomem *addr)
writel_relaxed(val, addr);
}
+static void brcm_sata_alpm_init(struct ahci_host_priv *hpriv)
+{
+ struct brcm_ahci_priv *priv = hpriv->plat_data;
+ u32 bus_ctrl, port_ctrl, host_caps;
+ int i;
+
+ /* Enable support for ALPM */
+ bus_ctrl = brcm_sata_readreg(priv->top_ctrl +
+ SATA_TOP_CTRL_BUS_CTRL);
+ brcm_sata_writereg(bus_ctrl | OVERRIDE_HWINIT,
+ priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
+ host_caps = readl(hpriv->mmio + HOST_CAP);
+ writel(host_caps | HOST_CAP_ALPM, hpriv->mmio);
+ brcm_sata_writereg(bus_ctrl, priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
+
+ /*
+ * Adjust timeout to allow PLL sufficient time to lock while waking
+ * up from slumber mode.
+ */
+ for (i = 0, port_ctrl = SATA_FIRST_PORT_CTRL;
+ i < SATA_TOP_MAX_PHYS;
+ i++, port_ctrl += SATA_NEXT_PORT_CTRL_OFFSET) {
+ if (priv->port_mask & BIT(i))
+ writel(0xff1003fc,
+ hpriv->mmio + SATA_PORT_PCTRL6(port_ctrl));
+ }
+}
+
static void brcm_sata_phy_enable(struct brcm_ahci_priv *priv, int port)
{
void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL +
@@ -114,6 +151,9 @@ static void brcm_sata_phy_enable(struct brcm_ahci_priv *priv, int port)
void __iomem *p;
u32 reg;
+ if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE)
+ return;
+
/* clear PHY_DEFAULT_POWER_STATE */
p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1;
reg = brcm_sata_readreg(p);
@@ -143,6 +183,9 @@ static void brcm_sata_phy_disable(struct brcm_ahci_priv *priv, int port)
void __iomem *p;
u32 reg;
+ if (priv->quirks & BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE)
+ return;
+
/* power-off the PHY digital logic */
p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2;
reg = brcm_sata_readreg(p);
@@ -230,6 +273,7 @@ static int brcm_ahci_resume(struct device *dev)
brcm_sata_init(priv);
brcm_sata_phys_enable(priv);
+ brcm_sata_alpm_init(hpriv);
return ahci_platform_resume(dev);
}
#endif
@@ -256,6 +300,11 @@ static int brcm_ahci_probe(struct platform_device *pdev)
if (IS_ERR(priv->top_ctrl))
return PTR_ERR(priv->top_ctrl);
+ if (of_device_is_compatible(dev->of_node, "brcm,bcm7425-ahci")) {
+ priv->quirks |= BRCM_AHCI_QUIRK_NO_NCQ;
+ priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE;
+ }
+
brcm_sata_init(priv);
priv->port_mask = brcm_ahci_get_portmask(pdev, priv);
@@ -269,10 +318,15 @@ static int brcm_ahci_probe(struct platform_device *pdev)
return PTR_ERR(hpriv);
hpriv->plat_data = priv;
+ brcm_sata_alpm_init(hpriv);
+
ret = ahci_platform_enable_resources(hpriv);
if (ret)
return ret;
+ if (priv->quirks & BRCM_AHCI_QUIRK_NO_NCQ)
+ hpriv->flags |= AHCI_HFLAG_NO_NCQ;
+
ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info,
&ahci_platform_sht);
if (ret)
@@ -300,6 +354,7 @@ static int brcm_ahci_remove(struct platform_device *pdev)
}
static const struct of_device_id ahci_of_match[] = {
+ {.compatible = "brcm,bcm7425-ahci"},
{.compatible = "brcm,bcm7445-ahci"},
{},
};
diff --git a/drivers/ata/ahci_qoriq.c b/drivers/ata/ahci_qoriq.c
index d0f9de96e4ea..7bdee9bd8786 100644
--- a/drivers/ata/ahci_qoriq.c
+++ b/drivers/ata/ahci_qoriq.c
@@ -34,14 +34,20 @@
/* port register default value */
#define AHCI_PORT_PHY_1_CFG 0xa003fffe
-#define AHCI_PORT_PHY_2_CFG 0x28183411
-#define AHCI_PORT_PHY_3_CFG 0x0e081004
-#define AHCI_PORT_PHY_4_CFG 0x00480811
-#define AHCI_PORT_PHY_5_CFG 0x192c96a4
-#define AHCI_PORT_TRANS_CFG 0x08000025
+#define AHCI_PORT_TRANS_CFG 0x08000029
+
+/* for ls1021a */
+#define LS1021A_PORT_PHY2 0x28183414
+#define LS1021A_PORT_PHY3 0x0e080e06
+#define LS1021A_PORT_PHY4 0x064a080b
+#define LS1021A_PORT_PHY5 0x2aa86470
#define SATA_ECC_DISABLE 0x00020000
+/* for ls1043a */
+#define LS1043A_PORT_PHY2 0x28184d1f
+#define LS1043A_PORT_PHY3 0x0e081509
+
enum ahci_qoriq_type {
AHCI_LS1021A,
AHCI_LS1043A,
@@ -151,16 +157,23 @@ static int ahci_qoriq_phy_init(struct ahci_host_priv *hpriv)
case AHCI_LS1021A:
writel(SATA_ECC_DISABLE, qpriv->ecc_addr);
writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
- writel(AHCI_PORT_PHY_2_CFG, reg_base + PORT_PHY2);
- writel(AHCI_PORT_PHY_3_CFG, reg_base + PORT_PHY3);
- writel(AHCI_PORT_PHY_4_CFG, reg_base + PORT_PHY4);
- writel(AHCI_PORT_PHY_5_CFG, reg_base + PORT_PHY5);
+ writel(LS1021A_PORT_PHY2, reg_base + PORT_PHY2);
+ writel(LS1021A_PORT_PHY3, reg_base + PORT_PHY3);
+ writel(LS1021A_PORT_PHY4, reg_base + PORT_PHY4);
+ writel(LS1021A_PORT_PHY5, reg_base + PORT_PHY5);
writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
break;
case AHCI_LS1043A:
+ writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
+ writel(LS1043A_PORT_PHY2, reg_base + PORT_PHY2);
+ writel(LS1043A_PORT_PHY3, reg_base + PORT_PHY3);
+ writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
+ break;
+
case AHCI_LS2080A:
writel(AHCI_PORT_PHY_1_CFG, reg_base + PORT_PHY1);
+ writel(AHCI_PORT_TRANS_CFG, reg_base + PORT_TRANS);
break;
}
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 4665512dae44..d61740e78d6d 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -43,6 +43,7 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
#include <linux/libata.h>
+#include <linux/pci.h>
#include "ahci.h"
#include "libata.h"
@@ -1804,41 +1805,24 @@ static void ahci_port_intr(struct ata_port *ap)
ahci_handle_port_interrupt(ap, port_mmio, status);
}
-static irqreturn_t ahci_port_thread_fn(int irq, void *dev_instance)
+static irqreturn_t ahci_multi_irqs_intr_hard(int irq, void *dev_instance)
{
struct ata_port *ap = dev_instance;
- struct ahci_port_priv *pp = ap->private_data;
void __iomem *port_mmio = ahci_port_base(ap);
u32 status;
- status = atomic_xchg(&pp->intr_status, 0);
- if (!status)
- return IRQ_NONE;
-
- spin_lock_bh(ap->lock);
- ahci_handle_port_interrupt(ap, port_mmio, status);
- spin_unlock_bh(ap->lock);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t ahci_multi_irqs_intr(int irq, void *dev_instance)
-{
- struct ata_port *ap = dev_instance;
- void __iomem *port_mmio = ahci_port_base(ap);
- struct ahci_port_priv *pp = ap->private_data;
- u32 status;
-
VPRINTK("ENTER\n");
status = readl(port_mmio + PORT_IRQ_STAT);
writel(status, port_mmio + PORT_IRQ_STAT);
- atomic_or(status, &pp->intr_status);
+ spin_lock(ap->lock);
+ ahci_handle_port_interrupt(ap, port_mmio, status);
+ spin_unlock(ap->lock);
VPRINTK("EXIT\n");
- return IRQ_WAKE_THREAD;
+ return IRQ_HANDLED;
}
static u32 ahci_handle_port_intr(struct ata_host *host, u32 irq_masked)
@@ -2479,9 +2463,10 @@ void ahci_set_em_messages(struct ahci_host_priv *hpriv,
}
EXPORT_SYMBOL_GPL(ahci_set_em_messages);
-static int ahci_host_activate_multi_irqs(struct ata_host *host, int irq,
+static int ahci_host_activate_multi_irqs(struct ata_host *host,
struct scsi_host_template *sht)
{
+ struct ahci_host_priv *hpriv = host->private_data;
int i, rc;
rc = ata_host_start(host);
@@ -2493,6 +2478,7 @@ static int ahci_host_activate_multi_irqs(struct ata_host *host, int irq,
*/
for (i = 0; i < host->n_ports; i++) {
struct ahci_port_priv *pp = host->ports[i]->private_data;
+ int irq = ahci_irq_vector(hpriv, i);
/* Do not receive interrupts sent by dummy ports */
if (!pp) {
@@ -2500,14 +2486,14 @@ static int ahci_host_activate_multi_irqs(struct ata_host *host, int irq,
continue;
}
- rc = devm_request_threaded_irq(host->dev, irq + i,
- ahci_multi_irqs_intr,
- ahci_port_thread_fn, 0,
- pp->irq_desc, host->ports[i]);
+ rc = devm_request_irq(host->dev, irq, ahci_multi_irqs_intr_hard,
+ 0, pp->irq_desc, host->ports[i]);
+
if (rc)
return rc;
- ata_port_desc(host->ports[i], "irq %d", irq + i);
+ ata_port_desc(host->ports[i], "irq %d", irq);
}
+
return ata_host_register(host, sht);
}
@@ -2528,8 +2514,8 @@ int ahci_host_activate(struct ata_host *host, struct scsi_host_template *sht)
int irq = hpriv->irq;
int rc;
- if (hpriv->flags & AHCI_HFLAG_MULTI_MSI)
- rc = ahci_host_activate_multi_irqs(host, irq, sht);
+ if (hpriv->flags & (AHCI_HFLAG_MULTI_MSI | AHCI_HFLAG_MULTI_MSIX))
+ rc = ahci_host_activate_multi_irqs(host, sht);
else if (hpriv->flags & AHCI_HFLAG_EDGE_IRQ)
rc = ata_host_activate(host, irq, ahci_single_edge_irq_intr,
IRQF_SHARED, sht);
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index b79cb10e289e..cbb74719d2c1 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -50,6 +50,7 @@
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/timer.h>
+#include <linux/time.h>
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/suspend.h>
@@ -3597,7 +3598,8 @@ int sata_link_resume(struct ata_link *link, const unsigned long *params,
* immediately after resuming. Delay 200ms before
* debouncing.
*/
- ata_msleep(link->ap, 200);
+ if (!(link->flags & ATA_LFLAG_NO_DB_DELAY))
+ ata_msleep(link->ap, 200);
/* is SControl restored correctly? */
if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol)))
@@ -6223,6 +6225,7 @@ int ata_host_activate(struct ata_host *host, int irq,
struct scsi_host_template *sht)
{
int i, rc;
+ char *irq_desc;
rc = ata_host_start(host);
if (rc)
@@ -6234,8 +6237,14 @@ int ata_host_activate(struct ata_host *host, int irq,
return ata_host_register(host, sht);
}
+ irq_desc = devm_kasprintf(host->dev, GFP_KERNEL, "%s[%s]",
+ dev_driver_string(host->dev),
+ dev_name(host->dev));
+ if (!irq_desc)
+ return -ENOMEM;
+
rc = devm_request_irq(host->dev, irq, irq_handler, irq_flags,
- dev_name(host->dev), host);
+ irq_desc, host);
if (rc)
return rc;
@@ -6697,7 +6706,12 @@ void ata_msleep(struct ata_port *ap, unsigned int msecs)
if (owns_eh)
ata_eh_release(ap);
- msleep(msecs);
+ if (msecs < 20) {
+ unsigned long usecs = msecs * USEC_PER_MSEC;
+ usleep_range(usecs, usecs + 50);
+ } else {
+ msleep(msecs);
+ }
if (owns_eh)
ata_eh_acquire(ap);
diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c
index 8804127b108c..f72d601e300a 100644
--- a/drivers/ata/sata_rcar.c
+++ b/drivers/ata/sata_rcar.c
@@ -854,17 +854,14 @@ static struct of_device_id sata_rcar_match[] = {
.compatible = "renesas,sata-r8a7793",
.data = (void *)RCAR_GEN2_SATA
},
+ {
+ .compatible = "renesas,sata-r8a7795",
+ .data = (void *)RCAR_GEN2_SATA
+ },
{ },
};
MODULE_DEVICE_TABLE(of, sata_rcar_match);
-static const struct platform_device_id sata_rcar_id_table[] = {
- { "sata_rcar", RCAR_GEN1_SATA }, /* Deprecated by "sata-r8a7779" */
- { "sata-r8a7779", RCAR_GEN1_SATA },
- { },
-};
-MODULE_DEVICE_TABLE(platform, sata_rcar_id_table);
-
static int sata_rcar_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id;
@@ -884,11 +881,10 @@ static int sata_rcar_probe(struct platform_device *pdev)
return -ENOMEM;
of_id = of_match_device(sata_rcar_match, &pdev->dev);
- if (of_id)
- priv->type = (enum sata_rcar_type)of_id->data;
- else
- priv->type = platform_get_device_id(pdev)->driver_data;
+ if (!of_id)
+ return -ENODEV;
+ priv->type = (enum sata_rcar_type)of_id->data;
priv->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(priv->clk)) {
dev_err(&pdev->dev, "failed to get access to sata clock\n");
@@ -1018,7 +1014,6 @@ static const struct dev_pm_ops sata_rcar_pm_ops = {
static struct platform_driver sata_rcar_driver = {
.probe = sata_rcar_probe,
.remove = sata_rcar_remove,
- .id_table = sata_rcar_id_table,
.driver = {
.name = DRV_NAME,
.of_match_table = sata_rcar_match,
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index fab504fd9cfd..48301cb3a316 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -1396,6 +1396,8 @@ static unsigned int pdc20621_dimm_init(struct ata_host *host)
addr = 0;
length = size * 1024 * 1024;
buf = kzalloc(ECC_ERASE_BUF_SZ, GFP_KERNEL);
+ if (!buf)
+ return 1;
while (addr < length) {
pdc20621_put_to_dimm(host, buf, addr,
ECC_ERASE_BUF_SZ);
diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
index 5df4575b5ba7..47c43386786b 100644
--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -24,13 +24,17 @@
#include <linux/msi.h>
#include <linux/slab.h>
-#define DEV_ID_SHIFT 24
+#define DEV_ID_SHIFT 21
+#define MAX_DEV_MSIS (1 << (32 - DEV_ID_SHIFT))
/*
* Internal data structure containing a (made up, but unique) devid
* and the callback to write the MSI message.
*/
struct platform_msi_priv_data {
+ struct device *dev;
+ void *host_data;
+ msi_alloc_info_t arg;
irq_write_msi_msg_t write_msg;
int devid;
};
@@ -110,39 +114,49 @@ static void platform_msi_update_chip_ops(struct msi_domain_info *info)
chip->irq_write_msi_msg = platform_msi_write_msg;
}
-static void platform_msi_free_descs(struct device *dev)
+static void platform_msi_free_descs(struct device *dev, int base, int nvec)
{
struct msi_desc *desc, *tmp;
list_for_each_entry_safe(desc, tmp, dev_to_msi_list(dev), list) {
- list_del(&desc->list);
- free_msi_entry(desc);
+ if (desc->platform.msi_index >= base &&
+ desc->platform.msi_index < (base + nvec)) {
+ list_del(&desc->list);
+ free_msi_entry(desc);
+ }
}
}
-static int platform_msi_alloc_descs(struct device *dev, int nvec,
- struct platform_msi_priv_data *data)
+static int platform_msi_alloc_descs_with_irq(struct device *dev, int virq,
+ int nvec,
+ struct platform_msi_priv_data *data)
{
- int i;
+ struct msi_desc *desc;
+ int i, base = 0;
- for (i = 0; i < nvec; i++) {
- struct msi_desc *desc;
+ if (!list_empty(dev_to_msi_list(dev))) {
+ desc = list_last_entry(dev_to_msi_list(dev),
+ struct msi_desc, list);
+ base = desc->platform.msi_index + 1;
+ }
+ for (i = 0; i < nvec; i++) {
desc = alloc_msi_entry(dev);
if (!desc)
break;
desc->platform.msi_priv_data = data;
- desc->platform.msi_index = i;
+ desc->platform.msi_index = base + i;
desc->nvec_used = 1;
+ desc->irq = virq ? virq + i : 0;
list_add_tail(&desc->list, dev_to_msi_list(dev));
}
if (i != nvec) {
/* Clean up the mess */
- platform_msi_free_descs(dev);
+ platform_msi_free_descs(dev, base, nvec);
return -ENOMEM;
}
@@ -150,6 +164,13 @@ static int platform_msi_alloc_descs(struct device *dev, int nvec,
return 0;
}
+static int platform_msi_alloc_descs(struct device *dev, int nvec,
+ struct platform_msi_priv_data *data)
+
+{
+ return platform_msi_alloc_descs_with_irq(dev, 0, nvec, data);
+}
+
/**
* platform_msi_create_irq_domain - Create a platform MSI interrupt domain
* @fwnode: Optional fwnode of the interrupt controller
@@ -180,56 +201,75 @@ struct irq_domain *platform_msi_create_irq_domain(struct fwnode_handle *fwnode,
return domain;
}
-/**
- * platform_msi_domain_alloc_irqs - Allocate MSI interrupts for @dev
- * @dev: The device for which to allocate interrupts
- * @nvec: The number of interrupts to allocate
- * @write_msi_msg: Callback to write an interrupt message for @dev
- *
- * Returns:
- * Zero for success, or an error code in case of failure
- */
-int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
- irq_write_msi_msg_t write_msi_msg)
+static struct platform_msi_priv_data *
+platform_msi_alloc_priv_data(struct device *dev, unsigned int nvec,
+ irq_write_msi_msg_t write_msi_msg)
{
- struct platform_msi_priv_data *priv_data;
- int err;
-
+ struct platform_msi_priv_data *datap;
/*
* Limit the number of interrupts to 256 per device. Should we
* need to bump this up, DEV_ID_SHIFT should be adjusted
* accordingly (which would impact the max number of MSI
* capable devices).
*/
- if (!dev->msi_domain || !write_msi_msg || !nvec ||
- nvec > (1 << (32 - DEV_ID_SHIFT)))
- return -EINVAL;
+ if (!dev->msi_domain || !write_msi_msg || !nvec || nvec > MAX_DEV_MSIS)
+ return ERR_PTR(-EINVAL);
if (dev->msi_domain->bus_token != DOMAIN_BUS_PLATFORM_MSI) {
dev_err(dev, "Incompatible msi_domain, giving up\n");
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
/* Already had a helping of MSI? Greed... */
if (!list_empty(dev_to_msi_list(dev)))
- return -EBUSY;
+ return ERR_PTR(-EBUSY);
+
+ datap = kzalloc(sizeof(*datap), GFP_KERNEL);
+ if (!datap)
+ return ERR_PTR(-ENOMEM);
+
+ datap->devid = ida_simple_get(&platform_msi_devid_ida,
+ 0, 1 << DEV_ID_SHIFT, GFP_KERNEL);
+ if (datap->devid < 0) {
+ int err = datap->devid;
+ kfree(datap);
+ return ERR_PTR(err);
+ }
- priv_data = kzalloc(sizeof(*priv_data), GFP_KERNEL);
- if (!priv_data)
- return -ENOMEM;
+ datap->write_msg = write_msi_msg;
+ datap->dev = dev;
- priv_data->devid = ida_simple_get(&platform_msi_devid_ida,
- 0, 1 << DEV_ID_SHIFT, GFP_KERNEL);
- if (priv_data->devid < 0) {
- err = priv_data->devid;
- goto out_free_data;
- }
+ return datap;
+}
+
+static void platform_msi_free_priv_data(struct platform_msi_priv_data *data)
+{
+ ida_simple_remove(&platform_msi_devid_ida, data->devid);
+ kfree(data);
+}
+
+/**
+ * platform_msi_domain_alloc_irqs - Allocate MSI interrupts for @dev
+ * @dev: The device for which to allocate interrupts
+ * @nvec: The number of interrupts to allocate
+ * @write_msi_msg: Callback to write an interrupt message for @dev
+ *
+ * Returns:
+ * Zero for success, or an error code in case of failure
+ */
+int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
+ irq_write_msi_msg_t write_msi_msg)
+{
+ struct platform_msi_priv_data *priv_data;
+ int err;
- priv_data->write_msg = write_msi_msg;
+ priv_data = platform_msi_alloc_priv_data(dev, nvec, write_msi_msg);
+ if (IS_ERR(priv_data))
+ return PTR_ERR(priv_data);
err = platform_msi_alloc_descs(dev, nvec, priv_data);
if (err)
- goto out_free_id;
+ goto out_free_priv_data;
err = msi_domain_alloc_irqs(dev->msi_domain, dev, nvec);
if (err)
@@ -238,11 +278,9 @@ int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
return 0;
out_free_desc:
- platform_msi_free_descs(dev);
-out_free_id:
- ida_simple_remove(&platform_msi_devid_ida, priv_data->devid);
-out_free_data:
- kfree(priv_data);
+ platform_msi_free_descs(dev, 0, nvec);
+out_free_priv_data:
+ platform_msi_free_priv_data(priv_data);
return err;
}
@@ -253,18 +291,126 @@ out_free_data:
*/
void platform_msi_domain_free_irqs(struct device *dev)
{
- struct msi_desc *desc;
+ if (!list_empty(dev_to_msi_list(dev))) {
+ struct msi_desc *desc;
+
+ desc = first_msi_entry(dev);
+ platform_msi_free_priv_data(desc->platform.msi_priv_data);
+ }
+
+ msi_domain_free_irqs(dev->msi_domain, dev);
+ platform_msi_free_descs(dev, 0, MAX_DEV_MSIS);
+}
+
+/**
+ * platform_msi_get_host_data - Query the private data associated with
+ * a platform-msi domain
+ * @domain: The platform-msi domain
+ *
+ * Returns the private data provided when calling
+ * platform_msi_create_device_domain.
+ */
+void *platform_msi_get_host_data(struct irq_domain *domain)
+{
+ struct platform_msi_priv_data *data = domain->host_data;
+ return data->host_data;
+}
+
+/**
+ * platform_msi_create_device_domain - Create a platform-msi domain
+ *
+ * @dev: The device generating the MSIs
+ * @nvec: The number of MSIs that need to be allocated
+ * @write_msi_msg: Callback to write an interrupt message for @dev
+ * @ops: The hierarchy domain operations to use
+ * @host_data: Private data associated to this domain
+ *
+ * Returns an irqdomain for @nvec interrupts
+ */
+struct irq_domain *
+platform_msi_create_device_domain(struct device *dev,
+ unsigned int nvec,
+ irq_write_msi_msg_t write_msi_msg,
+ const struct irq_domain_ops *ops,
+ void *host_data)
+{
+ struct platform_msi_priv_data *data;
+ struct irq_domain *domain;
+ int err;
+
+ data = platform_msi_alloc_priv_data(dev, nvec, write_msi_msg);
+ if (IS_ERR(data))
+ return NULL;
+
+ data->host_data = host_data;
+ domain = irq_domain_create_hierarchy(dev->msi_domain, 0, nvec,
+ of_node_to_fwnode(dev->of_node),
+ ops, data);
+ if (!domain)
+ goto free_priv;
- desc = first_msi_entry(dev);
- if (desc) {
- struct platform_msi_priv_data *data;
+ err = msi_domain_prepare_irqs(domain->parent, dev, nvec, &data->arg);
+ if (err)
+ goto free_domain;
+
+ return domain;
- data = desc->platform.msi_priv_data;
+free_domain:
+ irq_domain_remove(domain);
+free_priv:
+ platform_msi_free_priv_data(data);
+ return NULL;
+}
+
+/**
+ * platform_msi_domain_free - Free interrupts associated with a platform-msi
+ * domain
+ *
+ * @domain: The platform-msi domain
+ * @virq: The base irq from which to perform the free operation
+ * @nvec: How many interrupts to free from @virq
+ */
+void platform_msi_domain_free(struct irq_domain *domain, unsigned int virq,
+ unsigned int nvec)
+{
+ struct platform_msi_priv_data *data = domain->host_data;
+ struct msi_desc *desc;
+ for_each_msi_entry(desc, data->dev) {
+ if (WARN_ON(!desc->irq || desc->nvec_used != 1))
+ return;
+ if (!(desc->irq >= virq && desc->irq < (virq + nvec)))
+ continue;
- ida_simple_remove(&platform_msi_devid_ida, data->devid);
- kfree(data);
+ irq_domain_free_irqs_common(domain, desc->irq, 1);
}
+}
- msi_domain_free_irqs(dev->msi_domain, dev);
- platform_msi_free_descs(dev);
+/**
+ * platform_msi_domain_alloc - Allocate interrupts associated with
+ * a platform-msi domain
+ *
+ * @domain: The platform-msi domain
+ * @virq: The base irq from which to perform the allocate operation
+ * @nvec: How many interrupts to free from @virq
+ *
+ * Return 0 on success, or an error code on failure. Must be called
+ * with irq_domain_mutex held (which can only be done as part of a
+ * top-level interrupt allocation).
+ */
+int platform_msi_domain_alloc(struct irq_domain *domain, unsigned int virq,
+ unsigned int nr_irqs)
+{
+ struct platform_msi_priv_data *data = domain->host_data;
+ int err;
+
+ err = platform_msi_alloc_descs_with_irq(data->dev, virq, nr_irqs, data);
+ if (err)
+ return err;
+
+ err = msi_domain_populate_irqs(domain->parent, data->dev,
+ virq, nr_irqs, &data->arg);
+ if (err)
+ platform_msi_domain_free(domain, virq, nr_irqs);
+
+ return err;
}
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 1dd6d3bf1098..73e399466c6e 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -117,6 +117,26 @@ int platform_get_irq(struct platform_device *dev, unsigned int num)
EXPORT_SYMBOL_GPL(platform_get_irq);
/**
+ * platform_irq_count - Count the number of IRQs a platform device uses
+ * @dev: platform device
+ *
+ * Return: Number of IRQs a platform device uses or EPROBE_DEFER
+ */
+int platform_irq_count(struct platform_device *dev)
+{
+ int ret, nr = 0;
+
+ while ((ret = platform_get_irq(dev, nr)) >= 0)
+ nr++;
+
+ if (ret == -EPROBE_DEFER)
+ return ret;
+
+ return nr;
+}
+EXPORT_SYMBOL_GPL(platform_irq_count);
+
+/**
* platform_get_resource_byname - get a resource for a device by name
* @dev: platform device
* @type: resource type
diff --git a/drivers/base/regmap/regcache-flat.c b/drivers/base/regmap/regcache-flat.c
index 0246f44ded74..686c9e0b930e 100644
--- a/drivers/base/regmap/regcache-flat.c
+++ b/drivers/base/regmap/regcache-flat.c
@@ -21,7 +21,7 @@ static int regcache_flat_init(struct regmap *map)
int i;
unsigned int *cache;
- map->cache = kzalloc(sizeof(unsigned int) * (map->max_register + 1),
+ map->cache = kcalloc(map->max_register + 1, sizeof(unsigned int),
GFP_KERNEL);
if (!map->cache)
return -ENOMEM;
diff --git a/drivers/base/regmap/regcache-lzo.c b/drivers/base/regmap/regcache-lzo.c
index 736e0d378567..6f77d7319fc6 100644
--- a/drivers/base/regmap/regcache-lzo.c
+++ b/drivers/base/regmap/regcache-lzo.c
@@ -139,7 +139,7 @@ static int regcache_lzo_init(struct regmap *map)
ret = 0;
blkcount = regcache_lzo_block_count(map);
- map->cache = kzalloc(blkcount * sizeof *lzo_blocks,
+ map->cache = kcalloc(blkcount, sizeof(*lzo_blocks),
GFP_KERNEL);
if (!map->cache)
return -ENOMEM;
@@ -152,8 +152,8 @@ static int regcache_lzo_init(struct regmap *map)
* that register.
*/
bmp_size = map->num_reg_defaults_raw;
- sync_bmp = kmalloc(BITS_TO_LONGS(bmp_size) * sizeof(long),
- GFP_KERNEL);
+ sync_bmp = kmalloc_array(BITS_TO_LONGS(bmp_size), sizeof(long),
+ GFP_KERNEL);
if (!sync_bmp) {
ret = -ENOMEM;
goto err;
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
index 56486d92c4e7..aa56af87d941 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -361,13 +361,14 @@ regcache_rbtree_node_alloc(struct regmap *map, unsigned int reg)
rbnode->base_reg = reg;
}
- rbnode->block = kmalloc(rbnode->blklen * map->cache_word_size,
- GFP_KERNEL);
+ rbnode->block = kmalloc_array(rbnode->blklen, map->cache_word_size,
+ GFP_KERNEL);
if (!rbnode->block)
goto err_free;
- rbnode->cache_present = kzalloc(BITS_TO_LONGS(rbnode->blklen) *
- sizeof(*rbnode->cache_present), GFP_KERNEL);
+ rbnode->cache_present = kcalloc(BITS_TO_LONGS(rbnode->blklen),
+ sizeof(*rbnode->cache_present),
+ GFP_KERNEL);
if (!rbnode->cache_present)
goto err_free_block;
@@ -413,8 +414,8 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
max = reg + max_dist;
/* look for an adjacent register to the one we are about to add */
- for (node = rb_first(&rbtree_ctx->root); node;
- node = rb_next(node)) {
+ node = rbtree_ctx->root.rb_node;
+ while (node) {
rbnode_tmp = rb_entry(node, struct regcache_rbtree_node,
node);
@@ -425,6 +426,11 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg,
new_base_reg = min(reg, base_reg);
new_top_reg = max(reg, top_reg);
} else {
+ if (max < base_reg)
+ node = node->rb_left;
+ else
+ node = node->rb_right;
+
continue;
}
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c
index 4c07802986b2..348be3a35410 100644
--- a/drivers/base/regmap/regcache.c
+++ b/drivers/base/regmap/regcache.c
@@ -100,15 +100,25 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
int i;
void *tmp_buf;
- for (i = 0; i < config->num_reg_defaults; i++)
- if (config->reg_defaults[i].reg % map->reg_stride)
- return -EINVAL;
-
if (map->cache_type == REGCACHE_NONE) {
+ if (config->reg_defaults || config->num_reg_defaults_raw)
+ dev_warn(map->dev,
+ "No cache used with register defaults set!\n");
+
map->cache_bypass = true;
return 0;
}
+ if (config->reg_defaults && !config->num_reg_defaults) {
+ dev_err(map->dev,
+ "Register defaults are set without the number!\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < config->num_reg_defaults; i++)
+ if (config->reg_defaults[i].reg % map->reg_stride)
+ return -EINVAL;
+
for (i = 0; i < ARRAY_SIZE(cache_types); i++)
if (cache_types[i]->type == map->cache_type)
break;
@@ -138,8 +148,6 @@ int regcache_init(struct regmap *map, const struct regmap_config *config)
* a copy of it.
*/
if (config->reg_defaults) {
- if (!map->num_reg_defaults)
- return -EINVAL;
tmp_buf = kmemdup(config->reg_defaults, map->num_reg_defaults *
sizeof(struct reg_default), GFP_KERNEL);
if (!tmp_buf)
@@ -535,19 +543,30 @@ bool regcache_set_val(struct regmap *map, void *base, unsigned int idx,
switch (map->cache_word_size) {
case 1: {
u8 *cache = base;
+
cache[idx] = val;
break;
}
case 2: {
u16 *cache = base;
+
cache[idx] = val;
break;
}
case 4: {
u32 *cache = base;
+
+ cache[idx] = val;
+ break;
+ }
+#ifdef CONFIG_64BIT
+ case 8: {
+ u64 *cache = base;
+
cache[idx] = val;
break;
}
+#endif
default:
BUG();
}
@@ -568,16 +587,26 @@ unsigned int regcache_get_val(struct regmap *map, const void *base,
switch (map->cache_word_size) {
case 1: {
const u8 *cache = base;
+
return cache[idx];
}
case 2: {
const u16 *cache = base;
+
return cache[idx];
}
case 4: {
const u32 *cache = base;
+
+ return cache[idx];
+ }
+#ifdef CONFIG_64BIT
+ case 8: {
+ const u64 *cache = base;
+
return cache[idx];
}
+#endif
default:
BUG();
}
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index 3f0a7e262d69..1ee3d40861c7 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -397,72 +397,39 @@ static const struct file_operations regmap_reg_ranges_fops = {
.llseek = default_llseek,
};
-static ssize_t regmap_access_read_file(struct file *file,
- char __user *user_buf, size_t count,
- loff_t *ppos)
+static int regmap_access_show(struct seq_file *s, void *ignored)
{
- int reg_len, tot_len;
- size_t buf_pos = 0;
- loff_t p = 0;
- ssize_t ret;
- int i;
- struct regmap *map = file->private_data;
- char *buf;
-
- if (*ppos < 0 || !count)
- return -EINVAL;
+ struct regmap *map = s->private;
+ int i, reg_len;
- buf = kmalloc(count, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- /* Calculate the length of a fixed format */
reg_len = regmap_calc_reg_len(map->max_register);
- tot_len = reg_len + 10; /* ': R W V P\n' */
for (i = 0; i <= map->max_register; i += map->reg_stride) {
/* Ignore registers which are neither readable nor writable */
if (!regmap_readable(map, i) && !regmap_writeable(map, i))
continue;
- /* If we're in the region the user is trying to read */
- if (p >= *ppos) {
- /* ...but not beyond it */
- if (buf_pos + tot_len + 1 >= count)
- break;
-
- /* Format the register */
- snprintf(buf + buf_pos, count - buf_pos,
- "%.*x: %c %c %c %c\n",
- reg_len, i,
- regmap_readable(map, i) ? 'y' : 'n',
- regmap_writeable(map, i) ? 'y' : 'n',
- regmap_volatile(map, i) ? 'y' : 'n',
- regmap_precious(map, i) ? 'y' : 'n');
-
- buf_pos += tot_len;
- }
- p += tot_len;
- }
-
- ret = buf_pos;
-
- if (copy_to_user(user_buf, buf, buf_pos)) {
- ret = -EFAULT;
- goto out;
+ /* Format the register */
+ seq_printf(s, "%.*x: %c %c %c %c\n", reg_len, i,
+ regmap_readable(map, i) ? 'y' : 'n',
+ regmap_writeable(map, i) ? 'y' : 'n',
+ regmap_volatile(map, i) ? 'y' : 'n',
+ regmap_precious(map, i) ? 'y' : 'n');
}
- *ppos += buf_pos;
+ return 0;
+}
-out:
- kfree(buf);
- return ret;
+static int access_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, regmap_access_show, inode->i_private);
}
static const struct file_operations regmap_access_fops = {
- .open = simple_open,
- .read = regmap_access_read_file,
- .llseek = default_llseek,
+ .open = access_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
};
static ssize_t regmap_cache_only_write_file(struct file *file,
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 8d16db533527..9b0d202414d0 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -39,8 +39,11 @@ struct regmap_irq_chip_data {
unsigned int *mask_buf;
unsigned int *mask_buf_def;
unsigned int *wake_buf;
+ unsigned int *type_buf;
+ unsigned int *type_buf_def;
unsigned int irq_reg_stride;
+ unsigned int type_reg_stride;
};
static inline const
@@ -144,6 +147,22 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
}
}
+ for (i = 0; i < d->chip->num_type_reg; i++) {
+ if (!d->type_buf_def[i])
+ continue;
+ reg = d->chip->type_base +
+ (i * map->reg_stride * d->type_reg_stride);
+ if (d->chip->type_invert)
+ ret = regmap_update_bits(d->map, reg,
+ d->type_buf_def[i], ~d->type_buf[i]);
+ else
+ ret = regmap_update_bits(d->map, reg,
+ d->type_buf_def[i], d->type_buf[i]);
+ if (ret != 0)
+ dev_err(d->map->dev, "Failed to sync type in %x\n",
+ reg);
+ }
+
if (d->chip->runtime_pm)
pm_runtime_put(map->dev);
@@ -178,6 +197,38 @@ static void regmap_irq_disable(struct irq_data *data)
d->mask_buf[irq_data->reg_offset / map->reg_stride] |= irq_data->mask;
}
+static int regmap_irq_set_type(struct irq_data *data, unsigned int type)
+{
+ struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
+ struct regmap *map = d->map;
+ const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq);
+ int reg = irq_data->type_reg_offset / map->reg_stride;
+
+ if (!(irq_data->type_rising_mask | irq_data->type_falling_mask))
+ return 0;
+
+ d->type_buf[reg] &= ~(irq_data->type_falling_mask |
+ irq_data->type_rising_mask);
+ switch (type) {
+ case IRQ_TYPE_EDGE_FALLING:
+ d->type_buf[reg] |= irq_data->type_falling_mask;
+ break;
+
+ case IRQ_TYPE_EDGE_RISING:
+ d->type_buf[reg] |= irq_data->type_rising_mask;
+ break;
+
+ case IRQ_TYPE_EDGE_BOTH:
+ d->type_buf[reg] |= (irq_data->type_falling_mask |
+ irq_data->type_rising_mask);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int regmap_irq_set_wake(struct irq_data *data, unsigned int on)
{
struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
@@ -204,6 +255,7 @@ static const struct irq_chip regmap_irq_chip = {
.irq_bus_sync_unlock = regmap_irq_sync_unlock,
.irq_disable = regmap_irq_disable,
.irq_enable = regmap_irq_enable,
+ .irq_set_type = regmap_irq_set_type,
.irq_set_wake = regmap_irq_set_wake,
};
@@ -386,28 +438,40 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
if (!d)
return -ENOMEM;
- d->status_buf = kzalloc(sizeof(unsigned int) * chip->num_regs,
+ d->status_buf = kcalloc(chip->num_regs, sizeof(unsigned int),
GFP_KERNEL);
if (!d->status_buf)
goto err_alloc;
- d->mask_buf = kzalloc(sizeof(unsigned int) * chip->num_regs,
+ d->mask_buf = kcalloc(chip->num_regs, sizeof(unsigned int),
GFP_KERNEL);
if (!d->mask_buf)
goto err_alloc;
- d->mask_buf_def = kzalloc(sizeof(unsigned int) * chip->num_regs,
+ d->mask_buf_def = kcalloc(chip->num_regs, sizeof(unsigned int),
GFP_KERNEL);
if (!d->mask_buf_def)
goto err_alloc;
if (chip->wake_base) {
- d->wake_buf = kzalloc(sizeof(unsigned int) * chip->num_regs,
+ d->wake_buf = kcalloc(chip->num_regs, sizeof(unsigned int),
GFP_KERNEL);
if (!d->wake_buf)
goto err_alloc;
}
+ if (chip->num_type_reg) {
+ d->type_buf_def = kcalloc(chip->num_type_reg,
+ sizeof(unsigned int), GFP_KERNEL);
+ if (!d->type_buf_def)
+ goto err_alloc;
+
+ d->type_buf = kcalloc(chip->num_type_reg, sizeof(unsigned int),
+ GFP_KERNEL);
+ if (!d->type_buf)
+ goto err_alloc;
+ }
+
d->irq_chip = regmap_irq_chip;
d->irq_chip.name = chip->name;
d->irq = irq;
@@ -420,10 +484,16 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
else
d->irq_reg_stride = 1;
+ if (chip->type_reg_stride)
+ d->type_reg_stride = chip->type_reg_stride;
+ else
+ d->type_reg_stride = 1;
+
if (!map->use_single_read && map->reg_stride == 1 &&
d->irq_reg_stride == 1) {
- d->status_reg_buf = kmalloc(map->format.val_bytes *
- chip->num_regs, GFP_KERNEL);
+ d->status_reg_buf = kmalloc_array(chip->num_regs,
+ map->format.val_bytes,
+ GFP_KERNEL);
if (!d->status_reg_buf)
goto err_alloc;
}
@@ -511,6 +581,33 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
}
}
+ if (chip->num_type_reg) {
+ for (i = 0; i < chip->num_irqs; i++) {
+ reg = chip->irqs[i].type_reg_offset / map->reg_stride;
+ d->type_buf_def[reg] |= chip->irqs[i].type_rising_mask |
+ chip->irqs[i].type_falling_mask;
+ }
+ for (i = 0; i < chip->num_type_reg; ++i) {
+ if (!d->type_buf_def[i])
+ continue;
+
+ reg = chip->type_base +
+ (i * map->reg_stride * d->type_reg_stride);
+ if (chip->type_invert)
+ ret = regmap_update_bits(map, reg,
+ d->type_buf_def[i], 0xFF);
+ else
+ ret = regmap_update_bits(map, reg,
+ d->type_buf_def[i], 0x0);
+ if (ret != 0) {
+ dev_err(map->dev,
+ "Failed to set type in 0x%x: %x\n",
+ reg, ret);
+ goto err_alloc;
+ }
+ }
+ }
+
if (irq_base)
d->domain = irq_domain_add_legacy(map->dev->of_node,
chip->num_irqs, irq_base, 0,
@@ -541,6 +638,8 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
err_domain:
/* Should really dispose of the domain but... */
err_alloc:
+ kfree(d->type_buf);
+ kfree(d->type_buf_def);
kfree(d->wake_buf);
kfree(d->mask_buf_def);
kfree(d->mask_buf);
@@ -564,6 +663,8 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
free_irq(irq, d);
irq_domain_remove(d->domain);
+ kfree(d->type_buf);
+ kfree(d->type_buf_def);
kfree(d->wake_buf);
kfree(d->mask_buf_def);
kfree(d->mask_buf);
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c
index 426a57e41ac7..8812bfb9e3b8 100644
--- a/drivers/base/regmap/regmap-mmio.c
+++ b/drivers/base/regmap/regmap-mmio.c
@@ -61,6 +61,33 @@ static int regmap_mmio_regbits_check(size_t reg_bits)
}
}
+static int regmap_mmio_get_min_stride(size_t val_bits)
+{
+ int min_stride;
+
+ switch (val_bits) {
+ case 8:
+ /* The core treats 0 as 1 */
+ min_stride = 0;
+ return 0;
+ case 16:
+ min_stride = 2;
+ break;
+ case 32:
+ min_stride = 4;
+ break;
+#ifdef CONFIG_64BIT
+ case 64:
+ min_stride = 8;
+ break;
+#endif
+ default:
+ return -EINVAL;
+ }
+
+ return min_stride;
+}
+
static inline void regmap_mmio_count_check(size_t count, u32 offset)
{
BUG_ON(count <= offset);
@@ -106,17 +133,17 @@ static int regmap_mmio_gather_write(void *context,
while (val_size) {
switch (ctx->val_bytes) {
case 1:
- writeb(*(u8 *)val, ctx->regs + offset);
+ __raw_writeb(*(u8 *)val, ctx->regs + offset);
break;
case 2:
- writew(*(u16 *)val, ctx->regs + offset);
+ __raw_writew(*(u16 *)val, ctx->regs + offset);
break;
case 4:
- writel(*(u32 *)val, ctx->regs + offset);
+ __raw_writel(*(u32 *)val, ctx->regs + offset);
break;
#ifdef CONFIG_64BIT
case 8:
- writeq(*(u64 *)val, ctx->regs + offset);
+ __raw_writeq(*(u64 *)val, ctx->regs + offset);
break;
#endif
default:
@@ -166,17 +193,17 @@ static int regmap_mmio_read(void *context,
while (val_size) {
switch (ctx->val_bytes) {
case 1:
- *(u8 *)val = readb(ctx->regs + offset);
+ *(u8 *)val = __raw_readb(ctx->regs + offset);
break;
case 2:
- *(u16 *)val = readw(ctx->regs + offset);
+ *(u16 *)val = __raw_readw(ctx->regs + offset);
break;
case 4:
- *(u32 *)val = readl(ctx->regs + offset);
+ *(u32 *)val = __raw_readl(ctx->regs + offset);
break;
#ifdef CONFIG_64BIT
case 8:
- *(u64 *)val = readq(ctx->regs + offset);
+ *(u64 *)val = __raw_readq(ctx->regs + offset);
break;
#endif
default:
@@ -231,26 +258,9 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev,
if (config->pad_bits)
return ERR_PTR(-EINVAL);
- switch (config->val_bits) {
- case 8:
- /* The core treats 0 as 1 */
- min_stride = 0;
- break;
- case 16:
- min_stride = 2;
- break;
- case 32:
- min_stride = 4;
- break;
-#ifdef CONFIG_64BIT
- case 64:
- min_stride = 8;
- break;
-#endif
- break;
- default:
- return ERR_PTR(-EINVAL);
- }
+ min_stride = regmap_mmio_get_min_stride(config->val_bits);
+ if (min_stride < 0)
+ return ERR_PTR(min_stride);
if (config->reg_stride < min_stride)
return ERR_PTR(-EINVAL);
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 4ac63c0e50c7..ee54e841de4a 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -245,6 +245,28 @@ static void regmap_format_32_native(void *buf, unsigned int val,
*(u32 *)buf = val << shift;
}
+#ifdef CONFIG_64BIT
+static void regmap_format_64_be(void *buf, unsigned int val, unsigned int shift)
+{
+ __be64 *b = buf;
+
+ b[0] = cpu_to_be64((u64)val << shift);
+}
+
+static void regmap_format_64_le(void *buf, unsigned int val, unsigned int shift)
+{
+ __le64 *b = buf;
+
+ b[0] = cpu_to_le64((u64)val << shift);
+}
+
+static void regmap_format_64_native(void *buf, unsigned int val,
+ unsigned int shift)
+{
+ *(u64 *)buf = (u64)val << shift;
+}
+#endif
+
static void regmap_parse_inplace_noop(void *buf)
{
}
@@ -332,6 +354,41 @@ static unsigned int regmap_parse_32_native(const void *buf)
return *(u32 *)buf;
}
+#ifdef CONFIG_64BIT
+static unsigned int regmap_parse_64_be(const void *buf)
+{
+ const __be64 *b = buf;
+
+ return be64_to_cpu(b[0]);
+}
+
+static unsigned int regmap_parse_64_le(const void *buf)
+{
+ const __le64 *b = buf;
+
+ return le64_to_cpu(b[0]);
+}
+
+static void regmap_parse_64_be_inplace(void *buf)
+{
+ __be64 *b = buf;
+
+ b[0] = be64_to_cpu(b[0]);
+}
+
+static void regmap_parse_64_le_inplace(void *buf)
+{
+ __le64 *b = buf;
+
+ b[0] = le64_to_cpu(b[0]);
+}
+
+static unsigned int regmap_parse_64_native(const void *buf)
+{
+ return *(u64 *)buf;
+}
+#endif
+
static void regmap_lock_mutex(void *__map)
{
struct regmap *map = __map;
@@ -712,6 +769,21 @@ struct regmap *__regmap_init(struct device *dev,
}
break;
+#ifdef CONFIG_64BIT
+ case 64:
+ switch (reg_endian) {
+ case REGMAP_ENDIAN_BIG:
+ map->format.format_reg = regmap_format_64_be;
+ break;
+ case REGMAP_ENDIAN_NATIVE:
+ map->format.format_reg = regmap_format_64_native;
+ break;
+ default:
+ goto err_map;
+ }
+ break;
+#endif
+
default:
goto err_map;
}
@@ -771,6 +843,28 @@ struct regmap *__regmap_init(struct device *dev,
goto err_map;
}
break;
+#ifdef CONFIG_64BIT
+ case 64:
+ switch (val_endian) {
+ case REGMAP_ENDIAN_BIG:
+ map->format.format_val = regmap_format_64_be;
+ map->format.parse_val = regmap_parse_64_be;
+ map->format.parse_inplace = regmap_parse_64_be_inplace;
+ break;
+ case REGMAP_ENDIAN_LITTLE:
+ map->format.format_val = regmap_format_64_le;
+ map->format.parse_val = regmap_parse_64_le;
+ map->format.parse_inplace = regmap_parse_64_le_inplace;
+ break;
+ case REGMAP_ENDIAN_NATIVE:
+ map->format.format_val = regmap_format_64_native;
+ map->format.parse_val = regmap_parse_64_native;
+ break;
+ default:
+ goto err_map;
+ }
+ break;
+#endif
}
if (map->format.format_write) {
@@ -1513,7 +1607,7 @@ int regmap_write(struct regmap *map, unsigned int reg, unsigned int val)
{
int ret;
- if (reg % map->reg_stride)
+ if (!IS_ALIGNED(reg, map->reg_stride))
return -EINVAL;
map->lock(map->lock_arg);
@@ -1540,7 +1634,7 @@ int regmap_write_async(struct regmap *map, unsigned int reg, unsigned int val)
{
int ret;
- if (reg % map->reg_stride)
+ if (!IS_ALIGNED(reg, map->reg_stride))
return -EINVAL;
map->lock(map->lock_arg);
@@ -1714,7 +1808,7 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val,
if (map->bus && !map->format.parse_inplace)
return -EINVAL;
- if (reg % map->reg_stride)
+ if (!IS_ALIGNED(reg, map->reg_stride))
return -EINVAL;
/*
@@ -1983,7 +2077,7 @@ static int _regmap_multi_reg_write(struct regmap *map,
int reg = regs[i].reg;
if (!map->writeable_reg(map->dev, reg))
return -EINVAL;
- if (reg % map->reg_stride)
+ if (!IS_ALIGNED(reg, map->reg_stride))
return -EINVAL;
}
@@ -2133,7 +2227,7 @@ int regmap_raw_write_async(struct regmap *map, unsigned int reg,
if (val_len % map->format.val_bytes)
return -EINVAL;
- if (reg % map->reg_stride)
+ if (!IS_ALIGNED(reg, map->reg_stride))
return -EINVAL;
map->lock(map->lock_arg);
@@ -2260,7 +2354,7 @@ int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val)
{
int ret;
- if (reg % map->reg_stride)
+ if (!IS_ALIGNED(reg, map->reg_stride))
return -EINVAL;
map->lock(map->lock_arg);
@@ -2296,7 +2390,7 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
return -EINVAL;
if (val_len % map->format.val_bytes)
return -EINVAL;
- if (reg % map->reg_stride)
+ if (!IS_ALIGNED(reg, map->reg_stride))
return -EINVAL;
if (val_count == 0)
return -EINVAL;
@@ -2414,7 +2508,7 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
size_t val_bytes = map->format.val_bytes;
bool vol = regmap_volatile_range(map, reg, val_count);
- if (reg % map->reg_stride)
+ if (!IS_ALIGNED(reg, map->reg_stride))
return -EINVAL;
if (map->bus && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
@@ -2488,11 +2582,19 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val,
* we assume that the values are native
* endian.
*/
+#ifdef CONFIG_64BIT
+ u64 *u64 = val;
+#endif
u32 *u32 = val;
u16 *u16 = val;
u8 *u8 = val;
switch (map->format.val_bytes) {
+#ifdef CONFIG_64BIT
+ case 8:
+ u64[i] = ival;
+ break;
+#endif
case 4:
u32[i] = ival;
break;
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c
index 0c98a9d51a24..44ce80606944 100644
--- a/drivers/char/hw_random/via-rng.c
+++ b/drivers/char/hw_random/via-rng.c
@@ -140,7 +140,7 @@ static int via_rng_init(struct hwrng *rng)
* RNG configuration like it used to be the case in this
* register */
if ((c->x86 == 6) && (c->x86_model >= 0x0f)) {
- if (!cpu_has_xstore_enabled) {
+ if (!boot_cpu_has(X86_FEATURE_XSTORE_EN)) {
pr_err(PFX "can't enable hardware RNG "
"if XSTORE is not enabled\n");
return -ENODEV;
@@ -200,8 +200,9 @@ static int __init mod_init(void)
{
int err;
- if (!cpu_has_xstore)
+ if (!boot_cpu_has(X86_FEATURE_XSTORE))
return -ENODEV;
+
pr_info("VIA RNG detected\n");
err = hwrng_register(&via_rng);
if (err) {
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 2eb5f0efae90..b251013eef0a 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -28,10 +28,16 @@ config CLKSRC_MMIO
bool
config DIGICOLOR_TIMER
- bool
+ bool "Digicolor timer driver" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
+ help
+ Enables the support for the digicolor timer driver.
config DW_APB_TIMER
- bool
+ bool "DW APB timer driver" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
+ help
+ Enables the support for the dw_apb timer.
config DW_APB_TIMER_OF
bool
@@ -39,47 +45,77 @@ config DW_APB_TIMER_OF
select CLKSRC_OF
config ROCKCHIP_TIMER
- bool
+ bool "Rockchip timer driver" if COMPILE_TEST
+ depends on ARM || ARM64
select CLKSRC_OF
+ help
+ Enables the support for the rockchip timer driver.
config ARMADA_370_XP_TIMER
- bool
+ bool "Armada 370 and XP timer driver" if COMPILE_TEST
+ depends on ARM
select CLKSRC_OF
+ help
+ Enables the support for the Armada 370 and XP timer driver.
config MESON6_TIMER
- bool
+ bool "Meson6 timer driver" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
select CLKSRC_MMIO
+ help
+ Enables the support for the Meson6 timer driver.
config ORION_TIMER
+ bool "Orion timer driver" if COMPILE_TEST
+ depends on ARM
select CLKSRC_OF
select CLKSRC_MMIO
- bool
+ help
+ Enables the support for the Orion timer driver
config SUN4I_TIMER
+ bool "Sun4i timer driver" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
select CLKSRC_MMIO
- bool
+ help
+ Enables support for the Sun4i timer.
config SUN5I_HSTIMER
+ bool "Sun5i timer driver" if COMPILE_TEST
select CLKSRC_MMIO
- bool
+ depends on COMMON_CLK
+ help
+ Enables support the Sun5i timer.
config TEGRA_TIMER
- bool
+ bool "Tegra timer driver" if COMPILE_TEST
+ depends on ARM
+ help
+ Enables support for the Tegra driver.
config VT8500_TIMER
- bool
+ bool "VT8500 timer driver" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
+ help
+ Enables support for the VT8500 driver.
config CADENCE_TTC_TIMER
- bool
+ bool "Cadence TTC timer driver" if COMPILE_TEST
+ depends on COMMON_CLK
+ help
+ Enables support for the cadence ttc driver.
config ASM9260_TIMER
- bool
+ bool "ASM9260 timer driver" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
select CLKSRC_MMIO
select CLKSRC_OF
+ help
+ Enables support for the ASM9260 timer.
config CLKSRC_NOMADIK_MTU
- bool
- depends on (ARCH_NOMADIK || ARCH_U8500)
+ bool "Nomakdik clocksource driver" if COMPILE_TEST
+ depends on ARM
select CLKSRC_MMIO
help
Support for Multi Timer Unit. MTU provides access
@@ -93,9 +129,8 @@ config CLKSRC_NOMADIK_MTU_SCHED_CLOCK
Use the Multi Timer Unit as the sched_clock.
config CLKSRC_DBX500_PRCMU
- bool "Clocksource PRCMU Timer"
- depends on UX500_SOC_DB8500
- default y
+ bool "Clocksource PRCMU Timer" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
help
Use the always on PRCMU Timer as clocksource
@@ -116,13 +151,18 @@ config CLKSRC_EFM32
event device.
config CLKSRC_LPC32XX
- bool
+ bool "Clocksource for LPC32XX" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
select CLKSRC_MMIO
select CLKSRC_OF
+ help
+ Support for the LPC32XX clocksource.
config CLKSRC_PISTACHIO
- bool
+ bool "Clocksource for Pistachio SoC" if COMPILE_TEST
select CLKSRC_OF
+ help
+ Enables the clocksource for the Pistachio SoC.
config CLKSRC_TI_32K
bool "Texas Instruments 32.768 Hz Clocksource" if COMPILE_TEST
@@ -199,13 +239,14 @@ config CLKSRC_METAG_GENERIC
This option enables support for the Meta per-thread timers.
config CLKSRC_EXYNOS_MCT
- def_bool y if ARCH_EXYNOS
- depends on !ARM64
+ bool "Exynos multi core timer driver" if COMPILE_TEST
+ depends on ARM
help
Support for Multi Core Timer controller on Exynos SoCs.
config CLKSRC_SAMSUNG_PWM
- bool
+ bool "PWM timer drvier for Samsung S3C, S5P" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
help
This is a new clocksource driver for the PWM timer found in
Samsung S3C, S5P and Exynos SoCs, replacing an earlier driver
@@ -213,7 +254,8 @@ config CLKSRC_SAMSUNG_PWM
needed only on systems that do not have the Exynos MCT available.
config FSL_FTM_TIMER
- bool
+ bool "Freescale FlexTimer Module driver" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
help
Support for Freescale FlexTimer Module (FTM) timer.
@@ -226,9 +268,12 @@ config SYS_SUPPORTS_SH_CMT
bool
config MTK_TIMER
+ bool "Mediatek timer driver" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
select CLKSRC_OF
select CLKSRC_MMIO
- bool
+ help
+ Support for Mediatek timer driver.
config SYS_SUPPORTS_SH_MTU2
bool
@@ -279,7 +324,12 @@ config EM_TIMER_STI
such as EMEV2 from former NEC Electronics.
config CLKSRC_QCOM
- bool
+ bool "Qualcomm MSM timer" if COMPILE_TEST
+ depends on ARM
+ select CLKSRC_OF
+ help
+ This enables the clocksource and the per CPU clockevent driver for the
+ Qualcomm SoCs.
config CLKSRC_VERSATILE
bool "ARM Versatile (Express) reference platforms clock source"
@@ -298,21 +348,40 @@ config CLKSRC_MIPS_GIC
select CLKSRC_OF
config CLKSRC_TANGO_XTAL
- bool
+ bool "Clocksource for Tango SoC" if COMPILE_TEST
+ depends on ARM
select CLKSRC_OF
+ select CLKSRC_MMIO
+ help
+ This enables the clocksource for Tango SoC
config CLKSRC_PXA
- def_bool y if ARCH_PXA || ARCH_SA1100
- select CLKSRC_OF if OF
+ bool "Clocksource for PXA or SA-11x0 platform" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
+ select CLKSRC_MMIO
help
This enables OST0 support available on PXA and SA-11x0
platforms.
+config H8300_TMR8
+ bool "Clockevent timer for the H8300 platform" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
+ help
+ This enables the 8 bits timer for the H8300 platform.
+
config H8300_TMR16
- bool
+ bool "Clockevent timer for the H83069 platform" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
+ help
+ This enables the 16 bits timer for the H8300 platform with the
+ H83069 cpu.
config H8300_TPU
- bool
+ bool "Clocksource for the H8300 platform" if COMPILE_TEST
+ depends on GENERIC_CLOCKEVENTS
+ help
+ This enables the clocksource for the H8300 platform with the
+ H8S2678 cpu.
config CLKSRC_IMX_GPT
bool "Clocksource using i.MX GPT" if COMPILE_TEST
@@ -320,8 +389,7 @@ config CLKSRC_IMX_GPT
select CLKSRC_MMIO
config CLKSRC_ST_LPC
- bool
- depends on ARCH_STI
+ bool "Low power clocksource found in the LPC" if COMPILE_TEST
select CLKSRC_OF if OF
help
Enable this option to use the Low Power controller timer
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 56bd16e77ae3..dc2b8997f6e6 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -60,7 +60,7 @@ obj-$(CONFIG_CLKSRC_MIPS_GIC) += mips-gic-timer.o
obj-$(CONFIG_CLKSRC_TANGO_XTAL) += tango_xtal.o
obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o
obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o
-obj-$(CONFIG_H8300) += h8300_timer8.o
+obj-$(CONFIG_H8300_TMR8) += h8300_timer8.o
obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o
obj-$(CONFIG_H8300_TPU) += h8300_tpu.o
obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index 6eab88985670..28037d0b8dcd 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -109,10 +109,8 @@ static void acpi_pm_check_blacklist(struct pci_dev *dev)
/* the bug has been fixed in PIIX4M */
if (dev->revision < 3) {
- printk(KERN_WARNING "* Found PM-Timer Bug on the chipset."
- " Due to workarounds for a bug,\n"
- "* this clock source is slow. Consider trying"
- " other clock sources\n");
+ pr_warn("* Found PM-Timer Bug on the chipset. Due to workarounds for a bug,\n"
+ "* this clock source is slow. Consider trying other clock sources\n");
acpi_pm_need_workaround();
}
@@ -125,12 +123,9 @@ static void acpi_pm_check_graylist(struct pci_dev *dev)
if (acpi_pm_good)
return;
- printk(KERN_WARNING "* The chipset may have PM-Timer Bug. Due to"
- " workarounds for a bug,\n"
- "* this clock source is slow. If you are sure your timer"
- " does not have\n"
- "* this bug, please use \"acpi_pm_good\" to disable the"
- " workaround\n");
+ pr_warn("* The chipset may have PM-Timer Bug. Due to workarounds for a bug,\n"
+ "* this clock source is slow. If you are sure your timer does not have\n"
+ "* this bug, please use \"acpi_pm_good\" to disable the workaround\n");
acpi_pm_need_workaround();
}
@@ -162,8 +157,7 @@ static int verify_pmtmr_rate(void)
/* Check that the PMTMR delta is within 5% of what we expect */
if (delta < (PMTMR_EXPECTED_RATE * 19) / 20 ||
delta > (PMTMR_EXPECTED_RATE * 21) / 20) {
- printk(KERN_INFO "PM-Timer running at invalid rate: %lu%% "
- "of normal - aborting.\n",
+ pr_info("PM-Timer running at invalid rate: %lu%% of normal - aborting.\n",
100UL * delta / PMTMR_EXPECTED_RATE);
return -1;
}
@@ -199,15 +193,14 @@ static int __init init_acpi_pm_clocksource(void)
break;
if ((value2 < value1) && ((value2) < 0xFFF))
break;
- printk(KERN_INFO "PM-Timer had inconsistent results:"
- " %#llx, %#llx - aborting.\n",
- value1, value2);
+ pr_info("PM-Timer had inconsistent results: %#llx, %#llx - aborting.\n",
+ value1, value2);
pmtmr_ioport = 0;
return -EINVAL;
}
if (i == ACPI_PM_READ_CHECKS) {
- printk(KERN_INFO "PM-Timer failed consistency check "
- " (%#llx) - aborting.\n", value1);
+ pr_info("PM-Timer failed consistency check (%#llx) - aborting.\n",
+ value1);
pmtmr_ioport = 0;
return -ENODEV;
}
diff --git a/drivers/clocksource/arm_global_timer.c b/drivers/clocksource/arm_global_timer.c
index a2cb6fae9295..d189d8cb69f7 100644
--- a/drivers/clocksource/arm_global_timer.c
+++ b/drivers/clocksource/arm_global_timer.c
@@ -99,17 +99,17 @@ static void gt_compare_set(unsigned long delta, int periodic)
counter += delta;
ctrl = GT_CONTROL_TIMER_ENABLE;
- writel(ctrl, gt_base + GT_CONTROL);
- writel(lower_32_bits(counter), gt_base + GT_COMP0);
- writel(upper_32_bits(counter), gt_base + GT_COMP1);
+ writel_relaxed(ctrl, gt_base + GT_CONTROL);
+ writel_relaxed(lower_32_bits(counter), gt_base + GT_COMP0);
+ writel_relaxed(upper_32_bits(counter), gt_base + GT_COMP1);
if (periodic) {
- writel(delta, gt_base + GT_AUTO_INC);
+ writel_relaxed(delta, gt_base + GT_AUTO_INC);
ctrl |= GT_CONTROL_AUTO_INC;
}
ctrl |= GT_CONTROL_COMP_ENABLE | GT_CONTROL_IRQ_ENABLE;
- writel(ctrl, gt_base + GT_CONTROL);
+ writel_relaxed(ctrl, gt_base + GT_CONTROL);
}
static int gt_clockevent_shutdown(struct clock_event_device *evt)
@@ -195,12 +195,23 @@ static cycle_t gt_clocksource_read(struct clocksource *cs)
return gt_counter_read();
}
+static void gt_resume(struct clocksource *cs)
+{
+ unsigned long ctrl;
+
+ ctrl = readl(gt_base + GT_CONTROL);
+ if (!(ctrl & GT_CONTROL_TIMER_ENABLE))
+ /* re-enable timer on resume */
+ writel(GT_CONTROL_TIMER_ENABLE, gt_base + GT_CONTROL);
+}
+
static struct clocksource gt_clocksource = {
.name = "arm_global_timer",
.rating = 300,
.read = gt_clocksource_read,
.mask = CLOCKSOURCE_MASK(64),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ .resume = gt_resume,
};
#ifdef CONFIG_CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK
diff --git a/drivers/clocksource/dw_apb_timer.c b/drivers/clocksource/dw_apb_timer.c
index c76c75006ea6..63345260244d 100644
--- a/drivers/clocksource/dw_apb_timer.c
+++ b/drivers/clocksource/dw_apb_timer.c
@@ -49,20 +49,31 @@ clocksource_to_dw_apb_clocksource(struct clocksource *cs)
return container_of(cs, struct dw_apb_clocksource, cs);
}
-static unsigned long apbt_readl(struct dw_apb_timer *timer, unsigned long offs)
+static inline u32 apbt_readl(struct dw_apb_timer *timer, unsigned long offs)
{
return readl(timer->base + offs);
}
-static void apbt_writel(struct dw_apb_timer *timer, unsigned long val,
- unsigned long offs)
+static inline void apbt_writel(struct dw_apb_timer *timer, u32 val,
+ unsigned long offs)
{
writel(val, timer->base + offs);
}
+static inline u32 apbt_readl_relaxed(struct dw_apb_timer *timer, unsigned long offs)
+{
+ return readl_relaxed(timer->base + offs);
+}
+
+static inline void apbt_writel_relaxed(struct dw_apb_timer *timer, u32 val,
+ unsigned long offs)
+{
+ writel_relaxed(val, timer->base + offs);
+}
+
static void apbt_disable_int(struct dw_apb_timer *timer)
{
- unsigned long ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
+ u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
ctrl |= APBTMR_CONTROL_INT;
apbt_writel(timer, ctrl, APBTMR_N_CONTROL);
@@ -81,7 +92,7 @@ void dw_apb_clockevent_pause(struct dw_apb_clock_event_device *dw_ced)
static void apbt_eoi(struct dw_apb_timer *timer)
{
- apbt_readl(timer, APBTMR_N_EOI);
+ apbt_readl_relaxed(timer, APBTMR_N_EOI);
}
static irqreturn_t dw_apb_clockevent_irq(int irq, void *data)
@@ -103,7 +114,7 @@ static irqreturn_t dw_apb_clockevent_irq(int irq, void *data)
static void apbt_enable_int(struct dw_apb_timer *timer)
{
- unsigned long ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
+ u32 ctrl = apbt_readl(timer, APBTMR_N_CONTROL);
/* clear pending intr */
apbt_readl(timer, APBTMR_N_EOI);
ctrl &= ~APBTMR_CONTROL_INT;
@@ -113,7 +124,7 @@ static void apbt_enable_int(struct dw_apb_timer *timer)
static int apbt_shutdown(struct clock_event_device *evt)
{
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
- unsigned long ctrl;
+ u32 ctrl;
pr_debug("%s CPU %d state=shutdown\n", __func__,
cpumask_first(evt->cpumask));
@@ -127,7 +138,7 @@ static int apbt_shutdown(struct clock_event_device *evt)
static int apbt_set_oneshot(struct clock_event_device *evt)
{
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
- unsigned long ctrl;
+ u32 ctrl;
pr_debug("%s CPU %d state=oneshot\n", __func__,
cpumask_first(evt->cpumask));
@@ -160,7 +171,7 @@ static int apbt_set_periodic(struct clock_event_device *evt)
{
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
unsigned long period = DIV_ROUND_UP(dw_ced->timer.freq, HZ);
- unsigned long ctrl;
+ u32 ctrl;
pr_debug("%s CPU %d state=periodic\n", __func__,
cpumask_first(evt->cpumask));
@@ -196,17 +207,17 @@ static int apbt_resume(struct clock_event_device *evt)
static int apbt_next_event(unsigned long delta,
struct clock_event_device *evt)
{
- unsigned long ctrl;
+ u32 ctrl;
struct dw_apb_clock_event_device *dw_ced = ced_to_dw_apb_ced(evt);
/* Disable timer */
- ctrl = apbt_readl(&dw_ced->timer, APBTMR_N_CONTROL);
+ ctrl = apbt_readl_relaxed(&dw_ced->timer, APBTMR_N_CONTROL);
ctrl &= ~APBTMR_CONTROL_ENABLE;
- apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+ apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
/* write new count */
- apbt_writel(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT);
+ apbt_writel_relaxed(&dw_ced->timer, delta, APBTMR_N_LOAD_COUNT);
ctrl |= APBTMR_CONTROL_ENABLE;
- apbt_writel(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
+ apbt_writel_relaxed(&dw_ced->timer, ctrl, APBTMR_N_CONTROL);
return 0;
}
@@ -323,7 +334,7 @@ void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs)
* start count down from 0xffff_ffff. this is done by toggling the
* enable bit then load initial load count to ~0.
*/
- unsigned long ctrl = apbt_readl(&dw_cs->timer, APBTMR_N_CONTROL);
+ u32 ctrl = apbt_readl(&dw_cs->timer, APBTMR_N_CONTROL);
ctrl &= ~APBTMR_CONTROL_ENABLE;
apbt_writel(&dw_cs->timer, ctrl, APBTMR_N_CONTROL);
@@ -338,11 +349,12 @@ void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs)
static cycle_t __apbt_read_clocksource(struct clocksource *cs)
{
- unsigned long current_count;
+ u32 current_count;
struct dw_apb_clocksource *dw_cs =
clocksource_to_dw_apb_clocksource(cs);
- current_count = apbt_readl(&dw_cs->timer, APBTMR_N_CURRENT_VALUE);
+ current_count = apbt_readl_relaxed(&dw_cs->timer,
+ APBTMR_N_CURRENT_VALUE);
return (cycle_t)~current_count;
}
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c
index a19a3f619cc7..860843cef572 100644
--- a/drivers/clocksource/dw_apb_timer_of.c
+++ b/drivers/clocksource/dw_apb_timer_of.c
@@ -16,6 +16,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <linux/delay.h>
#include <linux/dw_apb_timer.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -130,6 +131,17 @@ static void __init init_sched_clock(void)
sched_clock_register(read_sched_clock, 32, sched_rate);
}
+#ifdef CONFIG_ARM
+static unsigned long dw_apb_delay_timer_read(void)
+{
+ return ~readl_relaxed(sched_io_base);
+}
+
+static struct delay_timer dw_apb_delay_timer = {
+ .read_current_timer = dw_apb_delay_timer_read,
+};
+#endif
+
static int num_called;
static void __init dw_apb_timer_init(struct device_node *timer)
{
@@ -142,6 +154,10 @@ static void __init dw_apb_timer_init(struct device_node *timer)
pr_debug("%s: found clocksource timer\n", __func__);
add_clocksource(timer);
init_sched_clock();
+#ifdef CONFIG_ARM
+ dw_apb_delay_timer.freq = sched_rate;
+ register_current_timer_delay(&dw_apb_delay_timer);
+#endif
break;
default:
break;
diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c
index 0e076c6fc006..75c44079b345 100644
--- a/drivers/clocksource/h8300_timer16.c
+++ b/drivers/clocksource/h8300_timer16.c
@@ -4,85 +4,56 @@
* Copyright 2015 Yoshinori Sato <ysato@users.sourcefoge.jp>
*/
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/init.h>
-#include <linux/platform_device.h>
#include <linux/clocksource.h>
-#include <linux/module.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/of.h>
-
-#include <asm/segment.h>
-#include <asm/irq.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#define TSTR 0
-#define TSNC 1
-#define TMDR 2
-#define TOLR 3
-#define TISRA 4
-#define TISRB 5
#define TISRC 6
#define TCR 0
-#define TIOR 1
#define TCNT 2
-#define GRA 4
-#define GRB 6
-
-#define FLAG_REPROGRAM (1 << 0)
-#define FLAG_SKIPEVENT (1 << 1)
-#define FLAG_IRQCONTEXT (1 << 2)
-#define FLAG_STARTED (1 << 3)
-#define ONESHOT 0
-#define PERIODIC 1
-
-#define RELATIVE 0
-#define ABSOLUTE 1
+#define bset(b, a) iowrite8(ioread8(a) | (1 << (b)), (a))
+#define bclr(b, a) iowrite8(ioread8(a) & ~(1 << (b)), (a))
struct timer16_priv {
- struct platform_device *pdev;
struct clocksource cs;
- struct irqaction irqaction;
unsigned long total_cycles;
- unsigned long mapbase;
- unsigned long mapcommon;
- unsigned long flags;
- unsigned short gra;
+ void __iomem *mapbase;
+ void __iomem *mapcommon;
unsigned short cs_enabled;
unsigned char enb;
- unsigned char imfa;
- unsigned char imiea;
unsigned char ovf;
- raw_spinlock_t lock;
- struct clk *clk;
+ unsigned char ovie;
};
static unsigned long timer16_get_counter(struct timer16_priv *p)
{
- unsigned long v1, v2, v3;
- int o1, o2;
+ unsigned short v1, v2, v3;
+ unsigned char o1, o2;
- o1 = ctrl_inb(p->mapcommon + TISRC) & p->ovf;
+ o1 = ioread8(p->mapcommon + TISRC) & p->ovf;
/* Make sure the timer value is stable. Stolen from acpi_pm.c */
do {
o2 = o1;
- v1 = ctrl_inw(p->mapbase + TCNT);
- v2 = ctrl_inw(p->mapbase + TCNT);
- v3 = ctrl_inw(p->mapbase + TCNT);
- o1 = ctrl_inb(p->mapcommon + TISRC) & p->ovf;
+ v1 = ioread16be(p->mapbase + TCNT);
+ v2 = ioread16be(p->mapbase + TCNT);
+ v3 = ioread16be(p->mapbase + TCNT);
+ o1 = ioread8(p->mapcommon + TISRC) & p->ovf;
} while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
|| (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
- v2 |= 0x10000;
- return v2;
+ if (likely(!o1))
+ return v2;
+ else
+ return v2 + 0x10000;
}
@@ -90,8 +61,7 @@ static irqreturn_t timer16_interrupt(int irq, void *dev_id)
{
struct timer16_priv *p = (struct timer16_priv *)dev_id;
- ctrl_outb(ctrl_inb(p->mapcommon + TISRA) & ~p->imfa,
- p->mapcommon + TISRA);
+ bclr(p->ovf, p->mapcommon + TISRC);
p->total_cycles += 0x10000;
return IRQ_HANDLED;
@@ -105,13 +75,10 @@ static inline struct timer16_priv *cs_to_priv(struct clocksource *cs)
static cycle_t timer16_clocksource_read(struct clocksource *cs)
{
struct timer16_priv *p = cs_to_priv(cs);
- unsigned long flags, raw;
- unsigned long value;
+ unsigned long raw, value;
- raw_spin_lock_irqsave(&p->lock, flags);
value = p->total_cycles;
raw = timer16_get_counter(p);
- raw_spin_unlock_irqrestore(&p->lock, flags);
return value + raw;
}
@@ -123,10 +90,10 @@ static int timer16_enable(struct clocksource *cs)
WARN_ON(p->cs_enabled);
p->total_cycles = 0;
- ctrl_outw(0x0000, p->mapbase + TCNT);
- ctrl_outb(0x83, p->mapbase + TCR);
- ctrl_outb(ctrl_inb(p->mapcommon + TSTR) | p->enb,
- p->mapcommon + TSTR);
+ iowrite16be(0x0000, p->mapbase + TCNT);
+ iowrite8(0x83, p->mapbase + TCR);
+ bset(p->ovie, p->mapcommon + TISRC);
+ bset(p->enb, p->mapcommon + TSTR);
p->cs_enabled = true;
return 0;
@@ -138,116 +105,83 @@ static void timer16_disable(struct clocksource *cs)
WARN_ON(!p->cs_enabled);
- ctrl_outb(ctrl_inb(p->mapcommon + TSTR) & ~p->enb,
- p->mapcommon + TSTR);
+ bclr(p->ovie, p->mapcommon + TISRC);
+ bclr(p->enb, p->mapcommon + TSTR);
p->cs_enabled = false;
}
+static struct timer16_priv timer16_priv = {
+ .cs = {
+ .name = "h8300_16timer",
+ .rating = 200,
+ .read = timer16_clocksource_read,
+ .enable = timer16_enable,
+ .disable = timer16_disable,
+ .mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ },
+};
+
#define REG_CH 0
#define REG_COMM 1
-static int timer16_setup(struct timer16_priv *p, struct platform_device *pdev)
+static void __init h8300_16timer_init(struct device_node *node)
{
- struct resource *res[2];
+ void __iomem *base[2];
int ret, irq;
unsigned int ch;
+ struct clk *clk;
- p->pdev = pdev;
-
- res[REG_CH] = platform_get_resource(p->pdev,
- IORESOURCE_MEM, REG_CH);
- res[REG_COMM] = platform_get_resource(p->pdev,
- IORESOURCE_MEM, REG_COMM);
- if (!res[REG_CH] || !res[REG_COMM]) {
- dev_err(&p->pdev->dev, "failed to get I/O memory\n");
- return -ENXIO;
- }
- irq = platform_get_irq(p->pdev, 0);
- if (irq < 0) {
- dev_err(&p->pdev->dev, "failed to get irq\n");
- return irq;
+ clk = of_clk_get(node, 0);
+ if (IS_ERR(clk)) {
+ pr_err("failed to get clock for clocksource\n");
+ return;
}
- p->clk = clk_get(&p->pdev->dev, "fck");
- if (IS_ERR(p->clk)) {
- dev_err(&p->pdev->dev, "can't get clk\n");
- return PTR_ERR(p->clk);
+ base[REG_CH] = of_iomap(node, 0);
+ if (!base[REG_CH]) {
+ pr_err("failed to map registers for clocksource\n");
+ goto free_clk;
}
- of_property_read_u32(p->pdev->dev.of_node, "renesas,channel", &ch);
-
- p->pdev = pdev;
- p->mapbase = res[REG_CH]->start;
- p->mapcommon = res[REG_COMM]->start;
- p->enb = 1 << ch;
- p->imfa = 1 << ch;
- p->imiea = 1 << (4 + ch);
- p->cs.name = pdev->name;
- p->cs.rating = 200;
- p->cs.read = timer16_clocksource_read;
- p->cs.enable = timer16_enable;
- p->cs.disable = timer16_disable;
- p->cs.mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
- p->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
- ret = request_irq(irq, timer16_interrupt,
- IRQF_TIMER, pdev->name, p);
- if (ret < 0) {
- dev_err(&p->pdev->dev, "failed to request irq %d\n", irq);
- return ret;
+ base[REG_COMM] = of_iomap(node, 1);
+ if (!base[REG_COMM]) {
+ pr_err("failed to map registers for clocksource\n");
+ goto unmap_ch;
}
- clocksource_register_hz(&p->cs, clk_get_rate(p->clk) / 8);
-
- return 0;
-}
-
-static int timer16_probe(struct platform_device *pdev)
-{
- struct timer16_priv *p = platform_get_drvdata(pdev);
-
- if (p) {
- dev_info(&pdev->dev, "kept as earlytimer\n");
- return 0;
+ irq = irq_of_parse_and_map(node, 0);
+ if (!irq) {
+ pr_err("failed to get irq for clockevent\n");
+ goto unmap_comm;
}
- p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
- if (!p)
- return -ENOMEM;
+ of_property_read_u32(node, "renesas,channel", &ch);
- return timer16_setup(p, pdev);
-}
-
-static int timer16_remove(struct platform_device *pdev)
-{
- return -EBUSY;
-}
+ timer16_priv.mapbase = base[REG_CH];
+ timer16_priv.mapcommon = base[REG_COMM];
+ timer16_priv.enb = ch;
+ timer16_priv.ovf = ch;
+ timer16_priv.ovie = 4 + ch;
-static const struct of_device_id timer16_of_table[] = {
- { .compatible = "renesas,16bit-timer" },
- { }
-};
-static struct platform_driver timer16_driver = {
- .probe = timer16_probe,
- .remove = timer16_remove,
- .driver = {
- .name = "h8300h-16timer",
- .of_match_table = of_match_ptr(timer16_of_table),
+ ret = request_irq(irq, timer16_interrupt,
+ IRQF_TIMER, timer16_priv.cs.name, &timer16_priv);
+ if (ret < 0) {
+ pr_err("failed to request irq %d of clocksource\n", irq);
+ goto unmap_comm;
}
-};
-static int __init timer16_init(void)
-{
- return platform_driver_register(&timer16_driver);
-}
+ clocksource_register_hz(&timer16_priv.cs,
+ clk_get_rate(clk) / 8);
+ return;
-static void __exit timer16_exit(void)
-{
- platform_driver_unregister(&timer16_driver);
+unmap_comm:
+ iounmap(base[REG_COMM]);
+unmap_ch:
+ iounmap(base[REG_CH]);
+free_clk:
+ clk_put(clk);
}
-subsys_initcall(timer16_init);
-module_exit(timer16_exit);
-MODULE_AUTHOR("Yoshinori Sato");
-MODULE_DESCRIPTION("H8/300H 16bit Timer Driver");
-MODULE_LICENSE("GPL v2");
+CLOCKSOURCE_OF_DECLARE(h8300_16bit, "renesas,16bit-timer", h8300_16timer_init);
diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c
index 44375d8b9bc4..c151941e1956 100644
--- a/drivers/clocksource/h8300_timer8.c
+++ b/drivers/clocksource/h8300_timer8.c
@@ -8,19 +8,15 @@
*/
#include <linux/errno.h>
-#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
#include <linux/clockchips.h>
-#include <linux/module.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/of.h>
-
-#include <asm/irq.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
#define _8TCR 0
#define _8TCSR 2
@@ -28,126 +24,74 @@
#define TCORB 6
#define _8TCNT 8
-#define FLAG_REPROGRAM (1 << 0)
-#define FLAG_SKIPEVENT (1 << 1)
-#define FLAG_IRQCONTEXT (1 << 2)
+#define CMIEA 6
+#define CMFA 6
+
#define FLAG_STARTED (1 << 3)
-#define ONESHOT 0
-#define PERIODIC 1
+#define SCALE 64
-#define RELATIVE 0
-#define ABSOLUTE 1
+#define bset(b, a) iowrite8(ioread8(a) | (1 << (b)), (a))
+#define bclr(b, a) iowrite8(ioread8(a) & ~(1 << (b)), (a))
struct timer8_priv {
- struct platform_device *pdev;
struct clock_event_device ced;
- struct irqaction irqaction;
- unsigned long mapbase;
- raw_spinlock_t lock;
+ void __iomem *mapbase;
unsigned long flags;
unsigned int rate;
- unsigned int tcora;
- struct clk *pclk;
};
-static unsigned long timer8_get_counter(struct timer8_priv *p)
-{
- unsigned long v1, v2, v3;
- int o1, o2;
-
- o1 = ctrl_inb(p->mapbase + _8TCSR) & 0x20;
-
- /* Make sure the timer value is stable. Stolen from acpi_pm.c */
- do {
- o2 = o1;
- v1 = ctrl_inw(p->mapbase + _8TCNT);
- v2 = ctrl_inw(p->mapbase + _8TCNT);
- v3 = ctrl_inw(p->mapbase + _8TCNT);
- o1 = ctrl_inb(p->mapbase + _8TCSR) & 0x20;
- } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
- || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
-
- v2 |= o1 << 10;
- return v2;
-}
-
static irqreturn_t timer8_interrupt(int irq, void *dev_id)
{
struct timer8_priv *p = dev_id;
- ctrl_outb(ctrl_inb(p->mapbase + _8TCSR) & ~0x40,
- p->mapbase + _8TCSR);
- p->flags |= FLAG_IRQCONTEXT;
- ctrl_outw(p->tcora, p->mapbase + TCORA);
- if (!(p->flags & FLAG_SKIPEVENT)) {
- if (clockevent_state_oneshot(&p->ced))
- ctrl_outw(0x0000, p->mapbase + _8TCR);
- p->ced.event_handler(&p->ced);
- }
- p->flags &= ~(FLAG_SKIPEVENT | FLAG_IRQCONTEXT);
+ if (clockevent_state_oneshot(&p->ced))
+ iowrite16be(0x0000, p->mapbase + _8TCR);
+
+ p->ced.event_handler(&p->ced);
+
+ bclr(CMFA, p->mapbase + _8TCSR);
return IRQ_HANDLED;
}
static void timer8_set_next(struct timer8_priv *p, unsigned long delta)
{
- unsigned long flags;
- unsigned long now;
-
- raw_spin_lock_irqsave(&p->lock, flags);
if (delta >= 0x10000)
- dev_warn(&p->pdev->dev, "delta out of range\n");
- now = timer8_get_counter(p);
- p->tcora = delta;
- ctrl_outb(ctrl_inb(p->mapbase + _8TCR) | 0x40, p->mapbase + _8TCR);
- if (delta > now)
- ctrl_outw(delta, p->mapbase + TCORA);
- else
- ctrl_outw(now + 1, p->mapbase + TCORA);
-
- raw_spin_unlock_irqrestore(&p->lock, flags);
+ pr_warn("delta out of range\n");
+ bclr(CMIEA, p->mapbase + _8TCR);
+ iowrite16be(delta, p->mapbase + TCORA);
+ iowrite16be(0x0000, p->mapbase + _8TCNT);
+ bclr(CMFA, p->mapbase + _8TCSR);
+ bset(CMIEA, p->mapbase + _8TCR);
}
static int timer8_enable(struct timer8_priv *p)
{
- p->rate = clk_get_rate(p->pclk) / 64;
- ctrl_outw(0xffff, p->mapbase + TCORA);
- ctrl_outw(0x0000, p->mapbase + _8TCNT);
- ctrl_outw(0x0c02, p->mapbase + _8TCR);
+ iowrite16be(0xffff, p->mapbase + TCORA);
+ iowrite16be(0x0000, p->mapbase + _8TCNT);
+ iowrite16be(0x0c02, p->mapbase + _8TCR);
return 0;
}
static int timer8_start(struct timer8_priv *p)
{
- int ret = 0;
- unsigned long flags;
-
- raw_spin_lock_irqsave(&p->lock, flags);
-
- if (!(p->flags & FLAG_STARTED))
- ret = timer8_enable(p);
+ int ret;
- if (ret)
- goto out;
- p->flags |= FLAG_STARTED;
+ if ((p->flags & FLAG_STARTED))
+ return 0;
- out:
- raw_spin_unlock_irqrestore(&p->lock, flags);
+ ret = timer8_enable(p);
+ if (!ret)
+ p->flags |= FLAG_STARTED;
return ret;
}
static void timer8_stop(struct timer8_priv *p)
{
- unsigned long flags;
-
- raw_spin_lock_irqsave(&p->lock, flags);
-
- ctrl_outw(0x0000, p->mapbase + _8TCR);
-
- raw_spin_unlock_irqrestore(&p->lock, flags);
+ iowrite16be(0x0000, p->mapbase + _8TCR);
}
static inline struct timer8_priv *ced_to_priv(struct clock_event_device *ced)
@@ -155,7 +99,7 @@ static inline struct timer8_priv *ced_to_priv(struct clock_event_device *ced)
return container_of(ced, struct timer8_priv, ced);
}
-static void timer8_clock_event_start(struct timer8_priv *p, int periodic)
+static void timer8_clock_event_start(struct timer8_priv *p, unsigned long delta)
{
struct clock_event_device *ced = &p->ced;
@@ -166,7 +110,7 @@ static void timer8_clock_event_start(struct timer8_priv *p, int periodic)
ced->max_delta_ns = clockevent_delta2ns(0xffff, ced);
ced->min_delta_ns = clockevent_delta2ns(0x0001, ced);
- timer8_set_next(p, periodic?(p->rate + HZ/2) / HZ:0x10000);
+ timer8_set_next(p, delta);
}
static int timer8_clock_event_shutdown(struct clock_event_device *ced)
@@ -179,9 +123,9 @@ static int timer8_clock_event_periodic(struct clock_event_device *ced)
{
struct timer8_priv *p = ced_to_priv(ced);
- dev_info(&p->pdev->dev, "used for periodic clock events\n");
+ pr_info("%s: used for periodic clock events\n", ced->name);
timer8_stop(p);
- timer8_clock_event_start(p, PERIODIC);
+ timer8_clock_event_start(p, (p->rate + HZ/2) / HZ);
return 0;
}
@@ -190,9 +134,9 @@ static int timer8_clock_event_oneshot(struct clock_event_device *ced)
{
struct timer8_priv *p = ced_to_priv(ced);
- dev_info(&p->pdev->dev, "used for oneshot clock events\n");
+ pr_info("%s: used for oneshot clock events\n", ced->name);
timer8_stop(p);
- timer8_clock_event_start(p, ONESHOT);
+ timer8_clock_event_start(p, 0x10000);
return 0;
}
@@ -208,110 +152,64 @@ static int timer8_clock_event_next(unsigned long delta,
return 0;
}
-static int timer8_setup(struct timer8_priv *p,
- struct platform_device *pdev)
+static struct timer8_priv timer8_priv = {
+ .ced = {
+ .name = "h8300_8timer",
+ .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+ .rating = 200,
+ .set_next_event = timer8_clock_event_next,
+ .set_state_shutdown = timer8_clock_event_shutdown,
+ .set_state_periodic = timer8_clock_event_periodic,
+ .set_state_oneshot = timer8_clock_event_oneshot,
+ },
+};
+
+static void __init h8300_8timer_init(struct device_node *node)
{
- struct resource *res;
+ void __iomem *base;
int irq;
- int ret;
+ struct clk *clk;
- p->pdev = pdev;
-
- res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&p->pdev->dev, "failed to get I/O memory\n");
- return -ENXIO;
+ clk = of_clk_get(node, 0);
+ if (IS_ERR(clk)) {
+ pr_err("failed to get clock for clockevent\n");
+ return;
}
- irq = platform_get_irq(p->pdev, 0);
- if (irq < 0) {
- dev_err(&p->pdev->dev, "failed to get irq\n");
- return -ENXIO;
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("failed to map registers for clockevent\n");
+ goto free_clk;
}
- p->mapbase = res->start;
-
- p->irqaction.name = dev_name(&p->pdev->dev);
- p->irqaction.handler = timer8_interrupt;
- p->irqaction.dev_id = p;
- p->irqaction.flags = IRQF_TIMER;
-
- p->pclk = clk_get(&p->pdev->dev, "fck");
- if (IS_ERR(p->pclk)) {
- dev_err(&p->pdev->dev, "can't get clk\n");
- return PTR_ERR(p->pclk);
+ irq = irq_of_parse_and_map(node, 0);
+ if (!irq) {
+ pr_err("failed to get irq for clockevent\n");
+ goto unmap_reg;
}
- p->ced.name = pdev->name;
- p->ced.features = CLOCK_EVT_FEAT_PERIODIC |
- CLOCK_EVT_FEAT_ONESHOT;
- p->ced.rating = 200;
- p->ced.cpumask = cpumask_of(0);
- p->ced.set_next_event = timer8_clock_event_next;
- p->ced.set_state_shutdown = timer8_clock_event_shutdown;
- p->ced.set_state_periodic = timer8_clock_event_periodic;
- p->ced.set_state_oneshot = timer8_clock_event_oneshot;
-
- ret = setup_irq(irq, &p->irqaction);
- if (ret < 0) {
- dev_err(&p->pdev->dev,
- "failed to request irq %d\n", irq);
- return ret;
- }
- clockevents_register_device(&p->ced);
- platform_set_drvdata(pdev, p);
+ timer8_priv.mapbase = base;
- return 0;
-}
-
-static int timer8_probe(struct platform_device *pdev)
-{
- struct timer8_priv *p = platform_get_drvdata(pdev);
-
- if (p) {
- dev_info(&pdev->dev, "kept as earlytimer\n");
- return 0;
+ timer8_priv.rate = clk_get_rate(clk) / SCALE;
+ if (!timer8_priv.rate) {
+ pr_err("Failed to get rate for the clocksource\n");
+ goto unmap_reg;
}
- p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
- if (!p)
- return -ENOMEM;
-
- return timer8_setup(p, pdev);
-}
-
-static int timer8_remove(struct platform_device *pdev)
-{
- return -EBUSY;
-}
-
-static const struct of_device_id timer8_of_table[] __maybe_unused = {
- { .compatible = "renesas,8bit-timer" },
- { }
-};
-
-MODULE_DEVICE_TABLE(of, timer8_of_table);
-static struct platform_driver timer8_driver = {
- .probe = timer8_probe,
- .remove = timer8_remove,
- .driver = {
- .name = "h8300-8timer",
- .of_match_table = of_match_ptr(timer8_of_table),
+ if (request_irq(irq, timer8_interrupt, IRQF_TIMER,
+ timer8_priv.ced.name, &timer8_priv) < 0) {
+ pr_err("failed to request irq %d for clockevent\n", irq);
+ goto unmap_reg;
}
-};
-static int __init timer8_init(void)
-{
- return platform_driver_register(&timer8_driver);
-}
+ clockevents_config_and_register(&timer8_priv.ced,
+ timer8_priv.rate, 1, 0x0000ffff);
-static void __exit timer8_exit(void)
-{
- platform_driver_unregister(&timer8_driver);
+ return;
+unmap_reg:
+ iounmap(base);
+free_clk:
+ clk_put(clk);
}
-subsys_initcall(timer8_init);
-module_exit(timer8_exit);
-MODULE_AUTHOR("Yoshinori Sato");
-MODULE_DESCRIPTION("H8/300 8bit Timer Driver");
-MODULE_LICENSE("GPL v2");
+CLOCKSOURCE_OF_DECLARE(h8300_8bit, "renesas,8bit-timer", h8300_8timer_init);
diff --git a/drivers/clocksource/h8300_tpu.c b/drivers/clocksource/h8300_tpu.c
index 5487410bfabb..d4c1a287c262 100644
--- a/drivers/clocksource/h8300_tpu.c
+++ b/drivers/clocksource/h8300_tpu.c
@@ -1,42 +1,30 @@
/*
- * H8/300 TPU Driver
+ * H8S TPU Driver
*
* Copyright 2015 Yoshinori Sato <ysato@users.sourcefoge.jp>
*
*/
#include <linux/errno.h>
-#include <linux/sched.h>
#include <linux/kernel.h>
-#include <linux/interrupt.h>
#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
#include <linux/clocksource.h>
-#include <linux/module.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
-#include <asm/irq.h>
+#define TCR 0x0
+#define TSR 0x5
+#define TCNT 0x6
-#define TCR 0
-#define TMDR 1
-#define TIOR 2
-#define TER 4
-#define TSR 5
-#define TCNT 6
-#define TGRA 8
-#define TGRB 10
-#define TGRC 12
-#define TGRD 14
+#define TCFV 0x10
struct tpu_priv {
- struct platform_device *pdev;
struct clocksource cs;
- struct clk *clk;
- unsigned long mapbase1;
- unsigned long mapbase2;
+ void __iomem *mapbase1;
+ void __iomem *mapbase2;
raw_spinlock_t lock;
unsigned int cs_enabled;
};
@@ -45,8 +33,8 @@ static inline unsigned long read_tcnt32(struct tpu_priv *p)
{
unsigned long tcnt;
- tcnt = ctrl_inw(p->mapbase1 + TCNT) << 16;
- tcnt |= ctrl_inw(p->mapbase2 + TCNT);
+ tcnt = ioread16be(p->mapbase1 + TCNT) << 16;
+ tcnt |= ioread16be(p->mapbase2 + TCNT);
return tcnt;
}
@@ -55,7 +43,7 @@ static int tpu_get_counter(struct tpu_priv *p, unsigned long long *val)
unsigned long v1, v2, v3;
int o1, o2;
- o1 = ctrl_inb(p->mapbase1 + TSR) & 0x10;
+ o1 = ioread8(p->mapbase1 + TSR) & TCFV;
/* Make sure the timer value is stable. Stolen from acpi_pm.c */
do {
@@ -63,7 +51,7 @@ static int tpu_get_counter(struct tpu_priv *p, unsigned long long *val)
v1 = read_tcnt32(p);
v2 = read_tcnt32(p);
v3 = read_tcnt32(p);
- o1 = ctrl_inb(p->mapbase1 + TSR) & 0x10;
+ o1 = ioread8(p->mapbase1 + TSR) & TCFV;
} while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
|| (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
@@ -96,10 +84,10 @@ static int tpu_clocksource_enable(struct clocksource *cs)
WARN_ON(p->cs_enabled);
- ctrl_outw(0, p->mapbase1 + TCNT);
- ctrl_outw(0, p->mapbase2 + TCNT);
- ctrl_outb(0x0f, p->mapbase1 + TCR);
- ctrl_outb(0x03, p->mapbase2 + TCR);
+ iowrite16be(0, p->mapbase1 + TCNT);
+ iowrite16be(0, p->mapbase2 + TCNT);
+ iowrite8(0x0f, p->mapbase1 + TCR);
+ iowrite8(0x03, p->mapbase2 + TCR);
p->cs_enabled = true;
return 0;
@@ -111,96 +99,59 @@ static void tpu_clocksource_disable(struct clocksource *cs)
WARN_ON(!p->cs_enabled);
- ctrl_outb(0, p->mapbase1 + TCR);
- ctrl_outb(0, p->mapbase2 + TCR);
+ iowrite8(0, p->mapbase1 + TCR);
+ iowrite8(0, p->mapbase2 + TCR);
p->cs_enabled = false;
}
+static struct tpu_priv tpu_priv = {
+ .cs = {
+ .name = "H8S_TPU",
+ .rating = 200,
+ .read = tpu_clocksource_read,
+ .enable = tpu_clocksource_enable,
+ .disable = tpu_clocksource_disable,
+ .mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+ },
+};
+
#define CH_L 0
#define CH_H 1
-static int __init tpu_setup(struct tpu_priv *p, struct platform_device *pdev)
+static void __init h8300_tpu_init(struct device_node *node)
{
- struct resource *res[2];
-
- p->pdev = pdev;
+ void __iomem *base[2];
+ struct clk *clk;
- res[CH_L] = platform_get_resource(p->pdev, IORESOURCE_MEM, CH_L);
- res[CH_H] = platform_get_resource(p->pdev, IORESOURCE_MEM, CH_H);
- if (!res[CH_L] || !res[CH_H]) {
- dev_err(&p->pdev->dev, "failed to get I/O memory\n");
- return -ENXIO;
+ clk = of_clk_get(node, 0);
+ if (IS_ERR(clk)) {
+ pr_err("failed to get clock for clocksource\n");
+ return;
}
- p->clk = clk_get(&p->pdev->dev, "fck");
- if (IS_ERR(p->clk)) {
- dev_err(&p->pdev->dev, "can't get clk\n");
- return PTR_ERR(p->clk);
+ base[CH_L] = of_iomap(node, CH_L);
+ if (!base[CH_L]) {
+ pr_err("failed to map registers for clocksource\n");
+ goto free_clk;
}
-
- p->mapbase1 = res[CH_L]->start;
- p->mapbase2 = res[CH_H]->start;
-
- p->cs.name = pdev->name;
- p->cs.rating = 200;
- p->cs.read = tpu_clocksource_read;
- p->cs.enable = tpu_clocksource_enable;
- p->cs.disable = tpu_clocksource_disable;
- p->cs.mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8);
- p->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
- clocksource_register_hz(&p->cs, clk_get_rate(p->clk) / 64);
- platform_set_drvdata(pdev, p);
-
- return 0;
-}
-
-static int tpu_probe(struct platform_device *pdev)
-{
- struct tpu_priv *p = platform_get_drvdata(pdev);
-
- if (p) {
- dev_info(&pdev->dev, "kept as earlytimer\n");
- return 0;
+ base[CH_H] = of_iomap(node, CH_H);
+ if (!base[CH_H]) {
+ pr_err("failed to map registers for clocksource\n");
+ goto unmap_L;
}
- p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
- if (!p)
- return -ENOMEM;
+ tpu_priv.mapbase1 = base[CH_L];
+ tpu_priv.mapbase2 = base[CH_H];
- return tpu_setup(p, pdev);
-}
-
-static int tpu_remove(struct platform_device *pdev)
-{
- return -EBUSY;
-}
-
-static const struct of_device_id tpu_of_table[] = {
- { .compatible = "renesas,tpu" },
- { }
-};
+ clocksource_register_hz(&tpu_priv.cs, clk_get_rate(clk) / 64);
-static struct platform_driver tpu_driver = {
- .probe = tpu_probe,
- .remove = tpu_remove,
- .driver = {
- .name = "h8s-tpu",
- .of_match_table = of_match_ptr(tpu_of_table),
- }
-};
-
-static int __init tpu_init(void)
-{
- return platform_driver_register(&tpu_driver);
-}
+ return;
-static void __exit tpu_exit(void)
-{
- platform_driver_unregister(&tpu_driver);
+unmap_L:
+ iounmap(base[CH_H]);
+free_clk:
+ clk_put(clk);
}
-subsys_initcall(tpu_init);
-module_exit(tpu_exit);
-MODULE_AUTHOR("Yoshinori Sato");
-MODULE_DESCRIPTION("H8S Timer Pulse Unit Driver");
-MODULE_LICENSE("GPL v2");
+CLOCKSOURCE_OF_DECLARE(h8300_tpu, "renesas,tpu", h8300_tpu_init);
diff --git a/drivers/clocksource/mtk_timer.c b/drivers/clocksource/mtk_timer.c
index fbfc74685e6a..d67bc356488f 100644
--- a/drivers/clocksource/mtk_timer.c
+++ b/drivers/clocksource/mtk_timer.c
@@ -16,6 +16,8 @@
* GNU General Public License for more details.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/clk.h>
#include <linux/clockchips.h>
#include <linux/interrupt.h>
@@ -187,10 +189,8 @@ static void __init mtk_timer_init(struct device_node *node)
struct clk *clk;
evt = kzalloc(sizeof(*evt), GFP_KERNEL);
- if (!evt) {
- pr_warn("Can't allocate mtk clock event driver struct");
+ if (!evt)
return;
- }
evt->dev.name = "mtk_tick";
evt->dev.rating = 300;
@@ -204,31 +204,31 @@ static void __init mtk_timer_init(struct device_node *node)
evt->gpt_base = of_io_request_and_map(node, 0, "mtk-timer");
if (IS_ERR(evt->gpt_base)) {
- pr_warn("Can't get resource\n");
- return;
+ pr_err("Can't get resource\n");
+ goto err_kzalloc;
}
evt->dev.irq = irq_of_parse_and_map(node, 0);
if (evt->dev.irq <= 0) {
- pr_warn("Can't parse IRQ");
+ pr_err("Can't parse IRQ\n");
goto err_mem;
}
clk = of_clk_get(node, 0);
if (IS_ERR(clk)) {
- pr_warn("Can't get timer clock");
+ pr_err("Can't get timer clock\n");
goto err_irq;
}
if (clk_prepare_enable(clk)) {
- pr_warn("Can't prepare clock");
+ pr_err("Can't prepare clock\n");
goto err_clk_put;
}
rate = clk_get_rate(clk);
if (request_irq(evt->dev.irq, mtk_timer_interrupt,
IRQF_TIMER | IRQF_IRQPOLL, "mtk_timer", evt)) {
- pr_warn("failed to setup irq %d\n", evt->dev.irq);
+ pr_err("failed to setup irq %d\n", evt->dev.irq);
goto err_clk_disable;
}
@@ -260,5 +260,7 @@ err_mem:
iounmap(evt->gpt_base);
of_address_to_resource(node, 0, &res);
release_mem_region(res.start, resource_size(&res));
+err_kzalloc:
+ kfree(evt);
}
CLOCKSOURCE_OF_DECLARE(mtk_mt6577, "mediatek,mt6577-timer", mtk_timer_init);
diff --git a/drivers/clocksource/rockchip_timer.c b/drivers/clocksource/rockchip_timer.c
index d3c1742ded1a..8c77a529d0d4 100644
--- a/drivers/clocksource/rockchip_timer.c
+++ b/drivers/clocksource/rockchip_timer.c
@@ -17,16 +17,16 @@
#define TIMER_NAME "rk_timer"
-#define TIMER_LOAD_COUNT0 0x00
-#define TIMER_LOAD_COUNT1 0x04
-#define TIMER_CONTROL_REG 0x10
-#define TIMER_INT_STATUS 0x18
+#define TIMER_LOAD_COUNT0 0x00
+#define TIMER_LOAD_COUNT1 0x04
+#define TIMER_CONTROL_REG 0x10
+#define TIMER_INT_STATUS 0x18
-#define TIMER_DISABLE 0x0
-#define TIMER_ENABLE 0x1
-#define TIMER_MODE_FREE_RUNNING (0 << 1)
-#define TIMER_MODE_USER_DEFINED_COUNT (1 << 1)
-#define TIMER_INT_UNMASK (1 << 2)
+#define TIMER_DISABLE 0x0
+#define TIMER_ENABLE 0x1
+#define TIMER_MODE_FREE_RUNNING (0 << 1)
+#define TIMER_MODE_USER_DEFINED_COUNT (1 << 1)
+#define TIMER_INT_UNMASK (1 << 2)
struct bc_timer {
struct clock_event_device ce;
@@ -49,14 +49,12 @@ static inline void __iomem *rk_base(struct clock_event_device *ce)
static inline void rk_timer_disable(struct clock_event_device *ce)
{
writel_relaxed(TIMER_DISABLE, rk_base(ce) + TIMER_CONTROL_REG);
- dsb();
}
static inline void rk_timer_enable(struct clock_event_device *ce, u32 flags)
{
writel_relaxed(TIMER_ENABLE | TIMER_INT_UNMASK | flags,
rk_base(ce) + TIMER_CONTROL_REG);
- dsb();
}
static void rk_timer_update_counter(unsigned long cycles,
@@ -64,13 +62,11 @@ static void rk_timer_update_counter(unsigned long cycles,
{
writel_relaxed(cycles, rk_base(ce) + TIMER_LOAD_COUNT0);
writel_relaxed(0, rk_base(ce) + TIMER_LOAD_COUNT1);
- dsb();
}
static void rk_timer_interrupt_clear(struct clock_event_device *ce)
{
writel_relaxed(1, rk_base(ce) + TIMER_INT_STATUS);
- dsb();
}
static inline int rk_timer_set_next_event(unsigned long cycles,
@@ -173,4 +169,5 @@ static void __init rk_timer_init(struct device_node *np)
clockevents_config_and_register(ce, bc_timer.freq, 1, UINT_MAX);
}
+
CLOCKSOURCE_OF_DECLARE(rk_timer, "rockchip,rk3288-timer", rk_timer_init);
diff --git a/drivers/clocksource/tango_xtal.c b/drivers/clocksource/tango_xtal.c
index d297b30d2bc0..2bcecafdeaea 100644
--- a/drivers/clocksource/tango_xtal.c
+++ b/drivers/clocksource/tango_xtal.c
@@ -19,19 +19,6 @@ static u64 notrace read_sched_clock(void)
return read_xtal_counter();
}
-static cycle_t read_clocksource(struct clocksource *cs)
-{
- return read_xtal_counter();
-}
-
-static struct clocksource tango_xtal = {
- .name = "tango-xtal",
- .rating = 350,
- .read = read_clocksource,
- .mask = CLOCKSOURCE_MASK(32),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
static void __init tango_clocksource_init(struct device_node *np)
{
struct clk *clk;
@@ -53,8 +40,9 @@ static void __init tango_clocksource_init(struct device_node *np)
delay_timer.freq = xtal_freq;
delay_timer.read_current_timer = read_xtal_counter;
- ret = clocksource_register_hz(&tango_xtal, xtal_freq);
- if (ret != 0) {
+ ret = clocksource_mmio_init(xtal_in_cnt, "tango-xtal", xtal_freq, 350,
+ 32, clocksource_mmio_readl_up);
+ if (!ret) {
pr_err("%s: registration failed\n", np->full_name);
return;
}
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c
index 6ebda1177e79..38333aba3055 100644
--- a/drivers/clocksource/tegra20_timer.c
+++ b/drivers/clocksource/tegra20_timer.c
@@ -96,7 +96,8 @@ static struct clock_event_device tegra_clockevent = {
.name = "timer0",
.rating = 300,
.features = CLOCK_EVT_FEAT_ONESHOT |
- CLOCK_EVT_FEAT_PERIODIC,
+ CLOCK_EVT_FEAT_PERIODIC |
+ CLOCK_EVT_FEAT_DYNIRQ,
.set_next_event = tegra_timer_set_next_event,
.set_state_shutdown = tegra_timer_shutdown,
.set_state_periodic = tegra_timer_set_periodic,
diff --git a/drivers/clocksource/time-lpc32xx.c b/drivers/clocksource/time-lpc32xx.c
index a1c06a2bc77c..1316876b487a 100644
--- a/drivers/clocksource/time-lpc32xx.c
+++ b/drivers/clocksource/time-lpc32xx.c
@@ -125,7 +125,7 @@ static int __init lpc32xx_clocksource_init(struct device_node *np)
clk = of_clk_get_by_name(np, "timerclk");
if (IS_ERR(clk)) {
- pr_err("clock get failed (%lu)\n", PTR_ERR(clk));
+ pr_err("clock get failed (%ld)\n", PTR_ERR(clk));
return PTR_ERR(clk);
}
@@ -184,7 +184,7 @@ static int __init lpc32xx_clockevent_init(struct device_node *np)
clk = of_clk_get_by_name(np, "timerclk");
if (IS_ERR(clk)) {
- pr_err("clock get failed (%lu)\n", PTR_ERR(clk));
+ pr_err("clock get failed (%ld)\n", PTR_ERR(clk));
return PTR_ERR(clk);
}
diff --git a/drivers/clocksource/time-pistachio.c b/drivers/clocksource/time-pistachio.c
index bba679900054..3269d9ef7a18 100644
--- a/drivers/clocksource/time-pistachio.c
+++ b/drivers/clocksource/time-pistachio.c
@@ -84,7 +84,7 @@ pistachio_clocksource_read_cycles(struct clocksource *cs)
counter = gpt_readl(pcs->base, TIMER_CURRENT_VALUE, 0);
raw_spin_unlock_irqrestore(&pcs->lock, flags);
- return ~(cycle_t)counter;
+ return (cycle_t)~counter;
}
static u64 notrace pistachio_read_sched_clock(void)
diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c
index bca9573e036a..24c83f9efd87 100644
--- a/drivers/clocksource/timer-sun5i.c
+++ b/drivers/clocksource/timer-sun5i.c
@@ -152,13 +152,6 @@ static irqreturn_t sun5i_timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static cycle_t sun5i_clksrc_read(struct clocksource *clksrc)
-{
- struct sun5i_timer_clksrc *cs = to_sun5i_timer_clksrc(clksrc);
-
- return ~readl(cs->timer.base + TIMER_CNTVAL_LO_REG(1));
-}
-
static int sun5i_rate_cb_clksrc(struct notifier_block *nb,
unsigned long event, void *data)
{
@@ -217,13 +210,8 @@ static int __init sun5i_setup_clocksource(struct device_node *node,
writel(TIMER_CTL_ENABLE | TIMER_CTL_RELOAD,
base + TIMER_CTL_REG(1));
- cs->clksrc.name = node->name;
- cs->clksrc.rating = 340;
- cs->clksrc.read = sun5i_clksrc_read;
- cs->clksrc.mask = CLOCKSOURCE_MASK(32);
- cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
-
- ret = clocksource_register_hz(&cs->clksrc, rate);
+ ret = clocksource_mmio_init(base + TIMER_CNTVAL_LO_REG(1), node->name,
+ rate, 340, 32, clocksource_mmio_readl_down);
if (ret) {
pr_err("Couldn't register clock source.\n");
goto err_remove_notifier;
diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c
index a92e94b40b5b..de49805fbb09 100644
--- a/drivers/clocksource/vt8500_timer.c
+++ b/drivers/clocksource/vt8500_timer.c
@@ -30,7 +30,6 @@
#include <linux/clocksource.h>
#include <linux/clockchips.h>
#include <linux/delay.h>
-#include <asm/mach/time.h>
#include <linux/of.h>
#include <linux/of_address.h>
diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c
index da2d6777bd09..97a364694bfc 100644
--- a/drivers/crypto/padlock-aes.c
+++ b/drivers/crypto/padlock-aes.c
@@ -515,7 +515,7 @@ static int __init padlock_init(void)
if (!x86_match_cpu(padlock_cpu_id))
return -ENODEV;
- if (!cpu_has_xcrypt_enabled) {
+ if (!boot_cpu_has(X86_FEATURE_XCRYPT_EN)) {
printk(KERN_NOTICE PFX "VIA PadLock detected, but not enabled. Hmm, strange...\n");
return -ENODEV;
}
diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c
index 4e154c9b9206..8c5f90647b7a 100644
--- a/drivers/crypto/padlock-sha.c
+++ b/drivers/crypto/padlock-sha.c
@@ -540,7 +540,7 @@ static int __init padlock_init(void)
struct shash_alg *sha1;
struct shash_alg *sha256;
- if (!x86_match_cpu(padlock_sha_ids) || !cpu_has_phe_enabled)
+ if (!x86_match_cpu(padlock_sha_ids) || !boot_cpu_has(X86_FEATURE_PHE_EN))
return -ENODEV;
/* Register the newly added algorithm module if on *
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index dbf53e08bdd1..be163e20fe56 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_EDAC) := edac_stub.o
obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o
edac_core-y := edac_mc.o edac_device.o edac_mc_sysfs.o
-edac_core-y += edac_module.o edac_device_sysfs.o
+edac_core-y += edac_module.o edac_device_sysfs.o wq.o
edac_core-$(CONFIG_EDAC_DEBUG) += debugfs.o
diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c
index 592af5f0cf39..a97900333e2d 100644
--- a/drivers/edac/edac_device.c
+++ b/drivers/edac/edac_device.c
@@ -390,11 +390,9 @@ static void edac_device_workq_function(struct work_struct *work_req)
* between integral seconds
*/
if (edac_dev->poll_msec == 1000)
- queue_delayed_work(edac_workqueue, &edac_dev->work,
- round_jiffies_relative(edac_dev->delay));
+ edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
else
- queue_delayed_work(edac_workqueue, &edac_dev->work,
- edac_dev->delay);
+ edac_queue_work(&edac_dev->work, edac_dev->delay);
}
/*
@@ -402,8 +400,8 @@ static void edac_device_workq_function(struct work_struct *work_req)
* initialize a workq item for this edac_device instance
* passing in the new delay period in msec
*/
-void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
- unsigned msec)
+static void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
+ unsigned msec)
{
edac_dbg(0, "\n");
@@ -422,29 +420,23 @@ void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
* to fire together on the 1 second exactly
*/
if (edac_dev->poll_msec == 1000)
- queue_delayed_work(edac_workqueue, &edac_dev->work,
- round_jiffies_relative(edac_dev->delay));
+ edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
else
- queue_delayed_work(edac_workqueue, &edac_dev->work,
- edac_dev->delay);
+ edac_queue_work(&edac_dev->work, edac_dev->delay);
}
/*
* edac_device_workq_teardown
* stop the workq processing on this edac_dev
*/
-void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev)
+static void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev)
{
- int status;
-
if (!edac_dev->edac_check)
return;
- status = cancel_delayed_work(&edac_dev->work);
- if (status == 0) {
- /* workq instance might be running, wait for it */
- flush_workqueue(edac_workqueue);
- }
+ edac_dev->op_state = OP_OFFLINE;
+
+ edac_stop_work(&edac_dev->work);
}
/*
@@ -457,16 +449,15 @@ void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev)
void edac_device_reset_delay_period(struct edac_device_ctl_info *edac_dev,
unsigned long value)
{
- /* cancel the current workq request, without the mutex lock */
- edac_device_workq_teardown(edac_dev);
+ unsigned long jiffs = msecs_to_jiffies(value);
- /* acquire the mutex before doing the workq setup */
- mutex_lock(&device_ctls_mutex);
+ if (value == 1000)
+ jiffs = round_jiffies_relative(value);
- /* restart the workq request, with new delay value */
- edac_device_workq_setup(edac_dev, value);
+ edac_dev->poll_msec = value;
+ edac_dev->delay = jiffs;
- mutex_unlock(&device_ctls_mutex);
+ edac_mod_work(&edac_dev->work, jiffs);
}
/*
diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c
index fb68a06ad683..93da1a45c716 100644
--- a/drivers/edac/edac_device_sysfs.c
+++ b/drivers/edac/edac_device_sysfs.c
@@ -237,11 +237,6 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
/* get the /sys/devices/system/edac reference */
edac_subsys = edac_get_sysfs_subsys();
- if (edac_subsys == NULL) {
- edac_dbg(1, "no edac_subsys error\n");
- err = -ENODEV;
- goto err_out;
- }
/* Point to the 'edac_subsys' this instance 'reports' to */
edac_dev->edac_subsys = edac_subsys;
@@ -256,7 +251,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
if (!try_module_get(edac_dev->owner)) {
err = -ENODEV;
- goto err_mod_get;
+ goto err_out;
}
/* register */
@@ -282,9 +277,6 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
err_kobj_reg:
module_put(edac_dev->owner);
-err_mod_get:
- edac_put_sysfs_subsys();
-
err_out:
return err;
}
@@ -306,7 +298,6 @@ void edac_device_unregister_sysfs_main_kobj(struct edac_device_ctl_info *dev)
* b) 'kfree' the memory
*/
kobject_put(&dev->kobj);
- edac_put_sysfs_subsys();
}
/* edac_dev -> instance information */
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 77ecd6a4179a..8adfc167c2e3 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -548,8 +548,7 @@ static void edac_mc_workq_function(struct work_struct *work_req)
mutex_unlock(&mem_ctls_mutex);
/* Reschedule */
- queue_delayed_work(edac_workqueue, &mci->work,
- msecs_to_jiffies(edac_mc_get_poll_msec()));
+ edac_queue_work(&mci->work, msecs_to_jiffies(edac_mc_get_poll_msec()));
}
/*
@@ -561,8 +560,7 @@ static void edac_mc_workq_function(struct work_struct *work_req)
*
* called with the mem_ctls_mutex held
*/
-static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec,
- bool init)
+static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec)
{
edac_dbg(0, "\n");
@@ -570,10 +568,9 @@ static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec,
if (mci->op_state != OP_RUNNING_POLL)
return;
- if (init)
- INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);
+ INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);
- mod_delayed_work(edac_workqueue, &mci->work, msecs_to_jiffies(msec));
+ edac_queue_work(&mci->work, msecs_to_jiffies(msec));
}
/*
@@ -586,18 +583,9 @@ static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec,
*/
static void edac_mc_workq_teardown(struct mem_ctl_info *mci)
{
- int status;
-
- if (mci->op_state != OP_RUNNING_POLL)
- return;
-
- status = cancel_delayed_work(&mci->work);
- if (status == 0) {
- edac_dbg(0, "not canceled, flush the queue\n");
+ mci->op_state = OP_OFFLINE;
- /* workq instance might be running, wait for it */
- flush_workqueue(edac_workqueue);
- }
+ edac_stop_work(&mci->work);
}
/*
@@ -616,9 +604,8 @@ void edac_mc_reset_delay_period(unsigned long value)
list_for_each(item, &mc_devices) {
mci = list_entry(item, struct mem_ctl_info, link);
- edac_mc_workq_setup(mci, value, false);
+ edac_mod_work(&mci->work, value);
}
-
mutex_unlock(&mem_ctls_mutex);
}
@@ -789,7 +776,7 @@ int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
/* This instance is NOW RUNNING */
mci->op_state = OP_RUNNING_POLL;
- edac_mc_workq_setup(mci, edac_mc_get_poll_msec(), true);
+ edac_mc_workq_setup(mci, edac_mc_get_poll_msec());
} else {
mci->op_state = OP_RUNNING_INTERRUPT;
}
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index a75acea0f674..26e65ab5932a 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -880,21 +880,26 @@ static struct device_type mci_attr_type = {
int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
const struct attribute_group **groups)
{
+ char *name;
int i, err;
/*
* The memory controller needs its own bus, in order to avoid
* namespace conflicts at /sys/bus/edac.
*/
- mci->bus->name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx);
- if (!mci->bus->name)
+ name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx);
+ if (!name)
return -ENOMEM;
+ mci->bus->name = name;
+
edac_dbg(0, "creating bus %s\n", mci->bus->name);
err = bus_register(mci->bus);
- if (err < 0)
- goto fail_free_name;
+ if (err < 0) {
+ kfree(name);
+ return err;
+ }
/* get the /sys/devices/system/edac subsys reference */
mci->dev.type = &mci_attr_type;
@@ -961,8 +966,8 @@ fail_unregister_dimm:
device_unregister(&mci->dev);
fail_unregister_bus:
bus_unregister(mci->bus);
-fail_free_name:
- kfree(mci->bus->name);
+ kfree(name);
+
return err;
}
@@ -993,10 +998,12 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
void edac_unregister_sysfs(struct mem_ctl_info *mci)
{
+ const char *name = mci->bus->name;
+
edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev));
device_unregister(&mci->dev);
bus_unregister(mci->bus);
- kfree(mci->bus->name);
+ kfree(name);
}
static void mc_attr_release(struct device *dev)
@@ -1018,24 +1025,15 @@ static struct device_type mc_attr_type = {
*/
int __init edac_mc_sysfs_init(void)
{
- struct bus_type *edac_subsys;
int err;
- /* get the /sys/devices/system/edac subsys reference */
- edac_subsys = edac_get_sysfs_subsys();
- if (edac_subsys == NULL) {
- edac_dbg(1, "no edac_subsys\n");
- err = -EINVAL;
- goto out;
- }
-
mci_pdev = kzalloc(sizeof(*mci_pdev), GFP_KERNEL);
if (!mci_pdev) {
err = -ENOMEM;
- goto out_put_sysfs;
+ goto out;
}
- mci_pdev->bus = edac_subsys;
+ mci_pdev->bus = edac_get_sysfs_subsys();
mci_pdev->type = &mc_attr_type;
device_initialize(mci_pdev);
dev_set_name(mci_pdev, "mc");
@@ -1050,8 +1048,6 @@ int __init edac_mc_sysfs_init(void)
out_dev_free:
kfree(mci_pdev);
- out_put_sysfs:
- edac_put_sysfs_subsys();
out:
return err;
}
@@ -1059,5 +1055,4 @@ int __init edac_mc_sysfs_init(void)
void edac_mc_sysfs_exit(void)
{
device_unregister(mci_pdev);
- edac_put_sysfs_subsys();
}
diff --git a/drivers/edac/edac_module.c b/drivers/edac/edac_module.c
index 9cb082a19d8a..5f8543be995a 100644
--- a/drivers/edac/edac_module.c
+++ b/drivers/edac/edac_module.c
@@ -43,9 +43,6 @@ module_param_call(edac_debug_level, edac_set_debug_level, param_get_int,
MODULE_PARM_DESC(edac_debug_level, "EDAC debug level: [0-4], default: 2");
#endif
-/* scope is to module level only */
-struct workqueue_struct *edac_workqueue;
-
/*
* edac_op_state_to_string()
*/
@@ -66,31 +63,37 @@ char *edac_op_state_to_string(int opstate)
}
/*
- * edac_workqueue_setup
- * initialize the edac work queue for polling operations
+ * sysfs object: /sys/devices/system/edac
+ * need to export to other files
*/
-static int edac_workqueue_setup(void)
+static struct bus_type edac_subsys = {
+ .name = "edac",
+ .dev_name = "edac",
+};
+
+static int edac_subsys_init(void)
{
- edac_workqueue = create_singlethread_workqueue("edac-poller");
- if (edac_workqueue == NULL)
- return -ENODEV;
- else
- return 0;
+ int err;
+
+ /* create the /sys/devices/system/edac directory */
+ err = subsys_system_register(&edac_subsys, NULL);
+ if (err)
+ printk(KERN_ERR "Error registering toplevel EDAC sysfs dir\n");
+
+ return err;
}
-/*
- * edac_workqueue_teardown
- * teardown the edac workqueue
- */
-static void edac_workqueue_teardown(void)
+static void edac_subsys_exit(void)
{
- if (edac_workqueue) {
- flush_workqueue(edac_workqueue);
- destroy_workqueue(edac_workqueue);
- edac_workqueue = NULL;
- }
+ bus_unregister(&edac_subsys);
}
+/* return pointer to the 'edac' node in sysfs */
+struct bus_type *edac_get_sysfs_subsys(void)
+{
+ return &edac_subsys;
+}
+EXPORT_SYMBOL_GPL(edac_get_sysfs_subsys);
/*
* edac_init
* module initialization entry point
@@ -101,6 +104,10 @@ static int __init edac_init(void)
edac_printk(KERN_INFO, EDAC_MC, EDAC_VERSION "\n");
+ err = edac_subsys_init();
+ if (err)
+ return err;
+
/*
* Harvest and clear any boot/initialization PCI parity errors
*
@@ -129,6 +136,8 @@ err_wq:
edac_mc_sysfs_exit();
err_sysfs:
+ edac_subsys_exit();
+
return err;
}
@@ -144,6 +153,7 @@ static void __exit edac_exit(void)
edac_workqueue_teardown();
edac_mc_sysfs_exit();
edac_debugfs_exit();
+ edac_subsys_exit();
}
/*
diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h
index b95a48fc723d..cfaacb99c973 100644
--- a/drivers/edac/edac_module.h
+++ b/drivers/edac/edac_module.h
@@ -47,10 +47,12 @@ extern int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev);
extern void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev);
/* edac core workqueue: single CPU mode */
-extern struct workqueue_struct *edac_workqueue;
-extern void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
- unsigned msec);
-extern void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev);
+int edac_workqueue_setup(void);
+void edac_workqueue_teardown(void);
+bool edac_queue_work(struct delayed_work *work, unsigned long delay);
+bool edac_stop_work(struct delayed_work *work);
+bool edac_mod_work(struct delayed_work *work, unsigned long delay);
+
extern void edac_device_reset_delay_period(struct edac_device_ctl_info
*edac_dev, unsigned long value);
extern void edac_mc_reset_delay_period(unsigned long value);
diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c
index 2cf44b4db80c..99685388d3fb 100644
--- a/drivers/edac/edac_pci.c
+++ b/drivers/edac/edac_pci.c
@@ -178,41 +178,6 @@ static void del_edac_pci_from_global_list(struct edac_pci_ctl_info *pci)
INIT_LIST_HEAD(&pci->link);
}
-#if 0
-/* Older code, but might use in the future */
-
-/*
- * edac_pci_find()
- * Search for an edac_pci_ctl_info structure whose index is 'idx'
- *
- * If found, return a pointer to the structure
- * Else return NULL.
- *
- * Caller must hold pci_ctls_mutex.
- */
-struct edac_pci_ctl_info *edac_pci_find(int idx)
-{
- struct list_head *item;
- struct edac_pci_ctl_info *pci;
-
- /* Iterage over list, looking for exact match of ID */
- list_for_each(item, &edac_pci_list) {
- pci = list_entry(item, struct edac_pci_ctl_info, link);
-
- if (pci->pci_idx >= idx) {
- if (pci->pci_idx == idx)
- return pci;
-
- /* not on list, so terminate early */
- break;
- }
- }
-
- return NULL;
-}
-EXPORT_SYMBOL_GPL(edac_pci_find);
-#endif
-
/*
* edac_pci_workq_function()
*
@@ -244,7 +209,7 @@ static void edac_pci_workq_function(struct work_struct *work_req)
delay = msecs_to_jiffies(msec);
/* Reschedule only if we are in POLL mode */
- queue_delayed_work(edac_workqueue, &pci->work, delay);
+ edac_queue_work(&pci->work, delay);
}
mutex_unlock(&edac_pci_ctls_mutex);
@@ -264,8 +229,8 @@ static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci,
edac_dbg(0, "\n");
INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function);
- queue_delayed_work(edac_workqueue, &pci->work,
- msecs_to_jiffies(edac_pci_get_poll_msec()));
+
+ edac_queue_work(&pci->work, msecs_to_jiffies(edac_pci_get_poll_msec()));
}
/*
@@ -274,37 +239,12 @@ static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci,
*/
static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci)
{
- int status;
-
- edac_dbg(0, "\n");
-
- status = cancel_delayed_work(&pci->work);
- if (status == 0)
- flush_workqueue(edac_workqueue);
-}
-
-/*
- * edac_pci_reset_delay_period
- *
- * called with a new period value for the workq period
- * a) stop current workq timer
- * b) restart workq timer with new value
- */
-void edac_pci_reset_delay_period(struct edac_pci_ctl_info *pci,
- unsigned long value)
-{
edac_dbg(0, "\n");
- edac_pci_workq_teardown(pci);
-
- /* need to lock for the setup */
- mutex_lock(&edac_pci_ctls_mutex);
-
- edac_pci_workq_setup(pci, value);
+ pci->op_state = OP_OFFLINE;
- mutex_unlock(&edac_pci_ctls_mutex);
+ edac_stop_work(&pci->work);
}
-EXPORT_SYMBOL_GPL(edac_pci_reset_delay_period);
/*
* edac_pci_alloc_index: Allocate a unique PCI index number
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
index 24d877f6e577..6e3428ba400f 100644
--- a/drivers/edac/edac_pci_sysfs.c
+++ b/drivers/edac/edac_pci_sysfs.c
@@ -331,10 +331,7 @@ static struct kobj_type ktype_edac_pci_main_kobj = {
};
/**
- * edac_pci_main_kobj_setup()
- *
- * setup the sysfs for EDAC PCI attributes
- * assumes edac_subsys has already been initialized
+ * edac_pci_main_kobj_setup: Setup the sysfs for EDAC PCI attributes.
*/
static int edac_pci_main_kobj_setup(void)
{
@@ -351,11 +348,6 @@ static int edac_pci_main_kobj_setup(void)
* controls and attributes
*/
edac_subsys = edac_get_sysfs_subsys();
- if (edac_subsys == NULL) {
- edac_dbg(1, "no edac_subsys\n");
- err = -ENODEV;
- goto decrement_count_fail;
- }
/* Bump the reference count on this module to ensure the
* modules isn't unloaded until we deconstruct the top
@@ -364,7 +356,7 @@ static int edac_pci_main_kobj_setup(void)
if (!try_module_get(THIS_MODULE)) {
edac_dbg(1, "try_module_get() failed\n");
err = -ENODEV;
- goto mod_get_fail;
+ goto decrement_count_fail;
}
edac_pci_top_main_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL);
@@ -399,9 +391,6 @@ kobject_init_and_add_fail:
kzalloc_fail:
module_put(THIS_MODULE);
-mod_get_fail:
- edac_put_sysfs_subsys();
-
decrement_count_fail:
/* if are on this error exit, nothing to tear down */
atomic_dec(&edac_pci_sysfs_refcount);
@@ -426,7 +415,6 @@ static void edac_pci_main_kobj_teardown(void)
if (atomic_dec_return(&edac_pci_sysfs_refcount) == 0) {
edac_dbg(0, "called kobject_put on main kobj\n");
kobject_put(edac_pci_top_main_kobj);
- edac_put_sysfs_subsys();
}
}
diff --git a/drivers/edac/edac_stub.c b/drivers/edac/edac_stub.c
index ff07aae5b7fb..952e411f01f2 100644
--- a/drivers/edac/edac_stub.c
+++ b/drivers/edac/edac_stub.c
@@ -26,8 +26,6 @@ EXPORT_SYMBOL_GPL(edac_handlers);
int edac_err_assert = 0;
EXPORT_SYMBOL_GPL(edac_err_assert);
-static atomic_t edac_subsys_valid = ATOMIC_INIT(0);
-
int edac_report_status = EDAC_REPORTING_ENABLED;
EXPORT_SYMBOL_GPL(edac_report_status);
@@ -68,42 +66,3 @@ void edac_atomic_assert_error(void)
edac_err_assert++;
}
EXPORT_SYMBOL_GPL(edac_atomic_assert_error);
-
-/*
- * sysfs object: /sys/devices/system/edac
- * need to export to other files
- */
-struct bus_type edac_subsys = {
- .name = "edac",
- .dev_name = "edac",
-};
-EXPORT_SYMBOL_GPL(edac_subsys);
-
-/* return pointer to the 'edac' node in sysfs */
-struct bus_type *edac_get_sysfs_subsys(void)
-{
- int err = 0;
-
- if (atomic_read(&edac_subsys_valid))
- goto out;
-
- /* create the /sys/devices/system/edac directory */
- err = subsys_system_register(&edac_subsys, NULL);
- if (err) {
- printk(KERN_ERR "Error registering toplevel EDAC sysfs dir\n");
- return NULL;
- }
-
-out:
- atomic_inc(&edac_subsys_valid);
- return &edac_subsys;
-}
-EXPORT_SYMBOL_GPL(edac_get_sysfs_subsys);
-
-void edac_put_sysfs_subsys(void)
-{
- /* last user unregisters it */
- if (atomic_dec_and_test(&edac_subsys_valid))
- bus_unregister(&edac_subsys);
-}
-EXPORT_SYMBOL_GPL(edac_put_sysfs_subsys);
diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c
index 40917775dca1..c655162caf08 100644
--- a/drivers/edac/i5100_edac.c
+++ b/drivers/edac/i5100_edac.c
@@ -575,9 +575,7 @@ static void i5100_check_error(struct mem_ctl_info *mci)
static void i5100_refresh_scrubbing(struct work_struct *work)
{
- struct delayed_work *i5100_scrubbing = container_of(work,
- struct delayed_work,
- work);
+ struct delayed_work *i5100_scrubbing = to_delayed_work(work);
struct i5100_priv *priv = container_of(i5100_scrubbing,
struct i5100_priv,
i5100_scrubbing);
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 23ef8e9f2c9a..b7139c160baf 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -20,6 +20,7 @@
#include <linux/edac.h>
#include <linux/smp.h>
#include <linux/gfp.h>
+#include <linux/fsl/edac.h>
#include <linux/of_platform.h>
#include <linux/of_device.h>
@@ -238,10 +239,12 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
return IRQ_HANDLED;
}
-int mpc85xx_pci_err_probe(struct platform_device *op)
+static int mpc85xx_pci_err_probe(struct platform_device *op)
{
struct edac_pci_ctl_info *pci;
struct mpc85xx_pci_pdata *pdata;
+ struct mpc85xx_edac_pci_plat_data *plat_data;
+ struct device_node *of_node;
struct resource r;
int res = 0;
@@ -266,7 +269,15 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
pdata->name = "mpc85xx_pci_err";
pdata->irq = NO_IRQ;
- if (mpc85xx_pcie_find_capability(op->dev.of_node) > 0)
+ plat_data = op->dev.platform_data;
+ if (!plat_data) {
+ dev_err(&op->dev, "no platform data");
+ res = -ENXIO;
+ goto err;
+ }
+ of_node = plat_data->of_node;
+
+ if (mpc85xx_pcie_find_capability(of_node) > 0)
pdata->is_pcie = true;
dev_set_drvdata(&op->dev, pci);
@@ -284,7 +295,7 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
pdata->edac_idx = edac_pci_idx++;
- res = of_address_to_resource(op->dev.of_node, 0, &r);
+ res = of_address_to_resource(of_node, 0, &r);
if (res) {
printk(KERN_ERR "%s: Unable to get resource for "
"PCI err regs\n", __func__);
@@ -339,7 +350,7 @@ int mpc85xx_pci_err_probe(struct platform_device *op)
}
if (edac_op_state == EDAC_OPSTATE_INT) {
- pdata->irq = irq_of_parse_and_map(op->dev.of_node, 0);
+ pdata->irq = irq_of_parse_and_map(of_node, 0);
res = devm_request_irq(&op->dev, pdata->irq,
mpc85xx_pci_isr,
IRQF_SHARED,
@@ -386,8 +397,22 @@ err:
devres_release_group(&op->dev, mpc85xx_pci_err_probe);
return res;
}
-EXPORT_SYMBOL(mpc85xx_pci_err_probe);
+static const struct platform_device_id mpc85xx_pci_err_match[] = {
+ {
+ .name = "mpc85xx-pci-edac"
+ },
+ {}
+};
+
+static struct platform_driver mpc85xx_pci_err_driver = {
+ .probe = mpc85xx_pci_err_probe,
+ .id_table = mpc85xx_pci_err_match,
+ .driver = {
+ .name = "mpc85xx_pci_err",
+ .suppress_bind_attrs = true,
+ },
+};
#endif /* CONFIG_PCI */
/**************************** L2 Err device ***************************/
@@ -1208,6 +1233,14 @@ static void __init mpc85xx_mc_clear_rfxe(void *data)
}
#endif
+static struct platform_driver * const drivers[] = {
+ &mpc85xx_mc_err_driver,
+ &mpc85xx_l2_err_driver,
+#ifdef CONFIG_PCI
+ &mpc85xx_pci_err_driver,
+#endif
+};
+
static int __init mpc85xx_mc_init(void)
{
int res = 0;
@@ -1226,13 +1259,9 @@ static int __init mpc85xx_mc_init(void)
break;
}
- res = platform_driver_register(&mpc85xx_mc_err_driver);
- if (res)
- printk(KERN_WARNING EDAC_MOD_STR "MC fails to register\n");
-
- res = platform_driver_register(&mpc85xx_l2_err_driver);
+ res = platform_register_drivers(drivers, ARRAY_SIZE(drivers));
if (res)
- printk(KERN_WARNING EDAC_MOD_STR "L2 fails to register\n");
+ printk(KERN_WARNING EDAC_MOD_STR "drivers fail to register\n");
#ifdef CONFIG_FSL_SOC_BOOKE
pvr = mfspr(SPRN_PVR);
@@ -1270,8 +1299,7 @@ static void __exit mpc85xx_mc_exit(void)
on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0);
}
#endif
- platform_driver_unregister(&mpc85xx_l2_err_driver);
- platform_driver_unregister(&mpc85xx_mc_err_driver);
+ platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
}
module_exit(mpc85xx_mc_exit);
diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c
index 0574e1bbe45c..6c54127e6eae 100644
--- a/drivers/edac/mv64x60_edac.c
+++ b/drivers/edac/mv64x60_edac.c
@@ -847,6 +847,15 @@ static struct platform_driver mv64x60_mc_err_driver = {
}
};
+static struct platform_driver * const drivers[] = {
+ &mv64x60_mc_err_driver,
+ &mv64x60_cpu_err_driver,
+ &mv64x60_sram_err_driver,
+#ifdef CONFIG_PCI
+ &mv64x60_pci_err_driver,
+#endif
+};
+
static int __init mv64x60_edac_init(void)
{
int ret = 0;
@@ -863,39 +872,13 @@ static int __init mv64x60_edac_init(void)
break;
}
- ret = platform_driver_register(&mv64x60_mc_err_driver);
- if (ret)
- printk(KERN_WARNING EDAC_MOD_STR "MC err failed to register\n");
-
- ret = platform_driver_register(&mv64x60_cpu_err_driver);
- if (ret)
- printk(KERN_WARNING EDAC_MOD_STR
- "CPU err failed to register\n");
-
- ret = platform_driver_register(&mv64x60_sram_err_driver);
- if (ret)
- printk(KERN_WARNING EDAC_MOD_STR
- "SRAM err failed to register\n");
-
-#ifdef CONFIG_PCI
- ret = platform_driver_register(&mv64x60_pci_err_driver);
- if (ret)
- printk(KERN_WARNING EDAC_MOD_STR
- "PCI err failed to register\n");
-#endif
-
- return ret;
+ return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
}
module_init(mv64x60_edac_init);
static void __exit mv64x60_edac_exit(void)
{
-#ifdef CONFIG_PCI
- platform_driver_unregister(&mv64x60_pci_err_driver);
-#endif
- platform_driver_unregister(&mv64x60_sram_err_driver);
- platform_driver_unregister(&mv64x60_cpu_err_driver);
- platform_driver_unregister(&mv64x60_mc_err_driver);
+ platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
}
module_exit(mv64x60_edac_exit);
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 429309c62699..e438ee5b433f 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -65,15 +65,20 @@ static const u32 ibridge_dram_rule[] = {
0xd8, 0xe0, 0xe8, 0xf0, 0xf8,
};
-#define SAD_LIMIT(reg) ((GET_BITFIELD(reg, 6, 25) << 26) | 0x3ffffff)
-#define DRAM_ATTR(reg) GET_BITFIELD(reg, 2, 3)
-#define INTERLEAVE_MODE(reg) GET_BITFIELD(reg, 1, 1)
+static const u32 knl_dram_rule[] = {
+ 0x60, 0x68, 0x70, 0x78, 0x80, /* 0-4 */
+ 0x88, 0x90, 0x98, 0xa0, 0xa8, /* 5-9 */
+ 0xb0, 0xb8, 0xc0, 0xc8, 0xd0, /* 10-14 */
+ 0xd8, 0xe0, 0xe8, 0xf0, 0xf8, /* 15-19 */
+ 0x100, 0x108, 0x110, 0x118, /* 20-23 */
+};
+
#define DRAM_RULE_ENABLE(reg) GET_BITFIELD(reg, 0, 0)
#define A7MODE(reg) GET_BITFIELD(reg, 26, 26)
-static char *get_dram_attr(u32 reg)
+static char *show_dram_attr(u32 attr)
{
- switch(DRAM_ATTR(reg)) {
+ switch (attr) {
case 0:
return "DRAM";
case 1:
@@ -97,6 +102,14 @@ static const u32 ibridge_interleave_list[] = {
0xdc, 0xe4, 0xec, 0xf4, 0xfc,
};
+static const u32 knl_interleave_list[] = {
+ 0x64, 0x6c, 0x74, 0x7c, 0x84, /* 0-4 */
+ 0x8c, 0x94, 0x9c, 0xa4, 0xac, /* 5-9 */
+ 0xb4, 0xbc, 0xc4, 0xcc, 0xd4, /* 10-14 */
+ 0xdc, 0xe4, 0xec, 0xf4, 0xfc, /* 15-19 */
+ 0x104, 0x10c, 0x114, 0x11c, /* 20-23 */
+};
+
struct interleave_pkg {
unsigned char start;
unsigned char end;
@@ -134,10 +147,13 @@ static inline int sad_pkg(const struct interleave_pkg *table, u32 reg,
/* Devices 12 Function 7 */
#define TOLM 0x80
-#define TOHM 0x84
+#define TOHM 0x84
#define HASWELL_TOLM 0xd0
#define HASWELL_TOHM_0 0xd4
#define HASWELL_TOHM_1 0xd8
+#define KNL_TOLM 0xd0
+#define KNL_TOHM_0 0xd4
+#define KNL_TOHM_1 0xd8
#define GET_TOLM(reg) ((GET_BITFIELD(reg, 0, 3) << 28) | 0x3ffffff)
#define GET_TOHM(reg) ((GET_BITFIELD(reg, 0, 20) << 25) | 0x3ffffff)
@@ -148,6 +164,8 @@ static inline int sad_pkg(const struct interleave_pkg *table, u32 reg,
#define SOURCE_ID(reg) GET_BITFIELD(reg, 9, 11)
+#define SOURCE_ID_KNL(reg) GET_BITFIELD(reg, 12, 14)
+
#define SAD_CONTROL 0xf4
/* Device 14 function 0 */
@@ -170,6 +188,7 @@ static const u32 tad_dram_rule[] = {
/* Device 15, function 0 */
#define MCMTR 0x7c
+#define KNL_MCMTR 0x624
#define IS_ECC_ENABLED(mcmtr) GET_BITFIELD(mcmtr, 2, 2)
#define IS_LOCKSTEP_ENABLED(mcmtr) GET_BITFIELD(mcmtr, 1, 1)
@@ -186,6 +205,8 @@ static const int mtr_regs[] = {
0x80, 0x84, 0x88,
};
+static const int knl_mtr_reg = 0xb60;
+
#define RANK_DISABLE(mtr) GET_BITFIELD(mtr, 16, 19)
#define IS_DIMM_PRESENT(mtr) GET_BITFIELD(mtr, 14, 14)
#define RANK_CNT_BITS(mtr) GET_BITFIELD(mtr, 12, 13)
@@ -256,6 +277,9 @@ static const u32 correrrthrsld[] = {
#define NUM_CHANNELS 8 /* 2MC per socket, four chan per MC */
#define MAX_DIMMS 3 /* Max DIMMS per channel */
+#define KNL_MAX_CHAS 38 /* KNL max num. of Cache Home Agents */
+#define KNL_MAX_CHANNELS 6 /* KNL max num. of PCI channels */
+#define KNL_MAX_EDCS 8 /* Embedded DRAM controllers */
#define CHANNEL_UNSPECIFIED 0xf /* Intel IA32 SDM 15-14 */
enum type {
@@ -263,6 +287,7 @@ enum type {
IVY_BRIDGE,
HASWELL,
BROADWELL,
+ KNIGHTS_LANDING,
};
struct sbridge_pvt;
@@ -273,6 +298,10 @@ struct sbridge_info {
u64 (*get_tolm)(struct sbridge_pvt *pvt);
u64 (*get_tohm)(struct sbridge_pvt *pvt);
u64 (*rir_limit)(u32 reg);
+ u64 (*sad_limit)(u32 reg);
+ u32 (*interleave_mode)(u32 reg);
+ char* (*show_interleave_mode)(u32 reg);
+ u32 (*dram_attr)(u32 reg);
const u32 *dram_rule;
const u32 *interleave_list;
const struct interleave_pkg *interleave_pkg;
@@ -308,6 +337,16 @@ struct sbridge_dev {
struct mem_ctl_info *mci;
};
+struct knl_pvt {
+ struct pci_dev *pci_cha[KNL_MAX_CHAS];
+ struct pci_dev *pci_channel[KNL_MAX_CHANNELS];
+ struct pci_dev *pci_mc0;
+ struct pci_dev *pci_mc1;
+ struct pci_dev *pci_mc0_misc;
+ struct pci_dev *pci_mc1_misc;
+ struct pci_dev *pci_mc_info; /* tolm, tohm */
+};
+
struct sbridge_pvt {
struct pci_dev *pci_ta, *pci_ddrio, *pci_ras;
struct pci_dev *pci_sad0, *pci_sad1;
@@ -336,6 +375,7 @@ struct sbridge_pvt {
/* Memory description */
u64 tolm, tohm;
+ struct knl_pvt knl;
};
#define PCI_DESCR(device_id, opt) \
@@ -509,6 +549,50 @@ static const struct pci_id_table pci_dev_descr_haswell_table[] = {
{0,} /* 0 terminated list. */
};
+/* Knight's Landing Support */
+/*
+ * KNL's memory channels are swizzled between memory controllers.
+ * MC0 is mapped to CH3,5,6 and MC1 is mapped to CH0,1,2
+ */
+#define knl_channel_remap(channel) ((channel + 3) % 6)
+
+/* Memory controller, TAD tables, error injection - 2-8-0, 2-9-0 (2 of these) */
+#define PCI_DEVICE_ID_INTEL_KNL_IMC_MC 0x7840
+/* DRAM channel stuff; bank addrs, dimmmtr, etc.. 2-8-2 - 2-9-4 (6 of these) */
+#define PCI_DEVICE_ID_INTEL_KNL_IMC_CHANNEL 0x7843
+/* kdrwdbu TAD limits/offsets, MCMTR - 2-10-1, 2-11-1 (2 of these) */
+#define PCI_DEVICE_ID_INTEL_KNL_IMC_TA 0x7844
+/* CHA broadcast registers, dram rules - 1-29-0 (1 of these) */
+#define PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0 0x782a
+/* SAD target - 1-29-1 (1 of these) */
+#define PCI_DEVICE_ID_INTEL_KNL_IMC_SAD1 0x782b
+/* Caching / Home Agent */
+#define PCI_DEVICE_ID_INTEL_KNL_IMC_CHA 0x782c
+/* Device with TOLM and TOHM, 0-5-0 (1 of these) */
+#define PCI_DEVICE_ID_INTEL_KNL_IMC_TOLHM 0x7810
+
+/*
+ * KNL differs from SB, IB, and Haswell in that it has multiple
+ * instances of the same device with the same device ID, so we handle that
+ * by creating as many copies in the table as we expect to find.
+ * (Like device ID must be grouped together.)
+ */
+
+static const struct pci_id_descr pci_dev_descr_knl[] = {
+ [0] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0, 0) },
+ [1] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_SAD1, 0) },
+ [2 ... 3] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_MC, 0)},
+ [4 ... 41] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHA, 0) },
+ [42 ... 47] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_CHANNEL, 0) },
+ [48] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TA, 0) },
+ [49] = { PCI_DESCR(PCI_DEVICE_ID_INTEL_KNL_IMC_TOLHM, 0) },
+};
+
+static const struct pci_id_table pci_dev_descr_knl_table[] = {
+ PCI_ID_TABLE_ENTRY(pci_dev_descr_knl),
+ {0,}
+};
+
/*
* Broadwell support
*
@@ -585,6 +669,7 @@ static const struct pci_device_id sbridge_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0)},
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0)},
{0,} /* 0 terminated list. */
};
@@ -598,7 +683,7 @@ static inline int numrank(enum type type, u32 mtr)
int ranks = (1 << RANK_CNT_BITS(mtr));
int max = 4;
- if (type == HASWELL || type == BROADWELL)
+ if (type == HASWELL || type == BROADWELL || type == KNIGHTS_LANDING)
max = 8;
if (ranks > max) {
@@ -636,10 +721,19 @@ static inline int numcol(u32 mtr)
return 1 << cols;
}
-static struct sbridge_dev *get_sbridge_dev(u8 bus)
+static struct sbridge_dev *get_sbridge_dev(u8 bus, int multi_bus)
{
struct sbridge_dev *sbridge_dev;
+ /*
+ * If we have devices scattered across several busses that pertain
+ * to the same memory controller, we'll lump them all together.
+ */
+ if (multi_bus) {
+ return list_first_entry_or_null(&sbridge_edac_list,
+ struct sbridge_dev, list);
+ }
+
list_for_each_entry(sbridge_dev, &sbridge_edac_list, list) {
if (sbridge_dev->bus == bus)
return sbridge_dev;
@@ -718,6 +812,67 @@ static u64 rir_limit(u32 reg)
return ((u64)GET_BITFIELD(reg, 1, 10) << 29) | 0x1fffffff;
}
+static u64 sad_limit(u32 reg)
+{
+ return (GET_BITFIELD(reg, 6, 25) << 26) | 0x3ffffff;
+}
+
+static u32 interleave_mode(u32 reg)
+{
+ return GET_BITFIELD(reg, 1, 1);
+}
+
+char *show_interleave_mode(u32 reg)
+{
+ return interleave_mode(reg) ? "8:6" : "[8:6]XOR[18:16]";
+}
+
+static u32 dram_attr(u32 reg)
+{
+ return GET_BITFIELD(reg, 2, 3);
+}
+
+static u64 knl_sad_limit(u32 reg)
+{
+ return (GET_BITFIELD(reg, 7, 26) << 26) | 0x3ffffff;
+}
+
+static u32 knl_interleave_mode(u32 reg)
+{
+ return GET_BITFIELD(reg, 1, 2);
+}
+
+static char *knl_show_interleave_mode(u32 reg)
+{
+ char *s;
+
+ switch (knl_interleave_mode(reg)) {
+ case 0:
+ s = "use address bits [8:6]";
+ break;
+ case 1:
+ s = "use address bits [10:8]";
+ break;
+ case 2:
+ s = "use address bits [14:12]";
+ break;
+ case 3:
+ s = "use address bits [32:30]";
+ break;
+ default:
+ WARN_ON(1);
+ break;
+ }
+
+ return s;
+}
+
+static u32 dram_attr_knl(u32 reg)
+{
+ return GET_BITFIELD(reg, 3, 4);
+}
+
+
static enum mem_type get_memory_type(struct sbridge_pvt *pvt)
{
u32 reg;
@@ -769,6 +924,12 @@ out:
return mtype;
}
+static enum dev_type knl_get_width(struct sbridge_pvt *pvt, u32 mtr)
+{
+ /* for KNL value is fixed */
+ return DEV_X16;
+}
+
static enum dev_type sbridge_get_width(struct sbridge_pvt *pvt, u32 mtr)
{
/* there's no way to figure out */
@@ -812,6 +973,12 @@ static enum dev_type broadwell_get_width(struct sbridge_pvt *pvt, u32 mtr)
return __ibridge_get_width(GET_BITFIELD(mtr, 8, 9));
}
+static enum mem_type knl_get_memory_type(struct sbridge_pvt *pvt)
+{
+ /* DDR4 RDIMMS and LRDIMMS are supported */
+ return MEM_RDDR4;
+}
+
static u8 get_node_id(struct sbridge_pvt *pvt)
{
u32 reg;
@@ -827,6 +994,15 @@ static u8 haswell_get_node_id(struct sbridge_pvt *pvt)
return GET_BITFIELD(reg, 0, 3);
}
+static u8 knl_get_node_id(struct sbridge_pvt *pvt)
+{
+ u32 reg;
+
+ pci_read_config_dword(pvt->pci_sad1, SAD_CONTROL, &reg);
+ return GET_BITFIELD(reg, 0, 2);
+}
+
+
static u64 haswell_get_tolm(struct sbridge_pvt *pvt)
{
u32 reg;
@@ -848,6 +1024,26 @@ static u64 haswell_get_tohm(struct sbridge_pvt *pvt)
return rc | 0x1ffffff;
}
+static u64 knl_get_tolm(struct sbridge_pvt *pvt)
+{
+ u32 reg;
+
+ pci_read_config_dword(pvt->knl.pci_mc_info, KNL_TOLM, &reg);
+ return (GET_BITFIELD(reg, 26, 31) << 26) | 0x3ffffff;
+}
+
+static u64 knl_get_tohm(struct sbridge_pvt *pvt)
+{
+ u64 rc;
+ u32 reg_lo, reg_hi;
+
+ pci_read_config_dword(pvt->knl.pci_mc_info, KNL_TOHM_0, &reg_lo);
+ pci_read_config_dword(pvt->knl.pci_mc_info, KNL_TOHM_1, &reg_hi);
+ rc = ((u64)reg_hi << 32) | reg_lo;
+ return rc | 0x3ffffff;
+}
+
+
static u64 haswell_rir_limit(u32 reg)
{
return (((u64)GET_BITFIELD(reg, 1, 11) + 1) << 29) - 1;
@@ -905,11 +1101,22 @@ static int check_if_ecc_is_active(const u8 bus, enum type type)
case BROADWELL:
id = PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA;
break;
+ case KNIGHTS_LANDING:
+ /*
+ * KNL doesn't group things by bus the same way
+ * SB/IB/Haswell does.
+ */
+ id = PCI_DEVICE_ID_INTEL_KNL_IMC_TA;
+ break;
default:
return -ENODEV;
}
- pdev = get_pdev_same_bus(bus, id);
+ if (type != KNIGHTS_LANDING)
+ pdev = get_pdev_same_bus(bus, id);
+ else
+ pdev = pci_get_device(PCI_VENDOR_ID_INTEL, id, 0);
+
if (!pdev) {
sbridge_printk(KERN_ERR, "Couldn't find PCI device "
"%04x:%04x! on bus %02d\n",
@@ -917,7 +1124,8 @@ static int check_if_ecc_is_active(const u8 bus, enum type type)
return -ENODEV;
}
- pci_read_config_dword(pdev, MCMTR, &mcmtr);
+ pci_read_config_dword(pdev,
+ type == KNIGHTS_LANDING ? KNL_MCMTR : MCMTR, &mcmtr);
if (!IS_ECC_ENABLED(mcmtr)) {
sbridge_printk(KERN_ERR, "ECC is disabled. Aborting\n");
return -ENODEV;
@@ -925,6 +1133,476 @@ static int check_if_ecc_is_active(const u8 bus, enum type type)
return 0;
}
+/* Low bits of TAD limit, and some metadata. */
+static const u32 knl_tad_dram_limit_lo[] = {
+ 0x400, 0x500, 0x600, 0x700,
+ 0x800, 0x900, 0xa00, 0xb00,
+};
+
+/* Low bits of TAD offset. */
+static const u32 knl_tad_dram_offset_lo[] = {
+ 0x404, 0x504, 0x604, 0x704,
+ 0x804, 0x904, 0xa04, 0xb04,
+};
+
+/* High 16 bits of TAD limit and offset. */
+static const u32 knl_tad_dram_hi[] = {
+ 0x408, 0x508, 0x608, 0x708,
+ 0x808, 0x908, 0xa08, 0xb08,
+};
+
+/* Number of ways a tad entry is interleaved. */
+static const u32 knl_tad_ways[] = {
+ 8, 6, 4, 3, 2, 1,
+};
+
+/*
+ * Retrieve the n'th Target Address Decode table entry
+ * from the memory controller's TAD table.
+ *
+ * @pvt: driver private data
+ * @entry: which entry you want to retrieve
+ * @mc: which memory controller (0 or 1)
+ * @offset: output tad range offset
+ * @limit: output address of first byte above tad range
+ * @ways: output number of interleave ways
+ *
+ * The offset value has curious semantics. It's a sort of running total
+ * of the sizes of all the memory regions that aren't mapped in this
+ * tad table.
+ */
+static int knl_get_tad(const struct sbridge_pvt *pvt,
+ const int entry,
+ const int mc,
+ u64 *offset,
+ u64 *limit,
+ int *ways)
+{
+ u32 reg_limit_lo, reg_offset_lo, reg_hi;
+ struct pci_dev *pci_mc;
+ int way_id;
+
+ switch (mc) {
+ case 0:
+ pci_mc = pvt->knl.pci_mc0;
+ break;
+ case 1:
+ pci_mc = pvt->knl.pci_mc1;
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ pci_read_config_dword(pci_mc,
+ knl_tad_dram_limit_lo[entry], &reg_limit_lo);
+ pci_read_config_dword(pci_mc,
+ knl_tad_dram_offset_lo[entry], &reg_offset_lo);
+ pci_read_config_dword(pci_mc,
+ knl_tad_dram_hi[entry], &reg_hi);
+
+ /* Is this TAD entry enabled? */
+ if (!GET_BITFIELD(reg_limit_lo, 0, 0))
+ return -ENODEV;
+
+ way_id = GET_BITFIELD(reg_limit_lo, 3, 5);
+
+ if (way_id < ARRAY_SIZE(knl_tad_ways)) {
+ *ways = knl_tad_ways[way_id];
+ } else {
+ *ways = 0;
+ sbridge_printk(KERN_ERR,
+ "Unexpected value %d in mc_tad_limit_lo wayness field\n",
+ way_id);
+ return -ENODEV;
+ }
+
+ /*
+ * The least significant 6 bits of base and limit are truncated.
+ * For limit, we fill the missing bits with 1s.
+ */
+ *offset = ((u64) GET_BITFIELD(reg_offset_lo, 6, 31) << 6) |
+ ((u64) GET_BITFIELD(reg_hi, 0, 15) << 32);
+ *limit = ((u64) GET_BITFIELD(reg_limit_lo, 6, 31) << 6) | 63 |
+ ((u64) GET_BITFIELD(reg_hi, 16, 31) << 32);
+
+ return 0;
+}
+
+/* Determine which memory controller is responsible for a given channel. */
+static int knl_channel_mc(int channel)
+{
+ WARN_ON(channel < 0 || channel >= 6);
+
+ return channel < 3 ? 1 : 0;
+}
+
+/*
+ * Get the Nth entry from EDC_ROUTE_TABLE register.
+ * (This is the per-tile mapping of logical interleave targets to
+ * physical EDC modules.)
+ *
+ * entry 0: 0:2
+ * 1: 3:5
+ * 2: 6:8
+ * 3: 9:11
+ * 4: 12:14
+ * 5: 15:17
+ * 6: 18:20
+ * 7: 21:23
+ * reserved: 24:31
+ */
+static u32 knl_get_edc_route(int entry, u32 reg)
+{
+ WARN_ON(entry >= KNL_MAX_EDCS);
+ return GET_BITFIELD(reg, entry*3, (entry*3)+2);
+}
+
+/*
+ * Get the Nth entry from MC_ROUTE_TABLE register.
+ * (This is the per-tile mapping of logical interleave targets to
+ * physical DRAM channels modules.)
+ *
+ * entry 0: mc 0:2 channel 18:19
+ * 1: mc 3:5 channel 20:21
+ * 2: mc 6:8 channel 22:23
+ * 3: mc 9:11 channel 24:25
+ * 4: mc 12:14 channel 26:27
+ * 5: mc 15:17 channel 28:29
+ * reserved: 30:31
+ *
+ * Though we have 3 bits to identify the MC, we should only see
+ * the values 0 or 1.
+ */
+
+static u32 knl_get_mc_route(int entry, u32 reg)
+{
+ int mc, chan;
+
+ WARN_ON(entry >= KNL_MAX_CHANNELS);
+
+ mc = GET_BITFIELD(reg, entry*3, (entry*3)+2);
+ chan = GET_BITFIELD(reg, (entry*2) + 18, (entry*2) + 18 + 1);
+
+ return knl_channel_remap(mc*3 + chan);
+}
+
+/*
+ * Render the EDC_ROUTE register in human-readable form.
+ * Output string s should be at least KNL_MAX_EDCS*2 bytes.
+ */
+static void knl_show_edc_route(u32 reg, char *s)
+{
+ int i;
+
+ for (i = 0; i < KNL_MAX_EDCS; i++) {
+ s[i*2] = knl_get_edc_route(i, reg) + '0';
+ s[i*2+1] = '-';
+ }
+
+ s[KNL_MAX_EDCS*2 - 1] = '\0';
+}
+
+/*
+ * Render the MC_ROUTE register in human-readable form.
+ * Output string s should be at least KNL_MAX_CHANNELS*2 bytes.
+ */
+static void knl_show_mc_route(u32 reg, char *s)
+{
+ int i;
+
+ for (i = 0; i < KNL_MAX_CHANNELS; i++) {
+ s[i*2] = knl_get_mc_route(i, reg) + '0';
+ s[i*2+1] = '-';
+ }
+
+ s[KNL_MAX_CHANNELS*2 - 1] = '\0';
+}
+
+#define KNL_EDC_ROUTE 0xb8
+#define KNL_MC_ROUTE 0xb4
+
+/* Is this dram rule backed by regular DRAM in flat mode? */
+#define KNL_EDRAM(reg) GET_BITFIELD(reg, 29, 29)
+
+/* Is this dram rule cached? */
+#define KNL_CACHEABLE(reg) GET_BITFIELD(reg, 28, 28)
+
+/* Is this rule backed by edc ? */
+#define KNL_EDRAM_ONLY(reg) GET_BITFIELD(reg, 29, 29)
+
+/* Is this rule backed by DRAM, cacheable in EDRAM? */
+#define KNL_CACHEABLE(reg) GET_BITFIELD(reg, 28, 28)
+
+/* Is this rule mod3? */
+#define KNL_MOD3(reg) GET_BITFIELD(reg, 27, 27)
+
+/*
+ * Figure out how big our RAM modules are.
+ *
+ * The DIMMMTR register in KNL doesn't tell us the size of the DIMMs, so we
+ * have to figure this out from the SAD rules, interleave lists, route tables,
+ * and TAD rules.
+ *
+ * SAD rules can have holes in them (e.g. the 3G-4G hole), so we have to
+ * inspect the TAD rules to figure out how large the SAD regions really are.
+ *
+ * When we know the real size of a SAD region and how many ways it's
+ * interleaved, we know the individual contribution of each channel to
+ * TAD is size/ways.
+ *
+ * Finally, we have to check whether each channel participates in each SAD
+ * region.
+ *
+ * Fortunately, KNL only supports one DIMM per channel, so once we know how
+ * much memory the channel uses, we know the DIMM is at least that large.
+ * (The BIOS might possibly choose not to map all available memory, in which
+ * case we will underreport the size of the DIMM.)
+ *
+ * In theory, we could try to determine the EDC sizes as well, but that would
+ * only work in flat mode, not in cache mode.
+ *
+ * @mc_sizes: Output sizes of channels (must have space for KNL_MAX_CHANNELS
+ * elements)
+ */
+static int knl_get_dimm_capacity(struct sbridge_pvt *pvt, u64 *mc_sizes)
+{
+ u64 sad_base, sad_size, sad_limit = 0;
+ u64 tad_base, tad_size, tad_limit, tad_deadspace, tad_livespace;
+ int sad_rule = 0;
+ int tad_rule = 0;
+ int intrlv_ways, tad_ways;
+ u32 first_pkg, pkg;
+ int i;
+ u64 sad_actual_size[2]; /* sad size accounting for holes, per mc */
+ u32 dram_rule, interleave_reg;
+ u32 mc_route_reg[KNL_MAX_CHAS];
+ u32 edc_route_reg[KNL_MAX_CHAS];
+ int edram_only;
+ char edc_route_string[KNL_MAX_EDCS*2];
+ char mc_route_string[KNL_MAX_CHANNELS*2];
+ int cur_reg_start;
+ int mc;
+ int channel;
+ int way;
+ int participants[KNL_MAX_CHANNELS];
+ int participant_count = 0;
+
+ for (i = 0; i < KNL_MAX_CHANNELS; i++)
+ mc_sizes[i] = 0;
+
+ /* Read the EDC route table in each CHA. */
+ cur_reg_start = 0;
+ for (i = 0; i < KNL_MAX_CHAS; i++) {
+ pci_read_config_dword(pvt->knl.pci_cha[i],
+ KNL_EDC_ROUTE, &edc_route_reg[i]);
+
+ if (i > 0 && edc_route_reg[i] != edc_route_reg[i-1]) {
+ knl_show_edc_route(edc_route_reg[i-1],
+ edc_route_string);
+ if (cur_reg_start == i-1)
+ edac_dbg(0, "edc route table for CHA %d: %s\n",
+ cur_reg_start, edc_route_string);
+ else
+ edac_dbg(0, "edc route table for CHA %d-%d: %s\n",
+ cur_reg_start, i-1, edc_route_string);
+ cur_reg_start = i;
+ }
+ }
+ knl_show_edc_route(edc_route_reg[i-1], edc_route_string);
+ if (cur_reg_start == i-1)
+ edac_dbg(0, "edc route table for CHA %d: %s\n",
+ cur_reg_start, edc_route_string);
+ else
+ edac_dbg(0, "edc route table for CHA %d-%d: %s\n",
+ cur_reg_start, i-1, edc_route_string);
+
+ /* Read the MC route table in each CHA. */
+ cur_reg_start = 0;
+ for (i = 0; i < KNL_MAX_CHAS; i++) {
+ pci_read_config_dword(pvt->knl.pci_cha[i],
+ KNL_MC_ROUTE, &mc_route_reg[i]);
+
+ if (i > 0 && mc_route_reg[i] != mc_route_reg[i-1]) {
+ knl_show_mc_route(mc_route_reg[i-1], mc_route_string);
+ if (cur_reg_start == i-1)
+ edac_dbg(0, "mc route table for CHA %d: %s\n",
+ cur_reg_start, mc_route_string);
+ else
+ edac_dbg(0, "mc route table for CHA %d-%d: %s\n",
+ cur_reg_start, i-1, mc_route_string);
+ cur_reg_start = i;
+ }
+ }
+ knl_show_mc_route(mc_route_reg[i-1], mc_route_string);
+ if (cur_reg_start == i-1)
+ edac_dbg(0, "mc route table for CHA %d: %s\n",
+ cur_reg_start, mc_route_string);
+ else
+ edac_dbg(0, "mc route table for CHA %d-%d: %s\n",
+ cur_reg_start, i-1, mc_route_string);
+
+ /* Process DRAM rules */
+ for (sad_rule = 0; sad_rule < pvt->info.max_sad; sad_rule++) {
+ /* previous limit becomes the new base */
+ sad_base = sad_limit;
+
+ pci_read_config_dword(pvt->pci_sad0,
+ pvt->info.dram_rule[sad_rule], &dram_rule);
+
+ if (!DRAM_RULE_ENABLE(dram_rule))
+ break;
+
+ edram_only = KNL_EDRAM_ONLY(dram_rule);
+
+ sad_limit = pvt->info.sad_limit(dram_rule)+1;
+ sad_size = sad_limit - sad_base;
+
+ pci_read_config_dword(pvt->pci_sad0,
+ pvt->info.interleave_list[sad_rule], &interleave_reg);
+
+ /*
+ * Find out how many ways this dram rule is interleaved.
+ * We stop when we see the first channel again.
+ */
+ first_pkg = sad_pkg(pvt->info.interleave_pkg,
+ interleave_reg, 0);
+ for (intrlv_ways = 1; intrlv_ways < 8; intrlv_ways++) {
+ pkg = sad_pkg(pvt->info.interleave_pkg,
+ interleave_reg, intrlv_ways);
+
+ if ((pkg & 0x8) == 0) {
+ /*
+ * 0 bit means memory is non-local,
+ * which KNL doesn't support
+ */
+ edac_dbg(0, "Unexpected interleave target %d\n",
+ pkg);
+ return -1;
+ }
+
+ if (pkg == first_pkg)
+ break;
+ }
+ if (KNL_MOD3(dram_rule))
+ intrlv_ways *= 3;
+
+ edac_dbg(3, "dram rule %d (base 0x%llx, limit 0x%llx), %d way interleave%s\n",
+ sad_rule,
+ sad_base,
+ sad_limit,
+ intrlv_ways,
+ edram_only ? ", EDRAM" : "");
+
+ /*
+ * Find out how big the SAD region really is by iterating
+ * over TAD tables (SAD regions may contain holes).
+ * Each memory controller might have a different TAD table, so
+ * we have to look at both.
+ *
+ * Livespace is the memory that's mapped in this TAD table,
+ * deadspace is the holes (this could be the MMIO hole, or it
+ * could be memory that's mapped by the other TAD table but
+ * not this one).
+ */
+ for (mc = 0; mc < 2; mc++) {
+ sad_actual_size[mc] = 0;
+ tad_livespace = 0;
+ for (tad_rule = 0;
+ tad_rule < ARRAY_SIZE(
+ knl_tad_dram_limit_lo);
+ tad_rule++) {
+ if (knl_get_tad(pvt,
+ tad_rule,
+ mc,
+ &tad_deadspace,
+ &tad_limit,
+ &tad_ways))
+ break;
+
+ tad_size = (tad_limit+1) -
+ (tad_livespace + tad_deadspace);
+ tad_livespace += tad_size;
+ tad_base = (tad_limit+1) - tad_size;
+
+ if (tad_base < sad_base) {
+ if (tad_limit > sad_base)
+ edac_dbg(0, "TAD region overlaps lower SAD boundary -- TAD tables may be configured incorrectly.\n");
+ } else if (tad_base < sad_limit) {
+ if (tad_limit+1 > sad_limit) {
+ edac_dbg(0, "TAD region overlaps upper SAD boundary -- TAD tables may be configured incorrectly.\n");
+ } else {
+ /* TAD region is completely inside SAD region */
+ edac_dbg(3, "TAD region %d 0x%llx - 0x%llx (%lld bytes) table%d\n",
+ tad_rule, tad_base,
+ tad_limit, tad_size,
+ mc);
+ sad_actual_size[mc] += tad_size;
+ }
+ }
+ tad_base = tad_limit+1;
+ }
+ }
+
+ for (mc = 0; mc < 2; mc++) {
+ edac_dbg(3, " total TAD DRAM footprint in table%d : 0x%llx (%lld bytes)\n",
+ mc, sad_actual_size[mc], sad_actual_size[mc]);
+ }
+
+ /* Ignore EDRAM rule */
+ if (edram_only)
+ continue;
+
+ /* Figure out which channels participate in interleave. */
+ for (channel = 0; channel < KNL_MAX_CHANNELS; channel++)
+ participants[channel] = 0;
+
+ /* For each channel, does at least one CHA have
+ * this channel mapped to the given target?
+ */
+ for (channel = 0; channel < KNL_MAX_CHANNELS; channel++) {
+ for (way = 0; way < intrlv_ways; way++) {
+ int target;
+ int cha;
+
+ if (KNL_MOD3(dram_rule))
+ target = way;
+ else
+ target = 0x7 & sad_pkg(
+ pvt->info.interleave_pkg, interleave_reg, way);
+
+ for (cha = 0; cha < KNL_MAX_CHAS; cha++) {
+ if (knl_get_mc_route(target,
+ mc_route_reg[cha]) == channel
+ && participants[channel]) {
+ participant_count++;
+ participants[channel] = 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if (participant_count != intrlv_ways)
+ edac_dbg(0, "participant_count (%d) != interleave_ways (%d): DIMM size may be incorrect\n",
+ participant_count, intrlv_ways);
+
+ for (channel = 0; channel < KNL_MAX_CHANNELS; channel++) {
+ mc = knl_channel_mc(channel);
+ if (participants[channel]) {
+ edac_dbg(4, "mc channel %d contributes %lld bytes via sad entry %d\n",
+ channel,
+ sad_actual_size[mc]/intrlv_ways,
+ sad_rule);
+ mc_sizes[channel] +=
+ sad_actual_size[mc]/intrlv_ways;
+ }
+ }
+ }
+
+ return 0;
+}
+
static int get_dimm_config(struct mem_ctl_info *mci)
{
struct sbridge_pvt *pvt = mci->pvt_info;
@@ -934,13 +1612,20 @@ static int get_dimm_config(struct mem_ctl_info *mci)
u32 reg;
enum edac_type mode;
enum mem_type mtype;
+ int channels = pvt->info.type == KNIGHTS_LANDING ?
+ KNL_MAX_CHANNELS : NUM_CHANNELS;
+ u64 knl_mc_sizes[KNL_MAX_CHANNELS];
- if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL)
+ if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL ||
+ pvt->info.type == KNIGHTS_LANDING)
pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, &reg);
else
pci_read_config_dword(pvt->pci_br0, SAD_TARGET, &reg);
- pvt->sbridge_dev->source_id = SOURCE_ID(reg);
+ if (pvt->info.type == KNIGHTS_LANDING)
+ pvt->sbridge_dev->source_id = SOURCE_ID_KNL(reg);
+ else
+ pvt->sbridge_dev->source_id = SOURCE_ID(reg);
pvt->sbridge_dev->node_id = pvt->info.get_node_id(pvt);
edac_dbg(0, "mc#%d: Node ID: %d, source ID: %d\n",
@@ -948,31 +1633,42 @@ static int get_dimm_config(struct mem_ctl_info *mci)
pvt->sbridge_dev->node_id,
pvt->sbridge_dev->source_id);
- pci_read_config_dword(pvt->pci_ras, RASENABLES, &reg);
- if (IS_MIRROR_ENABLED(reg)) {
- edac_dbg(0, "Memory mirror is enabled\n");
- pvt->is_mirrored = true;
- } else {
- edac_dbg(0, "Memory mirror is disabled\n");
+ /* KNL doesn't support mirroring or lockstep,
+ * and is always closed page
+ */
+ if (pvt->info.type == KNIGHTS_LANDING) {
+ mode = EDAC_S4ECD4ED;
pvt->is_mirrored = false;
- }
- pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr);
- if (IS_LOCKSTEP_ENABLED(pvt->info.mcmtr)) {
- edac_dbg(0, "Lockstep is enabled\n");
- mode = EDAC_S8ECD8ED;
- pvt->is_lockstep = true;
+ if (knl_get_dimm_capacity(pvt, knl_mc_sizes) != 0)
+ return -1;
} else {
- edac_dbg(0, "Lockstep is disabled\n");
- mode = EDAC_S4ECD4ED;
- pvt->is_lockstep = false;
- }
- if (IS_CLOSE_PG(pvt->info.mcmtr)) {
- edac_dbg(0, "address map is on closed page mode\n");
- pvt->is_close_pg = true;
- } else {
- edac_dbg(0, "address map is on open page mode\n");
- pvt->is_close_pg = false;
+ pci_read_config_dword(pvt->pci_ras, RASENABLES, &reg);
+ if (IS_MIRROR_ENABLED(reg)) {
+ edac_dbg(0, "Memory mirror is enabled\n");
+ pvt->is_mirrored = true;
+ } else {
+ edac_dbg(0, "Memory mirror is disabled\n");
+ pvt->is_mirrored = false;
+ }
+
+ pci_read_config_dword(pvt->pci_ta, MCMTR, &pvt->info.mcmtr);
+ if (IS_LOCKSTEP_ENABLED(pvt->info.mcmtr)) {
+ edac_dbg(0, "Lockstep is enabled\n");
+ mode = EDAC_S8ECD8ED;
+ pvt->is_lockstep = true;
+ } else {
+ edac_dbg(0, "Lockstep is disabled\n");
+ mode = EDAC_S4ECD4ED;
+ pvt->is_lockstep = false;
+ }
+ if (IS_CLOSE_PG(pvt->info.mcmtr)) {
+ edac_dbg(0, "address map is on closed page mode\n");
+ pvt->is_close_pg = true;
+ } else {
+ edac_dbg(0, "address map is on open page mode\n");
+ pvt->is_close_pg = false;
+ }
}
mtype = pvt->info.get_memory_type(pvt);
@@ -988,23 +1684,46 @@ static int get_dimm_config(struct mem_ctl_info *mci)
else
banks = 8;
- for (i = 0; i < NUM_CHANNELS; i++) {
+ for (i = 0; i < channels; i++) {
u32 mtr;
- if (!pvt->pci_tad[i])
- continue;
- for (j = 0; j < ARRAY_SIZE(mtr_regs); j++) {
+ int max_dimms_per_channel;
+
+ if (pvt->info.type == KNIGHTS_LANDING) {
+ max_dimms_per_channel = 1;
+ if (!pvt->knl.pci_channel[i])
+ continue;
+ } else {
+ max_dimms_per_channel = ARRAY_SIZE(mtr_regs);
+ if (!pvt->pci_tad[i])
+ continue;
+ }
+
+ for (j = 0; j < max_dimms_per_channel; j++) {
dimm = EDAC_DIMM_PTR(mci->layers, mci->dimms, mci->n_layers,
i, j, 0);
- pci_read_config_dword(pvt->pci_tad[i],
- mtr_regs[j], &mtr);
+ if (pvt->info.type == KNIGHTS_LANDING) {
+ pci_read_config_dword(pvt->knl.pci_channel[i],
+ knl_mtr_reg, &mtr);
+ } else {
+ pci_read_config_dword(pvt->pci_tad[i],
+ mtr_regs[j], &mtr);
+ }
edac_dbg(4, "Channel #%d MTR%d = %x\n", i, j, mtr);
if (IS_DIMM_PRESENT(mtr)) {
pvt->channel[i].dimms++;
ranks = numrank(pvt->info.type, mtr);
- rows = numrow(mtr);
- cols = numcol(mtr);
+
+ if (pvt->info.type == KNIGHTS_LANDING) {
+ /* For DDR4, this is fixed. */
+ cols = 1 << 10;
+ rows = knl_mc_sizes[i] /
+ ((u64) cols * ranks * banks * 8);
+ } else {
+ rows = numrow(mtr);
+ cols = numcol(mtr);
+ }
size = ((u64)rows * cols * banks * ranks) >> (20 - 3);
npages = MiB_TO_PAGES(size);
@@ -1069,7 +1788,7 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
/* SAD_LIMIT Address range is 45:26 */
pci_read_config_dword(pvt->pci_sad0, pvt->info.dram_rule[n_sads],
&reg);
- limit = SAD_LIMIT(reg);
+ limit = pvt->info.sad_limit(reg);
if (!DRAM_RULE_ENABLE(reg))
continue;
@@ -1081,10 +1800,10 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
gb = div_u64_rem(tmp_mb, 1024, &mb);
edac_dbg(0, "SAD#%d %s up to %u.%03u GB (0x%016Lx) Interleave: %s reg=0x%08x\n",
n_sads,
- get_dram_attr(reg),
+ show_dram_attr(pvt->info.dram_attr(reg)),
gb, (mb*1000)/1024,
((u64)tmp_mb) << 20L,
- INTERLEAVE_MODE(reg) ? "8:6" : "[8:6]XOR[18:16]",
+ pvt->info.show_interleave_mode(reg),
reg);
prv = limit;
@@ -1101,6 +1820,9 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
}
}
+ if (pvt->info.type == KNIGHTS_LANDING)
+ return;
+
/*
* Step 3) Get TAD range
*/
@@ -1248,7 +1970,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
if (!DRAM_RULE_ENABLE(reg))
continue;
- limit = SAD_LIMIT(reg);
+ limit = pvt->info.sad_limit(reg);
if (limit <= prv) {
sprintf(msg, "Can't discover the memory socket");
return -EINVAL;
@@ -1262,8 +1984,8 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
return -EINVAL;
}
dram_rule = reg;
- *area_type = get_dram_attr(dram_rule);
- interleave_mode = INTERLEAVE_MODE(dram_rule);
+ *area_type = show_dram_attr(pvt->info.dram_attr(dram_rule));
+ interleave_mode = pvt->info.interleave_mode(dram_rule);
pci_read_config_dword(pvt->pci_sad0, pvt->info.interleave_list[n_sads],
&reg);
@@ -1567,7 +2289,8 @@ static void sbridge_put_all_devices(void)
static int sbridge_get_onedevice(struct pci_dev **prev,
u8 *num_mc,
const struct pci_id_table *table,
- const unsigned devno)
+ const unsigned devno,
+ const int multi_bus)
{
struct sbridge_dev *sbridge_dev;
const struct pci_id_descr *dev_descr = &table->descr[devno];
@@ -1603,7 +2326,7 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
}
bus = pdev->bus->number;
- sbridge_dev = get_sbridge_dev(bus);
+ sbridge_dev = get_sbridge_dev(bus, multi_bus);
if (!sbridge_dev) {
sbridge_dev = alloc_sbridge_dev(bus, table);
if (!sbridge_dev) {
@@ -1652,21 +2375,32 @@ static int sbridge_get_onedevice(struct pci_dev **prev,
* @num_mc: pointer to the memory controllers count, to be incremented in case
* of success.
* @table: model specific table
+ * @allow_dups: allow for multiple devices to exist with the same device id
+ * (as implemented, this isn't expected to work correctly in the
+ * multi-socket case).
+ * @multi_bus: don't assume devices on different buses belong to different
+ * memory controllers.
*
* returns 0 in case of success or error code
*/
-static int sbridge_get_all_devices(u8 *num_mc,
- const struct pci_id_table *table)
+static int sbridge_get_all_devices_full(u8 *num_mc,
+ const struct pci_id_table *table,
+ int allow_dups,
+ int multi_bus)
{
int i, rc;
struct pci_dev *pdev = NULL;
while (table && table->descr) {
for (i = 0; i < table->n_devs; i++) {
- pdev = NULL;
+ if (!allow_dups || i == 0 ||
+ table->descr[i].dev_id !=
+ table->descr[i-1].dev_id) {
+ pdev = NULL;
+ }
do {
rc = sbridge_get_onedevice(&pdev, num_mc,
- table, i);
+ table, i, multi_bus);
if (rc < 0) {
if (i == 0) {
i = table->n_devs;
@@ -1675,7 +2409,7 @@ static int sbridge_get_all_devices(u8 *num_mc,
sbridge_put_all_devices();
return -ENODEV;
}
- } while (pdev);
+ } while (pdev && !allow_dups);
}
table++;
}
@@ -1683,6 +2417,11 @@ static int sbridge_get_all_devices(u8 *num_mc,
return 0;
}
+#define sbridge_get_all_devices(num_mc, table) \
+ sbridge_get_all_devices_full(num_mc, table, 0, 0)
+#define sbridge_get_all_devices_knl(num_mc, table) \
+ sbridge_get_all_devices_full(num_mc, table, 1, 1)
+
static int sbridge_mci_bind_devs(struct mem_ctl_info *mci,
struct sbridge_dev *sbridge_dev)
{
@@ -2038,6 +2777,131 @@ enodev:
return -ENODEV;
}
+static int knl_mci_bind_devs(struct mem_ctl_info *mci,
+ struct sbridge_dev *sbridge_dev)
+{
+ struct sbridge_pvt *pvt = mci->pvt_info;
+ struct pci_dev *pdev;
+ int dev, func;
+
+ int i;
+ int devidx;
+
+ for (i = 0; i < sbridge_dev->n_devs; i++) {
+ pdev = sbridge_dev->pdev[i];
+ if (!pdev)
+ continue;
+
+ /* Extract PCI device and function. */
+ dev = (pdev->devfn >> 3) & 0x1f;
+ func = pdev->devfn & 0x7;
+
+ switch (pdev->device) {
+ case PCI_DEVICE_ID_INTEL_KNL_IMC_MC:
+ if (dev == 8)
+ pvt->knl.pci_mc0 = pdev;
+ else if (dev == 9)
+ pvt->knl.pci_mc1 = pdev;
+ else {
+ sbridge_printk(KERN_ERR,
+ "Memory controller in unexpected place! (dev %d, fn %d)\n",
+ dev, func);
+ continue;
+ }
+ break;
+
+ case PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0:
+ pvt->pci_sad0 = pdev;
+ break;
+
+ case PCI_DEVICE_ID_INTEL_KNL_IMC_SAD1:
+ pvt->pci_sad1 = pdev;
+ break;
+
+ case PCI_DEVICE_ID_INTEL_KNL_IMC_CHA:
+ /* There are one of these per tile, and range from
+ * 1.14.0 to 1.18.5.
+ */
+ devidx = ((dev-14)*8)+func;
+
+ if (devidx < 0 || devidx >= KNL_MAX_CHAS) {
+ sbridge_printk(KERN_ERR,
+ "Caching and Home Agent in unexpected place! (dev %d, fn %d)\n",
+ dev, func);
+ continue;
+ }
+
+ WARN_ON(pvt->knl.pci_cha[devidx] != NULL);
+
+ pvt->knl.pci_cha[devidx] = pdev;
+ break;
+
+ case PCI_DEVICE_ID_INTEL_KNL_IMC_CHANNEL:
+ devidx = -1;
+
+ /*
+ * MC0 channels 0-2 are device 9 function 2-4,
+ * MC1 channels 3-5 are device 8 function 2-4.
+ */
+
+ if (dev == 9)
+ devidx = func-2;
+ else if (dev == 8)
+ devidx = 3 + (func-2);
+
+ if (devidx < 0 || devidx >= KNL_MAX_CHANNELS) {
+ sbridge_printk(KERN_ERR,
+ "DRAM Channel Registers in unexpected place! (dev %d, fn %d)\n",
+ dev, func);
+ continue;
+ }
+
+ WARN_ON(pvt->knl.pci_channel[devidx] != NULL);
+ pvt->knl.pci_channel[devidx] = pdev;
+ break;
+
+ case PCI_DEVICE_ID_INTEL_KNL_IMC_TOLHM:
+ pvt->knl.pci_mc_info = pdev;
+ break;
+
+ case PCI_DEVICE_ID_INTEL_KNL_IMC_TA:
+ pvt->pci_ta = pdev;
+ break;
+
+ default:
+ sbridge_printk(KERN_ERR, "Unexpected device %d\n",
+ pdev->device);
+ break;
+ }
+ }
+
+ if (!pvt->knl.pci_mc0 || !pvt->knl.pci_mc1 ||
+ !pvt->pci_sad0 || !pvt->pci_sad1 ||
+ !pvt->pci_ta) {
+ goto enodev;
+ }
+
+ for (i = 0; i < KNL_MAX_CHANNELS; i++) {
+ if (!pvt->knl.pci_channel[i]) {
+ sbridge_printk(KERN_ERR, "Missing channel %d\n", i);
+ goto enodev;
+ }
+ }
+
+ for (i = 0; i < KNL_MAX_CHAS; i++) {
+ if (!pvt->knl.pci_cha[i]) {
+ sbridge_printk(KERN_ERR, "Missing CHA %d\n", i);
+ goto enodev;
+ }
+ }
+
+ return 0;
+
+enodev:
+ sbridge_printk(KERN_ERR, "Some needed devices are missing\n");
+ return -ENODEV;
+}
+
/****************************************************************************
Error check routines
****************************************************************************/
@@ -2127,8 +2991,36 @@ static void sbridge_mce_output_error(struct mem_ctl_info *mci,
if (!GET_BITFIELD(m->status, 58, 58))
return;
- rc = get_memory_error_data(mci, m->addr, &socket, &ha,
- &channel_mask, &rank, &area_type, msg);
+ if (pvt->info.type == KNIGHTS_LANDING) {
+ if (channel == 14) {
+ edac_dbg(0, "%s%s err_code:%04x:%04x EDRAM bank %d\n",
+ overflow ? " OVERFLOW" : "",
+ (uncorrected_error && recoverable)
+ ? " recoverable" : "",
+ mscod, errcode,
+ m->bank);
+ } else {
+ char A = *("A");
+
+ channel = knl_channel_remap(channel);
+ channel_mask = 1 << channel;
+ snprintf(msg, sizeof(msg),
+ "%s%s err_code:%04x:%04x channel:%d (DIMM_%c)",
+ overflow ? " OVERFLOW" : "",
+ (uncorrected_error && recoverable)
+ ? " recoverable" : " ",
+ mscod, errcode, channel, A + channel);
+ edac_mc_handle_error(tp_event, mci, core_err_cnt,
+ m->addr >> PAGE_SHIFT, m->addr & ~PAGE_MASK, 0,
+ channel, 0, -1,
+ optype, msg);
+ }
+ return;
+ } else {
+ rc = get_memory_error_data(mci, m->addr, &socket, &ha,
+ &channel_mask, &rank, &area_type, msg);
+ }
+
if (rc < 0)
goto err_parsing;
new_mci = get_mci_for_node_id(socket);
@@ -2359,10 +3251,11 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
/* allocate a new MC control structure */
layers[0].type = EDAC_MC_LAYER_CHANNEL;
- layers[0].size = NUM_CHANNELS;
+ layers[0].size = type == KNIGHTS_LANDING ?
+ KNL_MAX_CHANNELS : NUM_CHANNELS;
layers[0].is_virt_csrow = false;
layers[1].type = EDAC_MC_LAYER_SLOT;
- layers[1].size = MAX_DIMMS;
+ layers[1].size = type == KNIGHTS_LANDING ? 1 : MAX_DIMMS;
layers[1].is_virt_csrow = true;
mci = edac_mc_alloc(sbridge_dev->mc, ARRAY_SIZE(layers), layers,
sizeof(*pvt));
@@ -2380,7 +3273,8 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
pvt->sbridge_dev = sbridge_dev;
sbridge_dev->mci = mci;
- mci->mtype_cap = MEM_FLAG_DDR3;
+ mci->mtype_cap = type == KNIGHTS_LANDING ?
+ MEM_FLAG_DDR4 : MEM_FLAG_DDR3;
mci->edac_ctl_cap = EDAC_FLAG_NONE;
mci->edac_cap = EDAC_FLAG_NONE;
mci->mod_name = "sbridge_edac.c";
@@ -2401,6 +3295,10 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
pvt->info.get_memory_type = get_memory_type;
pvt->info.get_node_id = get_node_id;
pvt->info.rir_limit = rir_limit;
+ pvt->info.sad_limit = sad_limit;
+ pvt->info.interleave_mode = interleave_mode;
+ pvt->info.show_interleave_mode = show_interleave_mode;
+ pvt->info.dram_attr = dram_attr;
pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
pvt->info.interleave_list = ibridge_interleave_list;
pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
@@ -2421,6 +3319,10 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
pvt->info.get_memory_type = get_memory_type;
pvt->info.get_node_id = get_node_id;
pvt->info.rir_limit = rir_limit;
+ pvt->info.sad_limit = sad_limit;
+ pvt->info.interleave_mode = interleave_mode;
+ pvt->info.show_interleave_mode = show_interleave_mode;
+ pvt->info.dram_attr = dram_attr;
pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule);
pvt->info.interleave_list = sbridge_interleave_list;
pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list);
@@ -2441,6 +3343,10 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
pvt->info.get_memory_type = haswell_get_memory_type;
pvt->info.get_node_id = haswell_get_node_id;
pvt->info.rir_limit = haswell_rir_limit;
+ pvt->info.sad_limit = sad_limit;
+ pvt->info.interleave_mode = interleave_mode;
+ pvt->info.show_interleave_mode = show_interleave_mode;
+ pvt->info.dram_attr = dram_attr;
pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
pvt->info.interleave_list = ibridge_interleave_list;
pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
@@ -2461,6 +3367,10 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
pvt->info.get_memory_type = haswell_get_memory_type;
pvt->info.get_node_id = haswell_get_node_id;
pvt->info.rir_limit = haswell_rir_limit;
+ pvt->info.sad_limit = sad_limit;
+ pvt->info.interleave_mode = interleave_mode;
+ pvt->info.show_interleave_mode = show_interleave_mode;
+ pvt->info.dram_attr = dram_attr;
pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
pvt->info.interleave_list = ibridge_interleave_list;
pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
@@ -2473,6 +3383,30 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
if (unlikely(rc < 0))
goto fail0;
break;
+ case KNIGHTS_LANDING:
+ /* pvt->info.rankcfgr == ??? */
+ pvt->info.get_tolm = knl_get_tolm;
+ pvt->info.get_tohm = knl_get_tohm;
+ pvt->info.dram_rule = knl_dram_rule;
+ pvt->info.get_memory_type = knl_get_memory_type;
+ pvt->info.get_node_id = knl_get_node_id;
+ pvt->info.rir_limit = NULL;
+ pvt->info.sad_limit = knl_sad_limit;
+ pvt->info.interleave_mode = knl_interleave_mode;
+ pvt->info.show_interleave_mode = knl_show_interleave_mode;
+ pvt->info.dram_attr = dram_attr_knl;
+ pvt->info.max_sad = ARRAY_SIZE(knl_dram_rule);
+ pvt->info.interleave_list = knl_interleave_list;
+ pvt->info.max_interleave = ARRAY_SIZE(knl_interleave_list);
+ pvt->info.interleave_pkg = ibridge_interleave_pkg;
+ pvt->info.get_width = knl_get_width;
+ mci->ctl_name = kasprintf(GFP_KERNEL,
+ "Knights Landing Socket#%d", mci->mc_idx);
+
+ rc = knl_mci_bind_devs(mci, sbridge_dev);
+ if (unlikely(rc < 0))
+ goto fail0;
+ break;
}
/* Get dimm basic config and the memory layout */
@@ -2527,20 +3461,29 @@ static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id)
switch (pdev->device) {
case PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA:
- rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_ibridge_table);
+ rc = sbridge_get_all_devices(&num_mc,
+ pci_dev_descr_ibridge_table);
type = IVY_BRIDGE;
break;
case PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0:
- rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_sbridge_table);
+ rc = sbridge_get_all_devices(&num_mc,
+ pci_dev_descr_sbridge_table);
type = SANDY_BRIDGE;
break;
case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0:
- rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_haswell_table);
+ rc = sbridge_get_all_devices(&num_mc,
+ pci_dev_descr_haswell_table);
type = HASWELL;
break;
case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0:
- rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_broadwell_table);
+ rc = sbridge_get_all_devices(&num_mc,
+ pci_dev_descr_broadwell_table);
type = BROADWELL;
+ break;
+ case PCI_DEVICE_ID_INTEL_KNL_IMC_SAD0:
+ rc = sbridge_get_all_devices_knl(&num_mc,
+ pci_dev_descr_knl_table);
+ type = KNIGHTS_LANDING;
break;
}
if (unlikely(rc < 0)) {
diff --git a/drivers/edac/wq.c b/drivers/edac/wq.c
new file mode 100644
index 000000000000..1b8c07e44fd8
--- /dev/null
+++ b/drivers/edac/wq.c
@@ -0,0 +1,42 @@
+#include "edac_module.h"
+
+static struct workqueue_struct *wq;
+
+bool edac_queue_work(struct delayed_work *work, unsigned long delay)
+{
+ return queue_delayed_work(wq, work, delay);
+}
+EXPORT_SYMBOL_GPL(edac_queue_work);
+
+bool edac_mod_work(struct delayed_work *work, unsigned long delay)
+{
+ return mod_delayed_work(wq, work, delay);
+}
+EXPORT_SYMBOL_GPL(edac_mod_work);
+
+bool edac_stop_work(struct delayed_work *work)
+{
+ bool ret;
+
+ ret = cancel_delayed_work_sync(work);
+ flush_workqueue(wq);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(edac_stop_work);
+
+int edac_workqueue_setup(void)
+{
+ wq = create_singlethread_workqueue("edac-poller");
+ if (!wq)
+ return -ENODEV;
+ else
+ return 0;
+}
+
+void edac_workqueue_teardown(void)
+{
+ flush_workqueue(wq);
+ destroy_workqueue(wq);
+ wq = NULL;
+}
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 80a73bfc1a65..60fb80bd353d 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -859,16 +859,6 @@ config SENSORS_MAX31790
This driver can also be built as a module. If so, the module
will be called max31790.
-config SENSORS_HTU21
- tristate "Measurement Specialties HTU21D humidity/temperature sensors"
- depends on I2C
- help
- If you say yes here you get support for the Measurement Specialties
- HTU21D humidity and temperature sensors.
-
- This driver can also be built as a module. If so, the module
- will be called htu21.
-
config SENSORS_MCP3021
tristate "Microchip MCP3021 and compatibles"
depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 12a32398fdcc..30c94df31465 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -68,7 +68,6 @@ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o
obj-$(CONFIG_SENSORS_HIH6130) += hih6130.o
-obj-$(CONFIG_SENSORS_HTU21) += htu21.o
obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o
obj-$(CONFIG_SENSORS_I5500) += i5500_temp.o
obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c
index 5f7067d7b625..f77eb971ce95 100644
--- a/drivers/hwmon/fam15h_power.c
+++ b/drivers/hwmon/fam15h_power.c
@@ -47,6 +47,8 @@ MODULE_LICENSE("GPL");
#define MSR_F15H_CU_MAX_PWR_ACCUMULATOR 0xc001007b
+#define PCI_DEVICE_ID_AMD_15H_M70H_NB_F4 0x15b4
+
struct fam15h_power_data {
struct pci_dev *pdev;
unsigned int tdp_to_watts;
@@ -124,7 +126,7 @@ static int fam15h_power_init_attrs(struct pci_dev *pdev,
if (c->x86 == 0x15 &&
(c->x86_model <= 0xf ||
- (c->x86_model >= 0x60 && c->x86_model <= 0x6f)))
+ (c->x86_model >= 0x60 && c->x86_model <= 0x7f)))
n += 1;
fam15h_power_attrs = devm_kcalloc(&pdev->dev, n,
@@ -138,7 +140,7 @@ static int fam15h_power_init_attrs(struct pci_dev *pdev,
fam15h_power_attrs[n++] = &dev_attr_power1_crit.attr;
if (c->x86 == 0x15 &&
(c->x86_model <= 0xf ||
- (c->x86_model >= 0x60 && c->x86_model <= 0x6f)))
+ (c->x86_model >= 0x60 && c->x86_model <= 0x7f)))
fam15h_power_attrs[n++] = &dev_attr_power1_input.attr;
data->group.attrs = fam15h_power_attrs;
@@ -296,6 +298,7 @@ static const struct pci_device_id fam15h_power_id_table[] = {
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F4) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F4) },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M70H_NB_F4) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) },
{}
diff --git a/drivers/hwmon/htu21.c b/drivers/hwmon/htu21.c
deleted file mode 100644
index 4c3bbb72f82a..000000000000
--- a/drivers/hwmon/htu21.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Measurement Specialties HTU21D humidity and temperature sensor driver
- *
- * Copyright (C) 2013 William Markezana <william.markezana@meas-spec.com>
- *
- * 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.
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/hwmon.h>
-#include <linux/hwmon-sysfs.h>
-#include <linux/err.h>
-#include <linux/mutex.h>
-#include <linux/device.h>
-#include <linux/jiffies.h>
-
-/* HTU21 Commands */
-#define HTU21_T_MEASUREMENT_HM 0xE3
-#define HTU21_RH_MEASUREMENT_HM 0xE5
-
-struct htu21 {
- struct i2c_client *client;
- struct mutex lock;
- bool valid;
- unsigned long last_update;
- int temperature;
- int humidity;
-};
-
-static inline int htu21_temp_ticks_to_millicelsius(int ticks)
-{
- ticks &= ~0x0003; /* clear status bits */
- /*
- * Formula T = -46.85 + 175.72 * ST / 2^16 from datasheet p14,
- * optimized for integer fixed point (3 digits) arithmetic
- */
- return ((21965 * ticks) >> 13) - 46850;
-}
-
-static inline int htu21_rh_ticks_to_per_cent_mille(int ticks)
-{
- ticks &= ~0x0003; /* clear status bits */
- /*
- * Formula RH = -6 + 125 * SRH / 2^16 from datasheet p14,
- * optimized for integer fixed point (3 digits) arithmetic
- */
- return ((15625 * ticks) >> 13) - 6000;
-}
-
-static int htu21_update_measurements(struct device *dev)
-{
- struct htu21 *htu21 = dev_get_drvdata(dev);
- struct i2c_client *client = htu21->client;
- int ret = 0;
-
- mutex_lock(&htu21->lock);
-
- if (time_after(jiffies, htu21->last_update + HZ / 2) ||
- !htu21->valid) {
- ret = i2c_smbus_read_word_swapped(client,
- HTU21_T_MEASUREMENT_HM);
- if (ret < 0)
- goto out;
- htu21->temperature = htu21_temp_ticks_to_millicelsius(ret);
- ret = i2c_smbus_read_word_swapped(client,
- HTU21_RH_MEASUREMENT_HM);
- if (ret < 0)
- goto out;
- htu21->humidity = htu21_rh_ticks_to_per_cent_mille(ret);
- htu21->last_update = jiffies;
- htu21->valid = true;
- }
-out:
- mutex_unlock(&htu21->lock);
-
- return ret >= 0 ? 0 : ret;
-}
-
-static ssize_t htu21_show_temperature(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct htu21 *htu21 = dev_get_drvdata(dev);
- int ret;
-
- ret = htu21_update_measurements(dev);
- if (ret < 0)
- return ret;
- return sprintf(buf, "%d\n", htu21->temperature);
-}
-
-static ssize_t htu21_show_humidity(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct htu21 *htu21 = dev_get_drvdata(dev);
- int ret;
-
- ret = htu21_update_measurements(dev);
- if (ret < 0)
- return ret;
- return sprintf(buf, "%d\n", htu21->humidity);
-}
-
-static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
- htu21_show_temperature, NULL, 0);
-static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO,
- htu21_show_humidity, NULL, 0);
-
-static struct attribute *htu21_attrs[] = {
- &sensor_dev_attr_temp1_input.dev_attr.attr,
- &sensor_dev_attr_humidity1_input.dev_attr.attr,
- NULL
-};
-
-ATTRIBUTE_GROUPS(htu21);
-
-static int htu21_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct device *dev = &client->dev;
- struct htu21 *htu21;
- struct device *hwmon_dev;
-
- if (!i2c_check_functionality(client->adapter,
- I2C_FUNC_SMBUS_READ_WORD_DATA)) {
- dev_err(&client->dev,
- "adapter does not support SMBus word transactions\n");
- return -ENODEV;
- }
-
- htu21 = devm_kzalloc(dev, sizeof(*htu21), GFP_KERNEL);
- if (!htu21)
- return -ENOMEM;
-
- htu21->client = client;
- mutex_init(&htu21->lock);
-
- hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
- htu21,
- htu21_groups);
- return PTR_ERR_OR_ZERO(hwmon_dev);
-}
-
-static const struct i2c_device_id htu21_id[] = {
- { "htu21", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, htu21_id);
-
-static struct i2c_driver htu21_driver = {
- .class = I2C_CLASS_HWMON,
- .driver = {
- .name = "htu21",
- },
- .probe = htu21_probe,
- .id_table = htu21_id,
-};
-
-module_i2c_driver(htu21_driver);
-
-MODULE_AUTHOR("William Markezana <william.markezana@meas-spec.com>");
-MODULE_DESCRIPTION("MEAS HTU21D humidity and temperature sensor driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c
index 7a8a6fbf11ff..1f643782ce04 100644
--- a/drivers/hwmon/ibmaem.c
+++ b/drivers/hwmon/ibmaem.c
@@ -920,8 +920,8 @@ static ssize_t aem_set_power_period(struct device *dev,
/* Discover sensors on an AEM device */
static int aem_register_sensors(struct aem_data *data,
- struct aem_ro_sensor_template *ro,
- struct aem_rw_sensor_template *rw)
+ const struct aem_ro_sensor_template *ro,
+ const struct aem_rw_sensor_template *rw)
{
struct device *dev = &data->pdev->dev;
struct sensor_device_attribute *sensors = data->sensors;
@@ -1020,19 +1020,19 @@ static void aem_remove_sensors(struct aem_data *data)
/* Sensor probe functions */
/* Description of AEM1 sensors */
-static struct aem_ro_sensor_template aem1_ro_sensors[] = {
+static const struct aem_ro_sensor_template aem1_ro_sensors[] = {
{"energy1_input", aem_show_energy, 0},
{"power1_average", aem_show_power, 0},
{NULL, NULL, 0},
};
-static struct aem_rw_sensor_template aem1_rw_sensors[] = {
+static const struct aem_rw_sensor_template aem1_rw_sensors[] = {
{"power1_average_interval", aem_show_power_period, aem_set_power_period, 0},
{NULL, NULL, NULL, 0},
};
/* Description of AEM2 sensors */
-static struct aem_ro_sensor_template aem2_ro_sensors[] = {
+static const struct aem_ro_sensor_template aem2_ro_sensors[] = {
{"energy1_input", aem_show_energy, 0},
{"energy2_input", aem_show_energy, 1},
{"power1_average", aem_show_power, 0},
@@ -1050,7 +1050,7 @@ static struct aem_ro_sensor_template aem2_ro_sensors[] = {
{NULL, NULL, 0},
};
-static struct aem_rw_sensor_template aem2_rw_sensors[] = {
+static const struct aem_rw_sensor_template aem2_rw_sensors[] = {
{"power1_average_interval", aem_show_power_period, aem_set_power_period, 0},
{"power2_average_interval", aem_show_power_period, aem_set_power_period, 1},
{NULL, NULL, NULL, 0},
diff --git a/drivers/hwmon/nct6683.c b/drivers/hwmon/nct6683.c
index 37f01702d081..559c596b24f9 100644
--- a/drivers/hwmon/nct6683.c
+++ b/drivers/hwmon/nct6683.c
@@ -29,7 +29,7 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/acpi.h>
-#include <linux/dmi.h>
+#include <linux/delay.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/io.h>
@@ -45,7 +45,7 @@ enum kinds { nct6683 };
static bool force;
module_param(force, bool, 0);
-MODULE_PARM_DESC(force, "Set to one to enable detection on non-Intel boards");
+MODULE_PARM_DESC(force, "Set to one to enable support for unknown vendors");
static const char * const nct6683_device_names[] = {
"nct6683",
@@ -141,6 +141,7 @@ superio_exit(int ioreg)
#define NCT6683_REG_MON(x) (0x100 + (x) * 2)
#define NCT6683_REG_FAN_RPM(x) (0x140 + (x) * 2)
#define NCT6683_REG_PWM(x) (0x160 + (x))
+#define NCT6683_REG_PWM_WRITE(x) (0xa28 + (x))
#define NCT6683_REG_MON_STS(x) (0x174 + (x))
#define NCT6683_REG_IDLE(x) (0x178 + (x))
@@ -165,8 +166,13 @@ superio_exit(int ioreg)
#define NCT6683_REG_FAN_MIN(x) (0x3b8 + (x) * 2) /* 16 bit */
+#define NCT6683_REG_FAN_CFG_CTRL 0xa01
+#define NCT6683_FAN_CFG_REQ 0x80
+#define NCT6683_FAN_CFG_DONE 0x40
+
#define NCT6683_REG_CUSTOMER_ID 0x602
#define NCT6683_CUSTOMER_ID_INTEL 0x805
+#define NCT6683_CUSTOMER_ID_MITAC 0xa0e
#define NCT6683_REG_BUILD_YEAR 0x604
#define NCT6683_REG_BUILD_MONTH 0x605
@@ -394,7 +400,8 @@ struct sensor_template_group {
};
static struct attribute_group *
-nct6683_create_attr_group(struct device *dev, struct sensor_template_group *tg,
+nct6683_create_attr_group(struct device *dev,
+ const struct sensor_template_group *tg,
int repeat)
{
struct sensor_device_attribute_2 *a2;
@@ -559,6 +566,7 @@ static int get_temp_reg(struct nct6683_data *data, int nr, int index)
break;
}
break;
+ case NCT6683_CUSTOMER_ID_MITAC:
default:
switch (nr) {
default:
@@ -703,7 +711,7 @@ static struct sensor_device_template *nct6683_attributes_in_template[] = {
NULL
};
-static struct sensor_template_group nct6683_in_template_group = {
+static const struct sensor_template_group nct6683_in_template_group = {
.templates = nct6683_attributes_in_template,
.is_visible = nct6683_in_is_visible,
};
@@ -774,7 +782,7 @@ static struct sensor_device_template *nct6683_attributes_fan_template[] = {
NULL
};
-static struct sensor_template_group nct6683_fan_template_group = {
+static const struct sensor_template_group nct6683_fan_template_group = {
.templates = nct6683_attributes_fan_template,
.is_visible = nct6683_fan_is_visible,
.base = 1,
@@ -902,7 +910,7 @@ static struct sensor_device_template *nct6683_attributes_temp_template[] = {
NULL
};
-static struct sensor_template_group nct6683_temp_template_group = {
+static const struct sensor_template_group nct6683_temp_template_group = {
.templates = nct6683_attributes_temp_template,
.is_visible = nct6683_temp_is_visible,
.base = 1,
@@ -918,7 +926,29 @@ show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
return sprintf(buf, "%d\n", data->pwm[index]);
}
-SENSOR_TEMPLATE(pwm, "pwm%d", S_IRUGO, show_pwm, NULL, 0);
+static ssize_t
+store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+ struct nct6683_data *data = dev_get_drvdata(dev);
+ int index = sattr->index;
+ unsigned long val;
+
+ if (kstrtoul(buf, 10, &val) || val > 255)
+ return -EINVAL;
+
+ mutex_lock(&data->update_lock);
+ nct6683_write(data, NCT6683_REG_FAN_CFG_CTRL, NCT6683_FAN_CFG_REQ);
+ usleep_range(1000, 2000);
+ nct6683_write(data, NCT6683_REG_PWM_WRITE(index), val);
+ nct6683_write(data, NCT6683_REG_FAN_CFG_CTRL, NCT6683_FAN_CFG_DONE);
+ mutex_unlock(&data->update_lock);
+
+ return count;
+}
+
+SENSOR_TEMPLATE(pwm, "pwm%d", S_IRUGO, show_pwm, store_pwm, 0);
static umode_t nct6683_pwm_is_visible(struct kobject *kobj,
struct attribute *attr, int index)
@@ -930,6 +960,10 @@ static umode_t nct6683_pwm_is_visible(struct kobject *kobj,
if (!(data->have_pwm & (1 << pwm)))
return 0;
+ /* Only update pwm values for Mitac boards */
+ if (data->customer_id == NCT6683_CUSTOMER_ID_MITAC)
+ return attr->mode | S_IWUSR;
+
return attr->mode;
}
@@ -938,7 +972,7 @@ static struct sensor_device_template *nct6683_attributes_pwm_template[] = {
NULL
};
-static struct sensor_template_group nct6683_pwm_template_group = {
+static const struct sensor_template_group nct6683_pwm_template_group = {
.templates = nct6683_attributes_pwm_template,
.is_visible = nct6683_pwm_is_visible,
.base = 1,
@@ -1170,6 +1204,7 @@ static int nct6683_probe(struct platform_device *pdev)
struct device *hwmon_dev;
struct resource *res;
int groups = 0;
+ char build[16];
res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!devm_request_region(dev, res->start, IOREGION_LENGTH, DRVNAME))
@@ -1187,6 +1222,17 @@ static int nct6683_probe(struct platform_device *pdev)
data->customer_id = nct6683_read16(data, NCT6683_REG_CUSTOMER_ID);
+ /* By default only instantiate driver if the customer ID is known */
+ switch (data->customer_id) {
+ case NCT6683_CUSTOMER_ID_INTEL:
+ break;
+ case NCT6683_CUSTOMER_ID_MITAC:
+ break;
+ default:
+ if (!force)
+ return -ENODEV;
+ }
+
nct6683_init_device(data);
nct6683_setup_fans(data);
nct6683_setup_sensors(data);
@@ -1230,13 +1276,22 @@ static int nct6683_probe(struct platform_device *pdev)
}
data->groups[groups++] = &nct6683_group_other;
- dev_info(dev, "%s EC firmware version %d.%d build %02x/%02x/%02x\n",
+ if (data->customer_id == NCT6683_CUSTOMER_ID_INTEL)
+ scnprintf(build, sizeof(build), "%02x/%02x/%02x",
+ nct6683_read(data, NCT6683_REG_BUILD_MONTH),
+ nct6683_read(data, NCT6683_REG_BUILD_DAY),
+ nct6683_read(data, NCT6683_REG_BUILD_YEAR));
+ else
+ scnprintf(build, sizeof(build), "%02d/%02d/%02d",
+ nct6683_read(data, NCT6683_REG_BUILD_MONTH),
+ nct6683_read(data, NCT6683_REG_BUILD_DAY),
+ nct6683_read(data, NCT6683_REG_BUILD_YEAR));
+
+ dev_info(dev, "%s EC firmware version %d.%d build %s\n",
nct6683_chip_names[data->kind],
nct6683_read(data, NCT6683_REG_VERSION_HI),
nct6683_read(data, NCT6683_REG_VERSION_LO),
- nct6683_read(data, NCT6683_REG_BUILD_MONTH),
- nct6683_read(data, NCT6683_REG_BUILD_DAY),
- nct6683_read(data, NCT6683_REG_BUILD_YEAR));
+ build);
hwmon_dev = devm_hwmon_device_register_with_groups(dev,
nct6683_device_names[data->kind], data, data->groups);
@@ -1292,20 +1347,10 @@ static struct platform_driver nct6683_driver = {
static int __init nct6683_find(int sioaddr, struct nct6683_sio_data *sio_data)
{
- const char *board_vendor;
int addr;
u16 val;
int err;
- /*
- * Only run on Intel boards unless the 'force' module parameter is set
- */
- if (!force) {
- board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
- if (!board_vendor || strcmp(board_vendor, "Intel Corporation"))
- return -ENODEV;
- }
-
err = superio_enter(sioaddr);
if (err)
return err;
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
index d7ebdf8651f5..d087a8e00cf5 100644
--- a/drivers/hwmon/nct6775.c
+++ b/drivers/hwmon/nct6775.c
@@ -1045,7 +1045,8 @@ struct sensor_template_group {
};
static struct attribute_group *
-nct6775_create_attr_group(struct device *dev, struct sensor_template_group *tg,
+nct6775_create_attr_group(struct device *dev,
+ const struct sensor_template_group *tg,
int repeat)
{
struct attribute_group *group;
@@ -1827,7 +1828,7 @@ static struct sensor_device_template *nct6775_attributes_in_template[] = {
NULL
};
-static struct sensor_template_group nct6775_in_template_group = {
+static const struct sensor_template_group nct6775_in_template_group = {
.templates = nct6775_attributes_in_template,
.is_visible = nct6775_in_is_visible,
};
@@ -2046,7 +2047,7 @@ static struct sensor_device_template *nct6775_attributes_fan_template[] = {
NULL
};
-static struct sensor_template_group nct6775_fan_template_group = {
+static const struct sensor_template_group nct6775_fan_template_group = {
.templates = nct6775_attributes_fan_template,
.is_visible = nct6775_fan_is_visible,
.base = 1,
@@ -2255,7 +2256,7 @@ static struct sensor_device_template *nct6775_attributes_temp_template[] = {
NULL
};
-static struct sensor_template_group nct6775_temp_template_group = {
+static const struct sensor_template_group nct6775_temp_template_group = {
.templates = nct6775_attributes_temp_template,
.is_visible = nct6775_temp_is_visible,
.base = 1,
@@ -3117,7 +3118,7 @@ static struct sensor_device_template *nct6775_attributes_pwm_template[] = {
NULL
};
-static struct sensor_template_group nct6775_pwm_template_group = {
+static const struct sensor_template_group nct6775_pwm_template_group = {
.templates = nct6775_attributes_pwm_template,
.is_visible = nct6775_pwm_is_visible,
.base = 1,
diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig
index df6ebb2b8f0f..7e5cc3d025ef 100644
--- a/drivers/hwmon/pmbus/Kconfig
+++ b/drivers/hwmon/pmbus/Kconfig
@@ -65,6 +65,16 @@ config SENSORS_LTC2978_REGULATOR
If you say yes here you get regulator support for Linear
Technology LTC2974, LTC2977, LTC2978, LTC3880, LTC3883, and LTM4676.
+config SENSORS_LTC3815
+ tristate "Linear Technologies LTC3815"
+ default n
+ help
+ If you say yes here you get hardware monitoring support for Linear
+ Technology LTC3815.
+
+ This driver can also be built as a module. If so, the module will
+ be called ltc3815.
+
config SENSORS_MAX16064
tristate "Maxim MAX16064"
default n
diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile
index bce046d37f02..562132054aaf 100644
--- a/drivers/hwmon/pmbus/Makefile
+++ b/drivers/hwmon/pmbus/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o
obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o
obj-$(CONFIG_SENSORS_LM25066) += lm25066.o
obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o
+obj-$(CONFIG_SENSORS_LTC3815) += ltc3815.o
obj-$(CONFIG_SENSORS_MAX16064) += max16064.o
obj-$(CONFIG_SENSORS_MAX20751) += max20751.o
obj-$(CONFIG_SENSORS_MAX34440) += max34440.o
diff --git a/drivers/hwmon/pmbus/ltc3815.c b/drivers/hwmon/pmbus/ltc3815.c
new file mode 100644
index 000000000000..bb32e6276622
--- /dev/null
+++ b/drivers/hwmon/pmbus/ltc3815.c
@@ -0,0 +1,215 @@
+/*
+ * Hardware monitoring driver for LTC3815
+ *
+ * Copyright (c) 2015 Linear Technology
+ * Copyright (c) 2015 Guenter Roeck
+ *
+ * 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.
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include "pmbus.h"
+
+#define LTC3815_MFR_IOUT_PEAK 0xd7
+#define LTC3815_MFR_VOUT_PEAK 0xdd
+#define LTC3815_MFR_VIN_PEAK 0xde
+#define LTC3815_MFR_TEMP_PEAK 0xdf
+#define LTC3815_MFR_IIN_PEAK 0xe1
+#define LTC3815_MFR_SPECIAL_ID 0xe7
+
+#define LTC3815_ID 0x8000
+#define LTC3815_ID_MASK 0xff00
+
+static int ltc3815_read_byte_data(struct i2c_client *client, int page, int reg)
+{
+ int ret;
+
+ switch (reg) {
+ case PMBUS_VOUT_MODE:
+ /*
+ * The chip returns 0x3e, suggesting VID mode with manufacturer
+ * specific VID codes. Since the output voltage is reported
+ * with a LSB of 0.5mV, override and report direct mode with
+ * appropriate coefficients.
+ */
+ ret = 0x40;
+ break;
+ default:
+ ret = -ENODATA;
+ break;
+ }
+ return ret;
+}
+
+static int ltc3815_write_byte(struct i2c_client *client, int page, u8 reg)
+{
+ int ret;
+
+ switch (reg) {
+ case PMBUS_CLEAR_FAULTS:
+ /*
+ * LTC3815 does not support the CLEAR_FAULTS command.
+ * Emulate it by clearing the status register.
+ */
+ ret = pmbus_read_word_data(client, 0, PMBUS_STATUS_WORD);
+ if (ret > 0) {
+ pmbus_write_word_data(client, 0, PMBUS_STATUS_WORD,
+ ret);
+ ret = 0;
+ }
+ break;
+ default:
+ ret = -ENODATA;
+ break;
+ }
+ return ret;
+}
+
+static int ltc3815_read_word_data(struct i2c_client *client, int page, int reg)
+{
+ int ret;
+
+ switch (reg) {
+ case PMBUS_VIRT_READ_VIN_MAX:
+ ret = pmbus_read_word_data(client, page, LTC3815_MFR_VIN_PEAK);
+ break;
+ case PMBUS_VIRT_READ_VOUT_MAX:
+ ret = pmbus_read_word_data(client, page, LTC3815_MFR_VOUT_PEAK);
+ break;
+ case PMBUS_VIRT_READ_TEMP_MAX:
+ ret = pmbus_read_word_data(client, page, LTC3815_MFR_TEMP_PEAK);
+ break;
+ case PMBUS_VIRT_READ_IOUT_MAX:
+ ret = pmbus_read_word_data(client, page, LTC3815_MFR_IOUT_PEAK);
+ break;
+ case PMBUS_VIRT_READ_IIN_MAX:
+ ret = pmbus_read_word_data(client, page, LTC3815_MFR_IIN_PEAK);
+ break;
+ case PMBUS_VIRT_RESET_VOUT_HISTORY:
+ case PMBUS_VIRT_RESET_VIN_HISTORY:
+ case PMBUS_VIRT_RESET_TEMP_HISTORY:
+ case PMBUS_VIRT_RESET_IOUT_HISTORY:
+ case PMBUS_VIRT_RESET_IIN_HISTORY:
+ ret = 0;
+ break;
+ default:
+ ret = -ENODATA;
+ break;
+ }
+ return ret;
+}
+
+static int ltc3815_write_word_data(struct i2c_client *client, int page,
+ int reg, u16 word)
+{
+ int ret;
+
+ switch (reg) {
+ case PMBUS_VIRT_RESET_IIN_HISTORY:
+ ret = pmbus_write_word_data(client, page,
+ LTC3815_MFR_IIN_PEAK, 0);
+ break;
+ case PMBUS_VIRT_RESET_IOUT_HISTORY:
+ ret = pmbus_write_word_data(client, page,
+ LTC3815_MFR_IOUT_PEAK, 0);
+ break;
+ case PMBUS_VIRT_RESET_VOUT_HISTORY:
+ ret = pmbus_write_word_data(client, page,
+ LTC3815_MFR_VOUT_PEAK, 0);
+ break;
+ case PMBUS_VIRT_RESET_VIN_HISTORY:
+ ret = pmbus_write_word_data(client, page,
+ LTC3815_MFR_VIN_PEAK, 0);
+ break;
+ case PMBUS_VIRT_RESET_TEMP_HISTORY:
+ ret = pmbus_write_word_data(client, page,
+ LTC3815_MFR_TEMP_PEAK, 0);
+ break;
+ default:
+ ret = -ENODATA;
+ break;
+ }
+ return ret;
+}
+
+static const struct i2c_device_id ltc3815_id[] = {
+ {"ltc3815", 0},
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, ltc3815_id);
+
+static struct pmbus_driver_info ltc3815_info = {
+ .pages = 1,
+ .format[PSC_VOLTAGE_IN] = direct,
+ .format[PSC_VOLTAGE_OUT] = direct,
+ .format[PSC_CURRENT_IN] = direct,
+ .format[PSC_CURRENT_OUT] = direct,
+ .format[PSC_TEMPERATURE] = direct,
+ .m[PSC_VOLTAGE_IN] = 250,
+ .b[PSC_VOLTAGE_IN] = 0,
+ .R[PSC_VOLTAGE_IN] = 0,
+ .m[PSC_VOLTAGE_OUT] = 2,
+ .b[PSC_VOLTAGE_OUT] = 0,
+ .R[PSC_VOLTAGE_OUT] = 3,
+ .m[PSC_CURRENT_IN] = 1,
+ .b[PSC_CURRENT_IN] = 0,
+ .R[PSC_CURRENT_IN] = 2,
+ .m[PSC_CURRENT_OUT] = 1,
+ .b[PSC_CURRENT_OUT] = 0,
+ .R[PSC_CURRENT_OUT] = 2,
+ .m[PSC_TEMPERATURE] = 1,
+ .b[PSC_TEMPERATURE] = 0,
+ .R[PSC_TEMPERATURE] = 0,
+ .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_VOUT |
+ PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP,
+ .read_byte_data = ltc3815_read_byte_data,
+ .read_word_data = ltc3815_read_word_data,
+ .write_byte = ltc3815_write_byte,
+ .write_word_data = ltc3815_write_word_data,
+};
+
+static int ltc3815_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int chip_id;
+
+ if (!i2c_check_functionality(client->adapter,
+ I2C_FUNC_SMBUS_READ_WORD_DATA))
+ return -ENODEV;
+
+ chip_id = i2c_smbus_read_word_data(client, LTC3815_MFR_SPECIAL_ID);
+ if (chip_id < 0)
+ return chip_id;
+ if ((chip_id & LTC3815_ID_MASK) != LTC3815_ID)
+ return -ENODEV;
+
+ return pmbus_do_probe(client, id, &ltc3815_info);
+}
+
+static struct i2c_driver ltc3815_driver = {
+ .driver = {
+ .name = "ltc3815",
+ },
+ .probe = ltc3815_probe,
+ .remove = pmbus_do_remove,
+ .id_table = ltc3815_id,
+};
+
+module_i2c_driver(ltc3815_driver);
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("PMBus driver for LTC3815");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c
index 1fae1881648c..c12ba4516df2 100644
--- a/drivers/iommu/intel_irq_remapping.c
+++ b/drivers/iommu/intel_irq_remapping.c
@@ -753,7 +753,7 @@ static inline void set_irq_posting_cap(void)
* should have X86_FEATURE_CX16 support, this has been confirmed
* with Intel hardware guys.
*/
- if ( cpu_has_cx16 )
+ if (boot_cpu_has(X86_FEATURE_CX16))
intel_irq_remap_ops.capability |= 1 << IRQ_POSTING_CAP;
for_each_iommu(iommu, drhd)
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 4d7294e5d982..11fc2a27fa2e 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -8,6 +8,11 @@ config ARM_GIC
select IRQ_DOMAIN_HIERARCHY
select MULTI_IRQ_HANDLER
+config ARM_GIC_MAX_NR
+ int
+ default 2 if ARCH_REALVIEW
+ default 1
+
config ARM_GIC_V2M
bool
depends on ARM_GIC
@@ -27,6 +32,14 @@ config ARM_GIC_V3_ITS
bool
select PCI_MSI_IRQ_DOMAIN
+config HISILICON_IRQ_MBIGEN
+ bool "Support mbigen interrupt controller"
+ default n
+ depends on ARM_GIC_V3 && ARM_GIC_V3_ITS && GENERIC_MSI_IRQ_DOMAIN
+ help
+ Enable the mbigen interrupt controller used on
+ Hisilicon platform.
+
config ARM_NVIC
bool
select IRQ_DOMAIN
@@ -138,6 +151,12 @@ config TB10X_IRQC
select IRQ_DOMAIN
select GENERIC_IRQ_CHIP
+config TS4800_IRQ
+ tristate "TS-4800 IRQ controller"
+ select IRQ_DOMAIN
+ help
+ Support for the TS-4800 FPGA IRQ controller
+
config VERSATILE_FPGA_IRQ
bool
select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 177f78f6e6d6..d4c2e4ebc308 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -21,9 +21,11 @@ obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o
obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o
obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o
+obj-$(CONFIG_REALVIEW_DT) += irq-gic-realview.o
obj-$(CONFIG_ARM_GIC_V2M) += irq-gic-v2m.o
obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o
obj-$(CONFIG_ARM_GIC_V3_ITS) += irq-gic-v3-its.o irq-gic-v3-its-pci-msi.o irq-gic-v3-its-platform-msi.o
+obj-$(CONFIG_HISILICON_IRQ_MBIGEN) += irq-mbigen.o
obj-$(CONFIG_ARM_NVIC) += irq-nvic.o
obj-$(CONFIG_ARM_VIC) += irq-vic.o
obj-$(CONFIG_ATMEL_AIC_IRQ) += irq-atmel-aic-common.o irq-atmel-aic.o
@@ -39,6 +41,7 @@ obj-$(CONFIG_ARCH_NSPIRE) += irq-zevio.o
obj-$(CONFIG_ARCH_VT8500) += irq-vt8500.o
obj-$(CONFIG_ST_IRQCHIP) += irq-st.o
obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o
+obj-$(CONFIG_TS4800_IRQ) += irq-ts4800.o
obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o
obj-$(CONFIG_XTENSA_MX) += irq-xtensa-mx.o
obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o
diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c
index f68708281fcf..963065a0d774 100644
--- a/drivers/irqchip/irq-bcm2836.c
+++ b/drivers/irqchip/irq-bcm2836.c
@@ -21,6 +21,9 @@
#include <linux/irqdomain.h>
#include <asm/exception.h>
+#define LOCAL_CONTROL 0x000
+#define LOCAL_PRESCALER 0x008
+
/*
* The low 2 bits identify the CPU that the GPU IRQ goes to, and the
* next 2 bits identify the CPU that the GPU FIQ goes to.
@@ -50,14 +53,16 @@
/* Same status bits as above, but for FIQ. */
#define LOCAL_FIQ_PENDING0 0x070
/*
- * Mailbox0 write-to-set bits. There are 16 mailboxes, 4 per CPU, and
+ * Mailbox write-to-set bits. There are 16 mailboxes, 4 per CPU, and
* these bits are organized by mailbox number and then CPU number. We
* use mailbox 0 for IPIs. The mailbox's interrupt is raised while
* any bit is set.
*/
#define LOCAL_MAILBOX0_SET0 0x080
-/* Mailbox0 write-to-clear bits. */
+#define LOCAL_MAILBOX3_SET0 0x08c
+/* Mailbox write-to-clear bits. */
#define LOCAL_MAILBOX0_CLR0 0x0c0
+#define LOCAL_MAILBOX3_CLR0 0x0cc
#define LOCAL_IRQ_CNTPSIRQ 0
#define LOCAL_IRQ_CNTPNSIRQ 1
@@ -162,7 +167,7 @@ __exception_irq_entry bcm2836_arm_irqchip_handle_irq(struct pt_regs *regs)
u32 stat;
stat = readl_relaxed(intc.base + LOCAL_IRQ_PENDING0 + 4 * cpu);
- if (stat & 0x10) {
+ if (stat & BIT(LOCAL_IRQ_MAILBOX0)) {
#ifdef CONFIG_SMP
void __iomem *mailbox0 = (intc.base +
LOCAL_MAILBOX0_CLR0 + 16 * cpu);
@@ -172,7 +177,7 @@ __exception_irq_entry bcm2836_arm_irqchip_handle_irq(struct pt_regs *regs)
writel(1 << ipi, mailbox0);
handle_IPI(ipi, regs);
#endif
- } else {
+ } else if (stat) {
u32 hwirq = ffs(stat) - 1;
handle_IRQ(irq_linear_revmap(intc.domain, hwirq), regs);
@@ -217,6 +222,24 @@ static struct notifier_block bcm2836_arm_irqchip_cpu_notifier = {
.notifier_call = bcm2836_arm_irqchip_cpu_notify,
.priority = 100,
};
+
+int __init bcm2836_smp_boot_secondary(unsigned int cpu,
+ struct task_struct *idle)
+{
+ unsigned long secondary_startup_phys =
+ (unsigned long)virt_to_phys((void *)secondary_startup);
+
+ dsb();
+ writel(secondary_startup_phys,
+ intc.base + LOCAL_MAILBOX3_SET0 + 16 * cpu);
+
+ return 0;
+}
+
+static const struct smp_operations bcm2836_smp_ops __initconst = {
+ .smp_boot_secondary = bcm2836_smp_boot_secondary,
+};
+
#endif
static const struct irq_domain_ops bcm2836_arm_irqchip_intc_ops = {
@@ -234,9 +257,31 @@ bcm2836_arm_irqchip_smp_init(void)
register_cpu_notifier(&bcm2836_arm_irqchip_cpu_notifier);
set_smp_cross_call(bcm2836_arm_irqchip_send_ipi);
+ smp_set_ops(&bcm2836_smp_ops);
#endif
}
+/*
+ * The LOCAL_IRQ_CNT* timer firings are based off of the external
+ * oscillator with some scaling. The firmware sets up CNTFRQ to
+ * report 19.2Mhz, but doesn't set up the scaling registers.
+ */
+static void bcm2835_init_local_timer_frequency(void)
+{
+ /*
+ * Set the timer to source from the 19.2Mhz crystal clock (bit
+ * 8 unset), and only increment by 1 instead of 2 (bit 9
+ * unset).
+ */
+ writel(0, intc.base + LOCAL_CONTROL);
+
+ /*
+ * Set the timer prescaler to 1:1 (timer freq = input freq *
+ * 2**31 / prescaler)
+ */
+ writel(0x80000000, intc.base + LOCAL_PRESCALER);
+}
+
static int __init bcm2836_arm_irqchip_l1_intc_of_init(struct device_node *node,
struct device_node *parent)
{
@@ -246,6 +291,8 @@ static int __init bcm2836_arm_irqchip_l1_intc_of_init(struct device_node *node,
node->full_name);
}
+ bcm2835_init_local_timer_frequency();
+
intc.domain = irq_domain_add_linear(node, LAST_IRQ + 1,
&bcm2836_arm_irqchip_intc_ops,
NULL);
diff --git a/drivers/irqchip/irq-gic-realview.c b/drivers/irqchip/irq-gic-realview.c
new file mode 100644
index 000000000000..aa46eb280a7f
--- /dev/null
+++ b/drivers/irqchip/irq-gic-realview.c
@@ -0,0 +1,43 @@
+/*
+ * Special GIC quirks for the ARM RealView
+ * Copyright (C) 2015 Linus Walleij
+ */
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/bitops.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/arm-gic.h>
+
+#define REALVIEW_SYS_LOCK_OFFSET 0x20
+#define REALVIEW_PB11MP_SYS_PLD_CTRL1 0x74
+#define VERSATILE_LOCK_VAL 0xA05F
+#define PLD_INTMODE_MASK BIT(22)|BIT(23)|BIT(24)
+#define PLD_INTMODE_LEGACY 0x0
+#define PLD_INTMODE_NEW_DCC BIT(22)
+#define PLD_INTMODE_NEW_NO_DCC BIT(23)
+#define PLD_INTMODE_FIQ_ENABLE BIT(24)
+
+static int __init
+realview_gic_of_init(struct device_node *node, struct device_node *parent)
+{
+ static struct regmap *map;
+
+ /* The PB11MPCore GIC needs to be configured in the syscon */
+ map = syscon_regmap_lookup_by_compatible("arm,realview-pb11mp-syscon");
+ if (!IS_ERR(map)) {
+ /* new irq mode with no DCC */
+ regmap_write(map, REALVIEW_SYS_LOCK_OFFSET,
+ VERSATILE_LOCK_VAL);
+ regmap_update_bits(map, REALVIEW_PB11MP_SYS_PLD_CTRL1,
+ PLD_INTMODE_NEW_NO_DCC,
+ PLD_INTMODE_MASK);
+ regmap_write(map, REALVIEW_SYS_LOCK_OFFSET, 0x0000);
+ pr_info("TC11MP GIC: set up interrupt controller to NEW mode, no DCC\n");
+ } else {
+ pr_err("TC11MP GIC setup: could not find syscon\n");
+ return -ENXIO;
+ }
+ return gic_of_init(node, parent);
+}
+IRQCHIP_DECLARE(armtc11mp_gic, "arm,tc11mp-gic", realview_gic_of_init);
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 87f8d104acab..c779f83e511d 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -15,9 +15,11 @@
#define pr_fmt(fmt) "GICv2m: " fmt
+#include <linux/acpi.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
+#include <linux/msi.h>
#include <linux/of_address.h>
#include <linux/of_pci.h>
#include <linux/slab.h>
@@ -55,7 +57,7 @@ static DEFINE_SPINLOCK(v2m_lock);
struct v2m_data {
struct list_head entry;
- struct device_node *node;
+ struct fwnode_handle *fwnode;
struct resource res; /* GICv2m resource */
void __iomem *base; /* GICv2m virt address */
u32 spi_start; /* The SPI number that MSIs start */
@@ -138,6 +140,11 @@ static int gicv2m_irq_gic_domain_alloc(struct irq_domain *domain,
fwspec.param[0] = 0;
fwspec.param[1] = hwirq - 32;
fwspec.param[2] = IRQ_TYPE_EDGE_RISING;
+ } else if (is_fwnode_irqchip(domain->parent->fwnode)) {
+ fwspec.fwnode = domain->parent->fwnode;
+ fwspec.param_count = 2;
+ fwspec.param[0] = hwirq;
+ fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
} else {
return -EINVAL;
}
@@ -254,7 +261,9 @@ static void gicv2m_teardown(void)
list_del(&v2m->entry);
kfree(v2m->bm);
iounmap(v2m->base);
- of_node_put(v2m->node);
+ of_node_put(to_of_node(v2m->fwnode));
+ if (is_fwnode_irqchip(v2m->fwnode))
+ irq_domain_free_fwnode(v2m->fwnode);
kfree(v2m);
}
}
@@ -268,7 +277,7 @@ static int gicv2m_allocate_domains(struct irq_domain *parent)
if (!v2m)
return 0;
- inner_domain = irq_domain_create_tree(of_node_to_fwnode(v2m->node),
+ inner_domain = irq_domain_create_tree(v2m->fwnode,
&gicv2m_domain_ops, v2m);
if (!inner_domain) {
pr_err("Failed to create GICv2m domain\n");
@@ -277,10 +286,10 @@ static int gicv2m_allocate_domains(struct irq_domain *parent)
inner_domain->bus_token = DOMAIN_BUS_NEXUS;
inner_domain->parent = parent;
- pci_domain = pci_msi_create_irq_domain(of_node_to_fwnode(v2m->node),
+ pci_domain = pci_msi_create_irq_domain(v2m->fwnode,
&gicv2m_msi_domain_info,
inner_domain);
- plat_domain = platform_msi_create_irq_domain(of_node_to_fwnode(v2m->node),
+ plat_domain = platform_msi_create_irq_domain(v2m->fwnode,
&gicv2m_pmsi_domain_info,
inner_domain);
if (!pci_domain || !plat_domain) {
@@ -296,8 +305,9 @@ static int gicv2m_allocate_domains(struct irq_domain *parent)
return 0;
}
-static int __init gicv2m_init_one(struct device_node *node,
- struct irq_domain *parent)
+static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
+ u32 spi_start, u32 nr_spis,
+ struct resource *res)
{
int ret;
struct v2m_data *v2m;
@@ -309,13 +319,9 @@ static int __init gicv2m_init_one(struct device_node *node,
}
INIT_LIST_HEAD(&v2m->entry);
- v2m->node = node;
+ v2m->fwnode = fwnode;
- ret = of_address_to_resource(node, 0, &v2m->res);
- if (ret) {
- pr_err("Failed to allocate v2m resource.\n");
- goto err_free_v2m;
- }
+ memcpy(&v2m->res, res, sizeof(struct resource));
v2m->base = ioremap(v2m->res.start, resource_size(&v2m->res));
if (!v2m->base) {
@@ -324,10 +330,9 @@ static int __init gicv2m_init_one(struct device_node *node,
goto err_free_v2m;
}
- if (!of_property_read_u32(node, "arm,msi-base-spi", &v2m->spi_start) &&
- !of_property_read_u32(node, "arm,msi-num-spis", &v2m->nr_spis)) {
- pr_info("Overriding V2M MSI_TYPER (base:%u, num:%u)\n",
- v2m->spi_start, v2m->nr_spis);
+ if (spi_start && nr_spis) {
+ v2m->spi_start = spi_start;
+ v2m->nr_spis = nr_spis;
} else {
u32 typer = readl_relaxed(v2m->base + V2M_MSI_TYPER);
@@ -359,10 +364,9 @@ static int __init gicv2m_init_one(struct device_node *node,
}
list_add_tail(&v2m->entry, &v2m_nodes);
- pr_info("Node %s: range[%#lx:%#lx], SPI[%d:%d]\n", node->name,
- (unsigned long)v2m->res.start, (unsigned long)v2m->res.end,
- v2m->spi_start, (v2m->spi_start + v2m->nr_spis));
+ pr_info("range%pR, SPI[%d:%d]\n", res,
+ v2m->spi_start, (v2m->spi_start + v2m->nr_spis - 1));
return 0;
err_iounmap:
@@ -377,19 +381,36 @@ static struct of_device_id gicv2m_device_id[] = {
{},
};
-int __init gicv2m_of_init(struct device_node *node, struct irq_domain *parent)
+static int __init gicv2m_of_init(struct fwnode_handle *parent_handle,
+ struct irq_domain *parent)
{
int ret = 0;
+ struct device_node *node = to_of_node(parent_handle);
struct device_node *child;
for (child = of_find_matching_node(node, gicv2m_device_id); child;
child = of_find_matching_node(child, gicv2m_device_id)) {
+ u32 spi_start = 0, nr_spis = 0;
+ struct resource res;
+
if (!of_find_property(child, "msi-controller", NULL))
continue;
- ret = gicv2m_init_one(child, parent);
+ ret = of_address_to_resource(child, 0, &res);
+ if (ret) {
+ pr_err("Failed to allocate v2m resource.\n");
+ break;
+ }
+
+ if (!of_property_read_u32(child, "arm,msi-base-spi",
+ &spi_start) &&
+ !of_property_read_u32(child, "arm,msi-num-spis", &nr_spis))
+ pr_info("DT overriding V2M MSI_TYPER (base:%u, num:%u)\n",
+ spi_start, nr_spis);
+
+ ret = gicv2m_init_one(&child->fwnode, spi_start, nr_spis, &res);
if (ret) {
- of_node_put(node);
+ of_node_put(child);
break;
}
}
@@ -400,3 +421,101 @@ int __init gicv2m_of_init(struct device_node *node, struct irq_domain *parent)
gicv2m_teardown();
return ret;
}
+
+#ifdef CONFIG_ACPI
+static int acpi_num_msi;
+
+static struct fwnode_handle *gicv2m_get_fwnode(struct device *dev)
+{
+ struct v2m_data *data;
+
+ if (WARN_ON(acpi_num_msi <= 0))
+ return NULL;
+
+ /* We only return the fwnode of the first MSI frame. */
+ data = list_first_entry_or_null(&v2m_nodes, struct v2m_data, entry);
+ if (!data)
+ return NULL;
+
+ return data->fwnode;
+}
+
+static int __init
+acpi_parse_madt_msi(struct acpi_subtable_header *header,
+ const unsigned long end)
+{
+ int ret;
+ struct resource res;
+ u32 spi_start = 0, nr_spis = 0;
+ struct acpi_madt_generic_msi_frame *m;
+ struct fwnode_handle *fwnode;
+
+ m = (struct acpi_madt_generic_msi_frame *)header;
+ if (BAD_MADT_ENTRY(m, end))
+ return -EINVAL;
+
+ res.start = m->base_address;
+ res.end = m->base_address + SZ_4K - 1;
+ res.flags = IORESOURCE_MEM;
+
+ if (m->flags & ACPI_MADT_OVERRIDE_SPI_VALUES) {
+ spi_start = m->spi_base;
+ nr_spis = m->spi_count;
+
+ pr_info("ACPI overriding V2M MSI_TYPER (base:%u, num:%u)\n",
+ spi_start, nr_spis);
+ }
+
+ fwnode = irq_domain_alloc_fwnode((void *)m->base_address);
+ if (!fwnode) {
+ pr_err("Unable to allocate GICv2m domain token\n");
+ return -EINVAL;
+ }
+
+ ret = gicv2m_init_one(fwnode, spi_start, nr_spis, &res);
+ if (ret)
+ irq_domain_free_fwnode(fwnode);
+
+ return ret;
+}
+
+static int __init gicv2m_acpi_init(struct irq_domain *parent)
+{
+ int ret;
+
+ if (acpi_num_msi > 0)
+ return 0;
+
+ acpi_num_msi = acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_MSI_FRAME,
+ acpi_parse_madt_msi, 0);
+
+ if (acpi_num_msi <= 0)
+ goto err_out;
+
+ ret = gicv2m_allocate_domains(parent);
+ if (ret)
+ goto err_out;
+
+ pci_msi_register_fwnode_provider(&gicv2m_get_fwnode);
+
+ return 0;
+
+err_out:
+ gicv2m_teardown();
+ return -EINVAL;
+}
+#else /* CONFIG_ACPI */
+static int __init gicv2m_acpi_init(struct irq_domain *parent)
+{
+ return -EINVAL;
+}
+#endif /* CONFIG_ACPI */
+
+int __init gicv2m_init(struct fwnode_handle *parent_handle,
+ struct irq_domain *parent)
+{
+ if (is_of_node(parent_handle))
+ return gicv2m_of_init(parent_handle, parent);
+
+ return gicv2m_acpi_init(parent);
+}
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index abf2ffaed392..911758c056c1 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -69,6 +69,7 @@ union gic_base {
};
struct gic_chip_data {
+ struct irq_chip chip;
union gic_base dist_base;
union gic_base cpu_base;
#ifdef CONFIG_CPU_PM
@@ -99,11 +100,7 @@ static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly;
static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE;
-#ifndef MAX_GIC_NR
-#define MAX_GIC_NR 1
-#endif
-
-static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly;
+static struct gic_chip_data gic_data[CONFIG_ARM_GIC_MAX_NR] __read_mostly;
#ifdef CONFIG_GIC_NON_BANKED
static void __iomem *gic_get_percpu_base(union gic_base *base)
@@ -336,7 +333,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
irqnr = irqstat & GICC_IAR_INT_ID_MASK;
- if (likely(irqnr > 15 && irqnr < 1021)) {
+ if (likely(irqnr > 15 && irqnr < 1020)) {
if (static_key_true(&supports_deactivate))
writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
handle_domain_irq(gic->domain, irqnr, regs);
@@ -383,7 +380,6 @@ static void gic_handle_cascade_irq(struct irq_desc *desc)
}
static struct irq_chip gic_chip = {
- .name = "GIC",
.irq_mask = gic_mask_irq,
.irq_unmask = gic_unmask_irq,
.irq_eoi = gic_eoi_irq,
@@ -417,8 +413,7 @@ static struct irq_chip gic_eoimode1_chip = {
void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
{
- if (gic_nr >= MAX_GIC_NR)
- BUG();
+ BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
irq_set_chained_handler_and_data(irq, gic_handle_cascade_irq,
&gic_data[gic_nr]);
}
@@ -524,7 +519,7 @@ int gic_cpu_if_down(unsigned int gic_nr)
void __iomem *cpu_base;
u32 val = 0;
- if (gic_nr >= MAX_GIC_NR)
+ if (gic_nr >= CONFIG_ARM_GIC_MAX_NR)
return -EINVAL;
cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
@@ -548,8 +543,7 @@ static void gic_dist_save(unsigned int gic_nr)
void __iomem *dist_base;
int i;
- if (gic_nr >= MAX_GIC_NR)
- BUG();
+ BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
gic_irqs = gic_data[gic_nr].gic_irqs;
dist_base = gic_data_dist_base(&gic_data[gic_nr]);
@@ -587,8 +581,7 @@ static void gic_dist_restore(unsigned int gic_nr)
unsigned int i;
void __iomem *dist_base;
- if (gic_nr >= MAX_GIC_NR)
- BUG();
+ BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
gic_irqs = gic_data[gic_nr].gic_irqs;
dist_base = gic_data_dist_base(&gic_data[gic_nr]);
@@ -634,8 +627,7 @@ static void gic_cpu_save(unsigned int gic_nr)
void __iomem *dist_base;
void __iomem *cpu_base;
- if (gic_nr >= MAX_GIC_NR)
- BUG();
+ BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
dist_base = gic_data_dist_base(&gic_data[gic_nr]);
cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
@@ -664,8 +656,7 @@ static void gic_cpu_restore(unsigned int gic_nr)
void __iomem *dist_base;
void __iomem *cpu_base;
- if (gic_nr >= MAX_GIC_NR)
- BUG();
+ BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
dist_base = gic_data_dist_base(&gic_data[gic_nr]);
cpu_base = gic_data_cpu_base(&gic_data[gic_nr]);
@@ -703,7 +694,7 @@ static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v)
{
int i;
- for (i = 0; i < MAX_GIC_NR; i++) {
+ for (i = 0; i < CONFIG_ARM_GIC_MAX_NR; i++) {
#ifdef CONFIG_GIC_NON_BANKED
/* Skip over unused GICs */
if (!gic_data[i].get_base)
@@ -835,8 +826,7 @@ void gic_migrate_target(unsigned int new_cpu_id)
int i, ror_val, cpu = smp_processor_id();
u32 val, cur_target_mask, active_mask;
- if (gic_nr >= MAX_GIC_NR)
- BUG();
+ BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
dist_base = gic_data_dist_base(&gic_data[gic_nr]);
if (!dist_base)
@@ -925,20 +915,15 @@ void __init gic_init_physaddr(struct device_node *node)
static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hw)
{
- struct irq_chip *chip = &gic_chip;
-
- if (static_key_true(&supports_deactivate)) {
- if (d->host_data == (void *)&gic_data[0])
- chip = &gic_eoimode1_chip;
- }
+ struct gic_chip_data *gic = d->host_data;
if (hw < 32) {
irq_set_percpu_devid(irq);
- irq_domain_set_info(d, irq, hw, chip, d->host_data,
+ irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data,
handle_percpu_devid_irq, NULL, NULL);
irq_set_status_flags(irq, IRQ_NOAUTOEN);
} else {
- irq_domain_set_info(d, irq, hw, chip, d->host_data,
+ irq_domain_set_info(d, irq, hw, &gic->chip, d->host_data,
handle_fasteoi_irq, NULL, NULL);
irq_set_probe(irq);
}
@@ -972,7 +957,7 @@ static int gic_irq_domain_translate(struct irq_domain *d,
return 0;
}
- if (fwspec->fwnode->type == FWNODE_IRQCHIP) {
+ if (is_fwnode_irqchip(fwspec->fwnode)) {
if(fwspec->param_count != 2)
return -EINVAL;
@@ -1040,11 +1025,20 @@ static void __init __gic_init_bases(unsigned int gic_nr, int irq_start,
struct gic_chip_data *gic;
int gic_irqs, irq_base, i;
- BUG_ON(gic_nr >= MAX_GIC_NR);
+ BUG_ON(gic_nr >= CONFIG_ARM_GIC_MAX_NR);
gic_check_cpu_features();
gic = &gic_data[gic_nr];
+
+ /* Initialize irq_chip */
+ if (static_key_true(&supports_deactivate) && gic_nr == 0) {
+ gic->chip = gic_eoimode1_chip;
+ } else {
+ gic->chip = gic_chip;
+ gic->chip.name = kasprintf(GFP_KERNEL, "GIC-%d", gic_nr);
+ }
+
#ifdef CONFIG_GIC_NON_BANKED
if (percpu_offset) { /* Frankein-GIC without banked registers... */
unsigned int cpu;
@@ -1196,7 +1190,7 @@ static bool gic_check_eoimode(struct device_node *node, void __iomem **base)
return true;
}
-static int __init
+int __init
gic_of_init(struct device_node *node, struct device_node *parent)
{
void __iomem *cpu_base;
@@ -1234,7 +1228,7 @@ gic_of_init(struct device_node *node, struct device_node *parent)
}
if (IS_ENABLED(CONFIG_ARM_GIC_V2M))
- gicv2m_of_init(node, gic_data[gic_cnt].domain);
+ gicv2m_init(&node->fwnode, gic_data[gic_cnt].domain);
gic_cnt++;
return 0;
@@ -1359,6 +1353,10 @@ static int __init gic_v2_acpi_init(struct acpi_subtable_header *header,
__gic_init_bases(0, -1, dist_base, cpu_base, 0, domain_handle);
acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, domain_handle);
+
+ if (IS_ENABLED(CONFIG_ARM_GIC_V2M))
+ gicv2m_init(NULL, gic_data[0].domain);
+
return 0;
}
IRQCHIP_ACPI_DECLARE(gic_v2, ACPI_MADT_TYPE_GENERIC_DISTRIBUTOR,
diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c
new file mode 100644
index 000000000000..4dd3eb8a40b3
--- /dev/null
+++ b/drivers/irqchip/irq-mbigen.c
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2015 Hisilicon Limited, All Rights Reserved.
+ * Author: Jun Ma <majun258@huawei.com>
+ * Author: Yun Wu <wuyun.wu@huawei.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.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irqchip.h>
+#include <linux/module.h>
+#include <linux/msi.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+/* Interrupt numbers per mbigen node supported */
+#define IRQS_PER_MBIGEN_NODE 128
+
+/* 64 irqs (Pin0-pin63) are reserved for each mbigen chip */
+#define RESERVED_IRQ_PER_MBIGEN_CHIP 64
+
+/* The maximum IRQ pin number of mbigen chip(start from 0) */
+#define MAXIMUM_IRQ_PIN_NUM 1407
+
+/**
+ * In mbigen vector register
+ * bit[21:12]: event id value
+ * bit[11:0]: device id
+ */
+#define IRQ_EVENT_ID_SHIFT 12
+#define IRQ_EVENT_ID_MASK 0x3ff
+
+/* register range of each mbigen node */
+#define MBIGEN_NODE_OFFSET 0x1000
+
+/* offset of vector register in mbigen node */
+#define REG_MBIGEN_VEC_OFFSET 0x200
+
+/**
+ * offset of clear register in mbigen node
+ * This register is used to clear the status
+ * of interrupt
+ */
+#define REG_MBIGEN_CLEAR_OFFSET 0xa000
+
+/**
+ * offset of interrupt type register
+ * This register is used to configure interrupt
+ * trigger type
+ */
+#define REG_MBIGEN_TYPE_OFFSET 0x0
+
+/**
+ * struct mbigen_device - holds the information of mbigen device.
+ *
+ * @pdev: pointer to the platform device structure of mbigen chip.
+ * @base: mapped address of this mbigen chip.
+ */
+struct mbigen_device {
+ struct platform_device *pdev;
+ void __iomem *base;
+};
+
+static inline unsigned int get_mbigen_vec_reg(irq_hw_number_t hwirq)
+{
+ unsigned int nid, pin;
+
+ hwirq -= RESERVED_IRQ_PER_MBIGEN_CHIP;
+ nid = hwirq / IRQS_PER_MBIGEN_NODE + 1;
+ pin = hwirq % IRQS_PER_MBIGEN_NODE;
+
+ return pin * 4 + nid * MBIGEN_NODE_OFFSET
+ + REG_MBIGEN_VEC_OFFSET;
+}
+
+static inline void get_mbigen_type_reg(irq_hw_number_t hwirq,
+ u32 *mask, u32 *addr)
+{
+ unsigned int nid, irq_ofst, ofst;
+
+ hwirq -= RESERVED_IRQ_PER_MBIGEN_CHIP;
+ nid = hwirq / IRQS_PER_MBIGEN_NODE + 1;
+ irq_ofst = hwirq % IRQS_PER_MBIGEN_NODE;
+
+ *mask = 1 << (irq_ofst % 32);
+ ofst = irq_ofst / 32 * 4;
+
+ *addr = ofst + nid * MBIGEN_NODE_OFFSET
+ + REG_MBIGEN_TYPE_OFFSET;
+}
+
+static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq,
+ u32 *mask, u32 *addr)
+{
+ unsigned int ofst;
+
+ hwirq -= RESERVED_IRQ_PER_MBIGEN_CHIP;
+ ofst = hwirq / 32 * 4;
+
+ *mask = 1 << (hwirq % 32);
+ *addr = ofst + REG_MBIGEN_CLEAR_OFFSET;
+}
+
+static void mbigen_eoi_irq(struct irq_data *data)
+{
+ void __iomem *base = data->chip_data;
+ u32 mask, addr;
+
+ get_mbigen_clear_reg(data->hwirq, &mask, &addr);
+
+ writel_relaxed(mask, base + addr);
+
+ irq_chip_eoi_parent(data);
+}
+
+static int mbigen_set_type(struct irq_data *data, unsigned int type)
+{
+ void __iomem *base = data->chip_data;
+ u32 mask, addr, val;
+
+ if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
+ return -EINVAL;
+
+ get_mbigen_type_reg(data->hwirq, &mask, &addr);
+
+ val = readl_relaxed(base + addr);
+
+ if (type == IRQ_TYPE_LEVEL_HIGH)
+ val |= mask;
+ else
+ val &= ~mask;
+
+ writel_relaxed(val, base + addr);
+
+ return 0;
+}
+
+static struct irq_chip mbigen_irq_chip = {
+ .name = "mbigen-v2",
+ .irq_mask = irq_chip_mask_parent,
+ .irq_unmask = irq_chip_unmask_parent,
+ .irq_eoi = mbigen_eoi_irq,
+ .irq_set_type = mbigen_set_type,
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+};
+
+static void mbigen_write_msg(struct msi_desc *desc, struct msi_msg *msg)
+{
+ struct irq_data *d = irq_get_irq_data(desc->irq);
+ void __iomem *base = d->chip_data;
+ u32 val;
+
+ base += get_mbigen_vec_reg(d->hwirq);
+ val = readl_relaxed(base);
+
+ val &= ~(IRQ_EVENT_ID_MASK << IRQ_EVENT_ID_SHIFT);
+ val |= (msg->data << IRQ_EVENT_ID_SHIFT);
+
+ /* The address of doorbell is encoded in mbigen register by default
+ * So,we don't need to program the doorbell address at here
+ */
+ writel_relaxed(val, base);
+}
+
+static int mbigen_domain_translate(struct irq_domain *d,
+ struct irq_fwspec *fwspec,
+ unsigned long *hwirq,
+ unsigned int *type)
+{
+ if (is_of_node(fwspec->fwnode)) {
+ if (fwspec->param_count != 2)
+ return -EINVAL;
+
+ if ((fwspec->param[0] > MAXIMUM_IRQ_PIN_NUM) ||
+ (fwspec->param[0] < RESERVED_IRQ_PER_MBIGEN_CHIP))
+ return -EINVAL;
+ else
+ *hwirq = fwspec->param[0];
+
+ /* If there is no valid irq type, just use the default type */
+ if ((fwspec->param[1] == IRQ_TYPE_EDGE_RISING) ||
+ (fwspec->param[1] == IRQ_TYPE_LEVEL_HIGH))
+ *type = fwspec->param[1];
+ else
+ return -EINVAL;
+
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int mbigen_irq_domain_alloc(struct irq_domain *domain,
+ unsigned int virq,
+ unsigned int nr_irqs,
+ void *args)
+{
+ struct irq_fwspec *fwspec = args;
+ irq_hw_number_t hwirq;
+ unsigned int type;
+ struct mbigen_device *mgn_chip;
+ int i, err;
+
+ err = mbigen_domain_translate(domain, fwspec, &hwirq, &type);
+ if (err)
+ return err;
+
+ err = platform_msi_domain_alloc(domain, virq, nr_irqs);
+ if (err)
+ return err;
+
+ mgn_chip = platform_msi_get_host_data(domain);
+
+ for (i = 0; i < nr_irqs; i++)
+ irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+ &mbigen_irq_chip, mgn_chip->base);
+
+ return 0;
+}
+
+static struct irq_domain_ops mbigen_domain_ops = {
+ .translate = mbigen_domain_translate,
+ .alloc = mbigen_irq_domain_alloc,
+ .free = irq_domain_free_irqs_common,
+};
+
+static int mbigen_device_probe(struct platform_device *pdev)
+{
+ struct mbigen_device *mgn_chip;
+ struct resource *res;
+ struct irq_domain *domain;
+ u32 num_pins;
+
+ mgn_chip = devm_kzalloc(&pdev->dev, sizeof(*mgn_chip), GFP_KERNEL);
+ if (!mgn_chip)
+ return -ENOMEM;
+
+ mgn_chip->pdev = pdev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mgn_chip->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mgn_chip->base))
+ return PTR_ERR(mgn_chip->base);
+
+ if (of_property_read_u32(pdev->dev.of_node, "num-pins", &num_pins) < 0) {
+ dev_err(&pdev->dev, "No num-pins property\n");
+ return -EINVAL;
+ }
+
+ domain = platform_msi_create_device_domain(&pdev->dev, num_pins,
+ mbigen_write_msg,
+ &mbigen_domain_ops,
+ mgn_chip);
+
+ if (!domain)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, mgn_chip);
+
+ dev_info(&pdev->dev, "Allocated %d MSIs\n", num_pins);
+
+ return 0;
+}
+
+static const struct of_device_id mbigen_of_match[] = {
+ { .compatible = "hisilicon,mbigen-v2" },
+ { /* END */ }
+};
+MODULE_DEVICE_TABLE(of, mbigen_of_match);
+
+static struct platform_driver mbigen_platform_driver = {
+ .driver = {
+ .name = "Hisilicon MBIGEN-V2",
+ .owner = THIS_MODULE,
+ .of_match_table = mbigen_of_match,
+ },
+ .probe = mbigen_device_probe,
+};
+
+module_platform_driver(mbigen_platform_driver);
+
+MODULE_AUTHOR("Jun Ma <majun258@huawei.com>");
+MODULE_AUTHOR("Yun Wu <wuyun.wu@huawei.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Hisilicon MBI Generator driver");
diff --git a/drivers/irqchip/irq-omap-intc.c b/drivers/irqchip/irq-omap-intc.c
index 8587d0f8d8c0..9d1bcfc33e4c 100644
--- a/drivers/irqchip/irq-omap-intc.c
+++ b/drivers/irqchip/irq-omap-intc.c
@@ -47,6 +47,7 @@
#define INTC_ILR0 0x0100
#define ACTIVEIRQ_MASK 0x7f /* omap2/3 active interrupt bits */
+#define SPURIOUSIRQ_MASK (0x1ffffff << 7)
#define INTCPS_NR_ILR_REGS 128
#define INTCPS_NR_MIR_REGS 4
@@ -207,7 +208,6 @@ static int __init omap_alloc_gc_of(struct irq_domain *d, void __iomem *base)
ct = gc->chip_types;
ct->type = IRQ_TYPE_LEVEL_MASK;
- ct->handler = handle_level_irq;
ct->chip.irq_ack = omap_mask_ack_irq;
ct->chip.irq_mask = irq_gc_mask_disable_reg;
@@ -330,11 +330,35 @@ static int __init omap_init_irq(u32 base, struct device_node *node)
static asmlinkage void __exception_irq_entry
omap_intc_handle_irq(struct pt_regs *regs)
{
+ extern unsigned long irq_err_count;
u32 irqnr;
irqnr = intc_readl(INTC_SIR);
+
+ /*
+ * A spurious IRQ can result if interrupt that triggered the
+ * sorting is no longer active during the sorting (10 INTC
+ * functional clock cycles after interrupt assertion). Or a
+ * change in interrupt mask affected the result during sorting
+ * time. There is no special handling required except ignoring
+ * the SIR register value just read and retrying.
+ * See section 6.2.5 of AM335x TRM Literature Number: SPRUH73K
+ *
+ * Many a times, a spurious interrupt situation has been fixed
+ * by adding a flush for the posted write acking the IRQ in
+ * the device driver. Typically, this is going be the device
+ * driver whose interrupt was handled just before the spurious
+ * IRQ occurred. Pay attention to those device drivers if you
+ * run into hitting the spurious IRQ condition below.
+ */
+ if (unlikely((irqnr & SPURIOUSIRQ_MASK) == SPURIOUSIRQ_MASK)) {
+ pr_err_once("%s: spurious irq!\n", __func__);
+ irq_err_count++;
+ omap_ack_irq(NULL);
+ return;
+ }
+
irqnr &= ACTIVEIRQ_MASK;
- WARN_ONCE(!irqnr, "Spurious IRQ ?\n");
handle_domain_irq(domain, irqnr, regs);
}
diff --git a/drivers/irqchip/irq-renesas-h8300h.c b/drivers/irqchip/irq-renesas-h8300h.c
index 6fd30d5ee14d..c378768d75b3 100644
--- a/drivers/irqchip/irq-renesas-h8300h.c
+++ b/drivers/irqchip/irq-renesas-h8300h.c
@@ -21,9 +21,9 @@ static const char ipr_bit[] = {
10, 10, 10, 10, 9, 9, 9, 9,
};
-static void *intc_baseaddr;
+static void __iomem *intc_baseaddr;
-#define IPR ((unsigned long)intc_baseaddr + 6)
+#define IPR (intc_baseaddr + 6)
static void h8300h_disable_irq(struct irq_data *data)
{
@@ -81,8 +81,8 @@ static int __init h8300h_intc_of_init(struct device_node *intc,
BUG_ON(!intc_baseaddr);
/* All interrupt priority low */
- ctrl_outb(0x00, IPR + 0);
- ctrl_outb(0x00, IPR + 1);
+ writeb(0x00, IPR + 0);
+ writeb(0x00, IPR + 1);
domain = irq_domain_add_linear(intc, NR_IRQS, &irq_ops, NULL);
BUG_ON(!domain);
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
index c325806561be..713177d97c7a 100644
--- a/drivers/irqchip/irq-renesas-intc-irqpin.c
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -31,7 +31,6 @@
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/of_device.h>
-#include <linux/platform_data/irq-renesas-intc-irqpin.h>
#include <linux/pm_runtime.h>
#define INTC_IRQPIN_MAX 8 /* maximum 8 interrupts per driver instance */
@@ -75,18 +74,20 @@ struct intc_irqpin_irq {
struct intc_irqpin_priv {
struct intc_irqpin_iomem iomem[INTC_IRQPIN_REG_NR];
struct intc_irqpin_irq irq[INTC_IRQPIN_MAX];
- struct renesas_intc_irqpin_config config;
- unsigned int number_of_irqs;
+ unsigned int sense_bitfield_width;
struct platform_device *pdev;
struct irq_chip irq_chip;
struct irq_domain *irq_domain;
struct clk *clk;
- bool shared_irqs;
+ unsigned shared_irqs:1;
+ unsigned needs_clk:1;
u8 shared_irq_mask;
};
-struct intc_irqpin_irlm_config {
+struct intc_irqpin_config {
unsigned int irlm_bit;
+ unsigned needs_irlm:1;
+ unsigned needs_clk:1;
};
static unsigned long intc_irqpin_read32(void __iomem *iomem)
@@ -171,7 +172,7 @@ static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value)
{
/* The SENSE register is assumed to be 32-bit. */
- int bitfield_width = p->config.sense_bitfield_width;
+ int bitfield_width = p->sense_bitfield_width;
int shift = 32 - (irq + 1) * bitfield_width;
dev_dbg(&p->pdev->dev, "sense irq = %d, mode = %d\n", irq, value);
@@ -361,8 +362,15 @@ static const struct irq_domain_ops intc_irqpin_irq_domain_ops = {
.xlate = irq_domain_xlate_twocell,
};
-static const struct intc_irqpin_irlm_config intc_irqpin_irlm_r8a777x = {
+static const struct intc_irqpin_config intc_irqpin_irlm_r8a777x = {
.irlm_bit = 23, /* ICR0.IRLM0 */
+ .needs_irlm = 1,
+ .needs_clk = 0,
+};
+
+static const struct intc_irqpin_config intc_irqpin_rmobile = {
+ .needs_irlm = 0,
+ .needs_clk = 1,
};
static const struct of_device_id intc_irqpin_dt_ids[] = {
@@ -371,14 +379,18 @@ static const struct of_device_id intc_irqpin_dt_ids[] = {
.data = &intc_irqpin_irlm_r8a777x },
{ .compatible = "renesas,intc-irqpin-r8a7779",
.data = &intc_irqpin_irlm_r8a777x },
+ { .compatible = "renesas,intc-irqpin-r8a7740",
+ .data = &intc_irqpin_rmobile },
+ { .compatible = "renesas,intc-irqpin-sh73a0",
+ .data = &intc_irqpin_rmobile },
{},
};
MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids);
static int intc_irqpin_probe(struct platform_device *pdev)
{
+ const struct intc_irqpin_config *config = NULL;
struct device *dev = &pdev->dev;
- struct renesas_intc_irqpin_config *pdata = dev->platform_data;
const struct of_device_id *of_id;
struct intc_irqpin_priv *p;
struct intc_irqpin_iomem *i;
@@ -388,6 +400,8 @@ static int intc_irqpin_probe(struct platform_device *pdev)
void (*enable_fn)(struct irq_data *d);
void (*disable_fn)(struct irq_data *d);
const char *name = dev_name(dev);
+ bool control_parent;
+ unsigned int nirqs;
int ref_irq;
int ret;
int k;
@@ -399,23 +413,28 @@ static int intc_irqpin_probe(struct platform_device *pdev)
}
/* deal with driver instance configuration */
- if (pdata) {
- memcpy(&p->config, pdata, sizeof(*pdata));
- } else {
- of_property_read_u32(dev->of_node, "sense-bitfield-width",
- &p->config.sense_bitfield_width);
- p->config.control_parent = of_property_read_bool(dev->of_node,
- "control-parent");
- }
- if (!p->config.sense_bitfield_width)
- p->config.sense_bitfield_width = 4; /* default to 4 bits */
+ of_property_read_u32(dev->of_node, "sense-bitfield-width",
+ &p->sense_bitfield_width);
+ control_parent = of_property_read_bool(dev->of_node, "control-parent");
+ if (!p->sense_bitfield_width)
+ p->sense_bitfield_width = 4; /* default to 4 bits */
p->pdev = pdev;
platform_set_drvdata(pdev, p);
+ of_id = of_match_device(intc_irqpin_dt_ids, dev);
+ if (of_id && of_id->data) {
+ config = of_id->data;
+ p->needs_clk = config->needs_clk;
+ }
+
p->clk = devm_clk_get(dev, NULL);
if (IS_ERR(p->clk)) {
- dev_warn(dev, "unable to get clock\n");
+ if (p->needs_clk) {
+ dev_err(dev, "unable to get clock\n");
+ ret = PTR_ERR(p->clk);
+ goto err0;
+ }
p->clk = NULL;
}
@@ -443,8 +462,8 @@ static int intc_irqpin_probe(struct platform_device *pdev)
p->irq[k].requested_irq = irq->start;
}
- p->number_of_irqs = k;
- if (p->number_of_irqs < 1) {
+ nirqs = k;
+ if (nirqs < 1) {
dev_err(dev, "not enough IRQ resources\n");
ret = -EINVAL;
goto err0;
@@ -485,20 +504,16 @@ static int intc_irqpin_probe(struct platform_device *pdev)
}
/* configure "individual IRQ mode" where needed */
- of_id = of_match_device(intc_irqpin_dt_ids, dev);
- if (of_id && of_id->data) {
- const struct intc_irqpin_irlm_config *irlm_config = of_id->data;
-
+ if (config && config->needs_irlm) {
if (io[INTC_IRQPIN_REG_IRLM])
intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_IRLM,
- irlm_config->irlm_bit,
- 1, 1);
+ config->irlm_bit, 1, 1);
else
dev_warn(dev, "unable to select IRLM mode\n");
}
/* mask all interrupts using priority */
- for (k = 0; k < p->number_of_irqs; k++)
+ for (k = 0; k < nirqs; k++)
intc_irqpin_mask_unmask_prio(p, k, 1);
/* clear all pending interrupts */
@@ -506,16 +521,16 @@ static int intc_irqpin_probe(struct platform_device *pdev)
/* scan for shared interrupt lines */
ref_irq = p->irq[0].requested_irq;
- p->shared_irqs = true;
- for (k = 1; k < p->number_of_irqs; k++) {
+ p->shared_irqs = 1;
+ for (k = 1; k < nirqs; k++) {
if (ref_irq != p->irq[k].requested_irq) {
- p->shared_irqs = false;
+ p->shared_irqs = 0;
break;
}
}
/* use more severe masking method if requested */
- if (p->config.control_parent) {
+ if (control_parent) {
enable_fn = intc_irqpin_irq_enable_force;
disable_fn = intc_irqpin_irq_disable_force;
} else if (!p->shared_irqs) {
@@ -534,9 +549,7 @@ static int intc_irqpin_probe(struct platform_device *pdev)
irq_chip->irq_set_wake = intc_irqpin_irq_set_wake;
irq_chip->flags = IRQCHIP_MASK_ON_SUSPEND;
- p->irq_domain = irq_domain_add_simple(dev->of_node,
- p->number_of_irqs,
- p->config.irq_base,
+ p->irq_domain = irq_domain_add_simple(dev->of_node, nirqs, 0,
&intc_irqpin_irq_domain_ops, p);
if (!p->irq_domain) {
ret = -ENXIO;
@@ -555,7 +568,7 @@ static int intc_irqpin_probe(struct platform_device *pdev)
}
} else {
/* request interrupts one by one */
- for (k = 0; k < p->number_of_irqs; k++) {
+ for (k = 0; k < nirqs; k++) {
if (devm_request_irq(dev, p->irq[k].requested_irq,
intc_irqpin_irq_handler, 0, name,
&p->irq[k])) {
@@ -567,17 +580,10 @@ static int intc_irqpin_probe(struct platform_device *pdev)
}
/* unmask all interrupts on prio level */
- for (k = 0; k < p->number_of_irqs; k++)
+ for (k = 0; k < nirqs; k++)
intc_irqpin_mask_unmask_prio(p, k, 0);
- dev_info(dev, "driving %d irqs\n", p->number_of_irqs);
-
- /* warn in case of mismatch if irq base is specified */
- if (p->config.irq_base) {
- if (p->config.irq_base != p->irq[0].domain_irq)
- dev_warn(dev, "irq base mismatch (%d/%d)\n",
- p->config.irq_base, p->irq[0].domain_irq);
- }
+ dev_info(dev, "driving %d irqs\n", nirqs);
return 0;
diff --git a/drivers/irqchip/irq-sunxi-nmi.c b/drivers/irqchip/irq-sunxi-nmi.c
index 4ef178078e5b..0820f67cc9a7 100644
--- a/drivers/irqchip/irq-sunxi-nmi.c
+++ b/drivers/irqchip/irq-sunxi-nmi.c
@@ -50,6 +50,12 @@ static struct sunxi_sc_nmi_reg_offs sun6i_reg_offs = {
.enable = 0x34,
};
+static struct sunxi_sc_nmi_reg_offs sun9i_reg_offs = {
+ .ctrl = 0x00,
+ .pend = 0x08,
+ .enable = 0x04,
+};
+
static inline void sunxi_sc_nmi_write(struct irq_chip_generic *gc, u32 off,
u32 val)
{
@@ -207,3 +213,10 @@ static int __init sun7i_sc_nmi_irq_init(struct device_node *node,
return sunxi_sc_nmi_irq_init(node, &sun7i_reg_offs);
}
IRQCHIP_DECLARE(sun7i_sc_nmi, "allwinner,sun7i-a20-sc-nmi", sun7i_sc_nmi_irq_init);
+
+static int __init sun9i_nmi_irq_init(struct device_node *node,
+ struct device_node *parent)
+{
+ return sunxi_sc_nmi_irq_init(node, &sun9i_reg_offs);
+}
+IRQCHIP_DECLARE(sun9i_nmi, "allwinner,sun9i-a80-nmi", sun9i_nmi_irq_init);
diff --git a/drivers/irqchip/irq-ts4800.c b/drivers/irqchip/irq-ts4800.c
new file mode 100644
index 000000000000..4192bdcd2734
--- /dev/null
+++ b/drivers/irqchip/irq-ts4800.c
@@ -0,0 +1,163 @@
+/*
+ * Multiplexed-IRQs driver for TS-4800's FPGA
+ *
+ * Copyright (c) 2015 - Savoir-faire Linux
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+
+#define IRQ_MASK 0x4
+#define IRQ_STATUS 0x8
+
+struct ts4800_irq_data {
+ void __iomem *base;
+ struct irq_domain *domain;
+ struct irq_chip irq_chip;
+};
+
+static void ts4800_irq_mask(struct irq_data *d)
+{
+ struct ts4800_irq_data *data = irq_data_get_irq_chip_data(d);
+ u16 reg = readw(data->base + IRQ_MASK);
+ u16 mask = 1 << d->hwirq;
+
+ writew(reg | mask, data->base + IRQ_MASK);
+}
+
+static void ts4800_irq_unmask(struct irq_data *d)
+{
+ struct ts4800_irq_data *data = irq_data_get_irq_chip_data(d);
+ u16 reg = readw(data->base + IRQ_MASK);
+ u16 mask = 1 << d->hwirq;
+
+ writew(reg & ~mask, data->base + IRQ_MASK);
+}
+
+static int ts4800_irqdomain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct ts4800_irq_data *data = d->host_data;
+
+ irq_set_chip_and_handler(irq, &data->irq_chip, handle_simple_irq);
+ irq_set_chip_data(irq, data);
+ irq_set_noprobe(irq);
+
+ return 0;
+}
+
+struct irq_domain_ops ts4800_ic_ops = {
+ .map = ts4800_irqdomain_map,
+ .xlate = irq_domain_xlate_onecell,
+};
+
+static void ts4800_ic_chained_handle_irq(struct irq_desc *desc)
+{
+ struct ts4800_irq_data *data = irq_desc_get_handler_data(desc);
+ struct irq_chip *chip = irq_desc_get_chip(desc);
+ u16 status = readw(data->base + IRQ_STATUS);
+
+ chained_irq_enter(chip, desc);
+
+ if (unlikely(status == 0)) {
+ handle_bad_irq(desc);
+ goto out;
+ }
+
+ do {
+ unsigned int bit = __ffs(status);
+ int irq = irq_find_mapping(data->domain, bit);
+
+ status &= ~(1 << bit);
+ generic_handle_irq(irq);
+ } while (status);
+
+out:
+ chained_irq_exit(chip, desc);
+}
+
+static int ts4800_ic_probe(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct ts4800_irq_data *data;
+ struct irq_chip *irq_chip;
+ struct resource *res;
+ int parent_irq;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ data->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(data->base))
+ return PTR_ERR(data->base);
+
+ writew(0xFFFF, data->base + IRQ_MASK);
+
+ parent_irq = irq_of_parse_and_map(node, 0);
+ if (!parent_irq) {
+ dev_err(&pdev->dev, "failed to get parent IRQ\n");
+ return -EINVAL;
+ }
+
+ irq_chip = &data->irq_chip;
+ irq_chip->name = dev_name(&pdev->dev);
+ irq_chip->irq_mask = ts4800_irq_mask;
+ irq_chip->irq_unmask = ts4800_irq_unmask;
+
+ data->domain = irq_domain_add_linear(node, 8, &ts4800_ic_ops, data);
+ if (!data->domain) {
+ dev_err(&pdev->dev, "cannot add IRQ domain\n");
+ return -ENOMEM;
+ }
+
+ irq_set_chained_handler_and_data(parent_irq,
+ ts4800_ic_chained_handle_irq, data);
+
+ platform_set_drvdata(pdev, data);
+
+ return 0;
+}
+
+static int ts4800_ic_remove(struct platform_device *pdev)
+{
+ struct ts4800_irq_data *data = platform_get_drvdata(pdev);
+
+ irq_domain_remove(data->domain);
+
+ return 0;
+}
+
+static const struct of_device_id ts4800_ic_of_match[] = {
+ { .compatible = "technologic,ts4800-irqc", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ts4800_ic_of_match);
+
+static struct platform_driver ts4800_ic_driver = {
+ .probe = ts4800_ic_probe,
+ .remove = ts4800_ic_remove,
+ .driver = {
+ .name = "ts4800-irqc",
+ .of_match_table = ts4800_ic_of_match,
+ },
+};
+module_platform_driver(ts4800_ic_driver);
+
+MODULE_AUTHOR("Damien Riegel <damien.riegel@savoirfairelinux.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:ts4800_irqc");
diff --git a/drivers/irqchip/irq-zevio.c b/drivers/irqchip/irq-zevio.c
index 4c48fa88a03d..cb9d8ec37507 100644
--- a/drivers/irqchip/irq-zevio.c
+++ b/drivers/irqchip/irq-zevio.c
@@ -43,8 +43,7 @@ static void __iomem *zevio_irq_io;
static void zevio_irq_ack(struct irq_data *irqd)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(irqd);
- struct irq_chip_regs *regs =
- &container_of(irqd->chip, struct irq_chip_type, chip)->regs;
+ struct irq_chip_regs *regs = &irq_data_get_chip_type(irqd)->regs;
readl(gc->reg_base + regs->ack);
}
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index b1ab8bdf8251..7f940c24a16b 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -52,6 +52,7 @@ config LEDS_AAT1290
config LEDS_BCM6328
tristate "LED Support for Broadcom BCM6328"
depends on LEDS_CLASS
+ depends on HAS_IOMEM
depends on OF
help
This option enables support for LEDs connected to the BCM6328
@@ -60,6 +61,7 @@ config LEDS_BCM6328
config LEDS_BCM6358
tristate "LED Support for Broadcom BCM6358"
depends on LEDS_CLASS
+ depends on HAS_IOMEM
depends on OF
help
This option enables support for LEDs connected to the BCM6358
diff --git a/drivers/leds/led-class-flash.c b/drivers/leds/led-class-flash.c
index 3b2573411a37..cf398275a53c 100644
--- a/drivers/leds/led-class-flash.c
+++ b/drivers/leds/led-class-flash.c
@@ -108,7 +108,7 @@ static ssize_t flash_strobe_store(struct device *dev,
if (ret)
goto unlock;
- if (state < 0 || state > 1) {
+ if (state > 1) {
ret = -EINVAL;
goto unlock;
}
@@ -298,7 +298,7 @@ int led_classdev_flash_register(struct device *parent,
led_cdev = &fled_cdev->led_cdev;
if (led_cdev->flags & LED_DEV_CAP_FLASH) {
- if (!led_cdev->brightness_set_sync)
+ if (!led_cdev->brightness_set_blocking)
return -EINVAL;
ops = fled_cdev->ops;
@@ -316,10 +316,6 @@ int led_classdev_flash_register(struct device *parent,
if (ret < 0)
return ret;
- /* Setting a torch brightness needs to have immediate effect */
- led_cdev->flags &= ~SET_BRIGHTNESS_ASYNC;
- led_cdev->flags |= SET_BRIGHTNESS_SYNC;
-
return 0;
}
EXPORT_SYMBOL_GPL(led_classdev_flash_register);
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 7385f98dd54b..14139c337312 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -109,7 +109,7 @@ static const struct attribute_group *led_groups[] = {
void led_classdev_suspend(struct led_classdev *led_cdev)
{
led_cdev->flags |= LED_SUSPENDED;
- led_cdev->brightness_set(led_cdev, 0);
+ led_set_brightness_nopm(led_cdev, 0);
}
EXPORT_SYMBOL_GPL(led_classdev_suspend);
@@ -119,7 +119,7 @@ EXPORT_SYMBOL_GPL(led_classdev_suspend);
*/
void led_classdev_resume(struct led_classdev *led_cdev)
{
- led_cdev->brightness_set(led_cdev, led_cdev->brightness);
+ led_set_brightness_nopm(led_cdev, led_cdev->brightness);
if (led_cdev->flash_resume)
led_cdev->flash_resume(led_cdev);
@@ -215,8 +215,6 @@ int led_classdev_register(struct device *parent, struct led_classdev *led_cdev)
if (!led_cdev->max_brightness)
led_cdev->max_brightness = LED_FULL;
- led_cdev->flags |= SET_BRIGHTNESS_ASYNC;
-
led_update_brightness(led_cdev);
led_init_core(led_cdev);
@@ -247,12 +245,13 @@ void led_classdev_unregister(struct led_classdev *led_cdev)
up_write(&led_cdev->trigger_lock);
#endif
- cancel_work_sync(&led_cdev->set_brightness_work);
-
/* Stop blinking */
led_stop_software_blink(led_cdev);
+
led_set_brightness(led_cdev, LED_OFF);
+ flush_work(&led_cdev->set_brightness_work);
+
device_unregister(led_cdev->dev);
down_write(&leds_list_lock);
diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c
index c1c3af089634..19e1e60dfaa3 100644
--- a/drivers/leds/led-core.c
+++ b/drivers/leds/led-core.c
@@ -32,7 +32,7 @@ static void led_timer_function(unsigned long data)
unsigned long delay;
if (!led_cdev->blink_delay_on || !led_cdev->blink_delay_off) {
- led_set_brightness_async(led_cdev, LED_OFF);
+ led_set_brightness_nosleep(led_cdev, LED_OFF);
return;
}
@@ -44,23 +44,23 @@ static void led_timer_function(unsigned long data)
brightness = led_get_brightness(led_cdev);
if (!brightness) {
/* Time to switch the LED on. */
- if (led_cdev->delayed_set_value) {
- led_cdev->blink_brightness =
- led_cdev->delayed_set_value;
- led_cdev->delayed_set_value = 0;
- }
brightness = led_cdev->blink_brightness;
delay = led_cdev->blink_delay_on;
} else {
/* Store the current brightness value to be able
* to restore it when the delay_off period is over.
+ * Do it only if there is no pending blink brightness
+ * change, to avoid overwriting the new value.
*/
- led_cdev->blink_brightness = brightness;
+ if (!(led_cdev->flags & LED_BLINK_BRIGHTNESS_CHANGE))
+ led_cdev->blink_brightness = brightness;
+ else
+ led_cdev->flags &= ~LED_BLINK_BRIGHTNESS_CHANGE;
brightness = LED_OFF;
delay = led_cdev->blink_delay_off;
}
- led_set_brightness_async(led_cdev, brightness);
+ led_set_brightness_nosleep(led_cdev, brightness);
/* Return in next iteration if led is in one-shot mode and we are in
* the final blink state so that the led is toggled each delay_on +
@@ -83,10 +83,24 @@ static void set_brightness_delayed(struct work_struct *ws)
{
struct led_classdev *led_cdev =
container_of(ws, struct led_classdev, set_brightness_work);
+ int ret = 0;
- led_stop_software_blink(led_cdev);
+ if (led_cdev->flags & LED_BLINK_DISABLE) {
+ led_cdev->delayed_set_value = LED_OFF;
+ led_stop_software_blink(led_cdev);
+ led_cdev->flags &= ~LED_BLINK_DISABLE;
+ }
- led_set_brightness_async(led_cdev, led_cdev->delayed_set_value);
+ if (led_cdev->brightness_set)
+ led_cdev->brightness_set(led_cdev, led_cdev->delayed_set_value);
+ else if (led_cdev->brightness_set_blocking)
+ ret = led_cdev->brightness_set_blocking(led_cdev,
+ led_cdev->delayed_set_value);
+ else
+ ret = -ENOTSUPP;
+ if (ret < 0)
+ dev_err(led_cdev->dev,
+ "Setting an LED's brightness failed (%d)\n", ret);
}
static void led_set_software_blink(struct led_classdev *led_cdev,
@@ -106,13 +120,14 @@ static void led_set_software_blink(struct led_classdev *led_cdev,
/* never on - just set to off */
if (!delay_on) {
- led_set_brightness_async(led_cdev, LED_OFF);
+ led_set_brightness_nosleep(led_cdev, LED_OFF);
return;
}
/* never off - just set to brightness */
if (!delay_off) {
- led_set_brightness_async(led_cdev, led_cdev->blink_brightness);
+ led_set_brightness_nosleep(led_cdev,
+ led_cdev->blink_brightness);
return;
}
@@ -156,7 +171,7 @@ void led_blink_set(struct led_classdev *led_cdev,
led_blink_setup(led_cdev, delay_on, delay_off);
}
-EXPORT_SYMBOL(led_blink_set);
+EXPORT_SYMBOL_GPL(led_blink_set);
void led_blink_set_oneshot(struct led_classdev *led_cdev,
unsigned long *delay_on,
@@ -177,7 +192,7 @@ void led_blink_set_oneshot(struct led_classdev *led_cdev,
led_blink_setup(led_cdev, delay_on, delay_off);
}
-EXPORT_SYMBOL(led_blink_set_oneshot);
+EXPORT_SYMBOL_GPL(led_blink_set_oneshot);
void led_stop_software_blink(struct led_classdev *led_cdev)
{
@@ -190,29 +205,74 @@ EXPORT_SYMBOL_GPL(led_stop_software_blink);
void led_set_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
- int ret = 0;
-
- /* delay brightness if soft-blink is active */
+ /*
+ * In case blinking is on delay brightness setting
+ * until the next timer tick.
+ */
if (led_cdev->blink_delay_on || led_cdev->blink_delay_off) {
- led_cdev->delayed_set_value = brightness;
- if (brightness == LED_OFF)
+ /*
+ * If we need to disable soft blinking delegate this to the
+ * work queue task to avoid problems in case we are called
+ * from hard irq context.
+ */
+ if (brightness == LED_OFF) {
+ led_cdev->flags |= LED_BLINK_DISABLE;
schedule_work(&led_cdev->set_brightness_work);
+ } else {
+ led_cdev->flags |= LED_BLINK_BRIGHTNESS_CHANGE;
+ led_cdev->blink_brightness = brightness;
+ }
return;
}
- if (led_cdev->flags & SET_BRIGHTNESS_ASYNC) {
- led_set_brightness_async(led_cdev, brightness);
+ led_set_brightness_nosleep(led_cdev, brightness);
+}
+EXPORT_SYMBOL_GPL(led_set_brightness);
+
+void led_set_brightness_nopm(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ /* Use brightness_set op if available, it is guaranteed not to sleep */
+ if (led_cdev->brightness_set) {
+ led_cdev->brightness_set(led_cdev, value);
return;
- } else if (led_cdev->flags & SET_BRIGHTNESS_SYNC)
- ret = led_set_brightness_sync(led_cdev, brightness);
- else
- ret = -EINVAL;
+ }
- if (ret < 0)
- dev_dbg(led_cdev->dev, "Setting LED brightness failed (%d)\n",
- ret);
+ /* If brightness setting can sleep, delegate it to a work queue task */
+ led_cdev->delayed_set_value = value;
+ schedule_work(&led_cdev->set_brightness_work);
+}
+EXPORT_SYMBOL_GPL(led_set_brightness_nopm);
+
+void led_set_brightness_nosleep(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ led_cdev->brightness = min(value, led_cdev->max_brightness);
+
+ if (led_cdev->flags & LED_SUSPENDED)
+ return;
+
+ led_set_brightness_nopm(led_cdev, led_cdev->brightness);
+}
+EXPORT_SYMBOL_GPL(led_set_brightness_nosleep);
+
+int led_set_brightness_sync(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ if (led_cdev->blink_delay_on || led_cdev->blink_delay_off)
+ return -EBUSY;
+
+ led_cdev->brightness = min(value, led_cdev->max_brightness);
+
+ if (led_cdev->flags & LED_SUSPENDED)
+ return 0;
+
+ if (led_cdev->brightness_set_blocking)
+ return led_cdev->brightness_set_blocking(led_cdev,
+ led_cdev->brightness);
+ return -ENOTSUPP;
}
-EXPORT_SYMBOL(led_set_brightness);
+EXPORT_SYMBOL_GPL(led_set_brightness_sync);
int led_update_brightness(struct led_classdev *led_cdev)
{
@@ -228,7 +288,7 @@ int led_update_brightness(struct led_classdev *led_cdev)
return ret;
}
-EXPORT_SYMBOL(led_update_brightness);
+EXPORT_SYMBOL_GPL(led_update_brightness);
/* Caller must ensure led_cdev->led_access held */
void led_sysfs_disable(struct led_classdev *led_cdev)
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index e8b1120f486d..e1e933424ac9 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -249,6 +249,34 @@ void led_trigger_unregister(struct led_trigger *trig)
}
EXPORT_SYMBOL_GPL(led_trigger_unregister);
+static void devm_led_trigger_release(struct device *dev, void *res)
+{
+ led_trigger_unregister(*(struct led_trigger **)res);
+}
+
+int devm_led_trigger_register(struct device *dev,
+ struct led_trigger *trig)
+{
+ struct led_trigger **dr;
+ int rc;
+
+ dr = devres_alloc(devm_led_trigger_release, sizeof(*dr),
+ GFP_KERNEL);
+ if (!dr)
+ return -ENOMEM;
+
+ *dr = trig;
+
+ rc = led_trigger_register(trig);
+ if (rc)
+ devres_free(dr);
+ else
+ devres_add(dev, dr);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(devm_led_trigger_register);
+
/* Simple LED Tigger Interface */
void led_trigger_event(struct led_trigger *trig,
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c
index 7870840e7cc9..1ad4d03a0a3c 100644
--- a/drivers/leds/leds-88pm860x.c
+++ b/drivers/leds/leds-88pm860x.c
@@ -16,7 +16,6 @@
#include <linux/i2c.h>
#include <linux/leds.h>
#include <linux/slab.h>
-#include <linux/workqueue.h>
#include <linux/mfd/88pm860x.h>
#include <linux/module.h>
@@ -33,7 +32,6 @@
struct pm860x_led {
struct led_classdev cdev;
struct i2c_client *i2c;
- struct work_struct work;
struct pm860x_chip *chip;
struct mutex lock;
char name[MFD_NAME_SIZE];
@@ -69,17 +67,18 @@ static int led_power_set(struct pm860x_chip *chip, int port, int on)
return ret;
}
-static void pm860x_led_work(struct work_struct *work)
+static int pm860x_led_set(struct led_classdev *cdev,
+ enum led_brightness value)
{
-
- struct pm860x_led *led;
+ struct pm860x_led *led = container_of(cdev, struct pm860x_led, cdev);
struct pm860x_chip *chip;
unsigned char buf[3];
int ret;
- led = container_of(work, struct pm860x_led, work);
chip = led->chip;
mutex_lock(&led->lock);
+ led->brightness = value >> 3;
+
if ((led->current_brightness == 0) && led->brightness) {
led_power_set(chip, led->port, 1);
if (led->iset) {
@@ -112,15 +111,8 @@ static void pm860x_led_work(struct work_struct *work)
dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n",
led->reg_control, led->brightness);
mutex_unlock(&led->lock);
-}
-static void pm860x_led_set(struct led_classdev *cdev,
- enum led_brightness value)
-{
- struct pm860x_led *data = container_of(cdev, struct pm860x_led, cdev);
-
- data->brightness = value >> 3;
- schedule_work(&data->work);
+ return 0;
}
#ifdef CONFIG_OF
@@ -213,9 +205,8 @@ static int pm860x_led_probe(struct platform_device *pdev)
data->current_brightness = 0;
data->cdev.name = data->name;
- data->cdev.brightness_set = pm860x_led_set;
+ data->cdev.brightness_set_blocking = pm860x_led_set;
mutex_init(&data->lock);
- INIT_WORK(&data->work, pm860x_led_work);
ret = led_classdev_register(chip->dev, &data->cdev);
if (ret < 0) {
diff --git a/drivers/leds/leds-aat1290.c b/drivers/leds/leds-aat1290.c
index ac77d36b630c..def3cf9f7e92 100644
--- a/drivers/leds/leds-aat1290.c
+++ b/drivers/leds/leds-aat1290.c
@@ -20,7 +20,6 @@
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <linux/workqueue.h>
#include <media/v4l2-flash-led-class.h>
#define AAT1290_MOVIE_MODE_CURRENT_ADDR 17
@@ -82,8 +81,6 @@ struct aat1290_led {
/* brightness cache */
unsigned int torch_brightness;
- /* assures led-triggers compatibility */
- struct work_struct work_brightness_set;
};
static struct aat1290_led *fled_cdev_to_led(
@@ -92,6 +89,12 @@ static struct aat1290_led *fled_cdev_to_led(
return container_of(fled_cdev, struct aat1290_led, fled_cdev);
}
+static struct led_classdev_flash *led_cdev_to_fled_cdev(
+ struct led_classdev *led_cdev)
+{
+ return container_of(led_cdev, struct led_classdev_flash, led_cdev);
+}
+
static void aat1290_as2cwire_write(struct aat1290_led *led, int addr, int value)
{
int i;
@@ -134,9 +137,14 @@ static void aat1290_set_flash_safety_timer(struct aat1290_led *led,
flash_tm_reg);
}
-static void aat1290_brightness_set(struct aat1290_led *led,
+/* LED subsystem callbacks */
+
+static int aat1290_led_brightness_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
+ struct led_classdev_flash *fled_cdev = led_cdev_to_fled_cdev(led_cdev);
+ struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
+
mutex_lock(&led->lock);
if (brightness == 0) {
@@ -158,35 +166,6 @@ static void aat1290_brightness_set(struct aat1290_led *led,
}
mutex_unlock(&led->lock);
-}
-
-/* LED subsystem callbacks */
-
-static void aat1290_brightness_set_work(struct work_struct *work)
-{
- struct aat1290_led *led =
- container_of(work, struct aat1290_led, work_brightness_set);
-
- aat1290_brightness_set(led, led->torch_brightness);
-}
-
-static void aat1290_led_brightness_set(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
- struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
-
- led->torch_brightness = brightness;
- schedule_work(&led->work_brightness_set);
-}
-
-static int aat1290_led_brightness_set_sync(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
- struct aat1290_led *led = fled_cdev_to_led(fled_cdev);
-
- aat1290_brightness_set(led, brightness);
return 0;
}
@@ -296,7 +275,7 @@ static int aat1290_led_parse_dt(struct aat1290_led *led,
if (ret < 0) {
dev_err(dev,
"flash-max-microamp DT property missing\n");
- return ret;
+ goto err_parse_dt;
}
ret = of_property_read_u32(child_node, "flash-max-timeout-us",
@@ -304,13 +283,14 @@ static int aat1290_led_parse_dt(struct aat1290_led *led,
if (ret < 0) {
dev_err(dev,
"flash-max-timeout-us DT property missing\n");
- return ret;
+ goto err_parse_dt;
}
- of_node_put(child_node);
-
*sub_node = child_node;
+err_parse_dt:
+ of_node_put(child_node);
+
return ret;
}
@@ -509,11 +489,9 @@ static int aat1290_led_probe(struct platform_device *pdev)
mutex_init(&led->lock);
/* Initialize LED Flash class device */
- led_cdev->brightness_set = aat1290_led_brightness_set;
- led_cdev->brightness_set_sync = aat1290_led_brightness_set_sync;
+ led_cdev->brightness_set_blocking = aat1290_led_brightness_set;
led_cdev->max_brightness = led_cfg.max_brightness;
led_cdev->flags |= LED_DEV_CAP_FLASH;
- INIT_WORK(&led->work_brightness_set, aat1290_brightness_set_work);
aat1290_init_flash_timeout(led, &led_cfg);
@@ -548,7 +526,6 @@ static int aat1290_led_remove(struct platform_device *pdev)
v4l2_flash_release(led->v4l2_flash);
led_classdev_flash_unregister(&led->fled_cdev);
- cancel_work_sync(&led->work_brightness_set);
mutex_destroy(&led->lock);
diff --git a/drivers/leds/leds-adp5520.c b/drivers/leds/leds-adp5520.c
index 07e66cae32d3..853b2d3bdb17 100644
--- a/drivers/leds/leds-adp5520.c
+++ b/drivers/leds/leds-adp5520.c
@@ -17,34 +17,24 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
-#include <linux/workqueue.h>
#include <linux/mfd/adp5520.h>
#include <linux/slab.h>
struct adp5520_led {
struct led_classdev cdev;
- struct work_struct work;
struct device *master;
- enum led_brightness new_brightness;
int id;
int flags;
};
-static void adp5520_led_work(struct work_struct *work)
-{
- struct adp5520_led *led = container_of(work, struct adp5520_led, work);
- adp5520_write(led->master, ADP5520_LED1_CURRENT + led->id - 1,
- led->new_brightness >> 2);
-}
-
-static void adp5520_led_set(struct led_classdev *led_cdev,
+static int adp5520_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct adp5520_led *led;
led = container_of(led_cdev, struct adp5520_led, cdev);
- led->new_brightness = value;
- schedule_work(&led->work);
+ return adp5520_write(led->master, ADP5520_LED1_CURRENT + led->id - 1,
+ value >> 2);
}
static int adp5520_led_setup(struct adp5520_led *led)
@@ -135,7 +125,7 @@ static int adp5520_led_probe(struct platform_device *pdev)
led_dat->cdev.name = cur_led->name;
led_dat->cdev.default_trigger = cur_led->default_trigger;
- led_dat->cdev.brightness_set = adp5520_led_set;
+ led_dat->cdev.brightness_set_blocking = adp5520_led_set;
led_dat->cdev.brightness = LED_OFF;
if (cur_led->flags & ADP5520_FLAG_LED_MASK)
@@ -146,9 +136,6 @@ static int adp5520_led_probe(struct platform_device *pdev)
led_dat->id = led_dat->flags & ADP5520_FLAG_LED_MASK;
led_dat->master = pdev->dev.parent;
- led_dat->new_brightness = LED_OFF;
-
- INIT_WORK(&led_dat->work, adp5520_led_work);
ret = led_classdev_register(led_dat->master, &led_dat->cdev);
if (ret) {
@@ -170,10 +157,8 @@ static int adp5520_led_probe(struct platform_device *pdev)
err:
if (i > 0) {
- for (i = i - 1; i >= 0; i--) {
+ for (i = i - 1; i >= 0; i--)
led_classdev_unregister(&led[i].cdev);
- cancel_work_sync(&led[i].work);
- }
}
return ret;
@@ -192,7 +177,6 @@ static int adp5520_led_remove(struct platform_device *pdev)
for (i = 0; i < pdata->num_leds; i++) {
led_classdev_unregister(&led[i].cdev);
- cancel_work_sync(&led[i].work);
}
return 0;
diff --git a/drivers/leds/leds-bcm6328.c b/drivers/leds/leds-bcm6328.c
index c7ea5c626331..1548259297c1 100644
--- a/drivers/leds/leds-bcm6328.c
+++ b/drivers/leds/leds-bcm6328.c
@@ -42,16 +42,16 @@
#define BCM6328_LED_SHIFT_TEST BIT(30)
#define BCM6328_LED_TEST BIT(31)
#define BCM6328_INIT_MASK (BCM6328_SERIAL_LED_EN | \
- BCM6328_SERIAL_LED_MUX | \
+ BCM6328_SERIAL_LED_MUX | \
BCM6328_SERIAL_LED_CLK_NPOL | \
BCM6328_SERIAL_LED_DATA_PPOL | \
BCM6328_SERIAL_LED_SHIFT_DIR)
#define BCM6328_LED_MODE_MASK 3
-#define BCM6328_LED_MODE_OFF 0
+#define BCM6328_LED_MODE_ON 0
#define BCM6328_LED_MODE_FAST 1
#define BCM6328_LED_MODE_BLINK 2
-#define BCM6328_LED_MODE_ON 3
+#define BCM6328_LED_MODE_OFF 3
#define BCM6328_LED_SHIFT(X) ((X) << 1)
/**
@@ -76,12 +76,20 @@ struct bcm6328_led {
static void bcm6328_led_write(void __iomem *reg, unsigned long data)
{
+#ifdef CONFIG_CPU_BIG_ENDIAN
iowrite32be(data, reg);
+#else
+ writel(data, reg);
+#endif
}
static unsigned long bcm6328_led_read(void __iomem *reg)
{
+#ifdef CONFIG_CPU_BIG_ENDIAN
return ioread32be(reg);
+#else
+ return readl(reg);
+#endif
}
/**
@@ -126,34 +134,45 @@ static void bcm6328_led_set(struct led_classdev *led_cdev,
*(led->blink_leds) &= ~BIT(led->pin);
if ((led->active_low && value == LED_OFF) ||
(!led->active_low && value != LED_OFF))
- bcm6328_led_mode(led, BCM6328_LED_MODE_OFF);
- else
bcm6328_led_mode(led, BCM6328_LED_MODE_ON);
+ else
+ bcm6328_led_mode(led, BCM6328_LED_MODE_OFF);
spin_unlock_irqrestore(led->lock, flags);
}
+static unsigned long bcm6328_blink_delay(unsigned long delay)
+{
+ unsigned long bcm6328_delay;
+
+ bcm6328_delay = delay + BCM6328_LED_INTERVAL_MS / 2;
+ bcm6328_delay = bcm6328_delay / BCM6328_LED_INTERVAL_MS;
+ if (bcm6328_delay == 0)
+ bcm6328_delay = 1;
+
+ return bcm6328_delay;
+}
+
static int bcm6328_blink_set(struct led_classdev *led_cdev,
unsigned long *delay_on, unsigned long *delay_off)
{
struct bcm6328_led *led =
container_of(led_cdev, struct bcm6328_led, cdev);
unsigned long delay, flags;
+ int rc;
if (!*delay_on)
*delay_on = BCM6328_LED_DEF_DELAY;
if (!*delay_off)
*delay_off = BCM6328_LED_DEF_DELAY;
- if (*delay_on != *delay_off) {
+ delay = bcm6328_blink_delay(*delay_on);
+ if (delay != bcm6328_blink_delay(*delay_off)) {
dev_dbg(led_cdev->dev,
"fallback to soft blinking (delay_on != delay_off)\n");
return -EINVAL;
}
- delay = *delay_on / BCM6328_LED_INTERVAL_MS;
- if (delay == 0)
- delay = 1;
- else if (delay > BCM6328_LED_INTV_MASK) {
+ if (delay > BCM6328_LED_INTV_MASK) {
dev_dbg(led_cdev->dev,
"fallback to soft blinking (delay > %ums)\n",
BCM6328_LED_INTV_MASK * BCM6328_LED_INTERVAL_MS);
@@ -175,16 +194,15 @@ static int bcm6328_blink_set(struct led_classdev *led_cdev,
bcm6328_led_write(led->mem + BCM6328_REG_INIT, val);
bcm6328_led_mode(led, BCM6328_LED_MODE_BLINK);
-
- spin_unlock_irqrestore(led->lock, flags);
+ rc = 0;
} else {
- spin_unlock_irqrestore(led->lock, flags);
dev_dbg(led_cdev->dev,
"fallback to soft blinking (delay already set)\n");
- return -EINVAL;
+ rc = -EINVAL;
}
+ spin_unlock_irqrestore(led->lock, flags);
- return 0;
+ return rc;
}
static int bcm6328_hwled(struct device *dev, struct device_node *nc, u32 reg,
@@ -264,7 +282,6 @@ static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg,
unsigned long *blink_leds, unsigned long *blink_delay)
{
struct bcm6328_led *led;
- unsigned long flags;
const char *state;
int rc;
@@ -286,7 +303,6 @@ static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg,
"linux,default-trigger",
NULL);
- spin_lock_irqsave(lock, flags);
if (!of_property_read_string(nc, "default-state", &state)) {
if (!strcmp(state, "on")) {
led->cdev.brightness = LED_FULL;
@@ -303,8 +319,8 @@ static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg,
val = bcm6328_led_read(mode) >>
BCM6328_LED_SHIFT(shift % 16);
val &= BCM6328_LED_MODE_MASK;
- if ((led->active_low && val == BCM6328_LED_MODE_ON) ||
- (!led->active_low && val == BCM6328_LED_MODE_OFF))
+ if ((led->active_low && val == BCM6328_LED_MODE_OFF) ||
+ (!led->active_low && val == BCM6328_LED_MODE_ON))
led->cdev.brightness = LED_FULL;
else
led->cdev.brightness = LED_OFF;
@@ -315,12 +331,7 @@ static int bcm6328_led(struct device *dev, struct device_node *nc, u32 reg,
led->cdev.brightness = LED_OFF;
}
- if ((led->active_low && led->cdev.brightness == LED_FULL) ||
- (!led->active_low && led->cdev.brightness == LED_OFF))
- bcm6328_led_mode(led, BCM6328_LED_MODE_ON);
- else
- bcm6328_led_mode(led, BCM6328_LED_MODE_OFF);
- spin_unlock_irqrestore(lock, flags);
+ bcm6328_led_set(&led->cdev, led->cdev.brightness);
led->cdev.brightness_set = bcm6328_led_set;
led->cdev.blink_set = bcm6328_blink_set;
@@ -341,7 +352,7 @@ static int bcm6328_leds_probe(struct platform_device *pdev)
struct device_node *child;
struct resource *mem_r;
void __iomem *mem;
- spinlock_t *lock;
+ spinlock_t *lock; /* memory lock */
unsigned long val, *blink_leds, *blink_delay;
mem_r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/leds/leds-bcm6358.c b/drivers/leds/leds-bcm6358.c
index 82b4ee1bc87e..b2cc06618abe 100644
--- a/drivers/leds/leds-bcm6358.c
+++ b/drivers/leds/leds-bcm6358.c
@@ -49,12 +49,20 @@ struct bcm6358_led {
static void bcm6358_led_write(void __iomem *reg, unsigned long data)
{
+#ifdef CONFIG_CPU_BIG_ENDIAN
iowrite32be(data, reg);
+#else
+ writel(data, reg);
+#endif
}
static unsigned long bcm6358_led_read(void __iomem *reg)
{
+#ifdef CONFIG_CPU_BIG_ENDIAN
return ioread32be(reg);
+#else
+ return readl(reg);
+#endif
}
static unsigned long bcm6358_led_busy(void __iomem *mem)
@@ -68,12 +76,15 @@ static unsigned long bcm6358_led_busy(void __iomem *mem)
return val;
}
-static void bcm6358_led_mode(struct bcm6358_led *led, unsigned long value)
+static void bcm6358_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
{
- unsigned long val;
+ struct bcm6358_led *led =
+ container_of(led_cdev, struct bcm6358_led, cdev);
+ unsigned long flags, val;
+ spin_lock_irqsave(led->lock, flags);
bcm6358_led_busy(led->mem);
-
val = bcm6358_led_read(led->mem + BCM6358_REG_MODE);
if ((led->active_low && value == LED_OFF) ||
(!led->active_low && value != LED_OFF))
@@ -81,17 +92,6 @@ static void bcm6358_led_mode(struct bcm6358_led *led, unsigned long value)
else
val &= ~(BIT(led->pin));
bcm6358_led_write(led->mem + BCM6358_REG_MODE, val);
-}
-
-static void bcm6358_led_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- struct bcm6358_led *led =
- container_of(led_cdev, struct bcm6358_led, cdev);
- unsigned long flags;
-
- spin_lock_irqsave(led->lock, flags);
- bcm6358_led_mode(led, value);
spin_unlock_irqrestore(led->lock, flags);
}
@@ -99,7 +99,6 @@ static int bcm6358_led(struct device *dev, struct device_node *nc, u32 reg,
void __iomem *mem, spinlock_t *lock)
{
struct bcm6358_led *led;
- unsigned long flags;
const char *state;
int rc;
@@ -119,15 +118,11 @@ static int bcm6358_led(struct device *dev, struct device_node *nc, u32 reg,
"linux,default-trigger",
NULL);
- spin_lock_irqsave(lock, flags);
if (!of_property_read_string(nc, "default-state", &state)) {
if (!strcmp(state, "on")) {
led->cdev.brightness = LED_FULL;
} else if (!strcmp(state, "keep")) {
unsigned long val;
-
- bcm6358_led_busy(led->mem);
-
val = bcm6358_led_read(led->mem + BCM6358_REG_MODE);
val &= BIT(led->pin);
if ((led->active_low && !val) ||
@@ -141,8 +136,8 @@ static int bcm6358_led(struct device *dev, struct device_node *nc, u32 reg,
} else {
led->cdev.brightness = LED_OFF;
}
- bcm6358_led_mode(led, led->cdev.brightness);
- spin_unlock_irqrestore(lock, flags);
+
+ bcm6358_led_set(&led->cdev, led->cdev.brightness);
led->cdev.brightness_set = bcm6358_led_set;
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c
index 6078c15d3452..6b4de762a760 100644
--- a/drivers/leds/leds-bd2802.c
+++ b/drivers/leds/leds-bd2802.c
@@ -72,7 +72,6 @@ struct bd2802_led {
struct bd2802_led_platform_data *pdata;
struct i2c_client *client;
struct rw_semaphore rwsem;
- struct work_struct work;
struct led_state led[2];
@@ -518,29 +517,22 @@ static struct device_attribute *bd2802_attributes[] = {
&bd2802_rgb_current_attr,
};
-static void bd2802_led_work(struct work_struct *work)
-{
- struct bd2802_led *led = container_of(work, struct bd2802_led, work);
-
- if (led->state)
- bd2802_turn_on(led, led->led_id, led->color, led->state);
- else
- bd2802_turn_off(led, led->led_id, led->color);
-}
-
#define BD2802_CONTROL_RGBS(name, id, clr) \
-static void bd2802_set_##name##_brightness(struct led_classdev *led_cdev,\
+static int bd2802_set_##name##_brightness(struct led_classdev *led_cdev,\
enum led_brightness value) \
{ \
struct bd2802_led *led = \
container_of(led_cdev, struct bd2802_led, cdev_##name); \
led->led_id = id; \
led->color = clr; \
- if (value == LED_OFF) \
+ if (value == LED_OFF) { \
led->state = BD2802_OFF; \
- else \
+ bd2802_turn_off(led, led->led_id, led->color); \
+ } else { \
led->state = BD2802_ON; \
- schedule_work(&led->work); \
+ bd2802_turn_on(led, led->led_id, led->color, BD2802_ON);\
+ } \
+ return 0; \
} \
static int bd2802_set_##name##_blink(struct led_classdev *led_cdev, \
unsigned long *delay_on, unsigned long *delay_off) \
@@ -552,7 +544,7 @@ static int bd2802_set_##name##_blink(struct led_classdev *led_cdev, \
led->led_id = id; \
led->color = clr; \
led->state = BD2802_BLINK; \
- schedule_work(&led->work); \
+ bd2802_turn_on(led, led->led_id, led->color, BD2802_BLINK); \
return 0; \
}
@@ -567,11 +559,9 @@ static int bd2802_register_led_classdev(struct bd2802_led *led)
{
int ret;
- INIT_WORK(&led->work, bd2802_led_work);
-
led->cdev_led1r.name = "led1_R";
led->cdev_led1r.brightness = LED_OFF;
- led->cdev_led1r.brightness_set = bd2802_set_led1r_brightness;
+ led->cdev_led1r.brightness_set_blocking = bd2802_set_led1r_brightness;
led->cdev_led1r.blink_set = bd2802_set_led1r_blink;
ret = led_classdev_register(&led->client->dev, &led->cdev_led1r);
@@ -583,7 +573,7 @@ static int bd2802_register_led_classdev(struct bd2802_led *led)
led->cdev_led1g.name = "led1_G";
led->cdev_led1g.brightness = LED_OFF;
- led->cdev_led1g.brightness_set = bd2802_set_led1g_brightness;
+ led->cdev_led1g.brightness_set_blocking = bd2802_set_led1g_brightness;
led->cdev_led1g.blink_set = bd2802_set_led1g_blink;
ret = led_classdev_register(&led->client->dev, &led->cdev_led1g);
@@ -595,7 +585,7 @@ static int bd2802_register_led_classdev(struct bd2802_led *led)
led->cdev_led1b.name = "led1_B";
led->cdev_led1b.brightness = LED_OFF;
- led->cdev_led1b.brightness_set = bd2802_set_led1b_brightness;
+ led->cdev_led1b.brightness_set_blocking = bd2802_set_led1b_brightness;
led->cdev_led1b.blink_set = bd2802_set_led1b_blink;
ret = led_classdev_register(&led->client->dev, &led->cdev_led1b);
@@ -607,7 +597,7 @@ static int bd2802_register_led_classdev(struct bd2802_led *led)
led->cdev_led2r.name = "led2_R";
led->cdev_led2r.brightness = LED_OFF;
- led->cdev_led2r.brightness_set = bd2802_set_led2r_brightness;
+ led->cdev_led2r.brightness_set_blocking = bd2802_set_led2r_brightness;
led->cdev_led2r.blink_set = bd2802_set_led2r_blink;
ret = led_classdev_register(&led->client->dev, &led->cdev_led2r);
@@ -619,7 +609,7 @@ static int bd2802_register_led_classdev(struct bd2802_led *led)
led->cdev_led2g.name = "led2_G";
led->cdev_led2g.brightness = LED_OFF;
- led->cdev_led2g.brightness_set = bd2802_set_led2g_brightness;
+ led->cdev_led2g.brightness_set_blocking = bd2802_set_led2g_brightness;
led->cdev_led2g.blink_set = bd2802_set_led2g_blink;
ret = led_classdev_register(&led->client->dev, &led->cdev_led2g);
@@ -631,7 +621,7 @@ static int bd2802_register_led_classdev(struct bd2802_led *led)
led->cdev_led2b.name = "led2_B";
led->cdev_led2b.brightness = LED_OFF;
- led->cdev_led2b.brightness_set = bd2802_set_led2b_brightness;
+ led->cdev_led2b.brightness_set_blocking = bd2802_set_led2b_brightness;
led->cdev_led2b.blink_set = bd2802_set_led2b_blink;
led->cdev_led2b.flags |= LED_CORE_SUSPENDRESUME;
@@ -661,7 +651,6 @@ failed_unregister_led1_R:
static void bd2802_unregister_led_classdev(struct bd2802_led *led)
{
- cancel_work_sync(&led->work);
led_classdev_unregister(&led->cdev_led2b);
led_classdev_unregister(&led->cdev_led2g);
led_classdev_unregister(&led->cdev_led2r);
diff --git a/drivers/leds/leds-blinkm.c b/drivers/leds/leds-blinkm.c
index d0452b099aee..617fe975bf6e 100644
--- a/drivers/leds/leds-blinkm.c
+++ b/drivers/leds/leds-blinkm.c
@@ -39,16 +39,9 @@ struct blinkm_led {
struct i2c_client *i2c_client;
struct led_classdev led_cdev;
int id;
- atomic_t active;
-};
-
-struct blinkm_work {
- struct blinkm_led *blinkm_led;
- struct work_struct work;
};
#define cdev_to_blmled(c) container_of(c, struct blinkm_led, led_cdev)
-#define work_to_blmwork(c) container_of(c, struct blinkm_work, work)
struct blinkm_data {
struct i2c_client *i2c_client;
@@ -439,65 +432,30 @@ static int blinkm_transfer_hw(struct i2c_client *client, int cmd)
return 0;
}
-static void led_work(struct work_struct *work)
-{
- int ret;
- struct blinkm_led *led;
- struct blinkm_data *data;
- struct blinkm_work *blm_work = work_to_blmwork(work);
-
- led = blm_work->blinkm_led;
- data = i2c_get_clientdata(led->i2c_client);
- ret = blinkm_transfer_hw(led->i2c_client, BLM_GO_RGB);
- atomic_dec(&led->active);
- dev_dbg(&led->i2c_client->dev,
- "# DONE # next_red = %d, next_green = %d,"
- " next_blue = %d, active = %d\n",
- data->next_red, data->next_green,
- data->next_blue, atomic_read(&led->active));
- kfree(blm_work);
-}
-
static int blinkm_led_common_set(struct led_classdev *led_cdev,
enum led_brightness value, int color)
{
/* led_brightness is 0, 127 or 255 - we just use it here as-is */
struct blinkm_led *led = cdev_to_blmled(led_cdev);
struct blinkm_data *data = i2c_get_clientdata(led->i2c_client);
- struct blinkm_work *bl_work;
switch (color) {
case RED:
/* bail out if there's no change */
if (data->next_red == (u8) value)
return 0;
- /* we assume a quite fast sequence here ([off]->on->off)
- * think of network led trigger - we cannot blink that fast, so
- * in case we already have a off->on->off transition queued up,
- * we refuse to queue up more.
- * Revisit: fast-changing brightness. */
- if (atomic_read(&led->active) > 1)
- return 0;
data->next_red = (u8) value;
break;
case GREEN:
/* bail out if there's no change */
if (data->next_green == (u8) value)
return 0;
- /* we assume a quite fast sequence here ([off]->on->off)
- * Revisit: fast-changing brightness. */
- if (atomic_read(&led->active) > 1)
- return 0;
data->next_green = (u8) value;
break;
case BLUE:
/* bail out if there's no change */
if (data->next_blue == (u8) value)
return 0;
- /* we assume a quite fast sequence here ([off]->on->off)
- * Revisit: fast-changing brightness. */
- if (atomic_read(&led->active) > 1)
- return 0;
data->next_blue = (u8) value;
break;
@@ -506,42 +464,31 @@ static int blinkm_led_common_set(struct led_classdev *led_cdev,
return -EINVAL;
}
- bl_work = kzalloc(sizeof(*bl_work), GFP_ATOMIC);
- if (!bl_work)
- return -ENOMEM;
-
- atomic_inc(&led->active);
+ blinkm_transfer_hw(led->i2c_client, BLM_GO_RGB);
dev_dbg(&led->i2c_client->dev,
- "#TO_SCHED# next_red = %d, next_green = %d,"
- " next_blue = %d, active = %d\n",
+ "# DONE # next_red = %d, next_green = %d,"
+ " next_blue = %d\n",
data->next_red, data->next_green,
- data->next_blue, atomic_read(&led->active));
-
- /* a fresh work _item_ for each change */
- bl_work->blinkm_led = led;
- INIT_WORK(&bl_work->work, led_work);
- /* queue work in own queue for easy sync on exit*/
- schedule_work(&bl_work->work);
-
+ data->next_blue);
return 0;
}
-static void blinkm_led_red_set(struct led_classdev *led_cdev,
+static int blinkm_led_red_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
- blinkm_led_common_set(led_cdev, value, RED);
+ return blinkm_led_common_set(led_cdev, value, RED);
}
-static void blinkm_led_green_set(struct led_classdev *led_cdev,
+static int blinkm_led_green_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
- blinkm_led_common_set(led_cdev, value, GREEN);
+ return blinkm_led_common_set(led_cdev, value, GREEN);
}
-static void blinkm_led_blue_set(struct led_classdev *led_cdev,
+static int blinkm_led_blue_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
- blinkm_led_common_set(led_cdev, value, BLUE);
+ return blinkm_led_common_set(led_cdev, value, BLUE);
}
static void blinkm_init_hw(struct i2c_client *client)
@@ -669,7 +616,6 @@ static int blinkm_probe(struct i2c_client *client,
led[i]->id = i;
led[i]->led_cdev.max_brightness = 255;
led[i]->led_cdev.flags = LED_CORE_SUSPENDRESUME;
- atomic_set(&led[i]->active, 0);
switch (i) {
case RED:
snprintf(blinkm_led_name, sizeof(blinkm_led_name),
@@ -677,7 +623,8 @@ static int blinkm_probe(struct i2c_client *client,
client->adapter->nr,
client->addr);
led[i]->led_cdev.name = blinkm_led_name;
- led[i]->led_cdev.brightness_set = blinkm_led_red_set;
+ led[i]->led_cdev.brightness_set_blocking =
+ blinkm_led_red_set;
err = led_classdev_register(&client->dev,
&led[i]->led_cdev);
if (err < 0) {
@@ -693,7 +640,8 @@ static int blinkm_probe(struct i2c_client *client,
client->adapter->nr,
client->addr);
led[i]->led_cdev.name = blinkm_led_name;
- led[i]->led_cdev.brightness_set = blinkm_led_green_set;
+ led[i]->led_cdev.brightness_set_blocking =
+ blinkm_led_green_set;
err = led_classdev_register(&client->dev,
&led[i]->led_cdev);
if (err < 0) {
@@ -709,7 +657,8 @@ static int blinkm_probe(struct i2c_client *client,
client->adapter->nr,
client->addr);
led[i]->led_cdev.name = blinkm_led_name;
- led[i]->led_cdev.brightness_set = blinkm_led_blue_set;
+ led[i]->led_cdev.brightness_set_blocking =
+ blinkm_led_blue_set;
err = led_classdev_register(&client->dev,
&led[i]->led_cdev);
if (err < 0) {
@@ -746,10 +695,8 @@ static int blinkm_remove(struct i2c_client *client)
int i;
/* make sure no workqueue entries are pending */
- for (i = 0; i < 3; i++) {
- flush_scheduled_work();
+ for (i = 0; i < 3; i++)
led_classdev_unregister(&data->blinkm_leds[i].led_cdev);
- }
/* reset rgb */
data->next_red = 0x00;
diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c
index 952ba96e5b38..4752a2b6ba2b 100644
--- a/drivers/leds/leds-da903x.c
+++ b/drivers/leds/leds-da903x.c
@@ -16,7 +16,6 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
-#include <linux/workqueue.h>
#include <linux/mfd/da903x.h>
#include <linux/slab.h>
@@ -33,9 +32,7 @@
struct da903x_led {
struct led_classdev cdev;
- struct work_struct work;
struct device *master;
- enum led_brightness new_brightness;
int id;
int flags;
};
@@ -43,11 +40,13 @@ struct da903x_led {
#define DA9030_LED_OFFSET(id) ((id) - DA9030_ID_LED_1)
#define DA9034_LED_OFFSET(id) ((id) - DA9034_ID_LED_1)
-static void da903x_led_work(struct work_struct *work)
+static int da903x_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
{
- struct da903x_led *led = container_of(work, struct da903x_led, work);
+ struct da903x_led *led =
+ container_of(led_cdev, struct da903x_led, cdev);
uint8_t val;
- int offset;
+ int offset, ret = -EINVAL;
switch (led->id) {
case DA9030_ID_LED_1:
@@ -57,37 +56,31 @@ static void da903x_led_work(struct work_struct *work)
case DA9030_ID_LED_PC:
offset = DA9030_LED_OFFSET(led->id);
val = led->flags & ~0x87;
- val |= (led->new_brightness) ? 0x80 : 0; /* EN bit */
- val |= (0x7 - (led->new_brightness >> 5)) & 0x7; /* PWM<2:0> */
- da903x_write(led->master, DA9030_LED1_CONTROL + offset, val);
+ val |= value ? 0x80 : 0; /* EN bit */
+ val |= (0x7 - (value >> 5)) & 0x7; /* PWM<2:0> */
+ ret = da903x_write(led->master, DA9030_LED1_CONTROL + offset,
+ val);
break;
case DA9030_ID_VIBRA:
val = led->flags & ~0x80;
- val |= (led->new_brightness) ? 0x80 : 0; /* EN bit */
- da903x_write(led->master, DA9030_MISC_CONTROL_A, val);
+ val |= value ? 0x80 : 0; /* EN bit */
+ ret = da903x_write(led->master, DA9030_MISC_CONTROL_A, val);
break;
case DA9034_ID_LED_1:
case DA9034_ID_LED_2:
offset = DA9034_LED_OFFSET(led->id);
- val = (led->new_brightness * 0x5f / LED_FULL) & 0x7f;
+ val = (value * 0x5f / LED_FULL) & 0x7f;
val |= (led->flags & DA9034_LED_RAMP) ? 0x80 : 0;
- da903x_write(led->master, DA9034_LED1_CONTROL + offset, val);
+ ret = da903x_write(led->master, DA9034_LED1_CONTROL + offset,
+ val);
break;
case DA9034_ID_VIBRA:
- val = led->new_brightness & 0xfe;
- da903x_write(led->master, DA9034_VIBRA, val);
+ val = value & 0xfe;
+ ret = da903x_write(led->master, DA9034_VIBRA, val);
break;
}
-}
-static void da903x_led_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- struct da903x_led *led;
-
- led = container_of(led_cdev, struct da903x_led, cdev);
- led->new_brightness = value;
- schedule_work(&led->work);
+ return ret;
}
static int da903x_led_probe(struct platform_device *pdev)
@@ -113,15 +106,12 @@ static int da903x_led_probe(struct platform_device *pdev)
led->cdev.name = pdata->name;
led->cdev.default_trigger = pdata->default_trigger;
- led->cdev.brightness_set = da903x_led_set;
+ led->cdev.brightness_set_blocking = da903x_led_set;
led->cdev.brightness = LED_OFF;
led->id = id;
led->flags = pdata->flags;
led->master = pdev->dev.parent;
- led->new_brightness = LED_OFF;
-
- INIT_WORK(&led->work, da903x_led_work);
ret = led_classdev_register(led->master, &led->cdev);
if (ret) {
diff --git a/drivers/leds/leds-da9052.c b/drivers/leds/leds-da9052.c
index 28291b6acc8e..f8c7d82c2652 100644
--- a/drivers/leds/leds-da9052.c
+++ b/drivers/leds/leds-da9052.c
@@ -16,7 +16,6 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
-#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/mfd/da9052/reg.h>
@@ -32,11 +31,9 @@
struct da9052_led {
struct led_classdev cdev;
- struct work_struct work;
struct da9052 *da9052;
unsigned char led_index;
unsigned char id;
- int brightness;
};
static unsigned char led_reg[] = {
@@ -44,12 +41,13 @@ static unsigned char led_reg[] = {
DA9052_LED_CONT_5_REG,
};
-static int da9052_set_led_brightness(struct da9052_led *led)
+static int da9052_set_led_brightness(struct da9052_led *led,
+ enum led_brightness brightness)
{
u8 val;
int error;
- val = (led->brightness & 0x7f) | DA9052_LED_CONT_DIM;
+ val = (brightness & 0x7f) | DA9052_LED_CONT_DIM;
error = da9052_reg_write(led->da9052, led_reg[led->led_index], val);
if (error < 0)
@@ -58,21 +56,13 @@ static int da9052_set_led_brightness(struct da9052_led *led)
return error;
}
-static void da9052_led_work(struct work_struct *work)
-{
- struct da9052_led *led = container_of(work, struct da9052_led, work);
-
- da9052_set_led_brightness(led);
-}
-
-static void da9052_led_set(struct led_classdev *led_cdev,
+static int da9052_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
- struct da9052_led *led;
+ struct da9052_led *led =
+ container_of(led_cdev, struct da9052_led, cdev);
- led = container_of(led_cdev, struct da9052_led, cdev);
- led->brightness = value;
- schedule_work(&led->work);
+ return da9052_set_led_brightness(led, value);
}
static int da9052_configure_leds(struct da9052 *da9052)
@@ -133,13 +123,11 @@ static int da9052_led_probe(struct platform_device *pdev)
for (i = 0; i < pled->num_leds; i++) {
led[i].cdev.name = pled->leds[i].name;
- led[i].cdev.brightness_set = da9052_led_set;
+ led[i].cdev.brightness_set_blocking = da9052_led_set;
led[i].cdev.brightness = LED_OFF;
led[i].cdev.max_brightness = DA9052_MAX_BRIGHTNESS;
- led[i].brightness = LED_OFF;
led[i].led_index = pled->leds[i].flags;
led[i].da9052 = dev_get_drvdata(pdev->dev.parent);
- INIT_WORK(&led[i].work, da9052_led_work);
error = led_classdev_register(pdev->dev.parent, &led[i].cdev);
if (error) {
@@ -148,7 +136,8 @@ static int da9052_led_probe(struct platform_device *pdev)
goto err_register;
}
- error = da9052_set_led_brightness(&led[i]);
+ error = da9052_set_led_brightness(&led[i],
+ led[i].cdev.brightness);
if (error) {
dev_err(&pdev->dev, "Unable to init led %d\n",
led[i].led_index);
@@ -166,10 +155,8 @@ static int da9052_led_probe(struct platform_device *pdev)
return 0;
err_register:
- for (i = i - 1; i >= 0; i--) {
+ for (i = i - 1; i >= 0; i--)
led_classdev_unregister(&led[i].cdev);
- cancel_work_sync(&led[i].work);
- }
err:
return error;
}
@@ -187,10 +174,8 @@ static int da9052_led_remove(struct platform_device *pdev)
pled = pdata->pled;
for (i = 0; i < pled->num_leds; i++) {
- led[i].brightness = 0;
- da9052_set_led_brightness(&led[i]);
+ da9052_set_led_brightness(&led[i], LED_OFF);
led_classdev_unregister(&led[i].cdev);
- cancel_work_sync(&led[i].work);
}
return 0;
diff --git a/drivers/leds/leds-dac124s085.c b/drivers/leds/leds-dac124s085.c
index 314159610d24..5a5a86d5f1f5 100644
--- a/drivers/leds/leds-dac124s085.c
+++ b/drivers/leds/leds-dac124s085.c
@@ -13,20 +13,15 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
#include <linux/spi/spi.h>
struct dac124s085_led {
struct led_classdev ldev;
struct spi_device *spi;
int id;
- int brightness;
char name[sizeof("dac124s085-3")];
struct mutex mutex;
- struct work_struct work;
- spinlock_t lock;
};
struct dac124s085 {
@@ -38,29 +33,21 @@ struct dac124s085 {
#define ALL_WRITE_UPDATE (2 << 12)
#define POWER_DOWN_OUTPUT (3 << 12)
-static void dac124s085_led_work(struct work_struct *work)
+static int dac124s085_set_brightness(struct led_classdev *ldev,
+ enum led_brightness brightness)
{
- struct dac124s085_led *led = container_of(work, struct dac124s085_led,
- work);
+ struct dac124s085_led *led = container_of(ldev, struct dac124s085_led,
+ ldev);
u16 word;
+ int ret;
mutex_lock(&led->mutex);
word = cpu_to_le16(((led->id) << 14) | REG_WRITE_UPDATE |
- (led->brightness & 0xfff));
- spi_write(led->spi, (const u8 *)&word, sizeof(word));
+ (brightness & 0xfff));
+ ret = spi_write(led->spi, (const u8 *)&word, sizeof(word));
mutex_unlock(&led->mutex);
-}
-
-static void dac124s085_set_brightness(struct led_classdev *ldev,
- enum led_brightness brightness)
-{
- struct dac124s085_led *led = container_of(ldev, struct dac124s085_led,
- ldev);
- spin_lock(&led->lock);
- led->brightness = brightness;
- schedule_work(&led->work);
- spin_unlock(&led->lock);
+ return ret;
}
static int dac124s085_probe(struct spi_device *spi)
@@ -78,16 +65,13 @@ static int dac124s085_probe(struct spi_device *spi)
for (i = 0; i < ARRAY_SIZE(dac->leds); i++) {
led = dac->leds + i;
led->id = i;
- led->brightness = LED_OFF;
led->spi = spi;
snprintf(led->name, sizeof(led->name), "dac124s085-%d", i);
- spin_lock_init(&led->lock);
- INIT_WORK(&led->work, dac124s085_led_work);
mutex_init(&led->mutex);
led->ldev.name = led->name;
led->ldev.brightness = LED_OFF;
led->ldev.max_brightness = 0xfff;
- led->ldev.brightness_set = dac124s085_set_brightness;
+ led->ldev.brightness_set_blocking = dac124s085_set_brightness;
ret = led_classdev_register(&spi->dev, &led->ldev);
if (ret < 0)
goto eledcr;
@@ -109,10 +93,8 @@ static int dac124s085_remove(struct spi_device *spi)
struct dac124s085 *dac = spi_get_drvdata(spi);
int i;
- for (i = 0; i < ARRAY_SIZE(dac->leds); i++) {
+ for (i = 0; i < ARRAY_SIZE(dac->leds); i++)
led_classdev_unregister(&dac->leds[i].ldev);
- cancel_work_sync(&dac->leds[i].work);
- }
return 0;
}
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 5db4515a4fd7..7bc53280dbfd 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -20,32 +20,16 @@
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>
-#include <linux/workqueue.h>
struct gpio_led_data {
struct led_classdev cdev;
struct gpio_desc *gpiod;
- struct work_struct work;
- u8 new_level;
u8 can_sleep;
u8 blinking;
int (*platform_gpio_blink_set)(struct gpio_desc *desc, int state,
unsigned long *delay_on, unsigned long *delay_off);
};
-static void gpio_led_work(struct work_struct *work)
-{
- struct gpio_led_data *led_dat =
- container_of(work, struct gpio_led_data, work);
-
- if (led_dat->blinking) {
- led_dat->platform_gpio_blink_set(led_dat->gpiod,
- led_dat->new_level, NULL, NULL);
- led_dat->blinking = 0;
- } else
- gpiod_set_value_cansleep(led_dat->gpiod, led_dat->new_level);
-}
-
static void gpio_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
@@ -58,23 +42,25 @@ static void gpio_led_set(struct led_classdev *led_cdev,
else
level = 1;
- /* Setting GPIOs with I2C/etc requires a task context, and we don't
- * seem to have a reliable way to know if we're already in one; so
- * let's just assume the worst.
- */
- if (led_dat->can_sleep) {
- led_dat->new_level = level;
- schedule_work(&led_dat->work);
+ if (led_dat->blinking) {
+ led_dat->platform_gpio_blink_set(led_dat->gpiod, level,
+ NULL, NULL);
+ led_dat->blinking = 0;
} else {
- if (led_dat->blinking) {
- led_dat->platform_gpio_blink_set(led_dat->gpiod, level,
- NULL, NULL);
- led_dat->blinking = 0;
- } else
+ if (led_dat->can_sleep)
+ gpiod_set_value_cansleep(led_dat->gpiod, level);
+ else
gpiod_set_value(led_dat->gpiod, level);
}
}
+static int gpio_led_set_blocking(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ gpio_led_set(led_cdev, value);
+ return 0;
+}
+
static int gpio_blink_set(struct led_classdev *led_cdev,
unsigned long *delay_on, unsigned long *delay_off)
{
@@ -125,12 +111,15 @@ static int create_gpio_led(const struct gpio_led *template,
led_dat->cdev.name = template->name;
led_dat->cdev.default_trigger = template->default_trigger;
led_dat->can_sleep = gpiod_cansleep(led_dat->gpiod);
+ if (!led_dat->can_sleep)
+ led_dat->cdev.brightness_set = gpio_led_set;
+ else
+ led_dat->cdev.brightness_set_blocking = gpio_led_set_blocking;
led_dat->blinking = 0;
if (blink_set) {
led_dat->platform_gpio_blink_set = blink_set;
led_dat->cdev.blink_set = gpio_blink_set;
}
- led_dat->cdev.brightness_set = gpio_led_set;
if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP)
state = !!gpiod_get_value_cansleep(led_dat->gpiod);
else
@@ -143,17 +132,9 @@ static int create_gpio_led(const struct gpio_led *template,
if (ret < 0)
return ret;
- INIT_WORK(&led_dat->work, gpio_led_work);
-
return led_classdev_register(parent, &led_dat->cdev);
}
-static void delete_gpio_led(struct gpio_led_data *led)
-{
- led_classdev_unregister(&led->cdev);
- cancel_work_sync(&led->work);
-}
-
struct gpio_leds_priv {
int num_leds;
struct gpio_led_data leds[];
@@ -233,7 +214,7 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
err:
for (count = priv->num_leds - 1; count >= 0; count--)
- delete_gpio_led(&priv->leds[count]);
+ led_classdev_unregister(&priv->leds[count].cdev);
return ERR_PTR(ret);
}
@@ -265,7 +246,8 @@ static int gpio_led_probe(struct platform_device *pdev)
if (ret < 0) {
/* On failure: unwind the led creations */
for (i = i - 1; i >= 0; i--)
- delete_gpio_led(&priv->leds[i]);
+ led_classdev_unregister(
+ &priv->leds[i].cdev);
return ret;
}
}
@@ -286,7 +268,7 @@ static int gpio_led_remove(struct platform_device *pdev)
int i;
for (i = 0; i < priv->num_leds; i++)
- delete_gpio_led(&priv->leds[i]);
+ led_classdev_unregister(&priv->leds[i].cdev);
return 0;
}
diff --git a/drivers/leds/leds-ipaq-micro.c b/drivers/leds/leds-ipaq-micro.c
index fa262b6b25eb..02f17331379d 100644
--- a/drivers/leds/leds-ipaq-micro.c
+++ b/drivers/leds/leds-ipaq-micro.c
@@ -20,7 +20,7 @@
#define LED_AUTOSTOP (1 << 5) /* LED ON/OFF auto stop set 0:disable, 1:enable */
#define LED_ALWAYS (1 << 6) /* LED Interrupt Mask 0:No mask, 1:mask */
-static void micro_leds_brightness_set(struct led_classdev *led_cdev,
+static int micro_leds_brightness_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct ipaq_micro *micro = dev_get_drvdata(led_cdev->dev->parent->parent);
@@ -50,7 +50,7 @@ static void micro_leds_brightness_set(struct led_classdev *led_cdev,
msg.tx_data[2] = 1;
msg.tx_data[3] = 0; /* Duty cycle 256 */
}
- ipaq_micro_tx_msg_sync(micro, &msg);
+ return ipaq_micro_tx_msg_sync(micro, &msg);
}
/* Maximum duty cycle in ms 256/10 sec = 25600 ms */
@@ -102,7 +102,7 @@ static int micro_leds_blink_set(struct led_classdev *led_cdev,
static struct led_classdev micro_led = {
.name = "led-ipaq-micro",
- .brightness_set = micro_leds_brightness_set,
+ .brightness_set_blocking = micro_leds_brightness_set,
.blink_set = micro_leds_blink_set,
.flags = LED_CORE_SUSPENDRESUME,
};
diff --git a/drivers/leds/leds-ktd2692.c b/drivers/leds/leds-ktd2692.c
index feca07be85f5..bf23ba191ad0 100644
--- a/drivers/leds/leds-ktd2692.c
+++ b/drivers/leds/leds-ktd2692.c
@@ -18,7 +18,6 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
-#include <linux/workqueue.h>
/* Value related the movie mode */
#define KTD2692_MOVIE_MODE_CURRENT_LEVELS 16
@@ -82,7 +81,6 @@ struct ktd2692_context {
/* secures access to the device */
struct mutex lock;
struct regulator *regulator;
- struct work_struct work_brightness_set;
struct gpio_desc *aux_gpio;
struct gpio_desc *ctrl_gpio;
@@ -158,9 +156,12 @@ static void ktd2692_expresswire_write(struct ktd2692_context *led, u8 value)
ktd2692_expresswire_end(led);
}
-static void ktd2692_brightness_set(struct ktd2692_context *led,
- enum led_brightness brightness)
+static int ktd2692_led_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
{
+ struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
+ struct ktd2692_context *led = fled_cdev_to_led(fled_cdev);
+
mutex_lock(&led->lock);
if (brightness == LED_OFF) {
@@ -174,33 +175,6 @@ static void ktd2692_brightness_set(struct ktd2692_context *led,
ktd2692_expresswire_write(led, led->mode | KTD2692_REG_MODE_BASE);
mutex_unlock(&led->lock);
-}
-
-static void ktd2692_brightness_set_work(struct work_struct *work)
-{
- struct ktd2692_context *led =
- container_of(work, struct ktd2692_context, work_brightness_set);
-
- ktd2692_brightness_set(led, led->torch_brightness);
-}
-
-static void ktd2692_led_brightness_set(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
- struct ktd2692_context *led = fled_cdev_to_led(fled_cdev);
-
- led->torch_brightness = brightness;
- schedule_work(&led->work_brightness_set);
-}
-
-static int ktd2692_led_brightness_set_sync(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
- struct ktd2692_context *led = fled_cdev_to_led(fled_cdev);
-
- ktd2692_brightness_set(led, brightness);
return 0;
}
@@ -332,21 +306,24 @@ static int ktd2692_parse_dt(struct ktd2692_context *led, struct device *dev,
&cfg->movie_max_microamp);
if (ret) {
dev_err(dev, "failed to parse led-max-microamp\n");
- return ret;
+ goto err_parse_dt;
}
ret = of_property_read_u32(child_node, "flash-max-microamp",
&cfg->flash_max_microamp);
if (ret) {
dev_err(dev, "failed to parse flash-max-microamp\n");
- return ret;
+ goto err_parse_dt;
}
ret = of_property_read_u32(child_node, "flash-max-timeout-us",
&cfg->flash_max_timeout);
- if (ret)
+ if (ret) {
dev_err(dev, "failed to parse flash-max-timeout-us\n");
+ goto err_parse_dt;
+ }
+err_parse_dt:
of_node_put(child_node);
return ret;
}
@@ -381,12 +358,10 @@ static int ktd2692_probe(struct platform_device *pdev)
fled_cdev->ops = &flash_ops;
led_cdev->max_brightness = led_cfg.max_brightness;
- led_cdev->brightness_set = ktd2692_led_brightness_set;
- led_cdev->brightness_set_sync = ktd2692_led_brightness_set_sync;
+ led_cdev->brightness_set_blocking = ktd2692_led_brightness_set;
led_cdev->flags |= LED_CORE_SUSPENDRESUME | LED_DEV_CAP_FLASH;
mutex_init(&led->lock);
- INIT_WORK(&led->work_brightness_set, ktd2692_brightness_set_work);
platform_set_drvdata(pdev, led);
@@ -408,7 +383,6 @@ static int ktd2692_remove(struct platform_device *pdev)
int ret;
led_classdev_flash_unregister(&led->fled_cdev);
- cancel_work_sync(&led->work_brightness_set);
if (led->regulator) {
ret = regulator_disable(led->regulator);
diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c
index 6e2e02035dd7..196dcb5e6004 100644
--- a/drivers/leds/leds-lm3533.c
+++ b/drivers/leds/leds-lm3533.c
@@ -17,7 +17,6 @@
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <linux/workqueue.h>
#include <linux/mfd/lm3533.h>
@@ -53,9 +52,6 @@ struct lm3533_led {
struct mutex mutex;
unsigned long flags;
-
- struct work_struct work;
- u8 new_brightness;
};
@@ -123,27 +119,17 @@ out:
return ret;
}
-static void lm3533_led_work(struct work_struct *work)
-{
- struct lm3533_led *led = container_of(work, struct lm3533_led, work);
-
- dev_dbg(led->cdev.dev, "%s - %u\n", __func__, led->new_brightness);
-
- if (led->new_brightness == 0)
- lm3533_led_pattern_enable(led, 0); /* disable blink */
-
- lm3533_ctrlbank_set_brightness(&led->cb, led->new_brightness);
-}
-
-static void lm3533_led_set(struct led_classdev *cdev,
+static int lm3533_led_set(struct led_classdev *cdev,
enum led_brightness value)
{
struct lm3533_led *led = to_lm3533_led(cdev);
dev_dbg(led->cdev.dev, "%s - %d\n", __func__, value);
- led->new_brightness = value;
- schedule_work(&led->work);
+ if (value == 0)
+ lm3533_led_pattern_enable(led, 0); /* disable blink */
+
+ return lm3533_ctrlbank_set_brightness(&led->cb, value);
}
static enum led_brightness lm3533_led_get(struct led_classdev *cdev)
@@ -693,7 +679,7 @@ static int lm3533_led_probe(struct platform_device *pdev)
led->lm3533 = lm3533;
led->cdev.name = pdata->name;
led->cdev.default_trigger = pdata->default_trigger;
- led->cdev.brightness_set = lm3533_led_set;
+ led->cdev.brightness_set_blocking = lm3533_led_set;
led->cdev.brightness_get = lm3533_led_get;
led->cdev.blink_set = lm3533_led_blink_set;
led->cdev.brightness = LED_OFF;
@@ -701,7 +687,6 @@ static int lm3533_led_probe(struct platform_device *pdev)
led->id = pdev->id;
mutex_init(&led->mutex);
- INIT_WORK(&led->work, lm3533_led_work);
/* The class framework makes a callback to get brightness during
* registration so use parent device (for error reporting) until
@@ -733,7 +718,6 @@ static int lm3533_led_probe(struct platform_device *pdev)
err_unregister:
led_classdev_unregister(&led->cdev);
- flush_work(&led->work);
return ret;
}
@@ -746,7 +730,6 @@ static int lm3533_led_remove(struct platform_device *pdev)
lm3533_ctrlbank_disable(&led->cb);
led_classdev_unregister(&led->cdev);
- flush_work(&led->work);
return 0;
}
@@ -760,7 +743,6 @@ static void lm3533_led_shutdown(struct platform_device *pdev)
lm3533_ctrlbank_disable(&led->cb);
lm3533_led_set(&led->cdev, LED_OFF); /* disable blink */
- flush_work(&led->work);
}
static struct platform_driver lm3533_led_driver = {
diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c
index 48872997d6b4..6cb94f9a2f3f 100644
--- a/drivers/leds/leds-lm355x.c
+++ b/drivers/leds/leds-lm355x.c
@@ -16,7 +16,6 @@
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/regmap.h>
-#include <linux/workqueue.h>
#include <linux/platform_data/leds-lm355x.h>
enum lm355x_type {
@@ -59,14 +58,6 @@ struct lm355x_chip_data {
struct led_classdev cdev_torch;
struct led_classdev cdev_indicator;
- struct work_struct work_flash;
- struct work_struct work_torch;
- struct work_struct work_indicator;
-
- u8 br_flash;
- u8 br_torch;
- u8 br_indicator;
-
struct lm355x_platform_data *pdata;
struct regmap *regmap;
struct mutex lock;
@@ -204,7 +195,7 @@ out:
}
/* chip control */
-static void lm355x_control(struct lm355x_chip_data *chip,
+static int lm355x_control(struct lm355x_chip_data *chip,
u8 brightness, enum lm355x_mode opmode)
{
int ret;
@@ -301,7 +292,7 @@ static void lm355x_control(struct lm355x_chip_data *chip,
case MODE_SHDN:
break;
default:
- return;
+ return -EINVAL;
}
/* operation mode control */
ret = regmap_update_bits(chip->regmap, preg[REG_OPMODE].regno,
@@ -309,73 +300,55 @@ static void lm355x_control(struct lm355x_chip_data *chip,
opmode << preg[REG_OPMODE].shift);
if (ret < 0)
goto out;
- return;
+ return ret;
out:
dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
- return;
+ return ret;
}
/* torch */
-static void lm355x_deferred_torch_brightness_set(struct work_struct *work)
-{
- struct lm355x_chip_data *chip =
- container_of(work, struct lm355x_chip_data, work_torch);
- mutex_lock(&chip->lock);
- lm355x_control(chip, chip->br_torch, MODE_TORCH);
- mutex_unlock(&chip->lock);
-}
-
-static void lm355x_torch_brightness_set(struct led_classdev *cdev,
+static int lm355x_torch_brightness_set(struct led_classdev *cdev,
enum led_brightness brightness)
{
struct lm355x_chip_data *chip =
container_of(cdev, struct lm355x_chip_data, cdev_torch);
-
- chip->br_torch = brightness;
- schedule_work(&chip->work_torch);
-}
-
-/* flash */
-static void lm355x_deferred_strobe_brightness_set(struct work_struct *work)
-{
- struct lm355x_chip_data *chip =
- container_of(work, struct lm355x_chip_data, work_flash);
+ int ret;
mutex_lock(&chip->lock);
- lm355x_control(chip, chip->br_flash, MODE_FLASH);
+ ret = lm355x_control(chip, brightness, MODE_TORCH);
mutex_unlock(&chip->lock);
+ return ret;
}
-static void lm355x_strobe_brightness_set(struct led_classdev *cdev,
+/* flash */
+
+static int lm355x_strobe_brightness_set(struct led_classdev *cdev,
enum led_brightness brightness)
{
struct lm355x_chip_data *chip =
container_of(cdev, struct lm355x_chip_data, cdev_flash);
-
- chip->br_flash = brightness;
- schedule_work(&chip->work_flash);
-}
-
-/* indicator */
-static void lm355x_deferred_indicator_brightness_set(struct work_struct *work)
-{
- struct lm355x_chip_data *chip =
- container_of(work, struct lm355x_chip_data, work_indicator);
+ int ret;
mutex_lock(&chip->lock);
- lm355x_control(chip, chip->br_indicator, MODE_INDIC);
+ ret = lm355x_control(chip, brightness, MODE_FLASH);
mutex_unlock(&chip->lock);
+ return ret;
}
-static void lm355x_indicator_brightness_set(struct led_classdev *cdev,
+/* indicator */
+
+static int lm355x_indicator_brightness_set(struct led_classdev *cdev,
enum led_brightness brightness)
{
struct lm355x_chip_data *chip =
container_of(cdev, struct lm355x_chip_data, cdev_indicator);
+ int ret;
- chip->br_indicator = brightness;
- schedule_work(&chip->work_indicator);
+ mutex_lock(&chip->lock);
+ ret = lm355x_control(chip, brightness, MODE_INDIC);
+ mutex_unlock(&chip->lock);
+ return ret;
}
/* indicator pattern only for lm3556*/
@@ -479,34 +452,31 @@ static int lm355x_probe(struct i2c_client *client,
goto err_out;
/* flash */
- INIT_WORK(&chip->work_flash, lm355x_deferred_strobe_brightness_set);
chip->cdev_flash.name = "flash";
chip->cdev_flash.max_brightness = 16;
- chip->cdev_flash.brightness_set = lm355x_strobe_brightness_set;
+ chip->cdev_flash.brightness_set_blocking = lm355x_strobe_brightness_set;
chip->cdev_flash.default_trigger = "flash";
err = led_classdev_register((struct device *)
&client->dev, &chip->cdev_flash);
if (err < 0)
goto err_out;
/* torch */
- INIT_WORK(&chip->work_torch, lm355x_deferred_torch_brightness_set);
chip->cdev_torch.name = "torch";
chip->cdev_torch.max_brightness = 8;
- chip->cdev_torch.brightness_set = lm355x_torch_brightness_set;
+ chip->cdev_torch.brightness_set_blocking = lm355x_torch_brightness_set;
chip->cdev_torch.default_trigger = "torch";
err = led_classdev_register((struct device *)
&client->dev, &chip->cdev_torch);
if (err < 0)
goto err_create_torch_file;
/* indicator */
- INIT_WORK(&chip->work_indicator,
- lm355x_deferred_indicator_brightness_set);
chip->cdev_indicator.name = "indicator";
if (id->driver_data == CHIP_LM3554)
chip->cdev_indicator.max_brightness = 4;
else
chip->cdev_indicator.max_brightness = 8;
- chip->cdev_indicator.brightness_set = lm355x_indicator_brightness_set;
+ chip->cdev_indicator.brightness_set_blocking =
+ lm355x_indicator_brightness_set;
/* indicator pattern control only for LM3556 */
if (id->driver_data == CHIP_LM3556)
chip->cdev_indicator.groups = lm355x_indicator_groups;
@@ -534,11 +504,8 @@ static int lm355x_remove(struct i2c_client *client)
regmap_write(chip->regmap, preg[REG_OPMODE].regno, 0);
led_classdev_unregister(&chip->cdev_indicator);
- flush_work(&chip->work_indicator);
led_classdev_unregister(&chip->cdev_torch);
- flush_work(&chip->work_torch);
led_classdev_unregister(&chip->cdev_flash);
- flush_work(&chip->work_flash);
dev_info(&client->dev, "%s is removed\n", lm355x_name[chip->type]);
return 0;
diff --git a/drivers/leds/leds-lm3642.c b/drivers/leds/leds-lm3642.c
index 02ebe342f5af..cada0848db7b 100644
--- a/drivers/leds/leds-lm3642.c
+++ b/drivers/leds/leds-lm3642.c
@@ -15,7 +15,6 @@
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/regmap.h>
-#include <linux/workqueue.h>
#include <linux/platform_data/leds-lm3642.h>
#define REG_FILT_TIME (0x0)
@@ -73,10 +72,6 @@ struct lm3642_chip_data {
struct led_classdev cdev_torch;
struct led_classdev cdev_indicator;
- struct work_struct work_flash;
- struct work_struct work_torch;
- struct work_struct work_indicator;
-
u8 br_flash;
u8 br_torch;
u8 br_indicator;
@@ -209,24 +204,18 @@ out_strtoint:
static DEVICE_ATTR(torch_pin, S_IWUSR, NULL, lm3642_torch_pin_store);
-static void lm3642_deferred_torch_brightness_set(struct work_struct *work)
-{
- struct lm3642_chip_data *chip =
- container_of(work, struct lm3642_chip_data, work_torch);
-
- mutex_lock(&chip->lock);
- lm3642_control(chip, chip->br_torch, MODES_TORCH);
- mutex_unlock(&chip->lock);
-}
-
-static void lm3642_torch_brightness_set(struct led_classdev *cdev,
+static int lm3642_torch_brightness_set(struct led_classdev *cdev,
enum led_brightness brightness)
{
struct lm3642_chip_data *chip =
container_of(cdev, struct lm3642_chip_data, cdev_torch);
+ int ret;
+ mutex_lock(&chip->lock);
chip->br_torch = brightness;
- schedule_work(&chip->work_torch);
+ ret = lm3642_control(chip, chip->br_torch, MODES_TORCH);
+ mutex_unlock(&chip->lock);
+ return ret;
}
/* flash */
@@ -266,45 +255,33 @@ out_strtoint:
static DEVICE_ATTR(strobe_pin, S_IWUSR, NULL, lm3642_strobe_pin_store);
-static void lm3642_deferred_strobe_brightness_set(struct work_struct *work)
-{
- struct lm3642_chip_data *chip =
- container_of(work, struct lm3642_chip_data, work_flash);
-
- mutex_lock(&chip->lock);
- lm3642_control(chip, chip->br_flash, MODES_FLASH);
- mutex_unlock(&chip->lock);
-}
-
-static void lm3642_strobe_brightness_set(struct led_classdev *cdev,
+static int lm3642_strobe_brightness_set(struct led_classdev *cdev,
enum led_brightness brightness)
{
struct lm3642_chip_data *chip =
container_of(cdev, struct lm3642_chip_data, cdev_flash);
-
- chip->br_flash = brightness;
- schedule_work(&chip->work_flash);
-}
-
-/* indicator */
-static void lm3642_deferred_indicator_brightness_set(struct work_struct *work)
-{
- struct lm3642_chip_data *chip =
- container_of(work, struct lm3642_chip_data, work_indicator);
+ int ret;
mutex_lock(&chip->lock);
- lm3642_control(chip, chip->br_indicator, MODES_INDIC);
+ chip->br_flash = brightness;
+ ret = lm3642_control(chip, chip->br_flash, MODES_FLASH);
mutex_unlock(&chip->lock);
+ return ret;
}
-static void lm3642_indicator_brightness_set(struct led_classdev *cdev,
+/* indicator */
+static int lm3642_indicator_brightness_set(struct led_classdev *cdev,
enum led_brightness brightness)
{
struct lm3642_chip_data *chip =
container_of(cdev, struct lm3642_chip_data, cdev_indicator);
+ int ret;
+ mutex_lock(&chip->lock);
chip->br_indicator = brightness;
- schedule_work(&chip->work_indicator);
+ ret = lm3642_control(chip, chip->br_indicator, MODES_INDIC);
+ mutex_unlock(&chip->lock);
+ return ret;
}
static const struct regmap_config lm3642_regmap = {
@@ -371,10 +348,9 @@ static int lm3642_probe(struct i2c_client *client,
goto err_out;
/* flash */
- INIT_WORK(&chip->work_flash, lm3642_deferred_strobe_brightness_set);
chip->cdev_flash.name = "flash";
chip->cdev_flash.max_brightness = 16;
- chip->cdev_flash.brightness_set = lm3642_strobe_brightness_set;
+ chip->cdev_flash.brightness_set_blocking = lm3642_strobe_brightness_set;
chip->cdev_flash.default_trigger = "flash";
chip->cdev_flash.groups = lm3642_flash_groups,
err = led_classdev_register((struct device *)
@@ -385,10 +361,9 @@ static int lm3642_probe(struct i2c_client *client,
}
/* torch */
- INIT_WORK(&chip->work_torch, lm3642_deferred_torch_brightness_set);
chip->cdev_torch.name = "torch";
chip->cdev_torch.max_brightness = 8;
- chip->cdev_torch.brightness_set = lm3642_torch_brightness_set;
+ chip->cdev_torch.brightness_set_blocking = lm3642_torch_brightness_set;
chip->cdev_torch.default_trigger = "torch";
chip->cdev_torch.groups = lm3642_torch_groups,
err = led_classdev_register((struct device *)
@@ -399,11 +374,10 @@ static int lm3642_probe(struct i2c_client *client,
}
/* indicator */
- INIT_WORK(&chip->work_indicator,
- lm3642_deferred_indicator_brightness_set);
chip->cdev_indicator.name = "indicator";
chip->cdev_indicator.max_brightness = 8;
- chip->cdev_indicator.brightness_set = lm3642_indicator_brightness_set;
+ chip->cdev_indicator.brightness_set_blocking =
+ lm3642_indicator_brightness_set;
err = led_classdev_register((struct device *)
&client->dev, &chip->cdev_indicator);
if (err < 0) {
@@ -427,11 +401,8 @@ static int lm3642_remove(struct i2c_client *client)
struct lm3642_chip_data *chip = i2c_get_clientdata(client);
led_classdev_unregister(&chip->cdev_indicator);
- flush_work(&chip->work_indicator);
led_classdev_unregister(&chip->cdev_torch);
- flush_work(&chip->work_torch);
led_classdev_unregister(&chip->cdev_flash);
- flush_work(&chip->work_flash);
regmap_write(chip->regmap, REG_ENABLE, 0);
return 0;
}
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c
index 53144fb96167..6c758aea1bbd 100644
--- a/drivers/leds/leds-lp3944.c
+++ b/drivers/leds/leds-lp3944.c
@@ -31,7 +31,6 @@
#include <linux/slab.h>
#include <linux/leds.h>
#include <linux/mutex.h>
-#include <linux/workqueue.h>
#include <linux/leds-lp3944.h>
/* Read Only Registers */
@@ -68,10 +67,8 @@
struct lp3944_led_data {
u8 id;
enum lp3944_type type;
- enum lp3944_status status;
struct led_classdev ldev;
struct i2c_client *client;
- struct work_struct work;
};
struct lp3944_data {
@@ -275,13 +272,12 @@ static int lp3944_led_set_blink(struct led_classdev *led_cdev,
dev_dbg(&led->client->dev, "%s: OK hardware accelerated blink!\n",
__func__);
- led->status = LP3944_LED_STATUS_DIM0;
- schedule_work(&led->work);
+ lp3944_led_set(led, LP3944_LED_STATUS_DIM0);
return 0;
}
-static void lp3944_led_set_brightness(struct led_classdev *led_cdev,
+static int lp3944_led_set_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct lp3944_led_data *led = ldev_to_led(led_cdev);
@@ -289,16 +285,7 @@ static void lp3944_led_set_brightness(struct led_classdev *led_cdev,
dev_dbg(&led->client->dev, "%s: %s, %d\n",
__func__, led_cdev->name, brightness);
- led->status = !!brightness;
- schedule_work(&led->work);
-}
-
-static void lp3944_led_work(struct work_struct *work)
-{
- struct lp3944_led_data *led;
-
- led = container_of(work, struct lp3944_led_data, work);
- lp3944_led_set(led, led->status);
+ return lp3944_led_set(led, !!brightness);
}
static int lp3944_configure(struct i2c_client *client,
@@ -318,14 +305,13 @@ static int lp3944_configure(struct i2c_client *client,
case LP3944_LED_TYPE_LED:
case LP3944_LED_TYPE_LED_INVERTED:
led->type = pled->type;
- led->status = pled->status;
led->ldev.name = pled->name;
led->ldev.max_brightness = 1;
- led->ldev.brightness_set = lp3944_led_set_brightness;
+ led->ldev.brightness_set_blocking =
+ lp3944_led_set_brightness;
led->ldev.blink_set = lp3944_led_set_blink;
led->ldev.flags = LED_CORE_SUSPENDRESUME;
- INIT_WORK(&led->work, lp3944_led_work);
err = led_classdev_register(&client->dev, &led->ldev);
if (err < 0) {
dev_err(&client->dev,
@@ -336,14 +322,14 @@ static int lp3944_configure(struct i2c_client *client,
/* to expose the default value to userspace */
led->ldev.brightness =
- (enum led_brightness) led->status;
+ (enum led_brightness) pled->status;
/* Set the default led status */
- err = lp3944_led_set(led, led->status);
+ err = lp3944_led_set(led, pled->status);
if (err < 0) {
dev_err(&client->dev,
"%s couldn't set STATUS %d\n",
- led->ldev.name, led->status);
+ led->ldev.name, pled->status);
goto exit;
}
break;
@@ -364,7 +350,6 @@ exit:
case LP3944_LED_TYPE_LED:
case LP3944_LED_TYPE_LED_INVERTED:
led_classdev_unregister(&data->leds[i].ldev);
- cancel_work_sync(&data->leds[i].work);
break;
case LP3944_LED_TYPE_NONE:
@@ -424,7 +409,6 @@ static int lp3944_remove(struct i2c_client *client)
case LP3944_LED_TYPE_LED:
case LP3944_LED_TYPE_LED_INVERTED:
led_classdev_unregister(&data->leds[i].ldev);
- cancel_work_sync(&data->leds[i].work);
break;
case LP3944_LED_TYPE_NONE:
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
index 63a92542c8cb..549b315ca8fe 100644
--- a/drivers/leds/leds-lp5521.c
+++ b/drivers/leds/leds-lp5521.c
@@ -362,16 +362,17 @@ static int lp5521_run_selftest(struct lp55xx_chip *chip, char *buf)
return 0;
}
-static void lp5521_led_brightness_work(struct work_struct *work)
+static int lp5521_led_brightness(struct lp55xx_led *led)
{
- struct lp55xx_led *led = container_of(work, struct lp55xx_led,
- brightness_work);
struct lp55xx_chip *chip = led->chip;
+ int ret;
mutex_lock(&chip->lock);
- lp55xx_write(chip, LP5521_REG_LED_PWM_BASE + led->chan_nr,
+ ret = lp55xx_write(chip, LP5521_REG_LED_PWM_BASE + led->chan_nr,
led->brightness);
mutex_unlock(&chip->lock);
+
+ return ret;
}
static ssize_t show_engine_mode(struct device *dev,
@@ -501,7 +502,7 @@ static struct lp55xx_device_config lp5521_cfg = {
},
.max_channel = LP5521_MAX_LEDS,
.post_init_device = lp5521_post_init_device,
- .brightness_work_fn = lp5521_led_brightness_work,
+ .brightness_fn = lp5521_led_brightness,
.set_led_current = lp5521_set_led_current,
.firmware_cb = lp5521_firmware_loaded,
.run_engine = lp5521_run_engine,
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
index 1d0187f42941..c5b30f06218a 100644
--- a/drivers/leds/leds-lp5523.c
+++ b/drivers/leds/leds-lp5523.c
@@ -802,16 +802,16 @@ leave:
return ret;
}
-static void lp5523_led_brightness_work(struct work_struct *work)
+static int lp5523_led_brightness(struct lp55xx_led *led)
{
- struct lp55xx_led *led = container_of(work, struct lp55xx_led,
- brightness_work);
struct lp55xx_chip *chip = led->chip;
+ int ret;
mutex_lock(&chip->lock);
- lp55xx_write(chip, LP5523_REG_LED_PWM_BASE + led->chan_nr,
+ ret = lp55xx_write(chip, LP5523_REG_LED_PWM_BASE + led->chan_nr,
led->brightness);
mutex_unlock(&chip->lock);
+ return ret;
}
static LP55XX_DEV_ATTR_RW(engine1_mode, show_engine1_mode, store_engine1_mode);
@@ -867,7 +867,7 @@ static struct lp55xx_device_config lp5523_cfg = {
},
.max_channel = LP5523_MAX_LEDS,
.post_init_device = lp5523_post_init_device,
- .brightness_work_fn = lp5523_led_brightness_work,
+ .brightness_fn = lp5523_led_brightness,
.set_led_current = lp5523_set_led_current,
.firmware_cb = lp5523_firmware_loaded,
.run_engine = lp5523_run_engine,
diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c
index 0360c59dbdc9..b75333803a63 100644
--- a/drivers/leds/leds-lp5562.c
+++ b/drivers/leds/leds-lp5562.c
@@ -311,10 +311,8 @@ static int lp5562_post_init_device(struct lp55xx_chip *chip)
return 0;
}
-static void lp5562_led_brightness_work(struct work_struct *work)
+static int lp5562_led_brightness(struct lp55xx_led *led)
{
- struct lp55xx_led *led = container_of(work, struct lp55xx_led,
- brightness_work);
struct lp55xx_chip *chip = led->chip;
u8 addr[] = {
LP5562_REG_R_PWM,
@@ -322,10 +320,13 @@ static void lp5562_led_brightness_work(struct work_struct *work)
LP5562_REG_B_PWM,
LP5562_REG_W_PWM,
};
+ int ret;
mutex_lock(&chip->lock);
- lp55xx_write(chip, addr[led->chan_nr], led->brightness);
+ ret = lp55xx_write(chip, addr[led->chan_nr], led->brightness);
mutex_unlock(&chip->lock);
+
+ return ret;
}
static void lp5562_write_program_memory(struct lp55xx_chip *chip,
@@ -503,7 +504,7 @@ static struct lp55xx_device_config lp5562_cfg = {
},
.post_init_device = lp5562_post_init_device,
.set_led_current = lp5562_set_led_current,
- .brightness_work_fn = lp5562_led_brightness_work,
+ .brightness_fn = lp5562_led_brightness,
.run_engine = lp5562_run_engine,
.firmware_cb = lp5562_firmware_loaded,
.dev_attr_group = &lp5562_group,
diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c
index 59b76833f0d3..5377f22ff994 100644
--- a/drivers/leds/leds-lp55xx-common.c
+++ b/drivers/leds/leds-lp55xx-common.c
@@ -134,13 +134,14 @@ static struct attribute *lp55xx_led_attrs[] = {
};
ATTRIBUTE_GROUPS(lp55xx_led);
-static void lp55xx_set_brightness(struct led_classdev *cdev,
+static int lp55xx_set_brightness(struct led_classdev *cdev,
enum led_brightness brightness)
{
struct lp55xx_led *led = cdev_to_lp55xx_led(cdev);
+ struct lp55xx_device_config *cfg = led->chip->cfg;
led->brightness = (u8)brightness;
- schedule_work(&led->brightness_work);
+ return cfg->brightness_fn(led);
}
static int lp55xx_init_led(struct lp55xx_led *led,
@@ -172,7 +173,7 @@ static int lp55xx_init_led(struct lp55xx_led *led,
return -EINVAL;
}
- led->cdev.brightness_set = lp55xx_set_brightness;
+ led->cdev.brightness_set_blocking = lp55xx_set_brightness;
led->cdev.groups = lp55xx_led_groups;
if (pdata->led_config[chan].name) {
@@ -464,7 +465,7 @@ int lp55xx_register_leds(struct lp55xx_led *led, struct lp55xx_chip *chip)
int ret;
int i;
- if (!cfg->brightness_work_fn) {
+ if (!cfg->brightness_fn) {
dev_err(&chip->cl->dev, "empty brightness configuration\n");
return -EINVAL;
}
@@ -481,8 +482,6 @@ int lp55xx_register_leds(struct lp55xx_led *led, struct lp55xx_chip *chip)
if (ret)
goto err_init_led;
- INIT_WORK(&each->brightness_work, cfg->brightness_work_fn);
-
chip->num_leds++;
each->chip = chip;
@@ -507,7 +506,6 @@ void lp55xx_unregister_leds(struct lp55xx_led *led, struct lp55xx_chip *chip)
for (i = 0; i < chip->num_leds; i++) {
each = led + i;
led_classdev_unregister(&each->cdev);
- flush_work(&each->brightness_work);
}
}
EXPORT_SYMBOL_GPL(lp55xx_unregister_leds);
diff --git a/drivers/leds/leds-lp55xx-common.h b/drivers/leds/leds-lp55xx-common.h
index c7f1e6155001..abf1fb5da37d 100644
--- a/drivers/leds/leds-lp55xx-common.h
+++ b/drivers/leds/leds-lp55xx-common.h
@@ -95,7 +95,7 @@ struct lp55xx_reg {
* @enable : Chip specific enable command
* @max_channel : Maximum number of channels
* @post_init_device : Chip specific initialization code
- * @brightness_work_fn : Brightness work function
+ * @brightness_fn : Brightness function
* @set_led_current : LED current set function
* @firmware_cb : Call function when the firmware is loaded
* @run_engine : Run internal engine for pattern
@@ -110,7 +110,7 @@ struct lp55xx_device_config {
int (*post_init_device) (struct lp55xx_chip *chip);
/* access brightness register */
- void (*brightness_work_fn)(struct work_struct *work);
+ int (*brightness_fn)(struct lp55xx_led *led);
/* current setting function */
void (*set_led_current) (struct lp55xx_led *led, u8 led_current);
@@ -164,7 +164,6 @@ struct lp55xx_chip {
* @cdev : LED class device
* @led_current : Current setting at each led channel
* @max_current : Maximun current at each led channel
- * @brightness_work : Workqueue for brightness control
* @brightness : Brightness value
* @chip : The lp55xx chip data
*/
@@ -173,7 +172,6 @@ struct lp55xx_led {
struct led_classdev cdev;
u8 led_current;
u8 max_current;
- struct work_struct brightness_work;
u8 brightness;
struct lp55xx_chip *chip;
};
diff --git a/drivers/leds/leds-lp8501.c b/drivers/leds/leds-lp8501.c
index 3f54f6f2b821..3f9675bd214a 100644
--- a/drivers/leds/leds-lp8501.c
+++ b/drivers/leds/leds-lp8501.c
@@ -272,16 +272,17 @@ static void lp8501_firmware_loaded(struct lp55xx_chip *chip)
lp8501_update_program_memory(chip, fw->data, fw->size);
}
-static void lp8501_led_brightness_work(struct work_struct *work)
+static int lp8501_led_brightness(struct lp55xx_led *led)
{
- struct lp55xx_led *led = container_of(work, struct lp55xx_led,
- brightness_work);
struct lp55xx_chip *chip = led->chip;
+ int ret;
mutex_lock(&chip->lock);
- lp55xx_write(chip, LP8501_REG_LED_PWM_BASE + led->chan_nr,
+ ret = lp55xx_write(chip, LP8501_REG_LED_PWM_BASE + led->chan_nr,
led->brightness);
mutex_unlock(&chip->lock);
+
+ return ret;
}
/* Chip specific configurations */
@@ -296,7 +297,7 @@ static struct lp55xx_device_config lp8501_cfg = {
},
.max_channel = LP8501_MAX_LEDS,
.post_init_device = lp8501_post_init_device,
- .brightness_work_fn = lp8501_led_brightness_work,
+ .brightness_fn = lp8501_led_brightness,
.set_led_current = lp8501_set_led_current,
.firmware_cb = lp8501_firmware_loaded,
.run_engine = lp8501_run_engine,
diff --git a/drivers/leds/leds-lp8788.c b/drivers/leds/leds-lp8788.c
index 3409f03c1fa8..0eee38fc0565 100644
--- a/drivers/leds/leds-lp8788.c
+++ b/drivers/leds/leds-lp8788.c
@@ -26,10 +26,8 @@
struct lp8788_led {
struct lp8788 *lp;
struct mutex lock;
- struct work_struct work;
struct led_classdev led_dev;
enum lp8788_isink_number isink_num;
- enum led_brightness brightness;
int on;
};
@@ -76,24 +74,29 @@ static int lp8788_led_init_device(struct lp8788_led *led,
return lp8788_update_bits(led->lp, addr, mask, val);
}
-static void lp8788_led_enable(struct lp8788_led *led,
+static int lp8788_led_enable(struct lp8788_led *led,
enum lp8788_isink_number num, int on)
{
+ int ret;
+
u8 mask = 1 << num;
u8 val = on << num;
- if (lp8788_update_bits(led->lp, LP8788_ISINK_CTRL, mask, val))
- return;
+ ret = lp8788_update_bits(led->lp, LP8788_ISINK_CTRL, mask, val);
+ if (ret == 0)
+ led->on = on;
- led->on = on;
+ return ret;
}
-static void lp8788_led_work(struct work_struct *work)
+static int lp8788_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness val)
{
- struct lp8788_led *led = container_of(work, struct lp8788_led, work);
+ struct lp8788_led *led =
+ container_of(led_cdev, struct lp8788_led, led_dev);
+
enum lp8788_isink_number num = led->isink_num;
- int enable;
- u8 val = led->brightness;
+ int enable, ret;
mutex_lock(&led->lock);
@@ -101,28 +104,21 @@ static void lp8788_led_work(struct work_struct *work)
case LP8788_ISINK_1:
case LP8788_ISINK_2:
case LP8788_ISINK_3:
- lp8788_write_byte(led->lp, lp8788_pwm_addr[num], val);
+ ret = lp8788_write_byte(led->lp, lp8788_pwm_addr[num], val);
+ if (ret < 0)
+ goto unlock;
break;
default:
mutex_unlock(&led->lock);
- return;
+ return -EINVAL;
}
enable = (val > 0) ? 1 : 0;
if (enable != led->on)
- lp8788_led_enable(led, num, enable);
-
+ ret = lp8788_led_enable(led, num, enable);
+unlock:
mutex_unlock(&led->lock);
-}
-
-static void lp8788_brightness_set(struct led_classdev *led_cdev,
- enum led_brightness brt_val)
-{
- struct lp8788_led *led =
- container_of(led_cdev, struct lp8788_led, led_dev);
-
- led->brightness = brt_val;
- schedule_work(&led->work);
+ return ret;
}
static int lp8788_led_probe(struct platform_device *pdev)
@@ -139,7 +135,7 @@ static int lp8788_led_probe(struct platform_device *pdev)
led->lp = lp;
led->led_dev.max_brightness = MAX_BRIGHTNESS;
- led->led_dev.brightness_set = lp8788_brightness_set;
+ led->led_dev.brightness_set_blocking = lp8788_brightness_set;
led_pdata = lp->pdata ? lp->pdata->led_pdata : NULL;
@@ -149,7 +145,6 @@ static int lp8788_led_probe(struct platform_device *pdev)
led->led_dev.name = led_pdata->name;
mutex_init(&led->lock);
- INIT_WORK(&led->work, lp8788_led_work);
platform_set_drvdata(pdev, led);
@@ -173,7 +168,6 @@ static int lp8788_led_remove(struct platform_device *pdev)
struct lp8788_led *led = platform_get_drvdata(pdev);
led_classdev_unregister(&led->led_dev);
- flush_work(&led->work);
return 0;
}
diff --git a/drivers/leds/leds-lp8860.c b/drivers/leds/leds-lp8860.c
index 79f084354e67..3e70775a2d54 100644
--- a/drivers/leds/leds-lp8860.c
+++ b/drivers/leds/leds-lp8860.c
@@ -91,26 +91,22 @@
/**
* struct lp8860_led -
* @lock - Lock for reading/writing the device
- * @work - Work item used to off load the brightness register writes
* @client - Pointer to the I2C client
* @led_dev - led class device pointer
* @regmap - Devices register map
* @eeprom_regmap - EEPROM register map
* @enable_gpio - VDDIO/EN gpio to enable communication interface
* @regulator - LED supply regulator pointer
- * @brightness - Current brightness value requested
* @label - LED label
**/
struct lp8860_led {
struct mutex lock;
- struct work_struct work;
struct i2c_client *client;
struct led_classdev led_dev;
struct regmap *regmap;
struct regmap *eeprom_regmap;
struct gpio_desc *enable_gpio;
struct regulator *regulator;
- enum led_brightness brightness;
const char *label;
};
@@ -212,11 +208,13 @@ out:
return ret;
}
-static void lp8860_led_brightness_work(struct work_struct *work)
+static int lp8860_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness brt_val)
{
- struct lp8860_led *led = container_of(work, struct lp8860_led, work);
+ struct lp8860_led *led =
+ container_of(led_cdev, struct lp8860_led, led_dev);
+ int disp_brightness = brt_val * 255;
int ret;
- int disp_brightness = led->brightness * 255;
mutex_lock(&led->lock);
@@ -241,16 +239,7 @@ static void lp8860_led_brightness_work(struct work_struct *work)
}
out:
mutex_unlock(&led->lock);
-}
-
-static void lp8860_brightness_set(struct led_classdev *led_cdev,
- enum led_brightness brt_val)
-{
- struct lp8860_led *led =
- container_of(led_cdev, struct lp8860_led, led_dev);
-
- led->brightness = brt_val;
- schedule_work(&led->work);
+ return ret;
}
static int lp8860_init(struct lp8860_led *led)
@@ -406,10 +395,9 @@ static int lp8860_probe(struct i2c_client *client,
led->client = client;
led->led_dev.name = led->label;
led->led_dev.max_brightness = LED_FULL;
- led->led_dev.brightness_set = lp8860_brightness_set;
+ led->led_dev.brightness_set_blocking = lp8860_brightness_set;
mutex_init(&led->lock);
- INIT_WORK(&led->work, lp8860_led_brightness_work);
i2c_set_clientdata(client, led);
@@ -448,7 +436,6 @@ static int lp8860_remove(struct i2c_client *client)
int ret;
led_classdev_unregister(&led->led_dev);
- cancel_work_sync(&led->work);
if (led->enable_gpio)
gpiod_direction_output(led->enable_gpio, 0);
diff --git a/drivers/leds/leds-lt3593.c b/drivers/leds/leds-lt3593.c
index 9f41124765cc..a7ff510cbdd0 100644
--- a/drivers/leds/leds-lt3593.c
+++ b/drivers/leds/leds-lt3593.c
@@ -19,7 +19,6 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
-#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/slab.h>
@@ -28,15 +27,14 @@
struct lt3593_led_data {
struct led_classdev cdev;
unsigned gpio;
- struct work_struct work;
- u8 new_level;
};
-static void lt3593_led_work(struct work_struct *work)
+static int lt3593_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
{
- int pulses;
struct lt3593_led_data *led_dat =
- container_of(work, struct lt3593_led_data, work);
+ container_of(led_cdev, struct lt3593_led_data, cdev);
+ int pulses;
/*
* The LT3593 resets its internal current level register to the maximum
@@ -47,18 +45,18 @@ static void lt3593_led_work(struct work_struct *work)
* applied is to the output driver.
*/
- if (led_dat->new_level == 0) {
+ if (value == 0) {
gpio_set_value_cansleep(led_dat->gpio, 0);
- return;
+ return 0;
}
- pulses = 32 - (led_dat->new_level * 32) / 255;
+ pulses = 32 - (value * 32) / 255;
if (pulses == 0) {
gpio_set_value_cansleep(led_dat->gpio, 0);
mdelay(1);
gpio_set_value_cansleep(led_dat->gpio, 1);
- return;
+ return 0;
}
gpio_set_value_cansleep(led_dat->gpio, 1);
@@ -69,16 +67,8 @@ static void lt3593_led_work(struct work_struct *work)
gpio_set_value_cansleep(led_dat->gpio, 1);
udelay(1);
}
-}
-static void lt3593_led_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- struct lt3593_led_data *led_dat =
- container_of(led_cdev, struct lt3593_led_data, cdev);
-
- led_dat->new_level = value;
- schedule_work(&led_dat->work);
+ return 0;
}
static int create_lt3593_led(const struct gpio_led *template,
@@ -97,7 +87,7 @@ static int create_lt3593_led(const struct gpio_led *template,
led_dat->cdev.default_trigger = template->default_trigger;
led_dat->gpio = template->gpio;
- led_dat->cdev.brightness_set = lt3593_led_set;
+ led_dat->cdev.brightness_set_blocking = lt3593_led_set;
state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
@@ -111,8 +101,6 @@ static int create_lt3593_led(const struct gpio_led *template,
if (ret < 0)
return ret;
- INIT_WORK(&led_dat->work, lt3593_led_work);
-
ret = led_classdev_register(parent, &led_dat->cdev);
if (ret < 0)
return ret;
@@ -129,7 +117,6 @@ static void delete_lt3593_led(struct lt3593_led_data *led)
return;
led_classdev_unregister(&led->cdev);
- cancel_work_sync(&led->work);
}
static int lt3593_led_probe(struct platform_device *pdev)
diff --git a/drivers/leds/leds-max77693.c b/drivers/leds/leds-max77693.c
index afbb1409b2e2..1eb58ef6aefe 100644
--- a/drivers/leds/leds-max77693.c
+++ b/drivers/leds/leds-max77693.c
@@ -20,7 +20,6 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
-#include <linux/workqueue.h>
#include <media/v4l2-flash-led-class.h>
#define MODE_OFF 0
@@ -62,8 +61,6 @@ struct max77693_sub_led {
int fled_id;
/* corresponding LED Flash class device */
struct led_classdev_flash fled_cdev;
- /* assures led-triggers compatibility */
- struct work_struct work_brightness_set;
/* V4L2 Flash device */
struct v4l2_flash *v4l2_flash;
@@ -463,10 +460,14 @@ static int max77693_setup(struct max77693_led_device *led,
return max77693_set_mode_reg(led, MODE_OFF);
}
-static int __max77693_led_brightness_set(struct max77693_led_device *led,
- int fled_id, enum led_brightness value)
+/* LED subsystem callbacks */
+static int max77693_led_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
{
- int ret;
+ struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
+ struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
+ struct max77693_led_device *led = sub_led_to_led(sub_led);
+ int fled_id = sub_led->fled_id, ret;
mutex_lock(&led->lock);
@@ -494,43 +495,8 @@ static int __max77693_led_brightness_set(struct max77693_led_device *led,
ret);
unlock:
mutex_unlock(&led->lock);
- return ret;
-}
-
-static void max77693_led_brightness_set_work(
- struct work_struct *work)
-{
- struct max77693_sub_led *sub_led =
- container_of(work, struct max77693_sub_led,
- work_brightness_set);
- struct max77693_led_device *led = sub_led_to_led(sub_led);
-
- __max77693_led_brightness_set(led, sub_led->fled_id,
- sub_led->torch_brightness);
-}
-
-/* LED subsystem callbacks */
-
-static int max77693_led_brightness_set_sync(
- struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
- struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
- struct max77693_led_device *led = sub_led_to_led(sub_led);
-
- return __max77693_led_brightness_set(led, sub_led->fled_id, value);
-}
-static void max77693_led_brightness_set(
- struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- struct led_classdev_flash *fled_cdev = lcdev_to_flcdev(led_cdev);
- struct max77693_sub_led *sub_led = flcdev_to_sub_led(fled_cdev);
-
- sub_led->torch_brightness = value;
- schedule_work(&sub_led->work_brightness_set);
+ return ret;
}
static int max77693_led_flash_brightness_set(
@@ -682,6 +648,7 @@ static int max77693_led_parse_dt(struct max77693_led_device *led,
if (sub_nodes[fled_id]) {
dev_err(dev,
"Conflicting \"led-sources\" DT properties\n");
+ of_node_put(child_node);
return -EINVAL;
}
@@ -931,16 +898,13 @@ static void max77693_init_fled_cdev(struct max77693_sub_led *sub_led,
led_cdev->name = led_cfg->label[fled_id];
- led_cdev->brightness_set = max77693_led_brightness_set;
- led_cdev->brightness_set_sync = max77693_led_brightness_set_sync;
+ led_cdev->brightness_set_blocking = max77693_led_brightness_set;
led_cdev->max_brightness = (led->iout_joint ?
led_cfg->iout_torch_max[FLED1] +
led_cfg->iout_torch_max[FLED2] :
led_cfg->iout_torch_max[fled_id]) /
TORCH_IOUT_STEP;
led_cdev->flags |= LED_DEV_CAP_FLASH;
- INIT_WORK(&sub_led->work_brightness_set,
- max77693_led_brightness_set_work);
max77693_init_flash_settings(sub_led, led_cfg);
@@ -1062,13 +1026,11 @@ static int max77693_led_remove(struct platform_device *pdev)
if (led->iout_joint || max77693_fled_used(led, FLED1)) {
v4l2_flash_release(sub_leds[FLED1].v4l2_flash);
led_classdev_flash_unregister(&sub_leds[FLED1].fled_cdev);
- cancel_work_sync(&sub_leds[FLED1].work_brightness_set);
}
if (!led->iout_joint && max77693_fled_used(led, FLED2)) {
v4l2_flash_release(sub_leds[FLED2].v4l2_flash);
led_classdev_flash_unregister(&sub_leds[FLED2].fled_cdev);
- cancel_work_sync(&sub_leds[FLED2].work_brightness_set);
}
mutex_destroy(&led->lock);
diff --git a/drivers/leds/leds-max8997.c b/drivers/leds/leds-max8997.c
index c592aa5662bb..01b459069358 100644
--- a/drivers/leds/leds-max8997.c
+++ b/drivers/leds/leds-max8997.c
@@ -13,7 +13,6 @@
#include <linux/module.h>
#include <linux/err.h>
#include <linux/slab.h>
-#include <linux/workqueue.h>
#include <linux/leds.h>
#include <linux/mfd/max8997.h>
#include <linux/mfd/max8997-private.h>
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c
index e2b847fe22a1..a2e4c1792e17 100644
--- a/drivers/leds/leds-mc13783.c
+++ b/drivers/leds/leds-mc13783.c
@@ -20,7 +20,6 @@
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/of.h>
-#include <linux/workqueue.h>
#include <linux/mfd/mc13xxx.h>
struct mc13xxx_led_devtype {
@@ -32,8 +31,6 @@ struct mc13xxx_led_devtype {
struct mc13xxx_led {
struct led_classdev cdev;
- struct work_struct work;
- enum led_brightness new_brightness;
int id;
struct mc13xxx_leds *leds;
};
@@ -55,9 +52,11 @@ static unsigned int mc13xxx_max_brightness(int id)
return 0x3f;
}
-static void mc13xxx_led_work(struct work_struct *work)
+static int mc13xxx_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
{
- struct mc13xxx_led *led = container_of(work, struct mc13xxx_led, work);
+ struct mc13xxx_led *led =
+ container_of(led_cdev, struct mc13xxx_led, cdev);
struct mc13xxx_leds *leds = led->leds;
unsigned int reg, bank, off, shift;
@@ -105,19 +104,9 @@ static void mc13xxx_led_work(struct work_struct *work)
BUG();
}
- mc13xxx_reg_rmw(leds->master, leds->devtype->ledctrl_base + reg,
+ return mc13xxx_reg_rmw(leds->master, leds->devtype->ledctrl_base + reg,
mc13xxx_max_brightness(led->id) << shift,
- led->new_brightness << shift);
-}
-
-static void mc13xxx_led_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- struct mc13xxx_led *led =
- container_of(led_cdev, struct mc13xxx_led, cdev);
-
- led->new_brightness = value;
- schedule_work(&led->work);
+ value << shift);
}
#ifdef CONFIG_OF
@@ -257,11 +246,9 @@ static int __init mc13xxx_led_probe(struct platform_device *pdev)
leds->led[i].cdev.name = name;
leds->led[i].cdev.default_trigger = trig;
leds->led[i].cdev.flags = LED_CORE_SUSPENDRESUME;
- leds->led[i].cdev.brightness_set = mc13xxx_led_set;
+ leds->led[i].cdev.brightness_set_blocking = mc13xxx_led_set;
leds->led[i].cdev.max_brightness = mc13xxx_max_brightness(id);
- INIT_WORK(&leds->led[i].work, mc13xxx_led_work);
-
ret = led_classdev_register(dev->parent, &leds->led[i].cdev);
if (ret) {
dev_err(dev, "Failed to register LED %i\n", id);
@@ -270,10 +257,8 @@ static int __init mc13xxx_led_probe(struct platform_device *pdev)
}
if (ret)
- while (--i >= 0) {
+ while (--i >= 0)
led_classdev_unregister(&leds->led[i].cdev);
- cancel_work_sync(&leds->led[i].work);
- }
return ret;
}
@@ -283,10 +268,8 @@ static int mc13xxx_led_remove(struct platform_device *pdev)
struct mc13xxx_leds *leds = platform_get_drvdata(pdev);
int i;
- for (i = 0; i < leds->num_leds; i++) {
+ for (i = 0; i < leds->num_leds; i++)
led_classdev_unregister(&leds->led[i].cdev);
- cancel_work_sync(&leds->led[i].work);
- }
return 0;
}
diff --git a/drivers/leds/leds-ns2.c b/drivers/leds/leds-ns2.c
index a95a61220169..506b75b190e7 100644
--- a/drivers/leds/leds-ns2.c
+++ b/drivers/leds/leds-ns2.c
@@ -45,24 +45,12 @@ struct ns2_led_data {
unsigned cmd;
unsigned slow;
bool can_sleep;
- int mode_index;
unsigned char sata; /* True when SATA mode active. */
rwlock_t rw_lock; /* Lock GPIOs. */
- struct work_struct work;
int num_modes;
struct ns2_led_modval *modval;
};
-static void ns2_led_work(struct work_struct *work)
-{
- struct ns2_led_data *led_dat =
- container_of(work, struct ns2_led_data, work);
- int i = led_dat->mode_index;
-
- gpio_set_value_cansleep(led_dat->cmd, led_dat->modval[i].cmd_level);
- gpio_set_value_cansleep(led_dat->slow, led_dat->modval[i].slow_level);
-}
-
static int ns2_led_get_mode(struct ns2_led_data *led_dat,
enum ns2_led_modes *mode)
{
@@ -112,8 +100,8 @@ static void ns2_led_set_mode(struct ns2_led_data *led_dat,
goto exit_unlock;
}
- led_dat->mode_index = i;
- schedule_work(&led_dat->work);
+ gpio_set_value_cansleep(led_dat->cmd, led_dat->modval[i].cmd_level);
+ gpio_set_value_cansleep(led_dat->slow, led_dat->modval[i].slow_level);
exit_unlock:
write_unlock_irqrestore(&led_dat->rw_lock, flags);
@@ -136,6 +124,13 @@ static void ns2_led_set(struct led_classdev *led_cdev,
ns2_led_set_mode(led_dat, mode);
}
+static int ns2_led_set_blocking(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ ns2_led_set(led_cdev, value);
+ return 0;
+}
+
static ssize_t ns2_led_sata_store(struct device *dev,
struct device_attribute *attr,
const char *buff, size_t count)
@@ -219,13 +214,16 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
led_dat->cdev.name = template->name;
led_dat->cdev.default_trigger = template->default_trigger;
led_dat->cdev.blink_set = NULL;
- led_dat->cdev.brightness_set = ns2_led_set;
led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
led_dat->cdev.groups = ns2_led_groups;
led_dat->cmd = template->cmd;
led_dat->slow = template->slow;
led_dat->can_sleep = gpio_cansleep(led_dat->cmd) |
gpio_cansleep(led_dat->slow);
+ if (led_dat->can_sleep)
+ led_dat->cdev.brightness_set_blocking = ns2_led_set_blocking;
+ else
+ led_dat->cdev.brightness_set = ns2_led_set;
led_dat->modval = template->modval;
led_dat->num_modes = template->num_modes;
@@ -238,8 +236,6 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
led_dat->cdev.brightness =
(mode == NS_V2_LED_OFF) ? LED_OFF : LED_FULL;
- INIT_WORK(&led_dat->work, ns2_led_work);
-
ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
if (ret < 0)
return ret;
@@ -250,7 +246,6 @@ create_ns2_led(struct platform_device *pdev, struct ns2_led_data *led_dat,
static void delete_ns2_led(struct ns2_led_data *led_dat)
{
led_classdev_unregister(&led_dat->cdev);
- cancel_work_sync(&led_dat->work);
}
#ifdef CONFIG_OF_GPIO
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c
index 5a6363d161a2..17c63ec9fb9e 100644
--- a/drivers/leds/leds-pca9532.c
+++ b/drivers/leds/leds-pca9532.c
@@ -158,7 +158,7 @@ static void pca9532_setled(struct pca9532_led *led)
mutex_unlock(&data->update_lock);
}
-static void pca9532_set_brightness(struct led_classdev *led_cdev,
+static int pca9532_set_brightness(struct led_classdev *led_cdev,
enum led_brightness value)
{
int err = 0;
@@ -172,9 +172,12 @@ static void pca9532_set_brightness(struct led_classdev *led_cdev,
led->state = PCA9532_PWM0; /* Thecus: hardcode one pwm */
err = pca9532_calcpwm(led->client, 0, 0, value);
if (err)
- return; /* XXX: led api doesn't allow error code? */
+ return err;
}
- schedule_work(&led->work);
+ if (led->state == PCA9532_PWM0)
+ pca9532_setpwm(led->client, 0);
+ pca9532_setled(led);
+ return err;
}
static int pca9532_set_blink(struct led_classdev *led_cdev,
@@ -198,7 +201,10 @@ static int pca9532_set_blink(struct led_classdev *led_cdev,
err = pca9532_calcpwm(client, 0, psc, led_cdev->brightness);
if (err)
return err;
- schedule_work(&led->work);
+ if (led->state == PCA9532_PWM0)
+ pca9532_setpwm(led->client, 0);
+ pca9532_setled(led);
+
return 0;
}
@@ -233,15 +239,6 @@ static void pca9532_input_work(struct work_struct *work)
mutex_unlock(&data->update_lock);
}
-static void pca9532_led_work(struct work_struct *work)
-{
- struct pca9532_led *led;
- led = container_of(work, struct pca9532_led, work);
- if (led->state == PCA9532_PWM0)
- pca9532_setpwm(led->client, 0);
- pca9532_setled(led);
-}
-
#ifdef CONFIG_LEDS_PCA9532_GPIO
static int pca9532_gpio_request_pin(struct gpio_chip *gc, unsigned offset)
{
@@ -307,7 +304,6 @@ static int pca9532_destroy_devices(struct pca9532_data *data, int n_devs)
break;
case PCA9532_TYPE_LED:
led_classdev_unregister(&data->leds[i].ldev);
- cancel_work_sync(&data->leds[i].work);
break;
case PCA9532_TYPE_N2100_BEEP:
if (data->idev != NULL) {
@@ -359,9 +355,9 @@ static int pca9532_configure(struct i2c_client *client,
led->name = pled->name;
led->ldev.name = led->name;
led->ldev.brightness = LED_OFF;
- led->ldev.brightness_set = pca9532_set_brightness;
+ led->ldev.brightness_set_blocking =
+ pca9532_set_brightness;
led->ldev.blink_set = pca9532_set_blink;
- INIT_WORK(&led->work, pca9532_led_work);
err = led_classdev_register(&client->dev, &led->ldev);
if (err < 0) {
dev_err(&client->dev,
diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c
index b775e1efecd3..840401ae9a4e 100644
--- a/drivers/leds/leds-pca955x.c
+++ b/drivers/leds/leds-pca955x.c
@@ -47,7 +47,6 @@
#include <linux/leds.h>
#include <linux/err.h>
#include <linux/i2c.h>
-#include <linux/workqueue.h>
#include <linux/slab.h>
/* LED select registers determine the source that drives LED outputs */
@@ -110,8 +109,6 @@ struct pca955x {
struct pca955x_led {
struct pca955x *pca955x;
- struct work_struct work;
- enum led_brightness brightness;
struct led_classdev led_cdev;
int led_num; /* 0 .. 15 potentially */
char name[32];
@@ -193,7 +190,8 @@ static u8 pca955x_read_ls(struct i2c_client *client, int n)
pca95xx_num_input_regs(pca955x->chipdef->bits) + 4 + n);
}
-static void pca955x_led_work(struct work_struct *work)
+static int pca955x_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
{
struct pca955x_led *pca955x_led;
struct pca955x *pca955x;
@@ -201,7 +199,7 @@ static void pca955x_led_work(struct work_struct *work)
int chip_ls; /* which LSx to use (0-3 potentially) */
int ls_led; /* which set of bits within LSx to use (0-3) */
- pca955x_led = container_of(work, struct pca955x_led, work);
+ pca955x_led = container_of(led_cdev, struct pca955x_led, led_cdev);
pca955x = pca955x_led->pca955x;
chip_ls = pca955x_led->led_num / 4;
@@ -211,7 +209,7 @@ static void pca955x_led_work(struct work_struct *work)
ls = pca955x_read_ls(pca955x->client, chip_ls);
- switch (pca955x_led->brightness) {
+ switch (value) {
case LED_FULL:
ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_LED_ON);
break;
@@ -230,7 +228,7 @@ static void pca955x_led_work(struct work_struct *work)
* just turning off for all other values.
*/
pca955x_write_pwm(pca955x->client, 1,
- 255 - pca955x_led->brightness);
+ 255 - value);
ls = pca955x_ledsel(ls, ls_led, PCA955X_LS_BLINK1);
break;
}
@@ -238,21 +236,8 @@ static void pca955x_led_work(struct work_struct *work)
pca955x_write_ls(pca955x->client, chip_ls, ls);
mutex_unlock(&pca955x->lock);
-}
-
-static void pca955x_led_set(struct led_classdev *led_cdev, enum led_brightness value)
-{
- struct pca955x_led *pca955x;
-
- pca955x = container_of(led_cdev, struct pca955x_led, led_cdev);
-
- pca955x->brightness = value;
- /*
- * Must use workqueue for the actual I/O since I2C operations
- * can sleep.
- */
- schedule_work(&pca955x->work);
+ return 0;
}
static int pca955x_probe(struct i2c_client *client,
@@ -328,9 +313,7 @@ static int pca955x_probe(struct i2c_client *client,
}
pca955x_led->led_cdev.name = pca955x_led->name;
- pca955x_led->led_cdev.brightness_set = pca955x_led_set;
-
- INIT_WORK(&pca955x_led->work, pca955x_led_work);
+ pca955x_led->led_cdev.brightness_set_blocking = pca955x_led_set;
err = led_classdev_register(&client->dev,
&pca955x_led->led_cdev);
@@ -355,10 +338,8 @@ static int pca955x_probe(struct i2c_client *client,
return 0;
exit:
- while (i--) {
+ while (i--)
led_classdev_unregister(&pca955x->leds[i].led_cdev);
- cancel_work_sync(&pca955x->leds[i].work);
- }
return err;
}
@@ -368,10 +349,8 @@ static int pca955x_remove(struct i2c_client *client)
struct pca955x *pca955x = i2c_get_clientdata(client);
int i;
- for (i = 0; i < pca955x->chipdef->bits; i++) {
+ for (i = 0; i < pca955x->chipdef->bits; i++)
led_classdev_unregister(&pca955x->leds[i].led_cdev);
- cancel_work_sync(&pca955x->leds[i].work);
- }
return 0;
}
diff --git a/drivers/leds/leds-pca963x.c b/drivers/leds/leds-pca963x.c
index 41f269fe0920..407eba11e187 100644
--- a/drivers/leds/leds-pca963x.c
+++ b/drivers/leds/leds-pca963x.c
@@ -32,7 +32,6 @@
#include <linux/leds.h>
#include <linux/err.h>
#include <linux/i2c.h>
-#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/platform_data/leds-pca963x.h>
@@ -96,11 +95,6 @@ static const struct i2c_device_id pca963x_id[] = {
};
MODULE_DEVICE_TABLE(i2c, pca963x_id);
-enum pca963x_cmd {
- BRIGHTNESS_SET,
- BLINK_SET,
-};
-
struct pca963x_led;
struct pca963x {
@@ -112,47 +106,52 @@ struct pca963x {
struct pca963x_led {
struct pca963x *chip;
- struct work_struct work;
- enum led_brightness brightness;
struct led_classdev led_cdev;
int led_num; /* 0 .. 15 potentially */
- enum pca963x_cmd cmd;
char name[32];
u8 gdc;
u8 gfrq;
};
-static void pca963x_brightness_work(struct pca963x_led *pca963x)
+static int pca963x_brightness(struct pca963x_led *pca963x,
+ enum led_brightness brightness)
{
u8 ledout_addr = pca963x->chip->chipdef->ledout_base
+ (pca963x->led_num / 4);
u8 ledout;
int shift = 2 * (pca963x->led_num % 4);
u8 mask = 0x3 << shift;
+ int ret;
mutex_lock(&pca963x->chip->mutex);
ledout = i2c_smbus_read_byte_data(pca963x->chip->client, ledout_addr);
- switch (pca963x->brightness) {
+ switch (brightness) {
case LED_FULL:
- i2c_smbus_write_byte_data(pca963x->chip->client, ledout_addr,
+ ret = i2c_smbus_write_byte_data(pca963x->chip->client,
+ ledout_addr,
(ledout & ~mask) | (PCA963X_LED_ON << shift));
break;
case LED_OFF:
- i2c_smbus_write_byte_data(pca963x->chip->client, ledout_addr,
- ledout & ~mask);
+ ret = i2c_smbus_write_byte_data(pca963x->chip->client,
+ ledout_addr, ledout & ~mask);
break;
default:
- i2c_smbus_write_byte_data(pca963x->chip->client,
+ ret = i2c_smbus_write_byte_data(pca963x->chip->client,
PCA963X_PWM_BASE + pca963x->led_num,
- pca963x->brightness);
- i2c_smbus_write_byte_data(pca963x->chip->client, ledout_addr,
+ brightness);
+ if (ret < 0)
+ goto unlock;
+ ret = i2c_smbus_write_byte_data(pca963x->chip->client,
+ ledout_addr,
(ledout & ~mask) | (PCA963X_LED_PWM << shift));
break;
}
+unlock:
mutex_unlock(&pca963x->chip->mutex);
+ return ret;
}
-static void pca963x_blink_work(struct pca963x_led *pca963x)
+static void pca963x_blink(struct pca963x_led *pca963x)
{
u8 ledout_addr = pca963x->chip->chipdef->ledout_base +
(pca963x->led_num / 4);
@@ -180,36 +179,14 @@ static void pca963x_blink_work(struct pca963x_led *pca963x)
mutex_unlock(&pca963x->chip->mutex);
}
-static void pca963x_work(struct work_struct *work)
-{
- struct pca963x_led *pca963x = container_of(work,
- struct pca963x_led, work);
-
- switch (pca963x->cmd) {
- case BRIGHTNESS_SET:
- pca963x_brightness_work(pca963x);
- break;
- case BLINK_SET:
- pca963x_blink_work(pca963x);
- break;
- }
-}
-
-static void pca963x_led_set(struct led_classdev *led_cdev,
+static int pca963x_led_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct pca963x_led *pca963x;
pca963x = container_of(led_cdev, struct pca963x_led, led_cdev);
- pca963x->cmd = BRIGHTNESS_SET;
- pca963x->brightness = value;
-
- /*
- * Must use workqueue for the actual I/O since I2C operations
- * can sleep.
- */
- schedule_work(&pca963x->work);
+ return pca963x_brightness(pca963x, value);
}
static int pca963x_blink_set(struct led_classdev *led_cdev,
@@ -254,15 +231,10 @@ static int pca963x_blink_set(struct led_classdev *led_cdev,
*/
gfrq = (period * 24 / 1000) - 1;
- pca963x->cmd = BLINK_SET;
pca963x->gdc = gdc;
pca963x->gfrq = gfrq;
- /*
- * Must use workqueue for the actual I/O since I2C operations
- * can sleep.
- */
- schedule_work(&pca963x->work);
+ pca963x_blink(pca963x);
*delay_on = time_on;
*delay_off = time_off;
@@ -409,13 +381,11 @@ static int pca963x_probe(struct i2c_client *client,
client->addr, i);
pca963x[i].led_cdev.name = pca963x[i].name;
- pca963x[i].led_cdev.brightness_set = pca963x_led_set;
+ pca963x[i].led_cdev.brightness_set_blocking = pca963x_led_set;
if (pdata && pdata->blink_type == PCA963X_HW_BLINK)
pca963x[i].led_cdev.blink_set = pca963x_blink_set;
- INIT_WORK(&pca963x[i].work, pca963x_work);
-
err = led_classdev_register(&client->dev, &pca963x[i].led_cdev);
if (err < 0)
goto exit;
@@ -435,10 +405,8 @@ static int pca963x_probe(struct i2c_client *client,
return 0;
exit:
- while (i--) {
+ while (i--)
led_classdev_unregister(&pca963x[i].led_cdev);
- cancel_work_sync(&pca963x[i].work);
- }
return err;
}
@@ -448,10 +416,8 @@ static int pca963x_remove(struct i2c_client *client)
struct pca963x *pca963x = i2c_get_clientdata(client);
int i;
- for (i = 0; i < pca963x->chipdef->n_leds; i++) {
+ for (i = 0; i < pca963x->chipdef->n_leds; i++)
led_classdev_unregister(&pca963x->leds[i].led_cdev);
- cancel_work_sync(&pca963x->leds[i].work);
- }
return 0;
}
diff --git a/drivers/leds/leds-powernv.c b/drivers/leds/leds-powernv.c
index 1e75e1fe9b72..dfb8bd390125 100644
--- a/drivers/leds/leds-powernv.c
+++ b/drivers/leds/leds-powernv.c
@@ -77,7 +77,7 @@ static int powernv_get_led_type(const char *led_type_desc)
* This function is called from work queue task context when ever it gets
* scheduled. This function can sleep at opal_async_wait_response call.
*/
-static void powernv_led_set(struct powernv_led_data *powernv_led,
+static int powernv_led_set(struct powernv_led_data *powernv_led,
enum led_brightness value)
{
int rc, token;
@@ -99,7 +99,7 @@ static void powernv_led_set(struct powernv_led_data *powernv_led,
if (token != -ERESTARTSYS)
dev_err(dev, "%s: Couldn't get OPAL async token\n",
__func__);
- return;
+ return token;
}
rc = opal_leds_set_ind(token, powernv_led->loc_code,
@@ -125,6 +125,7 @@ static void powernv_led_set(struct powernv_led_data *powernv_led,
out_token:
opal_async_release_token(token);
+ return rc;
}
/*
@@ -173,20 +174,23 @@ static enum led_brightness powernv_led_get(struct powernv_led_data *powernv_led)
* LED classdev 'brightness_get' function. This schedules work
* to update LED state.
*/
-static void powernv_brightness_set(struct led_classdev *led_cdev,
+static int powernv_brightness_set(struct led_classdev *led_cdev,
enum led_brightness value)
{
struct powernv_led_data *powernv_led =
container_of(led_cdev, struct powernv_led_data, cdev);
struct powernv_led_common *powernv_led_common = powernv_led->common;
+ int rc;
/* Do not modify LED in unload path */
if (powernv_led_common->led_disabled)
- return;
+ return 0;
mutex_lock(&powernv_led_common->lock);
- powernv_led_set(powernv_led, value);
+ rc = powernv_led_set(powernv_led, value);
mutex_unlock(&powernv_led_common->lock);
+
+ return rc;
}
/* LED classdev 'brightness_get' function */
@@ -227,7 +231,7 @@ static int powernv_led_create(struct device *dev,
return -ENOMEM;
}
- powernv_led->cdev.brightness_set = powernv_brightness_set;
+ powernv_led->cdev.brightness_set_blocking = powernv_brightness_set;
powernv_led->cdev.brightness_get = powernv_brightness_get;
powernv_led->cdev.brightness = LED_OFF;
powernv_led->cdev.max_brightness = LED_FULL;
@@ -256,8 +260,6 @@ static int powernv_led_classdev(struct platform_device *pdev,
for_each_child_of_node(led_node, np) {
p = of_find_property(np, "led-types", NULL);
- if (!p)
- continue;
while ((cur = of_prop_next_string(p, cur)) != NULL) {
powernv_led = devm_kzalloc(dev, sizeof(*powernv_led),
diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c
index 1d07e3e83d29..4783bacb2e9d 100644
--- a/drivers/leds/leds-pwm.c
+++ b/drivers/leds/leds-pwm.c
@@ -22,12 +22,10 @@
#include <linux/pwm.h>
#include <linux/leds_pwm.h>
#include <linux/slab.h>
-#include <linux/workqueue.h>
struct led_pwm_data {
struct led_classdev cdev;
struct pwm_device *pwm;
- struct work_struct work;
unsigned int active_low;
unsigned int period;
int duty;
@@ -51,14 +49,6 @@ static void __led_pwm_set(struct led_pwm_data *led_dat)
pwm_enable(led_dat->pwm);
}
-static void led_pwm_work(struct work_struct *work)
-{
- struct led_pwm_data *led_dat =
- container_of(work, struct led_pwm_data, work);
-
- __led_pwm_set(led_dat);
-}
-
static void led_pwm_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
@@ -75,10 +65,14 @@ static void led_pwm_set(struct led_classdev *led_cdev,
led_dat->duty = duty;
- if (led_dat->can_sleep)
- schedule_work(&led_dat->work);
- else
- __led_pwm_set(led_dat);
+ __led_pwm_set(led_dat);
+}
+
+static int led_pwm_set_blocking(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
+{
+ led_pwm_set(led_cdev, brightness);
+ return 0;
}
static inline size_t sizeof_pwm_leds_priv(int num_leds)
@@ -89,11 +83,8 @@ static inline size_t sizeof_pwm_leds_priv(int num_leds)
static void led_pwm_cleanup(struct led_pwm_priv *priv)
{
- while (priv->num_leds--) {
+ while (priv->num_leds--)
led_classdev_unregister(&priv->leds[priv->num_leds].cdev);
- if (priv->leds[priv->num_leds].can_sleep)
- cancel_work_sync(&priv->leds[priv->num_leds].work);
- }
}
static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
@@ -105,7 +96,6 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
led_data->active_low = led->active_low;
led_data->cdev.name = led->name;
led_data->cdev.default_trigger = led->default_trigger;
- led_data->cdev.brightness_set = led_pwm_set;
led_data->cdev.brightness = LED_OFF;
led_data->cdev.max_brightness = led->max_brightness;
led_data->cdev.flags = LED_CORE_SUSPENDRESUME;
@@ -122,8 +112,10 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
}
led_data->can_sleep = pwm_can_sleep(led_data->pwm);
- if (led_data->can_sleep)
- INIT_WORK(&led_data->work, led_pwm_work);
+ if (!led_data->can_sleep)
+ led_data->cdev.brightness_set = led_pwm_set;
+ else
+ led_data->cdev.brightness_set_blocking = led_pwm_set_blocking;
led_data->period = pwm_get_period(led_data->pwm);
if (!led_data->period && (led->pwm_period_ns > 0))
@@ -132,6 +124,7 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv,
ret = led_classdev_register(dev, &led_data->cdev);
if (ret == 0) {
priv->num_leds++;
+ led_pwm_set(&led_data->cdev, led_data->cdev.brightness);
} else {
dev_err(dev, "failed to register PWM led for %s: %d\n",
led->name, ret);
@@ -236,6 +229,6 @@ static struct platform_driver led_pwm_driver = {
module_platform_driver(led_pwm_driver);
MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
-MODULE_DESCRIPTION("PWM LED driver for PXA");
-MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("generic PWM LED driver");
+MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:leds-pwm");
diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c
index ffc21397a675..acf77ca47558 100644
--- a/drivers/leds/leds-regulator.c
+++ b/drivers/leds/leds-regulator.c
@@ -14,7 +14,6 @@
#include <linux/module.h>
#include <linux/err.h>
#include <linux/slab.h>
-#include <linux/workqueue.h>
#include <linux/leds.h>
#include <linux/leds-regulator.h>
#include <linux/platform_device.h>
@@ -25,10 +24,8 @@
struct regulator_led {
struct led_classdev cdev;
- enum led_brightness value;
int enabled;
struct mutex mutex;
- struct work_struct work;
struct regulator *vcc;
};
@@ -94,22 +91,24 @@ static void regulator_led_disable(struct regulator_led *led)
led->enabled = 0;
}
-static void regulator_led_set_value(struct regulator_led *led)
+static int regulator_led_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
{
+ struct regulator_led *led = to_regulator_led(led_cdev);
int voltage;
- int ret;
+ int ret = 0;
mutex_lock(&led->mutex);
- if (led->value == LED_OFF) {
+ if (value == LED_OFF) {
regulator_led_disable(led);
goto out;
}
if (led->cdev.max_brightness > 1) {
- voltage = led_regulator_get_voltage(led->vcc, led->value);
+ voltage = led_regulator_get_voltage(led->vcc, value);
dev_dbg(led->cdev.dev, "brightness: %d voltage: %d\n",
- led->value, voltage);
+ value, voltage);
ret = regulator_set_voltage(led->vcc, voltage, voltage);
if (ret != 0)
@@ -121,23 +120,7 @@ static void regulator_led_set_value(struct regulator_led *led)
out:
mutex_unlock(&led->mutex);
-}
-
-static void led_work(struct work_struct *work)
-{
- struct regulator_led *led;
-
- led = container_of(work, struct regulator_led, work);
- regulator_led_set_value(led);
-}
-
-static void regulator_led_brightness_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- struct regulator_led *led = to_regulator_led(led_cdev);
-
- led->value = value;
- schedule_work(&led->work);
+ return ret;
}
static int regulator_led_probe(struct platform_device *pdev)
@@ -169,9 +152,8 @@ static int regulator_led_probe(struct platform_device *pdev)
pdata->brightness);
return -EINVAL;
}
- led->value = pdata->brightness;
- led->cdev.brightness_set = regulator_led_brightness_set;
+ led->cdev.brightness_set_blocking = regulator_led_brightness_set;
led->cdev.name = pdata->name;
led->cdev.flags |= LED_CORE_SUSPENDRESUME;
led->vcc = vcc;
@@ -181,21 +163,18 @@ static int regulator_led_probe(struct platform_device *pdev)
led->enabled = 1;
mutex_init(&led->mutex);
- INIT_WORK(&led->work, led_work);
platform_set_drvdata(pdev, led);
ret = led_classdev_register(&pdev->dev, &led->cdev);
- if (ret < 0) {
- cancel_work_sync(&led->work);
+ if (ret < 0)
return ret;
- }
/* to expose the default value to userspace */
- led->cdev.brightness = led->value;
+ led->cdev.brightness = pdata->brightness;
/* Set the default led status */
- regulator_led_set_value(led);
+ regulator_led_brightness_set(&led->cdev, led->cdev.brightness);
return 0;
}
@@ -205,7 +184,6 @@ static int regulator_led_remove(struct platform_device *pdev)
struct regulator_led *led = platform_get_drvdata(pdev);
led_classdev_unregister(&led->cdev);
- cancel_work_sync(&led->work);
regulator_led_disable(led);
return 0;
}
diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c
index c2553c54f2cf..7c09db8bd4e8 100644
--- a/drivers/leds/leds-sunfire.c
+++ b/drivers/leds/leds-sunfire.c
@@ -234,28 +234,19 @@ static struct platform_driver sunfire_fhc_led_driver = {
},
};
+static struct platform_driver * const drivers[] = {
+ &sunfire_clockboard_led_driver,
+ &sunfire_fhc_led_driver,
+};
+
static int __init sunfire_leds_init(void)
{
- int err = platform_driver_register(&sunfire_clockboard_led_driver);
-
- if (err) {
- pr_err("Could not register clock board LED driver\n");
- return err;
- }
-
- err = platform_driver_register(&sunfire_fhc_led_driver);
- if (err) {
- pr_err("Could not register FHC LED driver\n");
- platform_driver_unregister(&sunfire_clockboard_led_driver);
- }
-
- return err;
+ return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
}
static void __exit sunfire_leds_exit(void)
{
- platform_driver_unregister(&sunfire_clockboard_led_driver);
- platform_driver_unregister(&sunfire_fhc_led_driver);
+ platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
}
module_init(sunfire_leds_init);
diff --git a/drivers/leds/leds-syscon.c b/drivers/leds/leds-syscon.c
index b88900d721e4..3be40f74f12a 100644
--- a/drivers/leds/leds-syscon.c
+++ b/drivers/leds/leds-syscon.c
@@ -20,7 +20,7 @@
* MA 02111-1307 USA
*/
#include <linux/io.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
@@ -139,29 +139,17 @@ static int syscon_led_probe(struct platform_device *pdev)
return 0;
}
-static int syscon_led_remove(struct platform_device *pdev)
-{
- struct syscon_led *sled = platform_get_drvdata(pdev);
-
- led_classdev_unregister(&sled->cdev);
- /* Turn it off */
- regmap_update_bits(sled->map, sled->offset, sled->mask, 0);
- return 0;
-}
-
static const struct of_device_id of_syscon_leds_match[] = {
{ .compatible = "register-bit-led", },
{},
};
-MODULE_DEVICE_TABLE(of, of_syscon_leds_match);
-
static struct platform_driver syscon_led_driver = {
.probe = syscon_led_probe,
- .remove = syscon_led_remove,
.driver = {
.name = "leds-syscon",
.of_match_table = of_syscon_leds_match,
+ .suppress_bind_attrs = true,
},
};
-module_platform_driver(syscon_led_driver);
+builtin_platform_driver(syscon_led_driver);
diff --git a/drivers/leds/leds-tlc591xx.c b/drivers/leds/leds-tlc591xx.c
index b806eca83d27..304531644938 100644
--- a/drivers/leds/leds-tlc591xx.c
+++ b/drivers/leds/leds-tlc591xx.c
@@ -14,7 +14,6 @@
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
-#include <linux/workqueue.h>
#define TLC591XX_MAX_LEDS 16
@@ -42,13 +41,11 @@
#define LEDOUT_MASK 0x3
#define ldev_to_led(c) container_of(c, struct tlc591xx_led, ldev)
-#define work_to_led(work) container_of(work, struct tlc591xx_led, work)
struct tlc591xx_led {
bool active;
unsigned int led_no;
struct led_classdev ldev;
- struct work_struct work;
struct tlc591xx_priv *priv;
};
@@ -110,12 +107,12 @@ tlc591xx_set_pwm(struct tlc591xx_priv *priv, struct tlc591xx_led *led,
return regmap_write(priv->regmap, pwm, brightness);
}
-static void
-tlc591xx_led_work(struct work_struct *work)
+static int
+tlc591xx_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness brightness)
{
- struct tlc591xx_led *led = work_to_led(work);
+ struct tlc591xx_led *led = ldev_to_led(led_cdev);
struct tlc591xx_priv *priv = led->priv;
- enum led_brightness brightness = led->ldev.brightness;
int err;
switch (brightness) {
@@ -131,18 +128,7 @@ tlc591xx_led_work(struct work_struct *work)
err = tlc591xx_set_pwm(priv, led, brightness);
}
- if (err)
- dev_err(led->ldev.dev, "Failed setting brightness\n");
-}
-
-static void
-tlc591xx_brightness_set(struct led_classdev *led_cdev,
- enum led_brightness brightness)
-{
- struct tlc591xx_led *led = ldev_to_led(led_cdev);
-
- led->ldev.brightness = brightness;
- schedule_work(&led->work);
+ return err;
}
static void
@@ -151,10 +137,8 @@ tlc591xx_destroy_devices(struct tlc591xx_priv *priv, unsigned int j)
int i = j;
while (--i >= 0) {
- if (priv->leds[i].active) {
+ if (priv->leds[i].active)
led_classdev_unregister(&priv->leds[i].ldev);
- cancel_work_sync(&priv->leds[i].work);
- }
}
}
@@ -175,9 +159,8 @@ tlc591xx_configure(struct device *dev,
led->priv = priv;
led->led_no = i;
- led->ldev.brightness_set = tlc591xx_brightness_set;
+ led->ldev.brightness_set_blocking = tlc591xx_brightness_set;
led->ldev.max_brightness = LED_FULL;
- INIT_WORK(&led->work, tlc591xx_led_work);
err = led_classdev_register(dev, &led->ldev);
if (err < 0) {
dev_err(dev, "couldn't register LED %s\n",
diff --git a/drivers/leds/leds-wm831x-status.c b/drivers/leds/leds-wm831x-status.c
index 56027ef7c7e8..64a22263e7fc 100644
--- a/drivers/leds/leds-wm831x-status.c
+++ b/drivers/leds/leds-wm831x-status.c
@@ -23,7 +23,6 @@
struct wm831x_status {
struct led_classdev cdev;
struct wm831x *wm831x;
- struct work_struct work;
struct mutex mutex;
spinlock_t value_lock;
@@ -40,10 +39,8 @@ struct wm831x_status {
#define to_wm831x_status(led_cdev) \
container_of(led_cdev, struct wm831x_status, cdev)
-static void wm831x_status_work(struct work_struct *work)
+static void wm831x_status_set(struct wm831x_status *led)
{
- struct wm831x_status *led = container_of(work, struct wm831x_status,
- work);
unsigned long flags;
mutex_lock(&led->mutex);
@@ -70,8 +67,8 @@ static void wm831x_status_work(struct work_struct *work)
mutex_unlock(&led->mutex);
}
-static void wm831x_status_set(struct led_classdev *led_cdev,
- enum led_brightness value)
+static int wm831x_status_brightness_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
{
struct wm831x_status *led = to_wm831x_status(led_cdev);
unsigned long flags;
@@ -80,8 +77,10 @@ static void wm831x_status_set(struct led_classdev *led_cdev,
led->brightness = value;
if (value == LED_OFF)
led->blink = 0;
- schedule_work(&led->work);
spin_unlock_irqrestore(&led->value_lock, flags);
+ wm831x_status_set(led);
+
+ return 0;
}
static int wm831x_status_blink_set(struct led_classdev *led_cdev,
@@ -147,11 +146,8 @@ static int wm831x_status_blink_set(struct led_classdev *led_cdev,
else
led->blink = 0;
- /* Always update; if we fail turn off blinking since we expect
- * a software fallback. */
- schedule_work(&led->work);
-
spin_unlock_irqrestore(&led->value_lock, flags);
+ wm831x_status_set(led);
return ret;
}
@@ -206,11 +202,9 @@ static ssize_t wm831x_status_src_store(struct device *dev,
for (i = 0; i < ARRAY_SIZE(led_src_texts); i++) {
if (!strcmp(name, led_src_texts[i])) {
mutex_lock(&led->mutex);
-
led->src = i;
- schedule_work(&led->work);
-
mutex_unlock(&led->mutex);
+ wm831x_status_set(led);
}
}
@@ -262,7 +256,6 @@ static int wm831x_status_probe(struct platform_device *pdev)
pdata.name = dev_name(&pdev->dev);
mutex_init(&drvdata->mutex);
- INIT_WORK(&drvdata->work, wm831x_status_work);
spin_lock_init(&drvdata->value_lock);
/* We cache the configuration register and read startup values
@@ -287,7 +280,7 @@ static int wm831x_status_probe(struct platform_device *pdev)
drvdata->cdev.name = pdata.name;
drvdata->cdev.default_trigger = pdata.default_trigger;
- drvdata->cdev.brightness_set = wm831x_status_set;
+ drvdata->cdev.brightness_set_blocking = wm831x_status_brightness_set;
drvdata->cdev.blink_set = wm831x_status_blink_set;
drvdata->cdev.groups = wm831x_status_groups;
diff --git a/drivers/leds/leds-wm8350.c b/drivers/leds/leds-wm8350.c
index 0d121835673f..e1e4e9d0b8b1 100644
--- a/drivers/leds/leds-wm8350.c
+++ b/drivers/leds/leds-wm8350.c
@@ -89,40 +89,42 @@ static const int isink_cur[] = {
#define to_wm8350_led(led_cdev) \
container_of(led_cdev, struct wm8350_led, cdev)
-static void wm8350_led_enable(struct wm8350_led *led)
+static int wm8350_led_enable(struct wm8350_led *led)
{
- int ret;
+ int ret = 0;
if (led->enabled)
- return;
+ return ret;
ret = regulator_enable(led->isink);
if (ret != 0) {
dev_err(led->cdev.dev, "Failed to enable ISINK: %d\n", ret);
- return;
+ return ret;
}
ret = regulator_enable(led->dcdc);
if (ret != 0) {
dev_err(led->cdev.dev, "Failed to enable DCDC: %d\n", ret);
regulator_disable(led->isink);
- return;
+ return ret;
}
led->enabled = 1;
+
+ return ret;
}
-static void wm8350_led_disable(struct wm8350_led *led)
+static int wm8350_led_disable(struct wm8350_led *led)
{
- int ret;
+ int ret = 0;
if (!led->enabled)
- return;
+ return ret;
ret = regulator_disable(led->dcdc);
if (ret != 0) {
dev_err(led->cdev.dev, "Failed to disable DCDC: %d\n", ret);
- return;
+ return ret;
}
ret = regulator_disable(led->isink);
@@ -132,27 +134,29 @@ static void wm8350_led_disable(struct wm8350_led *led)
if (ret != 0)
dev_err(led->cdev.dev, "Failed to reenable DCDC: %d\n",
ret);
- return;
+ return ret;
}
led->enabled = 0;
+
+ return ret;
}
-static void led_work(struct work_struct *work)
+static int wm8350_led_set(struct led_classdev *led_cdev,
+ enum led_brightness value)
{
- struct wm8350_led *led = container_of(work, struct wm8350_led, work);
+ struct wm8350_led *led = to_wm8350_led(led_cdev);
+ unsigned long flags;
int ret;
int uA;
- unsigned long flags;
- mutex_lock(&led->mutex);
+ led->value = value;
spin_lock_irqsave(&led->value_lock, flags);
if (led->value == LED_OFF) {
spin_unlock_irqrestore(&led->value_lock, flags);
- wm8350_led_disable(led);
- goto out;
+ return wm8350_led_disable(led);
}
/* This scales linearly into the index of valid current
@@ -166,36 +170,21 @@ static void led_work(struct work_struct *work)
ret = regulator_set_current_limit(led->isink, isink_cur[uA],
isink_cur[uA]);
- if (ret != 0)
+ if (ret != 0) {
dev_err(led->cdev.dev, "Failed to set %duA: %d\n",
isink_cur[uA], ret);
+ return ret;
+ }
- wm8350_led_enable(led);
-
-out:
- mutex_unlock(&led->mutex);
-}
-
-static void wm8350_led_set(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- struct wm8350_led *led = to_wm8350_led(led_cdev);
- unsigned long flags;
-
- spin_lock_irqsave(&led->value_lock, flags);
- led->value = value;
- schedule_work(&led->work);
- spin_unlock_irqrestore(&led->value_lock, flags);
+ return wm8350_led_enable(led);
}
static void wm8350_led_shutdown(struct platform_device *pdev)
{
struct wm8350_led *led = platform_get_drvdata(pdev);
- mutex_lock(&led->mutex);
led->value = LED_OFF;
wm8350_led_disable(led);
- mutex_unlock(&led->mutex);
}
static int wm8350_led_probe(struct platform_device *pdev)
@@ -232,7 +221,7 @@ static int wm8350_led_probe(struct platform_device *pdev)
if (led == NULL)
return -ENOMEM;
- led->cdev.brightness_set = wm8350_led_set;
+ led->cdev.brightness_set_blocking = wm8350_led_set;
led->cdev.default_trigger = pdata->default_trigger;
led->cdev.name = pdata->name;
led->cdev.flags |= LED_CORE_SUSPENDRESUME;
@@ -251,8 +240,6 @@ static int wm8350_led_probe(struct platform_device *pdev)
pdata->max_uA);
spin_lock_init(&led->value_lock);
- mutex_init(&led->mutex);
- INIT_WORK(&led->work, led_work);
led->value = LED_OFF;
platform_set_drvdata(pdev, led);
@@ -264,7 +251,6 @@ static int wm8350_led_remove(struct platform_device *pdev)
struct wm8350_led *led = platform_get_drvdata(pdev);
led_classdev_unregister(&led->cdev);
- flush_work(&led->work);
wm8350_led_disable(led);
return 0;
}
diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h
index 4238fbc31d35..db3f20da7221 100644
--- a/drivers/leds/leds.h
+++ b/drivers/leds/leds.h
@@ -16,29 +16,6 @@
#include <linux/rwsem.h>
#include <linux/leds.h>
-static inline void led_set_brightness_async(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- value = min(value, led_cdev->max_brightness);
- led_cdev->brightness = value;
-
- if (!(led_cdev->flags & LED_SUSPENDED))
- led_cdev->brightness_set(led_cdev, value);
-}
-
-static inline int led_set_brightness_sync(struct led_classdev *led_cdev,
- enum led_brightness value)
-{
- int ret = 0;
-
- led_cdev->brightness = min(value, led_cdev->max_brightness);
-
- if (!(led_cdev->flags & LED_SUSPENDED))
- ret = led_cdev->brightness_set_sync(led_cdev,
- led_cdev->brightness);
- return ret;
-}
-
static inline int led_get_brightness(struct led_classdev *led_cdev)
{
return led_cdev->brightness;
@@ -46,6 +23,10 @@ static inline int led_get_brightness(struct led_classdev *led_cdev)
void led_init_core(struct led_classdev *led_cdev);
void led_stop_software_blink(struct led_classdev *led_cdev);
+void led_set_brightness_nopm(struct led_classdev *led_cdev,
+ enum led_brightness value);
+void led_set_brightness_nosleep(struct led_classdev *led_cdev,
+ enum led_brightness value);
extern struct rw_semaphore leds_list_lock;
extern struct list_head leds_list;
diff --git a/drivers/leds/trigger/ledtrig-backlight.c b/drivers/leds/trigger/ledtrig-backlight.c
index 59eca17d9661..1ca1f1608f76 100644
--- a/drivers/leds/trigger/ledtrig-backlight.c
+++ b/drivers/leds/trigger/ledtrig-backlight.c
@@ -51,9 +51,9 @@ static int fb_notifier_callback(struct notifier_block *p,
if ((n->old_status == UNBLANK) ^ n->invert) {
n->brightness = led->brightness;
- led_set_brightness_async(led, LED_OFF);
+ led_set_brightness_nosleep(led, LED_OFF);
} else {
- led_set_brightness_async(led, n->brightness);
+ led_set_brightness_nosleep(led, n->brightness);
}
n->old_status = new_status;
@@ -89,9 +89,9 @@ static ssize_t bl_trig_invert_store(struct device *dev,
/* After inverting, we need to update the LED. */
if ((n->old_status == BLANK) ^ n->invert)
- led_set_brightness_async(led, LED_OFF);
+ led_set_brightness_nosleep(led, LED_OFF);
else
- led_set_brightness_async(led, n->brightness);
+ led_set_brightness_nosleep(led, n->brightness);
return num;
}
diff --git a/drivers/leds/trigger/ledtrig-cpu.c b/drivers/leds/trigger/ledtrig-cpu.c
index aec0f02b6b3e..938467fb82be 100644
--- a/drivers/leds/trigger/ledtrig-cpu.c
+++ b/drivers/leds/trigger/ledtrig-cpu.c
@@ -19,7 +19,6 @@
*
*/
-#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -140,27 +139,4 @@ static int __init ledtrig_cpu_init(void)
return 0;
}
-module_init(ledtrig_cpu_init);
-
-static void __exit ledtrig_cpu_exit(void)
-{
- int cpu;
-
- unregister_cpu_notifier(&ledtrig_cpu_nb);
-
- for_each_possible_cpu(cpu) {
- struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
-
- led_trigger_unregister_simple(trig->_trig);
- trig->_trig = NULL;
- memset(trig->name, 0, MAX_NAME_LEN);
- }
-
- unregister_syscore_ops(&ledtrig_cpu_syscore_ops);
-}
-module_exit(ledtrig_cpu_exit);
-
-MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
-MODULE_AUTHOR("Bryan Wu <bryan.wu@canonical.com>");
-MODULE_DESCRIPTION("CPU LED trigger");
-MODULE_LICENSE("GPL");
+device_initcall(ledtrig_cpu_init);
diff --git a/drivers/leds/trigger/ledtrig-default-on.c b/drivers/leds/trigger/ledtrig-default-on.c
index 6f38f883aaf1..ff455cb46680 100644
--- a/drivers/leds/trigger/ledtrig-default-on.c
+++ b/drivers/leds/trigger/ledtrig-default-on.c
@@ -19,7 +19,7 @@
static void defon_trig_activate(struct led_classdev *led_cdev)
{
- led_set_brightness_async(led_cdev, led_cdev->max_brightness);
+ led_set_brightness_nosleep(led_cdev, led_cdev->max_brightness);
}
static struct led_trigger defon_led_trigger = {
diff --git a/drivers/leds/trigger/ledtrig-gpio.c b/drivers/leds/trigger/ledtrig-gpio.c
index 4cc7040746c6..51288a45fbcb 100644
--- a/drivers/leds/trigger/ledtrig-gpio.c
+++ b/drivers/leds/trigger/ledtrig-gpio.c
@@ -54,12 +54,12 @@ static void gpio_trig_work(struct work_struct *work)
if (tmp) {
if (gpio_data->desired_brightness)
- led_set_brightness_async(gpio_data->led,
+ led_set_brightness_nosleep(gpio_data->led,
gpio_data->desired_brightness);
else
- led_set_brightness_async(gpio_data->led, LED_FULL);
+ led_set_brightness_nosleep(gpio_data->led, LED_FULL);
} else {
- led_set_brightness_async(gpio_data->led, LED_OFF);
+ led_set_brightness_nosleep(gpio_data->led, LED_OFF);
}
}
diff --git a/drivers/leds/trigger/ledtrig-heartbeat.c b/drivers/leds/trigger/ledtrig-heartbeat.c
index 8622ce651ae2..410c39c62dc7 100644
--- a/drivers/leds/trigger/ledtrig-heartbeat.c
+++ b/drivers/leds/trigger/ledtrig-heartbeat.c
@@ -38,7 +38,7 @@ static void led_heartbeat_function(unsigned long data)
unsigned long delay = 0;
if (unlikely(panic_heartbeats)) {
- led_set_brightness(led_cdev, LED_OFF);
+ led_set_brightness_nosleep(led_cdev, LED_OFF);
return;
}
@@ -81,7 +81,7 @@ static void led_heartbeat_function(unsigned long data)
break;
}
- led_set_brightness_async(led_cdev, brightness);
+ led_set_brightness_nosleep(led_cdev, brightness);
mod_timer(&heartbeat_data->timer, jiffies + delay);
}
diff --git a/drivers/leds/trigger/ledtrig-ide-disk.c b/drivers/leds/trigger/ledtrig-ide-disk.c
index 2cd7c0cf5924..c02a3ac3cd2b 100644
--- a/drivers/leds/trigger/ledtrig-ide-disk.c
+++ b/drivers/leds/trigger/ledtrig-ide-disk.c
@@ -11,7 +11,6 @@
*
*/
-#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/leds.h>
@@ -33,15 +32,4 @@ static int __init ledtrig_ide_init(void)
led_trigger_register_simple("ide-disk", &ledtrig_ide);
return 0;
}
-
-static void __exit ledtrig_ide_exit(void)
-{
- led_trigger_unregister_simple(ledtrig_ide);
-}
-
-module_init(ledtrig_ide_init);
-module_exit(ledtrig_ide_exit);
-
-MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>");
-MODULE_DESCRIPTION("LED IDE Disk Activity Trigger");
-MODULE_LICENSE("GPL");
+device_initcall(ledtrig_ide_init);
diff --git a/drivers/leds/trigger/ledtrig-oneshot.c b/drivers/leds/trigger/ledtrig-oneshot.c
index fbd02cdc3ad7..b8ea9f0f1e19 100644
--- a/drivers/leds/trigger/ledtrig-oneshot.c
+++ b/drivers/leds/trigger/ledtrig-oneshot.c
@@ -63,9 +63,9 @@ static ssize_t led_invert_store(struct device *dev,
oneshot_data->invert = !!state;
if (oneshot_data->invert)
- led_set_brightness_async(led_cdev, LED_FULL);
+ led_set_brightness_nosleep(led_cdev, LED_FULL);
else
- led_set_brightness_async(led_cdev, LED_OFF);
+ led_set_brightness_nosleep(led_cdev, LED_OFF);
return size;
}
@@ -201,4 +201,4 @@ module_exit(oneshot_trig_exit);
MODULE_AUTHOR("Fabio Baltieri <fabio.baltieri@gmail.com>");
MODULE_DESCRIPTION("One-shot LED trigger");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/trigger/ledtrig-transient.c b/drivers/leds/trigger/ledtrig-transient.c
index 3c34de404d18..7e6011bd3646 100644
--- a/drivers/leds/trigger/ledtrig-transient.c
+++ b/drivers/leds/trigger/ledtrig-transient.c
@@ -41,7 +41,7 @@ static void transient_timer_function(unsigned long data)
struct transient_trig_data *transient_data = led_cdev->trigger_data;
transient_data->activate = 0;
- led_set_brightness_async(led_cdev, transient_data->restore_state);
+ led_set_brightness_nosleep(led_cdev, transient_data->restore_state);
}
static ssize_t transient_activate_show(struct device *dev,
@@ -72,7 +72,7 @@ static ssize_t transient_activate_store(struct device *dev,
if (state == 0 && transient_data->activate == 1) {
del_timer(&transient_data->timer);
transient_data->activate = state;
- led_set_brightness_async(led_cdev,
+ led_set_brightness_nosleep(led_cdev,
transient_data->restore_state);
return size;
}
@@ -81,11 +81,11 @@ static ssize_t transient_activate_store(struct device *dev,
if (state == 1 && transient_data->activate == 0 &&
transient_data->duration != 0) {
transient_data->activate = state;
- led_set_brightness_async(led_cdev, transient_data->state);
+ led_set_brightness_nosleep(led_cdev, transient_data->state);
transient_data->restore_state =
(transient_data->state == LED_FULL) ? LED_OFF : LED_FULL;
mod_timer(&transient_data->timer,
- jiffies + transient_data->duration);
+ jiffies + msecs_to_jiffies(transient_data->duration));
}
/* state == 0 && transient_data->activate == 0
@@ -204,7 +204,7 @@ static void transient_trig_deactivate(struct led_classdev *led_cdev)
if (led_cdev->activated) {
del_timer_sync(&transient_data->timer);
- led_set_brightness_async(led_cdev,
+ led_set_brightness_nosleep(led_cdev,
transient_data->restore_state);
device_remove_file(led_cdev->dev, &dev_attr_activate);
device_remove_file(led_cdev->dev, &dev_attr_duration);
diff --git a/drivers/media/v4l2-core/v4l2-flash-led-class.c b/drivers/media/v4l2-core/v4l2-flash-led-class.c
index 5bdfb8d5263a..5d673357f75f 100644
--- a/drivers/media/v4l2-core/v4l2-flash-led-class.c
+++ b/drivers/media/v4l2-core/v4l2-flash-led-class.c
@@ -107,10 +107,10 @@ static void v4l2_flash_set_led_brightness(struct v4l2_flash *v4l2_flash,
if (ctrls[LED_MODE]->val != V4L2_FLASH_LED_MODE_TORCH)
return;
- led_set_brightness(&v4l2_flash->fled_cdev->led_cdev,
+ led_set_brightness_sync(&v4l2_flash->fled_cdev->led_cdev,
brightness);
} else {
- led_set_brightness(&v4l2_flash->iled_cdev->led_cdev,
+ led_set_brightness_sync(&v4l2_flash->iled_cdev->led_cdev,
brightness);
}
}
@@ -206,11 +206,11 @@ static int v4l2_flash_s_ctrl(struct v4l2_ctrl *c)
case V4L2_CID_FLASH_LED_MODE:
switch (c->val) {
case V4L2_FLASH_LED_MODE_NONE:
- led_set_brightness(led_cdev, LED_OFF);
+ led_set_brightness_sync(led_cdev, LED_OFF);
return led_set_flash_strobe(fled_cdev, false);
case V4L2_FLASH_LED_MODE_FLASH:
/* Turn the torch LED off */
- led_set_brightness(led_cdev, LED_OFF);
+ led_set_brightness_sync(led_cdev, LED_OFF);
if (ctrls[STROBE_SOURCE]) {
external_strobe = (ctrls[STROBE_SOURCE]->val ==
V4L2_FLASH_STROBE_SOURCE_EXTERNAL);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index d8486168415a..5914263090fc 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -171,11 +171,7 @@ static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
static inline int mmc_get_devidx(struct gendisk *disk)
{
- int devmaj = MAJOR(disk_devt(disk));
- int devidx = MINOR(disk_devt(disk)) / perdev_minors;
-
- if (!devmaj)
- devidx = disk->first_minor / perdev_minors;
+ int devidx = disk->first_minor / perdev_minors;
return devidx;
}
@@ -344,7 +340,7 @@ static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
struct mmc_blk_ioc_data *idata;
int err;
- idata = kzalloc(sizeof(*idata), GFP_KERNEL);
+ idata = kmalloc(sizeof(*idata), GFP_KERNEL);
if (!idata) {
err = -ENOMEM;
goto out;
@@ -364,7 +360,7 @@ static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
if (!idata->buf_bytes)
return idata;
- idata->buf = kzalloc(idata->buf_bytes, GFP_KERNEL);
+ idata->buf = kmalloc(idata->buf_bytes, GFP_KERNEL);
if (!idata->buf) {
err = -ENOMEM;
goto idata_err;
@@ -2244,6 +2240,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
md->disk->queue = md->queue.queue;
md->disk->driverfs_dev = parent;
set_disk_ro(md->disk, md->read_only || default_ro);
+ md->disk->flags = GENHD_FL_EXT_DEVT;
if (area_type & (MMC_BLK_DATA_AREA_RPMB | MMC_BLK_DATA_AREA_BOOT))
md->disk->flags |= GENHD_FL_NO_PART_SCAN;
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 972ff844cf5a..4bc48f10452f 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -349,6 +349,8 @@ int mmc_add_card(struct mmc_card *card)
card->dev.of_node = mmc_of_find_child_device(card->host, 0);
+ device_enable_async_suspend(&card->dev);
+
ret = device_add(&card->dev);
if (ret)
return ret;
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 5ae89e48fd85..f95d41ffc766 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -55,7 +55,6 @@
*/
#define MMC_BKOPS_MAX_TIMEOUT (4 * 60 * 1000) /* max time to wait in ms */
-static struct workqueue_struct *workqueue;
static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
/*
@@ -66,21 +65,16 @@ static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
bool use_spi_crc = 1;
module_param(use_spi_crc, bool, 0);
-/*
- * Internal function. Schedule delayed work in the MMC work queue.
- */
static int mmc_schedule_delayed_work(struct delayed_work *work,
unsigned long delay)
{
- return queue_delayed_work(workqueue, work, delay);
-}
-
-/*
- * Internal function. Flush all scheduled work from the MMC work queue.
- */
-static void mmc_flush_scheduled_work(void)
-{
- flush_workqueue(workqueue);
+ /*
+ * We use the system_freezable_wq, because of two reasons.
+ * First, it allows several works (not the same work item) to be
+ * executed simultaneously. Second, the queue becomes frozen when
+ * userspace becomes frozen during system PM.
+ */
+ return queue_delayed_work(system_freezable_wq, work, delay);
}
#ifdef CONFIG_FAIL_MMC_REQUEST
@@ -1485,7 +1479,7 @@ int mmc_regulator_get_supply(struct mmc_host *mmc)
if (IS_ERR(mmc->supply.vmmc)) {
if (PTR_ERR(mmc->supply.vmmc) == -EPROBE_DEFER)
return -EPROBE_DEFER;
- dev_info(dev, "No vmmc regulator found\n");
+ dev_dbg(dev, "No vmmc regulator found\n");
} else {
ret = mmc_regulator_get_ocrmask(mmc->supply.vmmc);
if (ret > 0)
@@ -1497,7 +1491,7 @@ int mmc_regulator_get_supply(struct mmc_host *mmc)
if (IS_ERR(mmc->supply.vqmmc)) {
if (PTR_ERR(mmc->supply.vqmmc) == -EPROBE_DEFER)
return -EPROBE_DEFER;
- dev_info(dev, "No vqmmc regulator found\n");
+ dev_dbg(dev, "No vqmmc regulator found\n");
}
return 0;
@@ -2476,15 +2470,20 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
* sdio_reset sends CMD52 to reset card. Since we do not know
* if the card is being re-initialized, just send it. CMD52
* should be ignored by SD/eMMC cards.
+ * Skip it if we already know that we do not support SDIO commands
*/
- sdio_reset(host);
+ if (!(host->caps2 & MMC_CAP2_NO_SDIO))
+ sdio_reset(host);
+
mmc_go_idle(host);
mmc_send_if_cond(host, host->ocr_avail);
/* Order's important: probe SDIO, then SD, then MMC */
- if (!mmc_attach_sdio(host))
- return 0;
+ if (!(host->caps2 & MMC_CAP2_NO_SDIO))
+ if (!mmc_attach_sdio(host))
+ return 0;
+
if (!mmc_attach_sd(host))
return 0;
if (!mmc_attach_mmc(host))
@@ -2498,9 +2497,6 @@ int _mmc_detect_card_removed(struct mmc_host *host)
{
int ret;
- if (host->caps & MMC_CAP_NONREMOVABLE)
- return 0;
-
if (!host->card || mmc_card_removed(host->card))
return 1;
@@ -2536,6 +2532,9 @@ int mmc_detect_card_removed(struct mmc_host *host)
if (!card)
return 1;
+ if (host->caps & MMC_CAP_NONREMOVABLE)
+ return 0;
+
ret = mmc_card_removed(card);
/*
* The card will be considered unchanged unless we have been asked to
@@ -2567,11 +2566,6 @@ void mmc_rescan(struct work_struct *work)
container_of(work, struct mmc_host, detect.work);
int i;
- if (host->trigger_card_event && host->ops->card_event) {
- host->ops->card_event(host);
- host->trigger_card_event = false;
- }
-
if (host->rescan_disable)
return;
@@ -2580,6 +2574,13 @@ void mmc_rescan(struct work_struct *work)
return;
host->rescan_entered = 1;
+ if (host->trigger_card_event && host->ops->card_event) {
+ mmc_claim_host(host);
+ host->ops->card_event(host);
+ mmc_release_host(host);
+ host->trigger_card_event = false;
+ }
+
mmc_bus_get(host);
/*
@@ -2611,15 +2612,14 @@ void mmc_rescan(struct work_struct *work)
*/
mmc_bus_put(host);
+ mmc_claim_host(host);
if (!(host->caps & MMC_CAP_NONREMOVABLE) && host->ops->get_cd &&
host->ops->get_cd(host) == 0) {
- mmc_claim_host(host);
mmc_power_off(host);
mmc_release_host(host);
goto out;
}
- mmc_claim_host(host);
for (i = 0; i < ARRAY_SIZE(freqs); i++) {
if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min)))
break;
@@ -2663,7 +2663,6 @@ void mmc_stop_host(struct mmc_host *host)
host->rescan_disable = 1;
cancel_delayed_work_sync(&host->detect);
- mmc_flush_scheduled_work();
/* clear pm flags now and let card drivers set them as needed */
host->pm_flags = 0;
@@ -2759,14 +2758,13 @@ int mmc_flush_cache(struct mmc_card *card)
}
EXPORT_SYMBOL(mmc_flush_cache);
-#ifdef CONFIG_PM
-
+#ifdef CONFIG_PM_SLEEP
/* Do the card removal on suspend if card is assumed removeable
* Do that in pm notifier while userspace isn't yet frozen, so we will be able
to sync the card.
*/
-int mmc_pm_notify(struct notifier_block *notify_block,
- unsigned long mode, void *unused)
+static int mmc_pm_notify(struct notifier_block *notify_block,
+ unsigned long mode, void *unused)
{
struct mmc_host *host = container_of(
notify_block, struct mmc_host, pm_notify);
@@ -2813,6 +2811,17 @@ int mmc_pm_notify(struct notifier_block *notify_block,
return 0;
}
+
+void mmc_register_pm_notifier(struct mmc_host *host)
+{
+ host->pm_notify.notifier_call = mmc_pm_notify;
+ register_pm_notifier(&host->pm_notify);
+}
+
+void mmc_unregister_pm_notifier(struct mmc_host *host)
+{
+ unregister_pm_notifier(&host->pm_notify);
+}
#endif
/**
@@ -2836,13 +2845,9 @@ static int __init mmc_init(void)
{
int ret;
- workqueue = alloc_ordered_workqueue("kmmcd", 0);
- if (!workqueue)
- return -ENOMEM;
-
ret = mmc_register_bus();
if (ret)
- goto destroy_workqueue;
+ return ret;
ret = mmc_register_host_class();
if (ret)
@@ -2858,9 +2863,6 @@ unregister_host_class:
mmc_unregister_host_class();
unregister_bus:
mmc_unregister_bus();
-destroy_workqueue:
- destroy_workqueue(workqueue);
-
return ret;
}
@@ -2869,7 +2871,6 @@ static void __exit mmc_exit(void)
sdio_unregister_bus();
mmc_unregister_host_class();
mmc_unregister_bus();
- destroy_workqueue(workqueue);
}
subsys_initcall(mmc_init);
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h
index 09241e56d628..0fa86a2afc26 100644
--- a/drivers/mmc/core/core.h
+++ b/drivers/mmc/core/core.h
@@ -90,5 +90,13 @@ int mmc_execute_tuning(struct mmc_card *card);
int mmc_hs200_to_hs400(struct mmc_card *card);
int mmc_hs400_to_hs200(struct mmc_card *card);
+#ifdef CONFIG_PM_SLEEP
+void mmc_register_pm_notifier(struct mmc_host *host);
+void mmc_unregister_pm_notifier(struct mmc_host *host);
+#else
+static inline void mmc_register_pm_notifier(struct mmc_host *host) { }
+static inline void mmc_unregister_pm_notifier(struct mmc_host *host) { }
+#endif
+
#endif
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c
index da950c44204d..0aecd5c00b86 100644
--- a/drivers/mmc/core/host.c
+++ b/drivers/mmc/core/host.c
@@ -21,7 +21,6 @@
#include <linux/export.h>
#include <linux/leds.h>
#include <linux/slab.h>
-#include <linux/suspend.h>
#include <linux/mmc/host.h>
#include <linux/mmc/card.h>
@@ -275,7 +274,8 @@ int mmc_of_parse(struct mmc_host *host)
host->caps2 |= MMC_CAP2_FULL_PWR_CYCLE;
if (of_property_read_bool(np, "keep-power-in-suspend"))
host->pm_caps |= MMC_PM_KEEP_POWER;
- if (of_property_read_bool(np, "enable-sdio-wakeup"))
+ if (of_property_read_bool(np, "wakeup-source") ||
+ of_property_read_bool(np, "enable-sdio-wakeup")) /* legacy */
host->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
if (of_property_read_bool(np, "mmc-ddr-1_8v"))
host->caps |= MMC_CAP_1_8V_DDR;
@@ -348,9 +348,6 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
spin_lock_init(&host->lock);
init_waitqueue_head(&host->wq);
INIT_DELAYED_WORK(&host->detect, mmc_rescan);
-#ifdef CONFIG_PM
- host->pm_notify.notifier_call = mmc_pm_notify;
-#endif
setup_timer(&host->retune_timer, mmc_retune_timer, (unsigned long)host);
/*
@@ -395,7 +392,7 @@ int mmc_add_host(struct mmc_host *host)
#endif
mmc_start_host(host);
- register_pm_notifier(&host->pm_notify);
+ mmc_register_pm_notifier(host);
return 0;
}
@@ -412,7 +409,7 @@ EXPORT_SYMBOL(mmc_add_host);
*/
void mmc_remove_host(struct mmc_host *host)
{
- unregister_pm_notifier(&host->pm_notify);
+ mmc_unregister_pm_notifier(host);
mmc_stop_host(host);
#ifdef CONFIG_DEBUG_FS
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index 3a9a79ec4343..bf49e44571f2 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1076,8 +1076,7 @@ static int mmc_select_hs400(struct mmc_card *card)
mmc_set_clock(host, max_dtr);
/* Switch card to HS mode */
- val = EXT_CSD_TIMING_HS |
- card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
+ val = EXT_CSD_TIMING_HS;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_HS_TIMING, val,
card->ext_csd.generic_cmd6_time,
@@ -1160,8 +1159,7 @@ int mmc_hs400_to_hs200(struct mmc_card *card)
mmc_set_clock(host, max_dtr);
/* Switch HS400 to HS DDR */
- val = EXT_CSD_TIMING_HS |
- card->drive_strength << EXT_CSD_DRV_STR_SHIFT;
+ val = EXT_CSD_TIMING_HS;
err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING,
val, card->ext_csd.generic_cmd6_time,
true, send_status, true);
@@ -1907,16 +1905,8 @@ static int mmc_shutdown(struct mmc_host *host)
*/
static int mmc_resume(struct mmc_host *host)
{
- int err = 0;
-
- if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) {
- err = _mmc_resume(host);
- pm_runtime_set_active(&host->card->dev);
- pm_runtime_mark_last_busy(&host->card->dev);
- }
pm_runtime_enable(&host->card->dev);
-
- return err;
+ return 0;
}
/*
@@ -1944,12 +1934,9 @@ static int mmc_runtime_resume(struct mmc_host *host)
{
int err;
- if (!(host->caps & (MMC_CAP_AGGRESSIVE_PM | MMC_CAP_RUNTIME_RESUME)))
- return 0;
-
err = _mmc_resume(host);
- if (err)
- pr_err("%s: error %d doing aggressive resume\n",
+ if (err && err != -ENOMEDIUM)
+ pr_err("%s: error %d doing runtime resume\n",
mmc_hostname(host), err);
return 0;
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 1f444269ebbe..2c90635c89af 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -489,6 +489,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
unsigned long timeout;
u32 status = 0;
bool use_r1b_resp = use_busy_signal;
+ bool expired = false;
mmc_retune_hold(host);
@@ -545,6 +546,12 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
timeout = jiffies + msecs_to_jiffies(timeout_ms);
do {
if (send_status) {
+ /*
+ * Due to the possibility of being preempted after
+ * sending the status command, check the expiration
+ * time first.
+ */
+ expired = time_after(jiffies, timeout);
err = __mmc_send_status(card, &status, ignore_crc);
if (err)
goto out;
@@ -565,7 +572,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value,
}
/* Timeout if the device never leaves the program state. */
- if (time_after(jiffies, timeout)) {
+ if (expired && R1_CURRENT_STATE(status) == R1_STATE_PRG) {
pr_err("%s: Card stuck in programming state! %s\n",
mmc_hostname(host), __func__);
err = -ETIMEDOUT;
diff --git a/drivers/mmc/core/pwrseq.h b/drivers/mmc/core/pwrseq.h
index 096da48c6a7e..133de0426687 100644
--- a/drivers/mmc/core/pwrseq.h
+++ b/drivers/mmc/core/pwrseq.h
@@ -16,7 +16,7 @@ struct mmc_pwrseq_ops {
};
struct mmc_pwrseq {
- struct mmc_pwrseq_ops *ops;
+ const struct mmc_pwrseq_ops *ops;
};
#ifdef CONFIG_OF
diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c
index ad4f94ec7e8d..4a82bc77fe49 100644
--- a/drivers/mmc/core/pwrseq_emmc.c
+++ b/drivers/mmc/core/pwrseq_emmc.c
@@ -51,7 +51,7 @@ static void mmc_pwrseq_emmc_free(struct mmc_host *host)
kfree(pwrseq);
}
-static struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = {
+static const struct mmc_pwrseq_ops mmc_pwrseq_emmc_ops = {
.post_power_on = mmc_pwrseq_emmc_reset,
.free = mmc_pwrseq_emmc_free,
};
diff --git a/drivers/mmc/core/pwrseq_simple.c b/drivers/mmc/core/pwrseq_simple.c
index d10538bb5e07..2b16263458af 100644
--- a/drivers/mmc/core/pwrseq_simple.c
+++ b/drivers/mmc/core/pwrseq_simple.c
@@ -87,7 +87,7 @@ static void mmc_pwrseq_simple_free(struct mmc_host *host)
kfree(pwrseq);
}
-static struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = {
+static const struct mmc_pwrseq_ops mmc_pwrseq_simple_ops = {
.pre_power_on = mmc_pwrseq_simple_pre_power_on,
.post_power_on = mmc_pwrseq_simple_post_power_on,
.power_off = mmc_pwrseq_simple_power_off,
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 141eaa923e18..f2b164b214ae 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1128,16 +1128,8 @@ out:
*/
static int mmc_sd_resume(struct mmc_host *host)
{
- int err = 0;
-
- if (!(host->caps & MMC_CAP_RUNTIME_RESUME)) {
- err = _mmc_sd_resume(host);
- pm_runtime_set_active(&host->card->dev);
- pm_runtime_mark_last_busy(&host->card->dev);
- }
pm_runtime_enable(&host->card->dev);
-
- return err;
+ return 0;
}
/*
@@ -1165,12 +1157,9 @@ static int mmc_sd_runtime_resume(struct mmc_host *host)
{
int err;
- if (!(host->caps & (MMC_CAP_AGGRESSIVE_PM | MMC_CAP_RUNTIME_RESUME)))
- return 0;
-
err = _mmc_sd_resume(host);
- if (err)
- pr_err("%s: error %d doing aggressive resume\n",
+ if (err && err != -ENOMEDIUM)
+ pr_err("%s: error %d doing runtime resume\n",
mmc_hostname(host), err);
return 0;
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index 16d838e6d623..d61ba1a0495e 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -630,7 +630,7 @@ try_again:
*/
if (!powered_resume && (rocr & ocr & R4_18V_PRESENT)) {
err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180,
- ocr);
+ ocr_card);
if (err == -EAGAIN) {
sdio_reset(host);
mmc_go_idle(host);
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 7e327a6dd53d..86f5b3223aae 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -322,6 +322,7 @@ int sdio_add_func(struct sdio_func *func)
sdio_set_of_node(func);
sdio_acpi_set_handle(func);
+ device_enable_async_suspend(&func->dev);
ret = device_add(&func->dev);
if (ret == 0)
sdio_func_set_present(func);
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 1dee533634c9..1526b8a10b09 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -455,6 +455,7 @@ config MMC_TIFM_SD
config MMC_MVSDIO
tristate "Marvell MMC/SD/SDIO host driver"
depends on PLAT_ORION
+ depends on OF
---help---
This selects the Marvell SDIO host driver.
SDIO may currently be found on the Kirkwood 88F6281 and 88F6192
diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h
deleted file mode 100644
index 0aa44e679df4..000000000000
--- a/drivers/mmc/host/atmel-mci-regs.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Atmel MultiMedia Card Interface driver
- *
- * Copyright (C) 2004-2006 Atmel Corporation
- *
- * 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.
- */
-
-/*
- * Superset of MCI IP registers integrated in Atmel AVR32 and AT91 Processors
- * Registers and bitfields marked with [2] are only available in MCI2
- */
-
-#ifndef __DRIVERS_MMC_ATMEL_MCI_H__
-#define __DRIVERS_MMC_ATMEL_MCI_H__
-
-/* MCI Register Definitions */
-#define ATMCI_CR 0x0000 /* Control */
-# define ATMCI_CR_MCIEN ( 1 << 0) /* MCI Enable */
-# define ATMCI_CR_MCIDIS ( 1 << 1) /* MCI Disable */
-# define ATMCI_CR_PWSEN ( 1 << 2) /* Power Save Enable */
-# define ATMCI_CR_PWSDIS ( 1 << 3) /* Power Save Disable */
-# define ATMCI_CR_SWRST ( 1 << 7) /* Software Reset */
-#define ATMCI_MR 0x0004 /* Mode */
-# define ATMCI_MR_CLKDIV(x) ((x) << 0) /* Clock Divider */
-# define ATMCI_MR_PWSDIV(x) ((x) << 8) /* Power Saving Divider */
-# define ATMCI_MR_RDPROOF ( 1 << 11) /* Read Proof */
-# define ATMCI_MR_WRPROOF ( 1 << 12) /* Write Proof */
-# define ATMCI_MR_PDCFBYTE ( 1 << 13) /* Force Byte Transfer */
-# define ATMCI_MR_PDCPADV ( 1 << 14) /* Padding Value */
-# define ATMCI_MR_PDCMODE ( 1 << 15) /* PDC-oriented Mode */
-# define ATMCI_MR_CLKODD(x) ((x) << 16) /* LSB of Clock Divider */
-#define ATMCI_DTOR 0x0008 /* Data Timeout */
-# define ATMCI_DTOCYC(x) ((x) << 0) /* Data Timeout Cycles */
-# define ATMCI_DTOMUL(x) ((x) << 4) /* Data Timeout Multiplier */
-#define ATMCI_SDCR 0x000c /* SD Card / SDIO */
-# define ATMCI_SDCSEL_SLOT_A ( 0 << 0) /* Select SD slot A */
-# define ATMCI_SDCSEL_SLOT_B ( 1 << 0) /* Select SD slot A */
-# define ATMCI_SDCSEL_MASK ( 3 << 0)
-# define ATMCI_SDCBUS_1BIT ( 0 << 6) /* 1-bit data bus */
-# define ATMCI_SDCBUS_4BIT ( 2 << 6) /* 4-bit data bus */
-# define ATMCI_SDCBUS_8BIT ( 3 << 6) /* 8-bit data bus[2] */
-# define ATMCI_SDCBUS_MASK ( 3 << 6)
-#define ATMCI_ARGR 0x0010 /* Command Argument */
-#define ATMCI_CMDR 0x0014 /* Command */
-# define ATMCI_CMDR_CMDNB(x) ((x) << 0) /* Command Opcode */
-# define ATMCI_CMDR_RSPTYP_NONE ( 0 << 6) /* No response */
-# define ATMCI_CMDR_RSPTYP_48BIT ( 1 << 6) /* 48-bit response */
-# define ATMCI_CMDR_RSPTYP_136BIT ( 2 << 6) /* 136-bit response */
-# define ATMCI_CMDR_SPCMD_INIT ( 1 << 8) /* Initialization command */
-# define ATMCI_CMDR_SPCMD_SYNC ( 2 << 8) /* Synchronized command */
-# define ATMCI_CMDR_SPCMD_INT ( 4 << 8) /* Interrupt command */
-# define ATMCI_CMDR_SPCMD_INTRESP ( 5 << 8) /* Interrupt response */
-# define ATMCI_CMDR_OPDCMD ( 1 << 11) /* Open Drain */
-# define ATMCI_CMDR_MAXLAT_5CYC ( 0 << 12) /* Max latency 5 cycles */
-# define ATMCI_CMDR_MAXLAT_64CYC ( 1 << 12) /* Max latency 64 cycles */
-# define ATMCI_CMDR_START_XFER ( 1 << 16) /* Start data transfer */
-# define ATMCI_CMDR_STOP_XFER ( 2 << 16) /* Stop data transfer */
-# define ATMCI_CMDR_TRDIR_WRITE ( 0 << 18) /* Write data */
-# define ATMCI_CMDR_TRDIR_READ ( 1 << 18) /* Read data */
-# define ATMCI_CMDR_BLOCK ( 0 << 19) /* Single-block transfer */
-# define ATMCI_CMDR_MULTI_BLOCK ( 1 << 19) /* Multi-block transfer */
-# define ATMCI_CMDR_STREAM ( 2 << 19) /* MMC Stream transfer */
-# define ATMCI_CMDR_SDIO_BYTE ( 4 << 19) /* SDIO Byte transfer */
-# define ATMCI_CMDR_SDIO_BLOCK ( 5 << 19) /* SDIO Block transfer */
-# define ATMCI_CMDR_SDIO_SUSPEND ( 1 << 24) /* SDIO Suspend Command */
-# define ATMCI_CMDR_SDIO_RESUME ( 2 << 24) /* SDIO Resume Command */
-#define ATMCI_BLKR 0x0018 /* Block */
-# define ATMCI_BCNT(x) ((x) << 0) /* Data Block Count */
-# define ATMCI_BLKLEN(x) ((x) << 16) /* Data Block Length */
-#define ATMCI_CSTOR 0x001c /* Completion Signal Timeout[2] */
-# define ATMCI_CSTOCYC(x) ((x) << 0) /* CST cycles */
-# define ATMCI_CSTOMUL(x) ((x) << 4) /* CST multiplier */
-#define ATMCI_RSPR 0x0020 /* Response 0 */
-#define ATMCI_RSPR1 0x0024 /* Response 1 */
-#define ATMCI_RSPR2 0x0028 /* Response 2 */
-#define ATMCI_RSPR3 0x002c /* Response 3 */
-#define ATMCI_RDR 0x0030 /* Receive Data */
-#define ATMCI_TDR 0x0034 /* Transmit Data */
-#define ATMCI_SR 0x0040 /* Status */
-#define ATMCI_IER 0x0044 /* Interrupt Enable */
-#define ATMCI_IDR 0x0048 /* Interrupt Disable */
-#define ATMCI_IMR 0x004c /* Interrupt Mask */
-# define ATMCI_CMDRDY ( 1 << 0) /* Command Ready */
-# define ATMCI_RXRDY ( 1 << 1) /* Receiver Ready */
-# define ATMCI_TXRDY ( 1 << 2) /* Transmitter Ready */
-# define ATMCI_BLKE ( 1 << 3) /* Data Block Ended */
-# define ATMCI_DTIP ( 1 << 4) /* Data Transfer In Progress */
-# define ATMCI_NOTBUSY ( 1 << 5) /* Data Not Busy */
-# define ATMCI_ENDRX ( 1 << 6) /* End of RX Buffer */
-# define ATMCI_ENDTX ( 1 << 7) /* End of TX Buffer */
-# define ATMCI_SDIOIRQA ( 1 << 8) /* SDIO IRQ in slot A */
-# define ATMCI_SDIOIRQB ( 1 << 9) /* SDIO IRQ in slot B */
-# define ATMCI_SDIOWAIT ( 1 << 12) /* SDIO Read Wait Operation Status */
-# define ATMCI_CSRCV ( 1 << 13) /* CE-ATA Completion Signal Received */
-# define ATMCI_RXBUFF ( 1 << 14) /* RX Buffer Full */
-# define ATMCI_TXBUFE ( 1 << 15) /* TX Buffer Empty */
-# define ATMCI_RINDE ( 1 << 16) /* Response Index Error */
-# define ATMCI_RDIRE ( 1 << 17) /* Response Direction Error */
-# define ATMCI_RCRCE ( 1 << 18) /* Response CRC Error */
-# define ATMCI_RENDE ( 1 << 19) /* Response End Bit Error */
-# define ATMCI_RTOE ( 1 << 20) /* Response Time-Out Error */
-# define ATMCI_DCRCE ( 1 << 21) /* Data CRC Error */
-# define ATMCI_DTOE ( 1 << 22) /* Data Time-Out Error */
-# define ATMCI_CSTOE ( 1 << 23) /* Completion Signal Time-out Error */
-# define ATMCI_BLKOVRE ( 1 << 24) /* DMA Block Overrun Error */
-# define ATMCI_DMADONE ( 1 << 25) /* DMA Transfer Done */
-# define ATMCI_FIFOEMPTY ( 1 << 26) /* FIFO Empty Flag */
-# define ATMCI_XFRDONE ( 1 << 27) /* Transfer Done Flag */
-# define ATMCI_ACKRCV ( 1 << 28) /* Boot Operation Acknowledge Received */
-# define ATMCI_ACKRCVE ( 1 << 29) /* Boot Operation Acknowledge Error */
-# define ATMCI_OVRE ( 1 << 30) /* RX Overrun Error */
-# define ATMCI_UNRE ( 1 << 31) /* TX Underrun Error */
-#define ATMCI_DMA 0x0050 /* DMA Configuration[2] */
-# define ATMCI_DMA_OFFSET(x) ((x) << 0) /* DMA Write Buffer Offset */
-# define ATMCI_DMA_CHKSIZE(x) ((x) << 4) /* DMA Channel Read and Write Chunk Size */
-# define ATMCI_DMAEN ( 1 << 8) /* DMA Hardware Handshaking Enable */
-#define ATMCI_CFG 0x0054 /* Configuration[2] */
-# define ATMCI_CFG_FIFOMODE_1DATA ( 1 << 0) /* MCI Internal FIFO control mode */
-# define ATMCI_CFG_FERRCTRL_COR ( 1 << 4) /* Flow Error flag reset control mode */
-# define ATMCI_CFG_HSMODE ( 1 << 8) /* High Speed Mode */
-# define ATMCI_CFG_LSYNC ( 1 << 12) /* Synchronize on the last block */
-#define ATMCI_WPMR 0x00e4 /* Write Protection Mode[2] */
-# define ATMCI_WP_EN ( 1 << 0) /* WP Enable */
-# define ATMCI_WP_KEY (0x4d4349 << 8) /* WP Key */
-#define ATMCI_WPSR 0x00e8 /* Write Protection Status[2] */
-# define ATMCI_GET_WP_VS(x) ((x) & 0x0f)
-# define ATMCI_GET_WP_VSRC(x) (((x) >> 8) & 0xffff)
-#define ATMCI_VERSION 0x00FC /* Version */
-#define ATMCI_FIFO_APERTURE 0x0200 /* FIFO Aperture[2] */
-
-/* This is not including the FIFO Aperture on MCI2 */
-#define ATMCI_REGS_SIZE 0x100
-
-/* Register access macros */
-#ifdef CONFIG_AVR32
-#define atmci_readl(port, reg) \
- __raw_readl((port)->regs + reg)
-#define atmci_writel(port, reg, value) \
- __raw_writel((value), (port)->regs + reg)
-#else
-#define atmci_readl(port, reg) \
- readl_relaxed((port)->regs + reg)
-#define atmci_writel(port, reg, value) \
- writel_relaxed((value), (port)->regs + reg)
-#endif
-
-/* On AVR chips the Peripheral DMA Controller is not connected to MCI. */
-#ifdef CONFIG_AVR32
-# define ATMCI_PDC_CONNECTED 0
-#else
-# define ATMCI_PDC_CONNECTED 1
-#endif
-
-/*
- * Fix sconfig's burst size according to atmel MCI. We need to convert them as:
- * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3.
- *
- * This can be done by finding most significant bit set.
- */
-static inline unsigned int atmci_convert_chksize(unsigned int maxburst)
-{
- if (maxburst > 1)
- return fls(maxburst) - 2;
- else
- return 0;
-}
-
-#endif /* __DRIVERS_MMC_ATMEL_MCI_H__ */
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index bf62e429f7fc..a36ebdae2388 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -44,7 +44,141 @@
#include <asm/io.h>
#include <asm/unaligned.h>
-#include "atmel-mci-regs.h"
+/*
+ * Superset of MCI IP registers integrated in Atmel AVR32 and AT91 Processors
+ * Registers and bitfields marked with [2] are only available in MCI2
+ */
+
+/* MCI Register Definitions */
+#define ATMCI_CR 0x0000 /* Control */
+#define ATMCI_CR_MCIEN BIT(0) /* MCI Enable */
+#define ATMCI_CR_MCIDIS BIT(1) /* MCI Disable */
+#define ATMCI_CR_PWSEN BIT(2) /* Power Save Enable */
+#define ATMCI_CR_PWSDIS BIT(3) /* Power Save Disable */
+#define ATMCI_CR_SWRST BIT(7) /* Software Reset */
+#define ATMCI_MR 0x0004 /* Mode */
+#define ATMCI_MR_CLKDIV(x) ((x) << 0) /* Clock Divider */
+#define ATMCI_MR_PWSDIV(x) ((x) << 8) /* Power Saving Divider */
+#define ATMCI_MR_RDPROOF BIT(11) /* Read Proof */
+#define ATMCI_MR_WRPROOF BIT(12) /* Write Proof */
+#define ATMCI_MR_PDCFBYTE BIT(13) /* Force Byte Transfer */
+#define ATMCI_MR_PDCPADV BIT(14) /* Padding Value */
+#define ATMCI_MR_PDCMODE BIT(15) /* PDC-oriented Mode */
+#define ATMCI_MR_CLKODD(x) ((x) << 16) /* LSB of Clock Divider */
+#define ATMCI_DTOR 0x0008 /* Data Timeout */
+#define ATMCI_DTOCYC(x) ((x) << 0) /* Data Timeout Cycles */
+#define ATMCI_DTOMUL(x) ((x) << 4) /* Data Timeout Multiplier */
+#define ATMCI_SDCR 0x000c /* SD Card / SDIO */
+#define ATMCI_SDCSEL_SLOT_A (0 << 0) /* Select SD slot A */
+#define ATMCI_SDCSEL_SLOT_B (1 << 0) /* Select SD slot A */
+#define ATMCI_SDCSEL_MASK (3 << 0)
+#define ATMCI_SDCBUS_1BIT (0 << 6) /* 1-bit data bus */
+#define ATMCI_SDCBUS_4BIT (2 << 6) /* 4-bit data bus */
+#define ATMCI_SDCBUS_8BIT (3 << 6) /* 8-bit data bus[2] */
+#define ATMCI_SDCBUS_MASK (3 << 6)
+#define ATMCI_ARGR 0x0010 /* Command Argument */
+#define ATMCI_CMDR 0x0014 /* Command */
+#define ATMCI_CMDR_CMDNB(x) ((x) << 0) /* Command Opcode */
+#define ATMCI_CMDR_RSPTYP_NONE (0 << 6) /* No response */
+#define ATMCI_CMDR_RSPTYP_48BIT (1 << 6) /* 48-bit response */
+#define ATMCI_CMDR_RSPTYP_136BIT (2 << 6) /* 136-bit response */
+#define ATMCI_CMDR_SPCMD_INIT (1 << 8) /* Initialization command */
+#define ATMCI_CMDR_SPCMD_SYNC (2 << 8) /* Synchronized command */
+#define ATMCI_CMDR_SPCMD_INT (4 << 8) /* Interrupt command */
+#define ATMCI_CMDR_SPCMD_INTRESP (5 << 8) /* Interrupt response */
+#define ATMCI_CMDR_OPDCMD (1 << 11) /* Open Drain */
+#define ATMCI_CMDR_MAXLAT_5CYC (0 << 12) /* Max latency 5 cycles */
+#define ATMCI_CMDR_MAXLAT_64CYC (1 << 12) /* Max latency 64 cycles */
+#define ATMCI_CMDR_START_XFER (1 << 16) /* Start data transfer */
+#define ATMCI_CMDR_STOP_XFER (2 << 16) /* Stop data transfer */
+#define ATMCI_CMDR_TRDIR_WRITE (0 << 18) /* Write data */
+#define ATMCI_CMDR_TRDIR_READ (1 << 18) /* Read data */
+#define ATMCI_CMDR_BLOCK (0 << 19) /* Single-block transfer */
+#define ATMCI_CMDR_MULTI_BLOCK (1 << 19) /* Multi-block transfer */
+#define ATMCI_CMDR_STREAM (2 << 19) /* MMC Stream transfer */
+#define ATMCI_CMDR_SDIO_BYTE (4 << 19) /* SDIO Byte transfer */
+#define ATMCI_CMDR_SDIO_BLOCK (5 << 19) /* SDIO Block transfer */
+#define ATMCI_CMDR_SDIO_SUSPEND (1 << 24) /* SDIO Suspend Command */
+#define ATMCI_CMDR_SDIO_RESUME (2 << 24) /* SDIO Resume Command */
+#define ATMCI_BLKR 0x0018 /* Block */
+#define ATMCI_BCNT(x) ((x) << 0) /* Data Block Count */
+#define ATMCI_BLKLEN(x) ((x) << 16) /* Data Block Length */
+#define ATMCI_CSTOR 0x001c /* Completion Signal Timeout[2] */
+#define ATMCI_CSTOCYC(x) ((x) << 0) /* CST cycles */
+#define ATMCI_CSTOMUL(x) ((x) << 4) /* CST multiplier */
+#define ATMCI_RSPR 0x0020 /* Response 0 */
+#define ATMCI_RSPR1 0x0024 /* Response 1 */
+#define ATMCI_RSPR2 0x0028 /* Response 2 */
+#define ATMCI_RSPR3 0x002c /* Response 3 */
+#define ATMCI_RDR 0x0030 /* Receive Data */
+#define ATMCI_TDR 0x0034 /* Transmit Data */
+#define ATMCI_SR 0x0040 /* Status */
+#define ATMCI_IER 0x0044 /* Interrupt Enable */
+#define ATMCI_IDR 0x0048 /* Interrupt Disable */
+#define ATMCI_IMR 0x004c /* Interrupt Mask */
+#define ATMCI_CMDRDY BIT(0) /* Command Ready */
+#define ATMCI_RXRDY BIT(1) /* Receiver Ready */
+#define ATMCI_TXRDY BIT(2) /* Transmitter Ready */
+#define ATMCI_BLKE BIT(3) /* Data Block Ended */
+#define ATMCI_DTIP BIT(4) /* Data Transfer In Progress */
+#define ATMCI_NOTBUSY BIT(5) /* Data Not Busy */
+#define ATMCI_ENDRX BIT(6) /* End of RX Buffer */
+#define ATMCI_ENDTX BIT(7) /* End of TX Buffer */
+#define ATMCI_SDIOIRQA BIT(8) /* SDIO IRQ in slot A */
+#define ATMCI_SDIOIRQB BIT(9) /* SDIO IRQ in slot B */
+#define ATMCI_SDIOWAIT BIT(12) /* SDIO Read Wait Operation Status */
+#define ATMCI_CSRCV BIT(13) /* CE-ATA Completion Signal Received */
+#define ATMCI_RXBUFF BIT(14) /* RX Buffer Full */
+#define ATMCI_TXBUFE BIT(15) /* TX Buffer Empty */
+#define ATMCI_RINDE BIT(16) /* Response Index Error */
+#define ATMCI_RDIRE BIT(17) /* Response Direction Error */
+#define ATMCI_RCRCE BIT(18) /* Response CRC Error */
+#define ATMCI_RENDE BIT(19) /* Response End Bit Error */
+#define ATMCI_RTOE BIT(20) /* Response Time-Out Error */
+#define ATMCI_DCRCE BIT(21) /* Data CRC Error */
+#define ATMCI_DTOE BIT(22) /* Data Time-Out Error */
+#define ATMCI_CSTOE BIT(23) /* Completion Signal Time-out Error */
+#define ATMCI_BLKOVRE BIT(24) /* DMA Block Overrun Error */
+#define ATMCI_DMADONE BIT(25) /* DMA Transfer Done */
+#define ATMCI_FIFOEMPTY BIT(26) /* FIFO Empty Flag */
+#define ATMCI_XFRDONE BIT(27) /* Transfer Done Flag */
+#define ATMCI_ACKRCV BIT(28) /* Boot Operation Acknowledge Received */
+#define ATMCI_ACKRCVE BIT(29) /* Boot Operation Acknowledge Error */
+#define ATMCI_OVRE BIT(30) /* RX Overrun Error */
+#define ATMCI_UNRE BIT(31) /* TX Underrun Error */
+#define ATMCI_DMA 0x0050 /* DMA Configuration[2] */
+#define ATMCI_DMA_OFFSET(x) ((x) << 0) /* DMA Write Buffer Offset */
+#define ATMCI_DMA_CHKSIZE(x) ((x) << 4) /* DMA Channel Read and Write Chunk Size */
+#define ATMCI_DMAEN BIT(8) /* DMA Hardware Handshaking Enable */
+#define ATMCI_CFG 0x0054 /* Configuration[2] */
+#define ATMCI_CFG_FIFOMODE_1DATA BIT(0) /* MCI Internal FIFO control mode */
+#define ATMCI_CFG_FERRCTRL_COR BIT(4) /* Flow Error flag reset control mode */
+#define ATMCI_CFG_HSMODE BIT(8) /* High Speed Mode */
+#define ATMCI_CFG_LSYNC BIT(12) /* Synchronize on the last block */
+#define ATMCI_WPMR 0x00e4 /* Write Protection Mode[2] */
+#define ATMCI_WP_EN BIT(0) /* WP Enable */
+#define ATMCI_WP_KEY (0x4d4349 << 8) /* WP Key */
+#define ATMCI_WPSR 0x00e8 /* Write Protection Status[2] */
+#define ATMCI_GET_WP_VS(x) ((x) & 0x0f)
+#define ATMCI_GET_WP_VSRC(x) (((x) >> 8) & 0xffff)
+#define ATMCI_VERSION 0x00FC /* Version */
+#define ATMCI_FIFO_APERTURE 0x0200 /* FIFO Aperture[2] */
+
+/* This is not including the FIFO Aperture on MCI2 */
+#define ATMCI_REGS_SIZE 0x100
+
+/* Register access macros */
+#define atmci_readl(port, reg) \
+ __raw_readl((port)->regs + reg)
+#define atmci_writel(port, reg, value) \
+ __raw_writel((value), (port)->regs + reg)
+
+/* On AVR chips the Peripheral DMA Controller is not connected to MCI. */
+#ifdef CONFIG_AVR32
+# define ATMCI_PDC_CONNECTED 0
+#else
+# define ATMCI_PDC_CONNECTED 1
+#endif
#define AUTOSUSPEND_DELAY 50
@@ -584,6 +718,29 @@ static inline unsigned int atmci_get_version(struct atmel_mci *host)
return atmci_readl(host, ATMCI_VERSION) & 0x00000fff;
}
+/*
+ * Fix sconfig's burst size according to atmel MCI. We need to convert them as:
+ * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3.
+ * With version 0x600, we need to convert them as: 1 -> 0, 2 -> 1, 4 -> 2,
+ * 8 -> 3, 16 -> 4.
+ *
+ * This can be done by finding most significant bit set.
+ */
+static inline unsigned int atmci_convert_chksize(struct atmel_mci *host,
+ unsigned int maxburst)
+{
+ unsigned int version = atmci_get_version(host);
+ unsigned int offset = 2;
+
+ if (version >= 0x600)
+ offset = 1;
+
+ if (maxburst > 1)
+ return fls(maxburst) - offset;
+ else
+ return 0;
+}
+
static void atmci_timeout_timer(unsigned long data)
{
struct atmel_mci *host;
@@ -1034,11 +1191,13 @@ atmci_prepare_data_dma(struct atmel_mci *host, struct mmc_data *data)
if (data->flags & MMC_DATA_READ) {
direction = DMA_FROM_DEVICE;
host->dma_conf.direction = slave_dirn = DMA_DEV_TO_MEM;
- maxburst = atmci_convert_chksize(host->dma_conf.src_maxburst);
+ maxburst = atmci_convert_chksize(host,
+ host->dma_conf.src_maxburst);
} else {
direction = DMA_TO_DEVICE;
host->dma_conf.direction = slave_dirn = DMA_MEM_TO_DEV;
- maxburst = atmci_convert_chksize(host->dma_conf.dst_maxburst);
+ maxburst = atmci_convert_chksize(host,
+ host->dma_conf.dst_maxburst);
}
if (host->caps.has_dma_conf_reg)
diff --git a/drivers/mmc/host/cb710-mmc.h b/drivers/mmc/host/cb710-mmc.h
index 8984ec878fc9..8ecd9e56636a 100644
--- a/drivers/mmc/host/cb710-mmc.h
+++ b/drivers/mmc/host/cb710-mmc.h
@@ -29,8 +29,7 @@ static inline struct mmc_host *cb710_slot_to_mmc(struct cb710_slot *slot)
static inline struct cb710_slot *cb710_mmc_to_slot(struct mmc_host *mmc)
{
- struct platform_device *pdev = container_of(mmc_dev(mmc),
- struct platform_device, dev);
+ struct platform_device *pdev = to_platform_device(mmc_dev(mmc));
return cb710_pdev_to_slot(pdev);
}
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index 7e1d13b68b06..81bdeeb05a4d 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -60,7 +60,7 @@ int dw_mci_pltfm_register(struct platform_device *pdev,
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
/* Get registers' physical base address */
- host->phy_regs = (void *)(regs->start);
+ host->phy_regs = regs->start;
host->regs = devm_ioremap_resource(&pdev->dev, regs);
if (IS_ERR(host->regs))
return PTR_ERR(host->regs);
diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c
index 9becebeeccd1..d9c92f31da64 100644
--- a/drivers/mmc/host/dw_mmc-rockchip.c
+++ b/drivers/mmc/host/dw_mmc-rockchip.c
@@ -239,20 +239,12 @@ static int dw_mci_rockchip_init(struct dw_mci *host)
return 0;
}
-/* Common capabilities of RK3288 SoC */
-static unsigned long dw_mci_rk3288_dwmmc_caps[4] = {
- MMC_CAP_RUNTIME_RESUME, /* emmc */
- MMC_CAP_RUNTIME_RESUME, /* sdmmc */
- MMC_CAP_RUNTIME_RESUME, /* sdio0 */
- MMC_CAP_RUNTIME_RESUME, /* sdio1 */
-};
static const struct dw_mci_drv_data rk2928_drv_data = {
.prepare_command = dw_mci_rockchip_prepare_command,
.init = dw_mci_rockchip_init,
};
static const struct dw_mci_drv_data rk3288_drv_data = {
- .caps = dw_mci_rk3288_dwmmc_caps,
.prepare_command = dw_mci_rockchip_prepare_command,
.set_ios = dw_mci_rk3288_set_ios,
.execute_tuning = dw_mci_rk3288_execute_tuning,
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 7a6cedbe48a8..712835177e8b 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -699,7 +699,7 @@ static int dw_mci_edmac_start_dma(struct dw_mci *host,
int ret = 0;
/* Set external dma config: burst size, burst width */
- cfg.dst_addr = (dma_addr_t)(host->phy_regs + fifo_offset);
+ cfg.dst_addr = host->phy_regs + fifo_offset;
cfg.src_addr = cfg.dst_addr;
cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
@@ -1634,12 +1634,6 @@ static int dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd)
else
cmd->error = 0;
- if (cmd->error) {
- /* newer ip versions need a delay between retries */
- if (host->quirks & DW_MCI_QUIRK_RETRY_DELAY)
- mdelay(20);
- }
-
return cmd->error;
}
@@ -2355,16 +2349,6 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
pending = mci_readl(host, MINTSTS); /* read-only mask reg */
- /*
- * DTO fix - version 2.10a and below, and only if internal DMA
- * is configured.
- */
- if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) {
- if (!pending &&
- ((mci_readl(host, STATUS) >> 17) & 0x1fff))
- pending |= SDMMC_INT_DATA_OVER;
- }
-
if (pending) {
/* Check volt switch first, since it can look like an error */
if ((host->state == STATE_SENDING_CMD11) &&
@@ -3165,9 +3149,6 @@ int dw_mci_probe(struct dw_mci *host)
/* Now that slots are all setup, we can enable card detect */
dw_mci_enable_cd(host);
- if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
- dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n");
-
return 0;
err_dmaunmap:
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index 33dfd7e72516..82a97ac4e956 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -972,7 +972,7 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
if ((events & MSDC_INT_XFER_COMPL) && (!stop || !stop->error)) {
data->bytes_xfered = data->blocks * data->blksz;
} else {
- dev_err(host->dev, "interrupt events: %x\n", events);
+ dev_dbg(host->dev, "interrupt events: %x\n", events);
msdc_reset_hw(host);
host->error |= REQ_DAT_ERR;
data->bytes_xfered = 0;
@@ -982,10 +982,10 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events,
else if (events & MSDC_INT_DATCRCERR)
data->error = -EILSEQ;
- dev_err(host->dev, "%s: cmd=%d; blocks=%d",
+ dev_dbg(host->dev, "%s: cmd=%d; blocks=%d",
__func__, mrq->cmd->opcode, data->blocks);
- dev_err(host->dev, "data_error=%d xfer_size=%d\n",
- (int)data->error, data->bytes_xfered);
+ dev_dbg(host->dev, "data_error=%d xfer_size=%d\n",
+ (int)data->error, data->bytes_xfered);
}
msdc_data_xfer_next(host, mrq, data);
@@ -1543,7 +1543,6 @@ static int msdc_drv_probe(struct platform_device *pdev)
mmc->f_min = host->src_clk_freq / (4 * 255);
mmc->caps |= MMC_CAP_ERASE | MMC_CAP_CMD23;
- mmc->caps |= MMC_CAP_RUNTIME_RESUME;
/* MMC core transfer sizes tunable parameters */
mmc->max_segs = MAX_BD_NUM;
mmc->max_seg_size = BDMA_DESC_BUFLEN;
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index a448498e3af2..42296e55b9de 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -20,15 +20,12 @@
#include <linux/scatterlist.h>
#include <linux/irq.h>
#include <linux/clk.h>
-#include <linux/gpio.h>
-#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/mmc/host.h>
#include <linux/mmc/slot-gpio.h>
#include <asm/sizes.h>
#include <asm/unaligned.h>
-#include <linux/platform_data/mmc-mvsdio.h>
#include "mvsdio.h"
@@ -704,6 +701,10 @@ static int mvsd_probe(struct platform_device *pdev)
struct resource *r;
int ret, irq;
+ if (!np) {
+ dev_err(&pdev->dev, "no DT node\n");
+ return -ENODEV;
+ }
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
if (!r || irq < 0)
@@ -727,8 +728,12 @@ static int mvsd_probe(struct platform_device *pdev)
* fixed rate clock).
*/
host->clk = devm_clk_get(&pdev->dev, NULL);
- if (!IS_ERR(host->clk))
- clk_prepare_enable(host->clk);
+ if (IS_ERR(host->clk)) {
+ dev_err(&pdev->dev, "no clock associated\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ clk_prepare_enable(host->clk);
mmc->ops = &mvsd_ops;
@@ -744,45 +749,10 @@ static int mvsd_probe(struct platform_device *pdev)
mmc->max_seg_size = mmc->max_blk_size * mmc->max_blk_count;
mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
- if (np) {
- if (IS_ERR(host->clk)) {
- dev_err(&pdev->dev, "DT platforms must have a clock associated\n");
- ret = -EINVAL;
- goto out;
- }
-
- host->base_clock = clk_get_rate(host->clk) / 2;
- ret = mmc_of_parse(mmc);
- if (ret < 0)
- goto out;
- } else {
- const struct mvsdio_platform_data *mvsd_data;
-
- mvsd_data = pdev->dev.platform_data;
- if (!mvsd_data) {
- ret = -ENXIO;
- goto out;
- }
- mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ |
- MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
- host->base_clock = mvsd_data->clock / 2;
- /* GPIO 0 regarded as invalid for backward compatibility */
- if (mvsd_data->gpio_card_detect &&
- gpio_is_valid(mvsd_data->gpio_card_detect)) {
- ret = mmc_gpio_request_cd(mmc,
- mvsd_data->gpio_card_detect,
- 0);
- if (ret)
- goto out;
- } else {
- mmc->caps |= MMC_CAP_NEEDS_POLL;
- }
-
- if (mvsd_data->gpio_write_protect &&
- gpio_is_valid(mvsd_data->gpio_write_protect))
- mmc_gpio_request_ro(mmc, mvsd_data->gpio_write_protect);
- }
-
+ host->base_clock = clk_get_rate(host->clk) / 2;
+ ret = mmc_of_parse(mmc);
+ if (ret < 0)
+ goto out;
if (maxfreq)
mmc->f_max = maxfreq;
diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c
index 6e218fb1a669..660170cd04d9 100644
--- a/drivers/mmc/host/of_mmc_spi.c
+++ b/drivers/mmc/host/of_mmc_spi.c
@@ -55,8 +55,8 @@ static int of_mmc_spi_init(struct device *dev,
{
struct of_mmc_spi *oms = to_of_mmc_spi(dev);
- return request_threaded_irq(oms->detect_irq, NULL, irqhandler, 0,
- dev_name(dev), mmc);
+ return request_threaded_irq(oms->detect_irq, NULL, irqhandler,
+ IRQF_ONESHOT, dev_name(dev), mmc);
}
static void of_mmc_spi_exit(struct device *dev, void *mmc)
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 7fb0753abe30..b6639ea0bf18 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -2250,10 +2250,8 @@ static int omap_hsmmc_remove(struct platform_device *pdev)
pm_runtime_get_sync(host->dev);
mmc_remove_host(host->mmc);
- if (host->tx_chan)
- dma_release_channel(host->tx_chan);
- if (host->rx_chan)
- dma_release_channel(host->rx_chan);
+ dma_release_channel(host->tx_chan);
+ dma_release_channel(host->rx_chan);
pm_runtime_put_sync(host->dev);
pm_runtime_disable(host->dev);
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index 1f1582f6cccb..f25f29253595 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -76,6 +76,7 @@
#define ESDHC_STD_TUNING_EN (1 << 24)
/* NOTE: the minimum valid tuning start tap for mx6sl is 1 */
#define ESDHC_TUNING_START_TAP 0x1
+#define ESDHC_TUNING_STEP_MASK 0x00070000
#define ESDHC_TUNING_STEP_SHIFT 16
/* pinctrl state */
@@ -489,9 +490,11 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
m |= ESDHC_MIX_CTRL_FBCLK_SEL;
tuning_ctrl = readl(host->ioaddr + ESDHC_TUNING_CTRL);
tuning_ctrl |= ESDHC_STD_TUNING_EN | ESDHC_TUNING_START_TAP;
- if (imx_data->boarddata.tuning_step)
+ if (imx_data->boarddata.tuning_step) {
+ tuning_ctrl &= ~ESDHC_TUNING_STEP_MASK;
tuning_ctrl |= imx_data->boarddata.tuning_step << ESDHC_TUNING_STEP_SHIFT;
- writel(tuning_ctrl, host->ioaddr + ESDHC_TUNING_CTRL);
+ }
+ writel(tuning_ctrl, host->ioaddr + ESDHC_TUNING_CTRL);
} else {
v &= ~ESDHC_MIX_CTRL_EXE_TUNE;
}
diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c
index 06d0b50dfe71..7e7d8f0c9438 100644
--- a/drivers/mmc/host/sdhci-of-at91.c
+++ b/drivers/mmc/host/sdhci-of-at91.c
@@ -21,6 +21,8 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
#include "sdhci-pltfm.h"
@@ -51,6 +53,60 @@ static const struct of_device_id sdhci_at91_dt_match[] = {
{}
};
+#ifdef CONFIG_PM
+static int sdhci_at91_runtime_suspend(struct device *dev)
+{
+ struct sdhci_host *host = dev_get_drvdata(dev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_at91_priv *priv = pltfm_host->priv;
+ int ret;
+
+ ret = sdhci_runtime_suspend_host(host);
+
+ clk_disable_unprepare(priv->gck);
+ clk_disable_unprepare(priv->hclock);
+ clk_disable_unprepare(priv->mainck);
+
+ return ret;
+}
+
+static int sdhci_at91_runtime_resume(struct device *dev)
+{
+ struct sdhci_host *host = dev_get_drvdata(dev);
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_at91_priv *priv = pltfm_host->priv;
+ int ret;
+
+ ret = clk_prepare_enable(priv->mainck);
+ if (ret) {
+ dev_err(dev, "can't enable mainck\n");
+ return ret;
+ }
+
+ ret = clk_prepare_enable(priv->hclock);
+ if (ret) {
+ dev_err(dev, "can't enable hclock\n");
+ return ret;
+ }
+
+ ret = clk_prepare_enable(priv->gck);
+ if (ret) {
+ dev_err(dev, "can't enable gck\n");
+ return ret;
+ }
+
+ return sdhci_runtime_resume_host(host);
+}
+#endif /* CONFIG_PM */
+
+static const struct dev_pm_ops sdhci_at91_dev_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+ pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(sdhci_at91_runtime_suspend,
+ sdhci_at91_runtime_resume,
+ NULL)
+};
+
static int sdhci_at91_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
@@ -144,12 +200,23 @@ static int sdhci_at91_probe(struct platform_device *pdev)
sdhci_get_of_property(pdev);
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
+ pm_runtime_use_autosuspend(&pdev->dev);
+
ret = sdhci_add_host(host);
if (ret)
- goto clocks_disable_unprepare;
+ goto pm_runtime_disable;
+
+ pm_runtime_put_autosuspend(&pdev->dev);
return 0;
+pm_runtime_disable:
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
clocks_disable_unprepare:
clk_disable_unprepare(priv->gck);
clk_disable_unprepare(priv->mainck);
@@ -165,6 +232,10 @@ static int sdhci_at91_remove(struct platform_device *pdev)
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_at91_priv *priv = pltfm_host->priv;
+ pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+
sdhci_pltfm_unregister(pdev);
clk_disable_unprepare(priv->gck);
@@ -178,7 +249,7 @@ static struct platform_driver sdhci_at91_driver = {
.driver = {
.name = "sdhci-at91",
.of_match_table = sdhci_at91_dt_match,
- .pm = SDHCI_PLTFM_PMOPS,
+ .pm = &sdhci_at91_dev_pm_ops,
},
.probe = sdhci_at91_probe,
.remove = sdhci_at91_remove,
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c
index 90e94a028a49..83b1226471c1 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -584,6 +584,8 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
{
struct sdhci_host *host;
struct device_node *np;
+ struct sdhci_pltfm_host *pltfm_host;
+ struct sdhci_esdhc *esdhc;
int ret;
np = pdev->dev.of_node;
@@ -600,6 +602,14 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
sdhci_get_of_property(pdev);
+ pltfm_host = sdhci_priv(host);
+ esdhc = pltfm_host->priv;
+ if (esdhc->vendor_ver == VENDOR_V_22)
+ host->quirks2 |= SDHCI_QUIRK2_HOST_NO_CMD23;
+
+ if (esdhc->vendor_ver > VENDOR_V_22)
+ host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
+
if (of_device_is_compatible(np, "fsl,p5040-esdhc") ||
of_device_is_compatible(np, "fsl,p5020-esdhc") ||
of_device_is_compatible(np, "fsl,p4080-esdhc") ||
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index cf7ad458b4f4..cc851b065d0a 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -277,7 +277,7 @@ static int spt_select_drive_strength(struct sdhci_host *host,
if (sdhci_pci_spt_drive_strength > 0)
drive_strength = sdhci_pci_spt_drive_strength & 0xf;
else
- drive_strength = 1; /* 33-ohm */
+ drive_strength = 0; /* Default 50-ohm */
if ((mmc_driver_type_mask(drive_strength) & card_drv) == 0)
drive_strength = 0; /* Default 50-ohm */
@@ -1464,7 +1464,7 @@ static int sdhci_pci_resume(struct device *dev)
static int sdhci_pci_runtime_suspend(struct device *dev)
{
- struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+ struct pci_dev *pdev = to_pci_dev(dev);
struct sdhci_pci_chip *chip;
struct sdhci_pci_slot *slot;
int i, ret;
@@ -1500,7 +1500,7 @@ err_pci_runtime_suspend:
static int sdhci_pci_runtime_resume(struct device *dev)
{
- struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
+ struct pci_dev *pdev = to_pci_dev(dev);
struct sdhci_pci_chip *chip;
struct sdhci_pci_slot *slot;
int i, ret;
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c
index 87fb5ea8ebe7..072bb27a65cf 100644
--- a/drivers/mmc/host/sdhci-pltfm.c
+++ b/drivers/mmc/host/sdhci-pltfm.c
@@ -104,7 +104,8 @@ void sdhci_get_of_property(struct platform_device *pdev)
if (of_find_property(np, "keep-power-in-suspend", NULL))
host->mmc->pm_caps |= MMC_PM_KEEP_POWER;
- if (of_find_property(np, "enable-sdio-wakeup", NULL))
+ if (of_property_read_bool(np, "wakeup-source") ||
+ of_property_read_bool(np, "enable-sdio-wakeup")) /* legacy */
host->mmc->pm_caps |= MMC_PM_WAKE_SDIO_IRQ;
}
#else
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index ad28b49f0203..83c4bf7bc16c 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -22,12 +22,20 @@
#include <linux/of_device.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
#include <linux/mmc/slot-gpio.h>
#include <linux/gpio/consumer.h>
#include "sdhci-pltfm.h"
/* Tegra SDHOST controller vendor register definitions */
+#define SDHCI_TEGRA_VENDOR_CLOCK_CTRL 0x100
+#define SDHCI_CLOCK_CTRL_TAP_MASK 0x00ff0000
+#define SDHCI_CLOCK_CTRL_TAP_SHIFT 16
+#define SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE BIT(5)
+#define SDHCI_CLOCK_CTRL_PADPIPE_CLKEN_OVERRIDE BIT(3)
+#define SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE BIT(2)
+
#define SDHCI_TEGRA_VENDOR_MISC_CTRL 0x120
#define SDHCI_MISC_CTRL_ENABLE_SDR104 0x8
#define SDHCI_MISC_CTRL_ENABLE_SDR50 0x10
@@ -37,9 +45,9 @@
#define NVQUIRK_FORCE_SDHCI_SPEC_200 BIT(0)
#define NVQUIRK_ENABLE_BLOCK_GAP_DET BIT(1)
#define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2)
-#define NVQUIRK_DISABLE_SDR50 BIT(3)
-#define NVQUIRK_DISABLE_SDR104 BIT(4)
-#define NVQUIRK_DISABLE_DDR50 BIT(5)
+#define NVQUIRK_ENABLE_SDR50 BIT(3)
+#define NVQUIRK_ENABLE_SDR104 BIT(4)
+#define NVQUIRK_ENABLE_DDR50 BIT(5)
struct sdhci_tegra_soc_data {
const struct sdhci_pltfm_data *pdata;
@@ -49,6 +57,7 @@ struct sdhci_tegra_soc_data {
struct sdhci_tegra {
const struct sdhci_tegra_soc_data *soc_data;
struct gpio_desc *power_gpio;
+ bool ddr_signaling;
};
static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
@@ -124,25 +133,33 @@ static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask)
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_tegra *tegra_host = pltfm_host->priv;
const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
- u32 misc_ctrl;
+ u32 misc_ctrl, clk_ctrl;
sdhci_reset(host, mask);
if (!(mask & SDHCI_RESET_ALL))
return;
- misc_ctrl = sdhci_readw(host, SDHCI_TEGRA_VENDOR_MISC_CTRL);
+ misc_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_MISC_CTRL);
/* Erratum: Enable SDHCI spec v3.00 support */
if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300)
misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300;
- /* Don't advertise UHS modes which aren't supported yet */
- if (soc_data->nvquirks & NVQUIRK_DISABLE_SDR50)
- misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_SDR50;
- if (soc_data->nvquirks & NVQUIRK_DISABLE_DDR50)
- misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_DDR50;
- if (soc_data->nvquirks & NVQUIRK_DISABLE_SDR104)
- misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_SDR104;
- sdhci_writew(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);
+ /* Advertise UHS modes as supported by host */
+ if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR50)
+ misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR50;
+ if (soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
+ misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_DDR50;
+ if (soc_data->nvquirks & NVQUIRK_ENABLE_SDR104)
+ misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDR104;
+ sdhci_writel(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL);
+
+ clk_ctrl = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
+ clk_ctrl &= ~SDHCI_CLOCK_CTRL_SPI_MODE_CLKEN_OVERRIDE;
+ if (soc_data->nvquirks & SDHCI_MISC_CTRL_ENABLE_SDR50)
+ clk_ctrl |= SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE;
+ sdhci_writel(host, clk_ctrl, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
+
+ tegra_host->ddr_signaling = false;
}
static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width)
@@ -164,15 +181,99 @@ static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width)
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
}
+static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_tegra *tegra_host = pltfm_host->priv;
+ unsigned long host_clk;
+
+ if (!clock)
+ return;
+
+ host_clk = tegra_host->ddr_signaling ? clock * 2 : clock;
+ clk_set_rate(pltfm_host->clk, host_clk);
+ host->max_clk = clk_get_rate(pltfm_host->clk);
+
+ return sdhci_set_clock(host, clock);
+}
+
+static void tegra_sdhci_set_uhs_signaling(struct sdhci_host *host,
+ unsigned timing)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+ struct sdhci_tegra *tegra_host = pltfm_host->priv;
+
+ if (timing == MMC_TIMING_UHS_DDR50)
+ tegra_host->ddr_signaling = true;
+
+ return sdhci_set_uhs_signaling(host, timing);
+}
+
+static unsigned int tegra_sdhci_get_max_clock(struct sdhci_host *host)
+{
+ struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+
+ /*
+ * DDR modes require the host to run at double the card frequency, so
+ * the maximum rate we can support is half of the module input clock.
+ */
+ return clk_round_rate(pltfm_host->clk, UINT_MAX) / 2;
+}
+
+static void tegra_sdhci_set_tap(struct sdhci_host *host, unsigned int tap)
+{
+ u32 reg;
+
+ reg = sdhci_readl(host, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
+ reg &= ~SDHCI_CLOCK_CTRL_TAP_MASK;
+ reg |= tap << SDHCI_CLOCK_CTRL_TAP_SHIFT;
+ sdhci_writel(host, reg, SDHCI_TEGRA_VENDOR_CLOCK_CTRL);
+}
+
+static int tegra_sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
+{
+ unsigned int min, max;
+
+ /*
+ * Start search for minimum tap value at 10, as smaller values are
+ * may wrongly be reported as working but fail at higher speeds,
+ * according to the TRM.
+ */
+ min = 10;
+ while (min < 255) {
+ tegra_sdhci_set_tap(host, min);
+ if (!mmc_send_tuning(host->mmc, opcode, NULL))
+ break;
+ min++;
+ }
+
+ /* Find the maximum tap value that still passes. */
+ max = min + 1;
+ while (max < 255) {
+ tegra_sdhci_set_tap(host, max);
+ if (mmc_send_tuning(host->mmc, opcode, NULL)) {
+ max--;
+ break;
+ }
+ max++;
+ }
+
+ /* The TRM states the ideal tap value is at 75% in the passing range. */
+ tegra_sdhci_set_tap(host, min + ((max - min) * 3 / 4));
+
+ return mmc_send_tuning(host->mmc, opcode, NULL);
+}
+
static const struct sdhci_ops tegra_sdhci_ops = {
.get_ro = tegra_sdhci_get_ro,
.read_w = tegra_sdhci_readw,
.write_l = tegra_sdhci_writel,
- .set_clock = sdhci_set_clock,
+ .set_clock = tegra_sdhci_set_clock,
.set_bus_width = tegra_sdhci_set_bus_width,
.reset = tegra_sdhci_reset,
- .set_uhs_signaling = sdhci_set_uhs_signaling,
- .get_max_clock = sdhci_pltfm_clk_get_max_clock,
+ .platform_execute_tuning = tegra_sdhci_execute_tuning,
+ .set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
+ .get_max_clock = tegra_sdhci_get_max_clock,
};
static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
@@ -184,7 +285,7 @@ static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
.ops = &tegra_sdhci_ops,
};
-static struct sdhci_tegra_soc_data soc_data_tegra20 = {
+static const struct sdhci_tegra_soc_data soc_data_tegra20 = {
.pdata = &sdhci_tegra20_pdata,
.nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 |
NVQUIRK_ENABLE_BLOCK_GAP_DET,
@@ -197,14 +298,15 @@ static const struct sdhci_pltfm_data sdhci_tegra30_pdata = {
SDHCI_QUIRK_NO_HISPD_BIT |
SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
.ops = &tegra_sdhci_ops,
};
-static struct sdhci_tegra_soc_data soc_data_tegra30 = {
+static const struct sdhci_tegra_soc_data soc_data_tegra30 = {
.pdata = &sdhci_tegra30_pdata,
.nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300 |
- NVQUIRK_DISABLE_SDR50 |
- NVQUIRK_DISABLE_SDR104,
+ NVQUIRK_ENABLE_SDR50 |
+ NVQUIRK_ENABLE_SDR104,
};
static const struct sdhci_ops tegra114_sdhci_ops = {
@@ -212,11 +314,12 @@ static const struct sdhci_ops tegra114_sdhci_ops = {
.read_w = tegra_sdhci_readw,
.write_w = tegra_sdhci_writew,
.write_l = tegra_sdhci_writel,
- .set_clock = sdhci_set_clock,
+ .set_clock = tegra_sdhci_set_clock,
.set_bus_width = tegra_sdhci_set_bus_width,
.reset = tegra_sdhci_reset,
- .set_uhs_signaling = sdhci_set_uhs_signaling,
- .get_max_clock = sdhci_pltfm_clk_get_max_clock,
+ .platform_execute_tuning = tegra_sdhci_execute_tuning,
+ .set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
+ .get_max_clock = tegra_sdhci_get_max_clock,
};
static const struct sdhci_pltfm_data sdhci_tegra114_pdata = {
@@ -226,17 +329,34 @@ static const struct sdhci_pltfm_data sdhci_tegra114_pdata = {
SDHCI_QUIRK_NO_HISPD_BIT |
SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
.ops = &tegra114_sdhci_ops,
};
-static struct sdhci_tegra_soc_data soc_data_tegra114 = {
+static const struct sdhci_tegra_soc_data soc_data_tegra114 = {
.pdata = &sdhci_tegra114_pdata,
- .nvquirks = NVQUIRK_DISABLE_SDR50 |
- NVQUIRK_DISABLE_DDR50 |
- NVQUIRK_DISABLE_SDR104,
+ .nvquirks = NVQUIRK_ENABLE_SDR50 |
+ NVQUIRK_ENABLE_DDR50 |
+ NVQUIRK_ENABLE_SDR104,
+};
+
+static const struct sdhci_pltfm_data sdhci_tegra210_pdata = {
+ .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
+ SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
+ SDHCI_QUIRK_SINGLE_POWER_WRITE |
+ SDHCI_QUIRK_NO_HISPD_BIT |
+ SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
+ SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+ .ops = &tegra114_sdhci_ops,
+};
+
+static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
+ .pdata = &sdhci_tegra210_pdata,
};
static const struct of_device_id sdhci_tegra_dt_match[] = {
+ { .compatible = "nvidia,tegra210-sdhci", .data = &soc_data_tegra210 },
{ .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra114 },
{ .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 },
{ .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 },
@@ -271,6 +391,7 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
rc = -ENOMEM;
goto err_alloc_tegra_host;
}
+ tegra_host->ddr_signaling = false;
tegra_host->soc_data = soc_data;
pltfm_host->priv = tegra_host;
@@ -278,6 +399,9 @@ static int sdhci_tegra_probe(struct platform_device *pdev)
if (rc)
goto err_parse_dt;
+ if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
+ host->mmc->caps |= MMC_CAP_1_8V_DDR;
+
tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power",
GPIOD_OUT_HIGH);
if (IS_ERR(tegra_host->power_gpio)) {
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index b48565ed5616..d622435d1bcc 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -492,7 +492,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
host->align_buffer, host->align_buffer_sz, direction);
if (dma_mapping_error(mmc_dev(host->mmc), host->align_addr))
goto fail;
- BUG_ON(host->align_addr & host->align_mask);
+ BUG_ON(host->align_addr & SDHCI_ADMA2_MASK);
host->sg_count = sdhci_pre_dma_transfer(host, data);
if (host->sg_count < 0)
@@ -514,8 +514,8 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
* the (up to three) bytes that screw up the
* alignment.
*/
- offset = (host->align_sz - (addr & host->align_mask)) &
- host->align_mask;
+ offset = (SDHCI_ADMA2_ALIGN - (addr & SDHCI_ADMA2_MASK)) &
+ SDHCI_ADMA2_MASK;
if (offset) {
if (data->flags & MMC_DATA_WRITE) {
buffer = sdhci_kmap_atomic(sg, &flags);
@@ -529,8 +529,8 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
BUG_ON(offset > 65536);
- align += host->align_sz;
- align_addr += host->align_sz;
+ align += SDHCI_ADMA2_ALIGN;
+ align_addr += SDHCI_ADMA2_ALIGN;
desc += host->desc_sz;
@@ -540,9 +540,12 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
BUG_ON(len > 65536);
- /* tran, valid */
- sdhci_adma_write_desc(host, desc, addr, len, ADMA2_TRAN_VALID);
- desc += host->desc_sz;
+ if (len) {
+ /* tran, valid */
+ sdhci_adma_write_desc(host, desc, addr, len,
+ ADMA2_TRAN_VALID);
+ desc += host->desc_sz;
+ }
/*
* If this triggers then we have a calculation bug
@@ -608,7 +611,7 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
/* Do a quick scan of the SG list for any unaligned mappings */
has_unaligned = false;
for_each_sg(data->sg, sg, host->sg_count, i)
- if (sg_dma_address(sg) & host->align_mask) {
+ if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) {
has_unaligned = true;
break;
}
@@ -620,15 +623,15 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
align = host->align_buffer;
for_each_sg(data->sg, sg, host->sg_count, i) {
- if (sg_dma_address(sg) & host->align_mask) {
- size = host->align_sz -
- (sg_dma_address(sg) & host->align_mask);
+ if (sg_dma_address(sg) & SDHCI_ADMA2_MASK) {
+ size = SDHCI_ADMA2_ALIGN -
+ (sg_dma_address(sg) & SDHCI_ADMA2_MASK);
buffer = sdhci_kmap_atomic(sg, &flags);
memcpy(buffer, align, size);
sdhci_kunmap_atomic(buffer, &flags);
- align += host->align_sz;
+ align += SDHCI_ADMA2_ALIGN;
}
}
}
@@ -768,8 +771,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
if (unlikely(broken)) {
for_each_sg(data->sg, sg, data->sg_len, i) {
if (sg->length & 0x3) {
- DBG("Reverting to PIO because of "
- "transfer size (%d)\n",
+ DBG("Reverting to PIO because of transfer size (%d)\n",
sg->length);
host->flags &= ~SDHCI_REQ_USE_DMA;
break;
@@ -803,8 +805,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
if (unlikely(broken)) {
for_each_sg(data->sg, sg, data->sg_len, i) {
if (sg->offset & 0x3) {
- DBG("Reverting to PIO because of "
- "bad alignment\n");
+ DBG("Reverting to PIO because of bad alignment\n");
host->flags &= ~SDHCI_REQ_USE_DMA;
break;
}
@@ -1016,8 +1017,8 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) {
if (timeout == 0) {
- pr_err("%s: Controller never released "
- "inhibit bit(s).\n", mmc_hostname(host->mmc));
+ pr_err("%s: Controller never released inhibit bit(s).\n",
+ mmc_hostname(host->mmc));
sdhci_dumpregs(host);
cmd->error = -EIO;
tasklet_schedule(&host->finish_tasklet);
@@ -1254,8 +1255,8 @@ clock_set:
while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
& SDHCI_CLOCK_INT_STABLE)) {
if (timeout == 0) {
- pr_err("%s: Internal clock never "
- "stabilised.\n", mmc_hostname(host->mmc));
+ pr_err("%s: Internal clock never stabilised.\n",
+ mmc_hostname(host->mmc));
sdhci_dumpregs(host);
return;
}
@@ -1274,19 +1275,6 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
struct mmc_host *mmc = host->mmc;
u8 pwr = 0;
- if (!IS_ERR(mmc->supply.vmmc)) {
- spin_unlock_irq(&host->lock);
- mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
- spin_lock_irq(&host->lock);
-
- if (mode != MMC_POWER_OFF)
- sdhci_writeb(host, SDHCI_POWER_ON, SDHCI_POWER_CONTROL);
- else
- sdhci_writeb(host, 0, SDHCI_POWER_CONTROL);
-
- return;
- }
-
if (mode != MMC_POWER_OFF) {
switch (1 << vdd) {
case MMC_VDD_165_195:
@@ -1301,7 +1289,9 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
pwr = SDHCI_POWER_330;
break;
default:
- BUG();
+ WARN(1, "%s: Invalid vdd %#x\n",
+ mmc_hostname(host->mmc), vdd);
+ break;
}
}
@@ -1345,6 +1335,12 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned char mode,
if (host->quirks & SDHCI_QUIRK_DELAY_AFTER_POWER)
mdelay(10);
}
+
+ if (!IS_ERR(mmc->supply.vmmc)) {
+ spin_unlock_irq(&host->lock);
+ mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
+ spin_lock_irq(&host->lock);
+ }
}
/*****************************************************************************\
@@ -1540,8 +1536,8 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios)
else if (ios->drv_type == MMC_SET_DRIVER_TYPE_D)
ctrl_2 |= SDHCI_CTRL_DRV_TYPE_D;
else {
- pr_warn("%s: invalid driver type, default to "
- "driver type B\n", mmc_hostname(mmc));
+ pr_warn("%s: invalid driver type, default to driver type B\n",
+ mmc_hostname(mmc));
ctrl_2 |= SDHCI_CTRL_DRV_TYPE_B;
}
@@ -2015,10 +2011,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
spin_lock_irqsave(&host->lock, flags);
if (!host->tuning_done) {
- pr_info(DRIVER_NAME ": Timeout waiting for "
- "Buffer Read Ready interrupt during tuning "
- "procedure, falling back to fixed sampling "
- "clock\n");
+ pr_info(DRIVER_NAME ": Timeout waiting for Buffer Read Ready interrupt during tuning procedure, falling back to fixed sampling clock\n");
ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
ctrl &= ~SDHCI_CTRL_TUNED_CLK;
ctrl &= ~SDHCI_CTRL_EXEC_TUNING;
@@ -2046,9 +2039,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
}
if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) {
- pr_info(DRIVER_NAME ": Tuning procedure"
- " failed, falling back to fixed sampling"
- " clock\n");
+ pr_info(DRIVER_NAME ": Tuning procedure failed, falling back to fixed sampling clock\n");
err = -EIO;
}
@@ -2293,8 +2284,8 @@ static void sdhci_timeout_timer(unsigned long data)
spin_lock_irqsave(&host->lock, flags);
if (host->mrq) {
- pr_err("%s: Timeout waiting for hardware "
- "interrupt.\n", mmc_hostname(host->mmc));
+ pr_err("%s: Timeout waiting for hardware interrupt.\n",
+ mmc_hostname(host->mmc));
sdhci_dumpregs(host);
if (host->data) {
@@ -2325,9 +2316,8 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask)
BUG_ON(intmask == 0);
if (!host->cmd) {
- pr_err("%s: Got command interrupt 0x%08x even "
- "though no command operation was in progress.\n",
- mmc_hostname(host->mmc), (unsigned)intmask);
+ pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n",
+ mmc_hostname(host->mmc), (unsigned)intmask);
sdhci_dumpregs(host);
return;
}
@@ -2356,8 +2346,7 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *mask)
*/
if (host->cmd->flags & MMC_RSP_BUSY) {
if (host->cmd->data)
- DBG("Cannot wait for busy signal when also "
- "doing a data transfer");
+ DBG("Cannot wait for busy signal when also doing a data transfer");
else if (!(host->quirks & SDHCI_QUIRK_NO_BUSY_IRQ)
&& !host->busy_handle) {
/* Mark that command complete before busy is ended */
@@ -2451,9 +2440,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
}
}
- pr_err("%s: Got data interrupt 0x%08x even "
- "though no data operation was in progress.\n",
- mmc_hostname(host->mmc), (unsigned)intmask);
+ pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n",
+ mmc_hostname(host->mmc), (unsigned)intmask);
sdhci_dumpregs(host);
return;
@@ -2760,7 +2748,7 @@ static int sdhci_runtime_pm_put(struct sdhci_host *host)
static void sdhci_runtime_pm_bus_on(struct sdhci_host *host)
{
- if (host->runtime_suspended || host->bus_on)
+ if (host->bus_on)
return;
host->bus_on = true;
pm_runtime_get_noresume(host->mmc->parent);
@@ -2768,7 +2756,7 @@ static void sdhci_runtime_pm_bus_on(struct sdhci_host *host)
static void sdhci_runtime_pm_bus_off(struct sdhci_host *host)
{
- if (host->runtime_suspended || !host->bus_on)
+ if (!host->bus_on)
return;
host->bus_on = false;
pm_runtime_put_noidle(host->mmc->parent);
@@ -2896,9 +2884,8 @@ int sdhci_add_host(struct sdhci_host *host)
host->version = (host->version & SDHCI_SPEC_VER_MASK)
>> SDHCI_SPEC_VER_SHIFT;
if (host->version > SDHCI_SPEC_300) {
- pr_err("%s: Unknown controller version (%d). "
- "You may experience problems.\n", mmc_hostname(mmc),
- host->version);
+ pr_err("%s: Unknown controller version (%d). You may experience problems.\n",
+ mmc_hostname(mmc), host->version);
}
caps[0] = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? host->caps :
@@ -2967,24 +2954,17 @@ int sdhci_add_host(struct sdhci_host *host)
if (host->flags & SDHCI_USE_64_BIT_DMA) {
host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) *
SDHCI_ADMA2_64_DESC_SZ;
- host->align_buffer_sz = SDHCI_MAX_SEGS *
- SDHCI_ADMA2_64_ALIGN;
host->desc_sz = SDHCI_ADMA2_64_DESC_SZ;
- host->align_sz = SDHCI_ADMA2_64_ALIGN;
- host->align_mask = SDHCI_ADMA2_64_ALIGN - 1;
} else {
host->adma_table_sz = (SDHCI_MAX_SEGS * 2 + 1) *
SDHCI_ADMA2_32_DESC_SZ;
- host->align_buffer_sz = SDHCI_MAX_SEGS *
- SDHCI_ADMA2_32_ALIGN;
host->desc_sz = SDHCI_ADMA2_32_DESC_SZ;
- host->align_sz = SDHCI_ADMA2_32_ALIGN;
- host->align_mask = SDHCI_ADMA2_32_ALIGN - 1;
}
host->adma_table = dma_alloc_coherent(mmc_dev(mmc),
host->adma_table_sz,
&host->adma_addr,
GFP_KERNEL);
+ host->align_buffer_sz = SDHCI_MAX_SEGS * SDHCI_ADMA2_ALIGN;
host->align_buffer = kmalloc(host->align_buffer_sz, GFP_KERNEL);
if (!host->adma_table || !host->align_buffer) {
if (host->adma_table)
@@ -2998,7 +2978,7 @@ int sdhci_add_host(struct sdhci_host *host)
host->flags &= ~SDHCI_USE_ADMA;
host->adma_table = NULL;
host->align_buffer = NULL;
- } else if (host->adma_addr & host->align_mask) {
+ } else if (host->adma_addr & (SDHCI_ADMA2_DESC_ALIGN - 1)) {
pr_warn("%s: unable to allocate aligned ADMA descriptor\n",
mmc_hostname(mmc));
host->flags &= ~SDHCI_USE_ADMA;
@@ -3031,8 +3011,8 @@ int sdhci_add_host(struct sdhci_host *host)
if (host->max_clk == 0 || host->quirks &
SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) {
if (!host->ops->get_max_clock) {
- pr_err("%s: Hardware doesn't specify base clock "
- "frequency.\n", mmc_hostname(mmc));
+ pr_err("%s: Hardware doesn't specify base clock frequency.\n",
+ mmc_hostname(mmc));
return -ENODEV;
}
host->max_clk = host->ops->get_max_clock(host);
@@ -3294,8 +3274,8 @@ int sdhci_add_host(struct sdhci_host *host)
mmc->ocr_avail_mmc &= host->ocr_avail_mmc;
if (mmc->ocr_avail == 0) {
- pr_err("%s: Hardware doesn't report any "
- "support voltages.\n", mmc_hostname(mmc));
+ pr_err("%s: Hardware doesn't report any support voltages.\n",
+ mmc_hostname(mmc));
return -ENODEV;
}
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 9d4aa31b683a..7654ae5d2b4e 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -272,22 +272,27 @@
/* ADMA2 32-bit DMA descriptor size */
#define SDHCI_ADMA2_32_DESC_SZ 8
-/* ADMA2 32-bit DMA alignment */
-#define SDHCI_ADMA2_32_ALIGN 4
-
/* ADMA2 32-bit descriptor */
struct sdhci_adma2_32_desc {
__le16 cmd;
__le16 len;
__le32 addr;
-} __packed __aligned(SDHCI_ADMA2_32_ALIGN);
+} __packed __aligned(4);
+
+/* ADMA2 data alignment */
+#define SDHCI_ADMA2_ALIGN 4
+#define SDHCI_ADMA2_MASK (SDHCI_ADMA2_ALIGN - 1)
+
+/*
+ * ADMA2 descriptor alignment. Some controllers (e.g. Intel) require 8 byte
+ * alignment for the descriptor table even in 32-bit DMA mode. Memory
+ * allocation is at least 8 byte aligned anyway, so just stipulate 8 always.
+ */
+#define SDHCI_ADMA2_DESC_ALIGN 8
/* ADMA2 64-bit DMA descriptor size */
#define SDHCI_ADMA2_64_DESC_SZ 12
-/* ADMA2 64-bit DMA alignment */
-#define SDHCI_ADMA2_64_ALIGN 8
-
/*
* ADMA2 64-bit descriptor. Note 12-byte descriptor can't always be 8-byte
* aligned.
@@ -482,8 +487,6 @@ struct sdhci_host {
dma_addr_t align_addr; /* Mapped bounce buffer */
unsigned int desc_sz; /* ADMA descriptor size */
- unsigned int align_sz; /* ADMA alignment */
- unsigned int align_mask; /* ADMA alignment mask */
struct tasklet_struct finish_tasklet; /* Tasklet structures */
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index ad9ffea7d659..1ca8a1359cbc 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -397,38 +397,26 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
}
static struct dma_chan *
-sh_mmcif_request_dma_one(struct sh_mmcif_host *host,
- struct sh_mmcif_plat_data *pdata,
- enum dma_transfer_direction direction)
+sh_mmcif_request_dma_pdata(struct sh_mmcif_host *host, uintptr_t slave_id)
{
- struct dma_slave_config cfg = { 0, };
- struct dma_chan *chan;
- void *slave_data = NULL;
- struct resource *res;
- struct device *dev = sh_mmcif_host_to_dev(host);
dma_cap_mask_t mask;
- int ret;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
+ if (slave_id <= 0)
+ return NULL;
- if (pdata)
- slave_data = direction == DMA_MEM_TO_DEV ?
- (void *)pdata->slave_id_tx :
- (void *)pdata->slave_id_rx;
-
- chan = dma_request_slave_channel_compat(mask, shdma_chan_filter,
- slave_data, dev,
- direction == DMA_MEM_TO_DEV ? "tx" : "rx");
-
- dev_dbg(dev, "%s: %s: got channel %p\n", __func__,
- direction == DMA_MEM_TO_DEV ? "TX" : "RX", chan);
+ return dma_request_channel(mask, shdma_chan_filter, (void *)slave_id);
+}
- if (!chan)
- return NULL;
+static int sh_mmcif_dma_slave_config(struct sh_mmcif_host *host,
+ struct dma_chan *chan,
+ enum dma_transfer_direction direction)
+{
+ struct resource *res;
+ struct dma_slave_config cfg = { 0, };
res = platform_get_resource(host->pd, IORESOURCE_MEM, 0);
-
cfg.direction = direction;
if (direction == DMA_DEV_TO_MEM) {
@@ -439,38 +427,42 @@ sh_mmcif_request_dma_one(struct sh_mmcif_host *host,
cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
}
- ret = dmaengine_slave_config(chan, &cfg);
- if (ret < 0) {
- dma_release_channel(chan);
- return NULL;
- }
-
- return chan;
+ return dmaengine_slave_config(chan, &cfg);
}
-static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
- struct sh_mmcif_plat_data *pdata)
+static void sh_mmcif_request_dma(struct sh_mmcif_host *host)
{
struct device *dev = sh_mmcif_host_to_dev(host);
host->dma_active = false;
- if (pdata) {
- if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0)
- return;
- } else if (!dev->of_node) {
- return;
+ /* We can only either use DMA for both Tx and Rx or not use it at all */
+ if (IS_ENABLED(CONFIG_SUPERH) && dev->platform_data) {
+ struct sh_mmcif_plat_data *pdata = dev->platform_data;
+
+ host->chan_tx = sh_mmcif_request_dma_pdata(host,
+ pdata->slave_id_tx);
+ host->chan_rx = sh_mmcif_request_dma_pdata(host,
+ pdata->slave_id_rx);
+ } else {
+ host->chan_tx = dma_request_slave_channel(dev, "tx");
+ host->chan_tx = dma_request_slave_channel(dev, "rx");
}
+ dev_dbg(dev, "%s: got channel TX %p RX %p\n", __func__, host->chan_tx,
+ host->chan_rx);
- /* We can only either use DMA for both Tx and Rx or not use it at all */
- host->chan_tx = sh_mmcif_request_dma_one(host, pdata, DMA_MEM_TO_DEV);
- if (!host->chan_tx)
- return;
+ if (!host->chan_tx || !host->chan_rx ||
+ sh_mmcif_dma_slave_config(host, host->chan_tx, DMA_MEM_TO_DEV) ||
+ sh_mmcif_dma_slave_config(host, host->chan_rx, DMA_DEV_TO_MEM))
+ goto error;
- host->chan_rx = sh_mmcif_request_dma_one(host, pdata, DMA_DEV_TO_MEM);
- if (!host->chan_rx) {
+ return;
+
+error:
+ if (host->chan_tx)
dma_release_channel(host->chan_tx);
- host->chan_tx = NULL;
- }
+ if (host->chan_rx)
+ dma_release_channel(host->chan_rx);
+ host->chan_tx = host->chan_rx = NULL;
}
static void sh_mmcif_release_dma(struct sh_mmcif_host *host)
@@ -1102,7 +1094,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
if (ios->power_mode == MMC_POWER_UP) {
if (!host->card_present) {
/* See if we also get DMA */
- sh_mmcif_request_dma(host, dev->platform_data);
+ sh_mmcif_request_dma(host);
host->card_present = true;
}
sh_mmcif_set_power(host, ios);
diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c
index 4498e92116b8..b47122d3e8d8 100644
--- a/drivers/mmc/host/usdhi6rol0.c
+++ b/drivers/mmc/host/usdhi6rol0.c
@@ -1634,7 +1634,7 @@ static void usdhi6_timeout_work(struct work_struct *work)
struct usdhi6_host *host = container_of(d, struct usdhi6_host, timeout_work);
struct mmc_request *mrq = host->mrq;
struct mmc_data *data = mrq ? mrq->data : NULL;
- struct scatterlist *sg = host->sg ?: data->sg;
+ struct scatterlist *sg;
dev_warn(mmc_dev(host->mmc),
"%s timeout wait %u CMD%d: IRQ 0x%08x:0x%08x, last IRQ 0x%08x\n",
@@ -1666,6 +1666,7 @@ static void usdhi6_timeout_work(struct work_struct *work)
case USDHI6_WAIT_FOR_MWRITE:
case USDHI6_WAIT_FOR_READ:
case USDHI6_WAIT_FOR_WRITE:
+ sg = host->sg ?: data->sg;
dev_dbg(mmc_dev(host->mmc),
"%c: page #%u @ +0x%zx %ux%u in SG%u. Current SG %u bytes @ %u\n",
data->flags & MMC_DATA_READ ? 'R' : 'W', host->page_idx,
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 7eaa4c87fec7..7a0df3fdbfae 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -257,6 +257,7 @@ void pci_msi_mask_irq(struct irq_data *data)
{
msi_set_mask_bit(data, 1);
}
+EXPORT_SYMBOL_GPL(pci_msi_mask_irq);
/**
* pci_msi_unmask_irq - Generic irq chip callback to unmask PCI/MSI interrupts
@@ -266,6 +267,7 @@ void pci_msi_unmask_irq(struct irq_data *data)
{
msi_set_mask_bit(data, 0);
}
+EXPORT_SYMBOL_GPL(pci_msi_unmask_irq);
void default_restore_msi_irqs(struct pci_dev *dev)
{
@@ -1126,6 +1128,7 @@ struct pci_dev *msi_desc_to_pci_dev(struct msi_desc *desc)
{
return to_pci_dev(desc->dev);
}
+EXPORT_SYMBOL(msi_desc_to_pci_dev);
void *msi_desc_to_pci_sysdata(struct msi_desc *desc)
{
@@ -1285,6 +1288,7 @@ struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
domain->bus_token = DOMAIN_BUS_PCI_MSI;
return domain;
}
+EXPORT_SYMBOL_GPL(pci_msi_create_irq_domain);
/**
* pci_msi_domain_alloc_irqs - Allocate interrupts for @dev in @domain
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index a32ba753e413..d3f32d6417ef 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -9,7 +9,9 @@
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/irqdomain.h>
#include <linux/pci.h>
+#include <linux/msi.h>
#include <linux/pci_hotplug.h>
#include <linux/module.h>
#include <linux/pci-aspm.h>
@@ -689,6 +691,46 @@ static struct acpi_bus_type acpi_pci_bus = {
.cleanup = pci_acpi_cleanup,
};
+
+static struct fwnode_handle *(*pci_msi_get_fwnode_cb)(struct device *dev);
+
+/**
+ * pci_msi_register_fwnode_provider - Register callback to retrieve fwnode
+ * @fn: Callback matching a device to a fwnode that identifies a PCI
+ * MSI domain.
+ *
+ * This should be called by irqchip driver, which is the parent of
+ * the MSI domain to provide callback interface to query fwnode.
+ */
+void
+pci_msi_register_fwnode_provider(struct fwnode_handle *(*fn)(struct device *))
+{
+ pci_msi_get_fwnode_cb = fn;
+}
+
+/**
+ * pci_host_bridge_acpi_msi_domain - Retrieve MSI domain of a PCI host bridge
+ * @bus: The PCI host bridge bus.
+ *
+ * This function uses the callback function registered by
+ * pci_msi_register_fwnode_provider() to retrieve the irq_domain with
+ * type DOMAIN_BUS_PCI_MSI of the specified host bridge bus.
+ * This returns NULL on error or when the domain is not found.
+ */
+struct irq_domain *pci_host_bridge_acpi_msi_domain(struct pci_bus *bus)
+{
+ struct fwnode_handle *fwnode;
+
+ if (!pci_msi_get_fwnode_cb)
+ return NULL;
+
+ fwnode = pci_msi_get_fwnode_cb(&bus->dev);
+ if (!fwnode)
+ return NULL;
+
+ return irq_find_matching_fwnode(fwnode, DOMAIN_BUS_PCI_MSI);
+}
+
static int __init acpi_pci_init(void)
{
int ret;
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index edb1984201e9..553a029e37f1 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -672,6 +672,8 @@ static struct irq_domain *pci_host_bridge_msi_domain(struct pci_bus *bus)
* should be called from here.
*/
d = pci_host_bridge_of_msi_domain(bus);
+ if (!d)
+ d = pci_host_bridge_acpi_msi_domain(bus);
return d;
}
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 312c78b27a32..99a4c10ed43f 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -244,7 +244,7 @@ config PINCTRL_ZYNQ
select PINMUX
select GENERIC_PINCONF
help
- This selectes the pinctrl driver for Xilinx Zynq.
+ This selects the pinctrl driver for Xilinx Zynq.
source "drivers/pinctrl/bcm/Kconfig"
source "drivers/pinctrl/berlin/Kconfig"
@@ -252,6 +252,7 @@ source "drivers/pinctrl/freescale/Kconfig"
source "drivers/pinctrl/intel/Kconfig"
source "drivers/pinctrl/mvebu/Kconfig"
source "drivers/pinctrl/nomadik/Kconfig"
+source "drivers/pinctrl/pxa/Kconfig"
source "drivers/pinctrl/qcom/Kconfig"
source "drivers/pinctrl/samsung/Kconfig"
source "drivers/pinctrl/sh-pfc/Kconfig"
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 738cb4929a49..bf1b5ca5180b 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -41,15 +41,16 @@ obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o
obj-$(CONFIG_PINCTRL_ZYNQ) += pinctrl-zynq.o
obj-$(CONFIG_ARCH_BCM) += bcm/
-obj-$(CONFIG_ARCH_BERLIN) += berlin/
+obj-$(CONFIG_PINCTRL_BERLIN) += berlin/
obj-y += freescale/
obj-$(CONFIG_X86) += intel/
-obj-$(CONFIG_PLAT_ORION) += mvebu/
+obj-$(CONFIG_PINCTRL_MVEBU) += mvebu/
obj-y += nomadik/
+obj-$(CONFIG_ARCH_PXA) += pxa/
obj-$(CONFIG_ARCH_QCOM) += qcom/
obj-$(CONFIG_PINCTRL_SAMSUNG) += samsung/
obj-$(CONFIG_PINCTRL_SH_PFC) += sh-pfc/
-obj-$(CONFIG_PLAT_SPEAR) += spear/
+obj-$(CONFIG_PINCTRL_SPEAR) += spear/
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/
obj-$(CONFIG_ARCH_VT8500) += vt8500/
diff --git a/drivers/pinctrl/bcm/Kconfig b/drivers/pinctrl/bcm/Kconfig
index cd11d4d9ad58..2cc74384cafa 100644
--- a/drivers/pinctrl/bcm/Kconfig
+++ b/drivers/pinctrl/bcm/Kconfig
@@ -9,6 +9,7 @@ config PINCTRL_BCM281XX
select PINCONF
select GENERIC_PINCONF
select REGMAP_MMIO
+ default ARCH_BCM_MOBILE
help
Say Y here to support Broadcom BCM281xx pinctrl driver, which is used
for the BCM281xx SoC family, including BCM11130, BCM11140, BCM11351,
@@ -20,27 +21,41 @@ config PINCTRL_BCM2835
select PINMUX
select PINCONF
-config PINCTRL_CYGNUS_GPIO
- bool "Broadcom Cygnus GPIO (with PINCONF) driver"
- depends on OF_GPIO && ARCH_BCM_CYGNUS
+config PINCTRL_IPROC_GPIO
+ bool "Broadcom iProc GPIO (with PINCONF) driver"
+ depends on OF_GPIO && (ARCH_BCM_IPROC || COMPILE_TEST)
select GPIOLIB_IRQCHIP
select PINCONF
select GENERIC_PINCONF
- default ARCH_BCM_CYGNUS
+ default ARCH_BCM_IPROC
help
- Say yes here to enable the Broadcom Cygnus GPIO driver.
+ Say yes here to enable the Broadcom iProc GPIO driver.
+
+ The Broadcom iProc based SoCs- Cygnus, NS2, NSP and Stingray, use
+ same GPIO Controller IP hence this driver could be used for all.
The Broadcom Cygnus SoC has 3 GPIO controllers including the ASIU
GPIO controller (ASIU), the chipCommonG GPIO controller (CCM), and
the always-ON GPIO controller (CRMU/AON). All 3 GPIO controllers are
supported by this driver.
- All 3 Cygnus GPIO controllers support basic PINCONF functions such
+ The Broadcom NSP has two GPIO controllers including the ChipcommonA
+ GPIO, the ChipcommonB GPIO. Later controller is supported by this
+ driver.
+
+ The Broadcom NS2 has two GPIO controller including the CRMU GPIO,
+ the ChipcommonG GPIO. Both controllers are supported by this driver.
+
+ The Broadcom Stingray GPIO controllers are supported by this driver.
+
+ All above SoCs GPIO controllers support basic PINCONF functions such
as bias pull up, pull down, and drive strength configurations, when
these pins are muxed to GPIO.
- Pins from the ASIU GPIO can be individually muxed to GPIO function,
- through interaction with the Cygnus IOMUX controller.
+ It provides the framework where pins from the individual GPIO can be
+ individually muxed to GPIO function, through interaction with the
+ SoCs IOMUX controller. This features could be used only on SoCs which
+ support individual pin muxing.
config PINCTRL_CYGNUS_MUX
bool "Broadcom Cygnus IOMUX driver"
@@ -54,3 +69,20 @@ config PINCTRL_CYGNUS_MUX
The Broadcom Cygnus IOMUX driver supports group based IOMUX
configuration, with the exception that certain individual pins
can be overrided to GPIO function
+
+config PINCTRL_NSP_GPIO
+ bool "Broadcom NSP GPIO (with PINCONF) driver"
+ depends on OF_GPIO && (ARCH_BCM_NSP || COMPILE_TEST)
+ select GPIOLIB_IRQCHIP
+ select PINCONF
+ select GENERIC_PINCONF
+ default ARCH_BCM_NSP
+ help
+ Say yes here to enable the Broadcom NSP GPIO driver.
+
+ The Broadcom Northstar Plus SoC ChipcommonA GPIO controller is
+ supported by this driver.
+
+ The ChipcommonA GPIO controller support basic PINCONF functions such
+ as bias pull up, pull down, and drive strength configurations, when
+ these pins are muxed to GPIO.
diff --git a/drivers/pinctrl/bcm/Makefile b/drivers/pinctrl/bcm/Makefile
index 2b2f70ee804c..6148367d5e8c 100644
--- a/drivers/pinctrl/bcm/Makefile
+++ b/drivers/pinctrl/bcm/Makefile
@@ -2,5 +2,6 @@
obj-$(CONFIG_PINCTRL_BCM281XX) += pinctrl-bcm281xx.o
obj-$(CONFIG_PINCTRL_BCM2835) += pinctrl-bcm2835.o
-obj-$(CONFIG_PINCTRL_CYGNUS_GPIO) += pinctrl-cygnus-gpio.o
+obj-$(CONFIG_PINCTRL_IPROC_GPIO) += pinctrl-iproc-gpio.o
obj-$(CONFIG_PINCTRL_CYGNUS_MUX) += pinctrl-cygnus-mux.o
+obj-$(CONFIG_PINCTRL_NSP_GPIO) += pinctrl-nsp-gpio.o
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
index 2e6ca69635aa..75b0d8c8f058 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -795,7 +795,7 @@ static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
return 0;
out:
- kfree(maps);
+ bcm2835_pctl_dt_free_map(pctldev, maps, num_pins * maps_per_pin);
return err;
}
diff --git a/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c
index 12a48f498b75..314591a4609b 100644
--- a/drivers/pinctrl/bcm/pinctrl-cygnus-gpio.c
+++ b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c
@@ -10,14 +10,16 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * This file contains the Broadcom Cygnus GPIO driver that supports 3
- * GPIO controllers on Cygnus including the ASIU GPIO controller, the
+ * This file contains the Broadcom Iproc GPIO driver that supports 3
+ * GPIO controllers on Iproc including the ASIU GPIO controller, the
* chipCommonG GPIO controller, and the always-on GPIO controller. Basic
* PINCONF such as bias pull up/down, and drive strength are also supported
* in this driver.
*
- * Pins from the ASIU GPIO can be individually muxed to GPIO function,
- * through the interaction with the Cygnus IOMUX controller
+ * It provides the functionality where pins from the GPIO can be
+ * individually muxed to GPIO function, if individual pad
+ * configuration is supported, through the interaction with respective
+ * SoCs IOMUX controller.
*/
#include <linux/kernel.h>
@@ -34,42 +36,42 @@
#include "../pinctrl-utils.h"
-#define CYGNUS_GPIO_DATA_IN_OFFSET 0x00
-#define CYGNUS_GPIO_DATA_OUT_OFFSET 0x04
-#define CYGNUS_GPIO_OUT_EN_OFFSET 0x08
-#define CYGNUS_GPIO_INT_TYPE_OFFSET 0x0c
-#define CYGNUS_GPIO_INT_DE_OFFSET 0x10
-#define CYGNUS_GPIO_INT_EDGE_OFFSET 0x14
-#define CYGNUS_GPIO_INT_MSK_OFFSET 0x18
-#define CYGNUS_GPIO_INT_STAT_OFFSET 0x1c
-#define CYGNUS_GPIO_INT_MSTAT_OFFSET 0x20
-#define CYGNUS_GPIO_INT_CLR_OFFSET 0x24
-#define CYGNUS_GPIO_PAD_RES_OFFSET 0x34
-#define CYGNUS_GPIO_RES_EN_OFFSET 0x38
+#define IPROC_GPIO_DATA_IN_OFFSET 0x00
+#define IPROC_GPIO_DATA_OUT_OFFSET 0x04
+#define IPROC_GPIO_OUT_EN_OFFSET 0x08
+#define IPROC_GPIO_INT_TYPE_OFFSET 0x0c
+#define IPROC_GPIO_INT_DE_OFFSET 0x10
+#define IPROC_GPIO_INT_EDGE_OFFSET 0x14
+#define IPROC_GPIO_INT_MSK_OFFSET 0x18
+#define IPROC_GPIO_INT_STAT_OFFSET 0x1c
+#define IPROC_GPIO_INT_MSTAT_OFFSET 0x20
+#define IPROC_GPIO_INT_CLR_OFFSET 0x24
+#define IPROC_GPIO_PAD_RES_OFFSET 0x34
+#define IPROC_GPIO_RES_EN_OFFSET 0x38
/* drive strength control for ASIU GPIO */
-#define CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET 0x58
+#define IPROC_GPIO_ASIU_DRV0_CTRL_OFFSET 0x58
/* drive strength control for CCM/CRMU (AON) GPIO */
-#define CYGNUS_GPIO_DRV0_CTRL_OFFSET 0x00
+#define IPROC_GPIO_DRV0_CTRL_OFFSET 0x00
#define GPIO_BANK_SIZE 0x200
#define NGPIOS_PER_BANK 32
#define GPIO_BANK(pin) ((pin) / NGPIOS_PER_BANK)
-#define CYGNUS_GPIO_REG(pin, reg) (GPIO_BANK(pin) * GPIO_BANK_SIZE + (reg))
-#define CYGNUS_GPIO_SHIFT(pin) ((pin) % NGPIOS_PER_BANK)
+#define IPROC_GPIO_REG(pin, reg) (GPIO_BANK(pin) * GPIO_BANK_SIZE + (reg))
+#define IPROC_GPIO_SHIFT(pin) ((pin) % NGPIOS_PER_BANK)
#define GPIO_DRV_STRENGTH_BIT_SHIFT 20
#define GPIO_DRV_STRENGTH_BITS 3
#define GPIO_DRV_STRENGTH_BIT_MASK ((1 << GPIO_DRV_STRENGTH_BITS) - 1)
/*
- * Cygnus GPIO core
+ * Iproc GPIO core
*
* @dev: pointer to device
- * @base: I/O register base for Cygnus GPIO controller
- * @io_ctrl: I/O register base for certain type of Cygnus GPIO controller that
+ * @base: I/O register base for Iproc GPIO controller
+ * @io_ctrl: I/O register base for certain type of Iproc GPIO controller that
* has the PINCONF support implemented outside of the GPIO block
* @lock: lock to protect access to I/O registers
* @gc: GPIO chip
@@ -79,7 +81,7 @@
* @pctl: pointer to pinctrl_dev
* @pctldesc: pinctrl descriptor
*/
-struct cygnus_gpio {
+struct iproc_gpio {
struct device *dev;
void __iomem *base;
@@ -96,33 +98,33 @@ struct cygnus_gpio {
struct pinctrl_desc pctldesc;
};
-static inline struct cygnus_gpio *to_cygnus_gpio(struct gpio_chip *gc)
+static inline struct iproc_gpio *to_iproc_gpio(struct gpio_chip *gc)
{
- return container_of(gc, struct cygnus_gpio, gc);
+ return container_of(gc, struct iproc_gpio, gc);
}
/*
* Mapping from PINCONF pins to GPIO pins is 1-to-1
*/
-static inline unsigned cygnus_pin_to_gpio(unsigned pin)
+static inline unsigned iproc_pin_to_gpio(unsigned pin)
{
return pin;
}
/**
- * cygnus_set_bit - set or clear one bit (corresponding to the GPIO pin) in a
- * Cygnus GPIO register
+ * iproc_set_bit - set or clear one bit (corresponding to the GPIO pin) in a
+ * Iproc GPIO register
*
- * @cygnus_gpio: Cygnus GPIO device
+ * @iproc_gpio: Iproc GPIO device
* @reg: register offset
* @gpio: GPIO pin
* @set: set or clear
*/
-static inline void cygnus_set_bit(struct cygnus_gpio *chip, unsigned int reg,
+static inline void iproc_set_bit(struct iproc_gpio *chip, unsigned int reg,
unsigned gpio, bool set)
{
- unsigned int offset = CYGNUS_GPIO_REG(gpio, reg);
- unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
+ unsigned int offset = IPROC_GPIO_REG(gpio, reg);
+ unsigned int shift = IPROC_GPIO_SHIFT(gpio);
u32 val;
val = readl(chip->base + offset);
@@ -133,19 +135,19 @@ static inline void cygnus_set_bit(struct cygnus_gpio *chip, unsigned int reg,
writel(val, chip->base + offset);
}
-static inline bool cygnus_get_bit(struct cygnus_gpio *chip, unsigned int reg,
+static inline bool iproc_get_bit(struct iproc_gpio *chip, unsigned int reg,
unsigned gpio)
{
- unsigned int offset = CYGNUS_GPIO_REG(gpio, reg);
- unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
+ unsigned int offset = IPROC_GPIO_REG(gpio, reg);
+ unsigned int shift = IPROC_GPIO_SHIFT(gpio);
return !!(readl(chip->base + offset) & BIT(shift));
}
-static void cygnus_gpio_irq_handler(struct irq_desc *desc)
+static void iproc_gpio_irq_handler(struct irq_desc *desc)
{
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
- struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+ struct iproc_gpio *chip = to_iproc_gpio(gc);
struct irq_chip *irq_chip = irq_desc_get_chip(desc);
int i, bit;
@@ -154,7 +156,7 @@ static void cygnus_gpio_irq_handler(struct irq_desc *desc)
/* go through the entire GPIO banks and handle all interrupts */
for (i = 0; i < chip->num_banks; i++) {
unsigned long val = readl(chip->base + (i * GPIO_BANK_SIZE) +
- CYGNUS_GPIO_INT_MSTAT_OFFSET);
+ IPROC_GPIO_INT_MSTAT_OFFSET);
for_each_set_bit(bit, &val, NGPIOS_PER_BANK) {
unsigned pin = NGPIOS_PER_BANK * i + bit;
@@ -165,7 +167,7 @@ static void cygnus_gpio_irq_handler(struct irq_desc *desc)
* handler, so we do not leave any window
*/
writel(BIT(bit), chip->base + (i * GPIO_BANK_SIZE) +
- CYGNUS_GPIO_INT_CLR_OFFSET);
+ IPROC_GPIO_INT_CLR_OFFSET);
generic_handle_irq(child_irq);
}
@@ -175,60 +177,60 @@ static void cygnus_gpio_irq_handler(struct irq_desc *desc)
}
-static void cygnus_gpio_irq_ack(struct irq_data *d)
+static void iproc_gpio_irq_ack(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+ struct iproc_gpio *chip = to_iproc_gpio(gc);
unsigned gpio = d->hwirq;
- unsigned int offset = CYGNUS_GPIO_REG(gpio,
- CYGNUS_GPIO_INT_CLR_OFFSET);
- unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
+ unsigned int offset = IPROC_GPIO_REG(gpio,
+ IPROC_GPIO_INT_CLR_OFFSET);
+ unsigned int shift = IPROC_GPIO_SHIFT(gpio);
u32 val = BIT(shift);
writel(val, chip->base + offset);
}
/**
- * cygnus_gpio_irq_set_mask - mask/unmask a GPIO interrupt
+ * iproc_gpio_irq_set_mask - mask/unmask a GPIO interrupt
*
* @d: IRQ chip data
* @unmask: mask/unmask GPIO interrupt
*/
-static void cygnus_gpio_irq_set_mask(struct irq_data *d, bool unmask)
+static void iproc_gpio_irq_set_mask(struct irq_data *d, bool unmask)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+ struct iproc_gpio *chip = to_iproc_gpio(gc);
unsigned gpio = d->hwirq;
- cygnus_set_bit(chip, CYGNUS_GPIO_INT_MSK_OFFSET, gpio, unmask);
+ iproc_set_bit(chip, IPROC_GPIO_INT_MSK_OFFSET, gpio, unmask);
}
-static void cygnus_gpio_irq_mask(struct irq_data *d)
+static void iproc_gpio_irq_mask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+ struct iproc_gpio *chip = to_iproc_gpio(gc);
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
- cygnus_gpio_irq_set_mask(d, false);
+ iproc_gpio_irq_set_mask(d, false);
spin_unlock_irqrestore(&chip->lock, flags);
}
-static void cygnus_gpio_irq_unmask(struct irq_data *d)
+static void iproc_gpio_irq_unmask(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+ struct iproc_gpio *chip = to_iproc_gpio(gc);
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
- cygnus_gpio_irq_set_mask(d, true);
+ iproc_gpio_irq_set_mask(d, true);
spin_unlock_irqrestore(&chip->lock, flags);
}
-static int cygnus_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+static int iproc_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+ struct iproc_gpio *chip = to_iproc_gpio(gc);
unsigned gpio = d->hwirq;
bool level_triggered = false;
bool dual_edge = false;
@@ -263,10 +265,10 @@ static int cygnus_gpio_irq_set_type(struct irq_data *d, unsigned int type)
}
spin_lock_irqsave(&chip->lock, flags);
- cygnus_set_bit(chip, CYGNUS_GPIO_INT_TYPE_OFFSET, gpio,
+ iproc_set_bit(chip, IPROC_GPIO_INT_TYPE_OFFSET, gpio,
level_triggered);
- cygnus_set_bit(chip, CYGNUS_GPIO_INT_DE_OFFSET, gpio, dual_edge);
- cygnus_set_bit(chip, CYGNUS_GPIO_INT_EDGE_OFFSET, gpio,
+ iproc_set_bit(chip, IPROC_GPIO_INT_DE_OFFSET, gpio, dual_edge);
+ iproc_set_bit(chip, IPROC_GPIO_INT_EDGE_OFFSET, gpio,
rising_or_high);
spin_unlock_irqrestore(&chip->lock, flags);
@@ -277,32 +279,32 @@ static int cygnus_gpio_irq_set_type(struct irq_data *d, unsigned int type)
return 0;
}
-static struct irq_chip cygnus_gpio_irq_chip = {
- .name = "bcm-cygnus-gpio",
- .irq_ack = cygnus_gpio_irq_ack,
- .irq_mask = cygnus_gpio_irq_mask,
- .irq_unmask = cygnus_gpio_irq_unmask,
- .irq_set_type = cygnus_gpio_irq_set_type,
+static struct irq_chip iproc_gpio_irq_chip = {
+ .name = "bcm-iproc-gpio",
+ .irq_ack = iproc_gpio_irq_ack,
+ .irq_mask = iproc_gpio_irq_mask,
+ .irq_unmask = iproc_gpio_irq_unmask,
+ .irq_set_type = iproc_gpio_irq_set_type,
};
/*
- * Request the Cygnus IOMUX pinmux controller to mux individual pins to GPIO
+ * Request the Iproc IOMUX pinmux controller to mux individual pins to GPIO
*/
-static int cygnus_gpio_request(struct gpio_chip *gc, unsigned offset)
+static int iproc_gpio_request(struct gpio_chip *gc, unsigned offset)
{
- struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+ struct iproc_gpio *chip = to_iproc_gpio(gc);
unsigned gpio = gc->base + offset;
- /* not all Cygnus GPIO pins can be muxed individually */
+ /* not all Iproc GPIO pins can be muxed individually */
if (!chip->pinmux_is_supported)
return 0;
return pinctrl_request_gpio(gpio);
}
-static void cygnus_gpio_free(struct gpio_chip *gc, unsigned offset)
+static void iproc_gpio_free(struct gpio_chip *gc, unsigned offset)
{
- struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+ struct iproc_gpio *chip = to_iproc_gpio(gc);
unsigned gpio = gc->base + offset;
if (!chip->pinmux_is_supported)
@@ -311,13 +313,13 @@ static void cygnus_gpio_free(struct gpio_chip *gc, unsigned offset)
pinctrl_free_gpio(gpio);
}
-static int cygnus_gpio_direction_input(struct gpio_chip *gc, unsigned gpio)
+static int iproc_gpio_direction_input(struct gpio_chip *gc, unsigned gpio)
{
- struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+ struct iproc_gpio *chip = to_iproc_gpio(gc);
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
- cygnus_set_bit(chip, CYGNUS_GPIO_OUT_EN_OFFSET, gpio, false);
+ iproc_set_bit(chip, IPROC_GPIO_OUT_EN_OFFSET, gpio, false);
spin_unlock_irqrestore(&chip->lock, flags);
dev_dbg(chip->dev, "gpio:%u set input\n", gpio);
@@ -325,15 +327,15 @@ static int cygnus_gpio_direction_input(struct gpio_chip *gc, unsigned gpio)
return 0;
}
-static int cygnus_gpio_direction_output(struct gpio_chip *gc, unsigned gpio,
+static int iproc_gpio_direction_output(struct gpio_chip *gc, unsigned gpio,
int val)
{
- struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+ struct iproc_gpio *chip = to_iproc_gpio(gc);
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
- cygnus_set_bit(chip, CYGNUS_GPIO_OUT_EN_OFFSET, gpio, true);
- cygnus_set_bit(chip, CYGNUS_GPIO_DATA_OUT_OFFSET, gpio, !!(val));
+ iproc_set_bit(chip, IPROC_GPIO_OUT_EN_OFFSET, gpio, true);
+ iproc_set_bit(chip, IPROC_GPIO_DATA_OUT_OFFSET, gpio, !!(val));
spin_unlock_irqrestore(&chip->lock, flags);
dev_dbg(chip->dev, "gpio:%u set output, value:%d\n", gpio, val);
@@ -341,29 +343,29 @@ static int cygnus_gpio_direction_output(struct gpio_chip *gc, unsigned gpio,
return 0;
}
-static void cygnus_gpio_set(struct gpio_chip *gc, unsigned gpio, int val)
+static void iproc_gpio_set(struct gpio_chip *gc, unsigned gpio, int val)
{
- struct cygnus_gpio *chip = to_cygnus_gpio(gc);
+ struct iproc_gpio *chip = to_iproc_gpio(gc);
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
- cygnus_set_bit(chip, CYGNUS_GPIO_DATA_OUT_OFFSET, gpio, !!(val));
+ iproc_set_bit(chip, IPROC_GPIO_DATA_OUT_OFFSET, gpio, !!(val));
spin_unlock_irqrestore(&chip->lock, flags);
dev_dbg(chip->dev, "gpio:%u set, value:%d\n", gpio, val);
}
-static int cygnus_gpio_get(struct gpio_chip *gc, unsigned gpio)
+static int iproc_gpio_get(struct gpio_chip *gc, unsigned gpio)
{
- struct cygnus_gpio *chip = to_cygnus_gpio(gc);
- unsigned int offset = CYGNUS_GPIO_REG(gpio,
- CYGNUS_GPIO_DATA_IN_OFFSET);
- unsigned int shift = CYGNUS_GPIO_SHIFT(gpio);
+ struct iproc_gpio *chip = to_iproc_gpio(gc);
+ unsigned int offset = IPROC_GPIO_REG(gpio,
+ IPROC_GPIO_DATA_IN_OFFSET);
+ unsigned int shift = IPROC_GPIO_SHIFT(gpio);
return !!(readl(chip->base + offset) & BIT(shift));
}
-static int cygnus_get_groups_count(struct pinctrl_dev *pctldev)
+static int iproc_get_groups_count(struct pinctrl_dev *pctldev)
{
return 1;
}
@@ -372,20 +374,20 @@ static int cygnus_get_groups_count(struct pinctrl_dev *pctldev)
* Only one group: "gpio_grp", since this local pinctrl device only performs
* GPIO specific PINCONF configurations
*/
-static const char *cygnus_get_group_name(struct pinctrl_dev *pctldev,
+static const char *iproc_get_group_name(struct pinctrl_dev *pctldev,
unsigned selector)
{
return "gpio_grp";
}
-static const struct pinctrl_ops cygnus_pctrl_ops = {
- .get_groups_count = cygnus_get_groups_count,
- .get_group_name = cygnus_get_group_name,
+static const struct pinctrl_ops iproc_pctrl_ops = {
+ .get_groups_count = iproc_get_groups_count,
+ .get_group_name = iproc_get_group_name,
.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
.dt_free_map = pinctrl_utils_dt_free_map,
};
-static int cygnus_gpio_set_pull(struct cygnus_gpio *chip, unsigned gpio,
+static int iproc_gpio_set_pull(struct iproc_gpio *chip, unsigned gpio,
bool disable, bool pull_up)
{
unsigned long flags;
@@ -393,11 +395,11 @@ static int cygnus_gpio_set_pull(struct cygnus_gpio *chip, unsigned gpio,
spin_lock_irqsave(&chip->lock, flags);
if (disable) {
- cygnus_set_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio, false);
+ iproc_set_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio, false);
} else {
- cygnus_set_bit(chip, CYGNUS_GPIO_PAD_RES_OFFSET, gpio,
+ iproc_set_bit(chip, IPROC_GPIO_PAD_RES_OFFSET, gpio,
pull_up);
- cygnus_set_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio, true);
+ iproc_set_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio, true);
}
spin_unlock_irqrestore(&chip->lock, flags);
@@ -407,18 +409,18 @@ static int cygnus_gpio_set_pull(struct cygnus_gpio *chip, unsigned gpio,
return 0;
}
-static void cygnus_gpio_get_pull(struct cygnus_gpio *chip, unsigned gpio,
+static void iproc_gpio_get_pull(struct iproc_gpio *chip, unsigned gpio,
bool *disable, bool *pull_up)
{
unsigned long flags;
spin_lock_irqsave(&chip->lock, flags);
- *disable = !cygnus_get_bit(chip, CYGNUS_GPIO_RES_EN_OFFSET, gpio);
- *pull_up = cygnus_get_bit(chip, CYGNUS_GPIO_PAD_RES_OFFSET, gpio);
+ *disable = !iproc_get_bit(chip, IPROC_GPIO_RES_EN_OFFSET, gpio);
+ *pull_up = iproc_get_bit(chip, IPROC_GPIO_PAD_RES_OFFSET, gpio);
spin_unlock_irqrestore(&chip->lock, flags);
}
-static int cygnus_gpio_set_strength(struct cygnus_gpio *chip, unsigned gpio,
+static int iproc_gpio_set_strength(struct iproc_gpio *chip, unsigned gpio,
unsigned strength)
{
void __iomem *base;
@@ -432,14 +434,14 @@ static int cygnus_gpio_set_strength(struct cygnus_gpio *chip, unsigned gpio,
if (chip->io_ctrl) {
base = chip->io_ctrl;
- offset = CYGNUS_GPIO_DRV0_CTRL_OFFSET;
+ offset = IPROC_GPIO_DRV0_CTRL_OFFSET;
} else {
base = chip->base;
- offset = CYGNUS_GPIO_REG(gpio,
- CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET);
+ offset = IPROC_GPIO_REG(gpio,
+ IPROC_GPIO_ASIU_DRV0_CTRL_OFFSET);
}
- shift = CYGNUS_GPIO_SHIFT(gpio);
+ shift = IPROC_GPIO_SHIFT(gpio);
dev_dbg(chip->dev, "gpio:%u set drive strength:%d mA\n", gpio,
strength);
@@ -458,7 +460,7 @@ static int cygnus_gpio_set_strength(struct cygnus_gpio *chip, unsigned gpio,
return 0;
}
-static int cygnus_gpio_get_strength(struct cygnus_gpio *chip, unsigned gpio,
+static int iproc_gpio_get_strength(struct iproc_gpio *chip, unsigned gpio,
u16 *strength)
{
void __iomem *base;
@@ -468,14 +470,14 @@ static int cygnus_gpio_get_strength(struct cygnus_gpio *chip, unsigned gpio,
if (chip->io_ctrl) {
base = chip->io_ctrl;
- offset = CYGNUS_GPIO_DRV0_CTRL_OFFSET;
+ offset = IPROC_GPIO_DRV0_CTRL_OFFSET;
} else {
base = chip->base;
- offset = CYGNUS_GPIO_REG(gpio,
- CYGNUS_GPIO_ASIU_DRV0_CTRL_OFFSET);
+ offset = IPROC_GPIO_REG(gpio,
+ IPROC_GPIO_ASIU_DRV0_CTRL_OFFSET);
}
- shift = CYGNUS_GPIO_SHIFT(gpio);
+ shift = IPROC_GPIO_SHIFT(gpio);
spin_lock_irqsave(&chip->lock, flags);
*strength = 0;
@@ -493,44 +495,43 @@ static int cygnus_gpio_get_strength(struct cygnus_gpio *chip, unsigned gpio,
return 0;
}
-static int cygnus_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
+static int iproc_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long *config)
{
- struct cygnus_gpio *chip = pinctrl_dev_get_drvdata(pctldev);
+ struct iproc_gpio *chip = pinctrl_dev_get_drvdata(pctldev);
enum pin_config_param param = pinconf_to_config_param(*config);
- unsigned gpio = cygnus_pin_to_gpio(pin);
+ unsigned gpio = iproc_pin_to_gpio(pin);
u16 arg;
bool disable, pull_up;
int ret;
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
- cygnus_gpio_get_pull(chip, gpio, &disable, &pull_up);
+ iproc_gpio_get_pull(chip, gpio, &disable, &pull_up);
if (disable)
return 0;
else
return -EINVAL;
case PIN_CONFIG_BIAS_PULL_UP:
- cygnus_gpio_get_pull(chip, gpio, &disable, &pull_up);
+ iproc_gpio_get_pull(chip, gpio, &disable, &pull_up);
if (!disable && pull_up)
return 0;
else
return -EINVAL;
case PIN_CONFIG_BIAS_PULL_DOWN:
- cygnus_gpio_get_pull(chip, gpio, &disable, &pull_up);
+ iproc_gpio_get_pull(chip, gpio, &disable, &pull_up);
if (!disable && !pull_up)
return 0;
else
return -EINVAL;
case PIN_CONFIG_DRIVE_STRENGTH:
- ret = cygnus_gpio_get_strength(chip, gpio, &arg);
+ ret = iproc_gpio_get_strength(chip, gpio, &arg);
if (ret)
return ret;
- else
- *config = pinconf_to_config_packed(param, arg);
+ *config = pinconf_to_config_packed(param, arg);
return 0;
@@ -541,13 +542,13 @@ static int cygnus_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
return -ENOTSUPP;
}
-static int cygnus_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
+static int iproc_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long *configs, unsigned num_configs)
{
- struct cygnus_gpio *chip = pinctrl_dev_get_drvdata(pctldev);
+ struct iproc_gpio *chip = pinctrl_dev_get_drvdata(pctldev);
enum pin_config_param param;
u16 arg;
- unsigned i, gpio = cygnus_pin_to_gpio(pin);
+ unsigned i, gpio = iproc_pin_to_gpio(pin);
int ret = -ENOTSUPP;
for (i = 0; i < num_configs; i++) {
@@ -556,25 +557,25 @@ static int cygnus_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
switch (param) {
case PIN_CONFIG_BIAS_DISABLE:
- ret = cygnus_gpio_set_pull(chip, gpio, true, false);
+ ret = iproc_gpio_set_pull(chip, gpio, true, false);
if (ret < 0)
goto out;
break;
case PIN_CONFIG_BIAS_PULL_UP:
- ret = cygnus_gpio_set_pull(chip, gpio, false, true);
+ ret = iproc_gpio_set_pull(chip, gpio, false, true);
if (ret < 0)
goto out;
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
- ret = cygnus_gpio_set_pull(chip, gpio, false, false);
+ ret = iproc_gpio_set_pull(chip, gpio, false, false);
if (ret < 0)
goto out;
break;
case PIN_CONFIG_DRIVE_STRENGTH:
- ret = cygnus_gpio_set_strength(chip, gpio, arg);
+ ret = iproc_gpio_set_strength(chip, gpio, arg);
if (ret < 0)
goto out;
break;
@@ -589,20 +590,20 @@ out:
return ret;
}
-static const struct pinconf_ops cygnus_pconf_ops = {
+static const struct pinconf_ops iproc_pconf_ops = {
.is_generic = true,
- .pin_config_get = cygnus_pin_config_get,
- .pin_config_set = cygnus_pin_config_set,
+ .pin_config_get = iproc_pin_config_get,
+ .pin_config_set = iproc_pin_config_set,
};
/*
- * Cygnus GPIO controller supports some PINCONF related configurations such as
+ * Iproc GPIO controller supports some PINCONF related configurations such as
* pull up, pull down, and drive strength, when the pin is configured to GPIO
*
* Here a local pinctrl device is created with simple 1-to-1 pin mapping to the
* local GPIO pins
*/
-static int cygnus_gpio_register_pinconf(struct cygnus_gpio *chip)
+static int iproc_gpio_register_pinconf(struct iproc_gpio *chip)
{
struct pinctrl_desc *pctldesc = &chip->pctldesc;
struct pinctrl_pin_desc *pins;
@@ -622,10 +623,10 @@ static int cygnus_gpio_register_pinconf(struct cygnus_gpio *chip)
}
pctldesc->name = dev_name(chip->dev);
- pctldesc->pctlops = &cygnus_pctrl_ops;
+ pctldesc->pctlops = &iproc_pctrl_ops;
pctldesc->pins = pins;
pctldesc->npins = gc->ngpio;
- pctldesc->confops = &cygnus_pconf_ops;
+ pctldesc->confops = &iproc_pconf_ops;
chip->pctl = pinctrl_register(pctldesc, chip->dev, chip);
if (IS_ERR(chip->pctl)) {
@@ -636,59 +637,27 @@ static int cygnus_gpio_register_pinconf(struct cygnus_gpio *chip)
return 0;
}
-static void cygnus_gpio_unregister_pinconf(struct cygnus_gpio *chip)
+static void iproc_gpio_unregister_pinconf(struct iproc_gpio *chip)
{
- if (chip->pctl)
- pinctrl_unregister(chip->pctl);
+ pinctrl_unregister(chip->pctl);
}
-struct cygnus_gpio_data {
- unsigned num_gpios;
-};
-
-static const struct cygnus_gpio_data cygnus_cmm_gpio_data = {
- .num_gpios = 24,
-};
-
-static const struct cygnus_gpio_data cygnus_asiu_gpio_data = {
- .num_gpios = 146,
+static const struct of_device_id iproc_gpio_of_match[] = {
+ { .compatible = "brcm,cygnus-ccm-gpio" },
+ { .compatible = "brcm,cygnus-asiu-gpio" },
+ { .compatible = "brcm,cygnus-crmu-gpio" },
+ { .compatible = "brcm,iproc-gpio" },
+ { }
};
-static const struct cygnus_gpio_data cygnus_crmu_gpio_data = {
- .num_gpios = 6,
-};
-
-static const struct of_device_id cygnus_gpio_of_match[] = {
- {
- .compatible = "brcm,cygnus-ccm-gpio",
- .data = &cygnus_cmm_gpio_data,
- },
- {
- .compatible = "brcm,cygnus-asiu-gpio",
- .data = &cygnus_asiu_gpio_data,
- },
- {
- .compatible = "brcm,cygnus-crmu-gpio",
- .data = &cygnus_crmu_gpio_data,
- }
-};
-
-static int cygnus_gpio_probe(struct platform_device *pdev)
+static int iproc_gpio_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct resource *res;
- struct cygnus_gpio *chip;
+ struct iproc_gpio *chip;
struct gpio_chip *gc;
u32 ngpios;
int irq, ret;
- const struct of_device_id *match;
- const struct cygnus_gpio_data *gpio_data;
-
- match = of_match_device(cygnus_gpio_of_match, dev);
- if (!match)
- return -ENODEV;
- gpio_data = match->data;
- ngpios = gpio_data->num_gpios;
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
if (!chip)
@@ -713,6 +682,11 @@ static int cygnus_gpio_probe(struct platform_device *pdev)
}
}
+ if (of_property_read_u32(dev->of_node, "ngpios", &ngpios)) {
+ dev_err(&pdev->dev, "missing ngpios DT property\n");
+ return -ENODEV;
+ }
+
spin_lock_init(&chip->lock);
gc = &chip->gc;
@@ -722,12 +696,12 @@ static int cygnus_gpio_probe(struct platform_device *pdev)
gc->label = dev_name(dev);
gc->dev = dev;
gc->of_node = dev->of_node;
- gc->request = cygnus_gpio_request;
- gc->free = cygnus_gpio_free;
- gc->direction_input = cygnus_gpio_direction_input;
- gc->direction_output = cygnus_gpio_direction_output;
- gc->set = cygnus_gpio_set;
- gc->get = cygnus_gpio_get;
+ gc->request = iproc_gpio_request;
+ gc->free = iproc_gpio_free;
+ gc->direction_input = iproc_gpio_direction_input;
+ gc->direction_output = iproc_gpio_direction_output;
+ gc->set = iproc_gpio_set;
+ gc->get = iproc_gpio_get;
chip->pinmux_is_supported = of_property_read_bool(dev->of_node,
"gpio-ranges");
@@ -738,7 +712,7 @@ static int cygnus_gpio_probe(struct platform_device *pdev)
return ret;
}
- ret = cygnus_gpio_register_pinconf(chip);
+ ret = iproc_gpio_register_pinconf(chip);
if (ret) {
dev_err(dev, "unable to register pinconf\n");
goto err_rm_gpiochip;
@@ -747,21 +721,21 @@ static int cygnus_gpio_probe(struct platform_device *pdev)
/* optional GPIO interrupt support */
irq = platform_get_irq(pdev, 0);
if (irq) {
- ret = gpiochip_irqchip_add(gc, &cygnus_gpio_irq_chip, 0,
+ ret = gpiochip_irqchip_add(gc, &iproc_gpio_irq_chip, 0,
handle_simple_irq, IRQ_TYPE_NONE);
if (ret) {
dev_err(dev, "no GPIO irqchip\n");
goto err_unregister_pinconf;
}
- gpiochip_set_chained_irqchip(gc, &cygnus_gpio_irq_chip, irq,
- cygnus_gpio_irq_handler);
+ gpiochip_set_chained_irqchip(gc, &iproc_gpio_irq_chip, irq,
+ iproc_gpio_irq_handler);
}
return 0;
err_unregister_pinconf:
- cygnus_gpio_unregister_pinconf(chip);
+ iproc_gpio_unregister_pinconf(chip);
err_rm_gpiochip:
gpiochip_remove(gc);
@@ -769,16 +743,16 @@ err_rm_gpiochip:
return ret;
}
-static struct platform_driver cygnus_gpio_driver = {
+static struct platform_driver iproc_gpio_driver = {
.driver = {
- .name = "cygnus-gpio",
- .of_match_table = cygnus_gpio_of_match,
+ .name = "iproc-gpio",
+ .of_match_table = iproc_gpio_of_match,
},
- .probe = cygnus_gpio_probe,
+ .probe = iproc_gpio_probe,
};
-static int __init cygnus_gpio_init(void)
+static int __init iproc_gpio_init(void)
{
- return platform_driver_probe(&cygnus_gpio_driver, cygnus_gpio_probe);
+ return platform_driver_probe(&iproc_gpio_driver, iproc_gpio_probe);
}
-arch_initcall_sync(cygnus_gpio_init);
+arch_initcall_sync(iproc_gpio_init);
diff --git a/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c b/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c
new file mode 100644
index 000000000000..725c36f917f9
--- /dev/null
+++ b/drivers/pinctrl/bcm/pinctrl-nsp-gpio.c
@@ -0,0 +1,749 @@
+/*
+ * Copyright (C) 2015 Broadcom Corporation
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file contains the Broadcom Northstar Plus (NSP) GPIO driver that
+ * supports the chipCommonA GPIO controller. Basic PINCONF such as bias,
+ * pull up/down, slew and drive strength are also supported in this driver.
+ *
+ * Pins from the chipCommonA GPIO can be individually muxed to GPIO function,
+ * through the interaction with the NSP IOMUX controller.
+ */
+
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/slab.h>
+
+#include "../pinctrl-utils.h"
+
+#define NSP_CHIP_A_INT_STATUS 0x00
+#define NSP_CHIP_A_INT_MASK 0x04
+#define NSP_GPIO_DATA_IN 0x40
+#define NSP_GPIO_DATA_OUT 0x44
+#define NSP_GPIO_OUT_EN 0x48
+#define NSP_GPIO_INT_POLARITY 0x50
+#define NSP_GPIO_INT_MASK 0x54
+#define NSP_GPIO_EVENT 0x58
+#define NSP_GPIO_EVENT_INT_MASK 0x5c
+#define NSP_GPIO_EVENT_INT_POLARITY 0x64
+#define NSP_CHIP_A_GPIO_INT_BIT 0x01
+
+/* I/O parameters offset for chipcommon A GPIO */
+#define NSP_GPIO_DRV_CTRL 0x00
+#define NSP_GPIO_HYSTERESIS_EN 0x10
+#define NSP_GPIO_SLEW_RATE_EN 0x14
+#define NSP_PULL_UP_EN 0x18
+#define NSP_PULL_DOWN_EN 0x1c
+#define GPIO_DRV_STRENGTH_BITS 0x03
+
+/*
+ * nsp GPIO core
+ *
+ * @dev: pointer to device
+ * @base: I/O register base for nsp GPIO controller
+ * @io_ctrl: I/O register base for PINCONF support outside the GPIO block
+ * @gc: GPIO chip
+ * @pctl: pointer to pinctrl_dev
+ * @pctldesc: pinctrl descriptor
+ * @irq_domain: pointer to irq domain
+ * @lock: lock to protect access to I/O registers
+ */
+struct nsp_gpio {
+ struct device *dev;
+ void __iomem *base;
+ void __iomem *io_ctrl;
+ struct gpio_chip gc;
+ struct pinctrl_dev *pctl;
+ struct pinctrl_desc pctldesc;
+ struct irq_domain *irq_domain;
+ spinlock_t lock;
+};
+
+enum base_type {
+ REG,
+ IO_CTRL
+};
+
+static inline struct nsp_gpio *to_nsp_gpio(struct gpio_chip *gc)
+{
+ return container_of(gc, struct nsp_gpio, gc);
+}
+
+/*
+ * Mapping from PINCONF pins to GPIO pins is 1-to-1
+ */
+static inline unsigned nsp_pin_to_gpio(unsigned pin)
+{
+ return pin;
+}
+
+/*
+ * nsp_set_bit - set or clear one bit (corresponding to the GPIO pin) in a
+ * nsp GPIO register
+ *
+ * @nsp_gpio: nsp GPIO device
+ * @base_type: reg base to modify
+ * @reg: register offset
+ * @gpio: GPIO pin
+ * @set: set or clear
+ */
+static inline void nsp_set_bit(struct nsp_gpio *chip, enum base_type address,
+ unsigned int reg, unsigned gpio, bool set)
+{
+ u32 val;
+ void __iomem *base_address;
+
+ if (address == IO_CTRL)
+ base_address = chip->io_ctrl;
+ else
+ base_address = chip->base;
+
+ val = readl(base_address + reg);
+ if (set)
+ val |= BIT(gpio);
+ else
+ val &= ~BIT(gpio);
+
+ writel(val, base_address + reg);
+}
+
+/*
+ * nsp_get_bit - get one bit (corresponding to the GPIO pin) in a
+ * nsp GPIO register
+ */
+static inline bool nsp_get_bit(struct nsp_gpio *chip, enum base_type address,
+ unsigned int reg, unsigned gpio)
+{
+ if (address == IO_CTRL)
+ return !!(readl(chip->io_ctrl + reg) & BIT(gpio));
+ else
+ return !!(readl(chip->base + reg) & BIT(gpio));
+}
+
+static irqreturn_t nsp_gpio_irq_handler(int irq, void *data)
+{
+ struct nsp_gpio *chip = (struct nsp_gpio *)data;
+ struct gpio_chip gc = chip->gc;
+ int bit;
+ unsigned long int_bits = 0;
+ u32 int_status;
+
+ /* go through the entire GPIOs and handle all interrupts */
+ int_status = readl(chip->base + NSP_CHIP_A_INT_STATUS);
+ if (int_status & NSP_CHIP_A_GPIO_INT_BIT) {
+ unsigned int event, level;
+
+ /* Get level and edge interrupts */
+ event = readl(chip->base + NSP_GPIO_EVENT_INT_MASK) &
+ readl(chip->base + NSP_GPIO_EVENT);
+ level = readl(chip->base + NSP_GPIO_DATA_IN) ^
+ readl(chip->base + NSP_GPIO_INT_POLARITY);
+ level &= readl(chip->base + NSP_GPIO_INT_MASK);
+ int_bits = level | event;
+
+ for_each_set_bit(bit, &int_bits, gc.ngpio) {
+ /*
+ * Clear the interrupt before invoking the
+ * handler, so we do not leave any window
+ */
+ writel(BIT(bit), chip->base + NSP_GPIO_EVENT);
+ generic_handle_irq(
+ irq_linear_revmap(chip->irq_domain, bit));
+ }
+ }
+
+ return int_bits ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static void nsp_gpio_irq_ack(struct irq_data *d)
+{
+ struct nsp_gpio *chip = irq_data_get_irq_chip_data(d);
+ unsigned gpio = d->hwirq;
+ u32 val = BIT(gpio);
+ u32 trigger_type;
+
+ trigger_type = irq_get_trigger_type(d->irq);
+ if (trigger_type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+ nsp_set_bit(chip, REG, NSP_GPIO_EVENT, gpio, val);
+}
+
+/*
+ * nsp_gpio_irq_set_mask - mask/unmask a GPIO interrupt
+ *
+ * @d: IRQ chip data
+ * @unmask: mask/unmask GPIO interrupt
+ */
+static void nsp_gpio_irq_set_mask(struct irq_data *d, bool unmask)
+{
+ struct nsp_gpio *chip = irq_data_get_irq_chip_data(d);
+ unsigned gpio = d->hwirq;
+ u32 trigger_type;
+
+ trigger_type = irq_get_trigger_type(d->irq);
+ if (trigger_type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
+ nsp_set_bit(chip, REG, NSP_GPIO_EVENT_INT_MASK, gpio, unmask);
+ else
+ nsp_set_bit(chip, REG, NSP_GPIO_INT_MASK, gpio, unmask);
+}
+
+static void nsp_gpio_irq_mask(struct irq_data *d)
+{
+ struct nsp_gpio *chip = irq_data_get_irq_chip_data(d);
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ nsp_gpio_irq_set_mask(d, false);
+ spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+static void nsp_gpio_irq_unmask(struct irq_data *d)
+{
+ struct nsp_gpio *chip = irq_data_get_irq_chip_data(d);
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ nsp_gpio_irq_set_mask(d, true);
+ spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+static int nsp_gpio_irq_set_type(struct irq_data *d, unsigned int type)
+{
+ struct nsp_gpio *chip = irq_data_get_irq_chip_data(d);
+ unsigned gpio = d->hwirq;
+ bool level_low;
+ bool falling;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ falling = nsp_get_bit(chip, REG, NSP_GPIO_EVENT_INT_POLARITY, gpio);
+ level_low = nsp_get_bit(chip, REG, NSP_GPIO_INT_POLARITY, gpio);
+
+ switch (type & IRQ_TYPE_SENSE_MASK) {
+ case IRQ_TYPE_EDGE_RISING:
+ falling = false;
+ break;
+
+ case IRQ_TYPE_EDGE_FALLING:
+ falling = true;
+ break;
+
+ case IRQ_TYPE_LEVEL_HIGH:
+ level_low = false;
+ break;
+
+ case IRQ_TYPE_LEVEL_LOW:
+ level_low = true;
+ break;
+
+ default:
+ dev_err(chip->dev, "invalid GPIO IRQ type 0x%x\n",
+ type);
+ spin_unlock_irqrestore(&chip->lock, flags);
+ return -EINVAL;
+ }
+
+ nsp_set_bit(chip, REG, NSP_GPIO_EVENT_INT_POLARITY, gpio, falling);
+ nsp_set_bit(chip, REG, NSP_GPIO_INT_POLARITY, gpio, level_low);
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ dev_dbg(chip->dev, "gpio:%u level_low:%s falling:%s\n", gpio,
+ level_low ? "true" : "false", falling ? "true" : "false");
+ return 0;
+}
+
+static struct irq_chip nsp_gpio_irq_chip = {
+ .name = "gpio-a",
+ .irq_enable = nsp_gpio_irq_unmask,
+ .irq_disable = nsp_gpio_irq_mask,
+ .irq_ack = nsp_gpio_irq_ack,
+ .irq_mask = nsp_gpio_irq_mask,
+ .irq_unmask = nsp_gpio_irq_unmask,
+ .irq_set_type = nsp_gpio_irq_set_type,
+};
+
+/*
+ * Request the nsp IOMUX pinmux controller to mux individual pins to GPIO
+ */
+static int nsp_gpio_request(struct gpio_chip *gc, unsigned offset)
+{
+ unsigned gpio = gc->base + offset;
+
+ return pinctrl_request_gpio(gpio);
+}
+
+static void nsp_gpio_free(struct gpio_chip *gc, unsigned offset)
+{
+ unsigned gpio = gc->base + offset;
+
+ pinctrl_free_gpio(gpio);
+}
+
+static int nsp_gpio_direction_input(struct gpio_chip *gc, unsigned gpio)
+{
+ struct nsp_gpio *chip = to_nsp_gpio(gc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ nsp_set_bit(chip, REG, NSP_GPIO_OUT_EN, gpio, false);
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ dev_dbg(chip->dev, "gpio:%u set input\n", gpio);
+ return 0;
+}
+
+static int nsp_gpio_direction_output(struct gpio_chip *gc, unsigned gpio,
+ int val)
+{
+ struct nsp_gpio *chip = to_nsp_gpio(gc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ nsp_set_bit(chip, REG, NSP_GPIO_OUT_EN, gpio, true);
+ nsp_set_bit(chip, REG, NSP_GPIO_DATA_OUT, gpio, !!(val));
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ dev_dbg(chip->dev, "gpio:%u set output, value:%d\n", gpio, val);
+ return 0;
+}
+
+static void nsp_gpio_set(struct gpio_chip *gc, unsigned gpio, int val)
+{
+ struct nsp_gpio *chip = to_nsp_gpio(gc);
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ nsp_set_bit(chip, REG, NSP_GPIO_DATA_OUT, gpio, !!(val));
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ dev_dbg(chip->dev, "gpio:%u set, value:%d\n", gpio, val);
+}
+
+static int nsp_gpio_get(struct gpio_chip *gc, unsigned gpio)
+{
+ struct nsp_gpio *chip = to_nsp_gpio(gc);
+
+ return !!(readl(chip->base + NSP_GPIO_DATA_IN) & BIT(gpio));
+}
+
+static int nsp_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+ struct nsp_gpio *chip = to_nsp_gpio(gc);
+
+ return irq_linear_revmap(chip->irq_domain, offset);
+}
+
+static int nsp_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ return 1;
+}
+
+/*
+ * Only one group: "gpio_grp", since this local pinctrl device only performs
+ * GPIO specific PINCONF configurations
+ */
+static const char *nsp_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return "gpio_grp";
+}
+
+static const struct pinctrl_ops nsp_pctrl_ops = {
+ .get_groups_count = nsp_get_groups_count,
+ .get_group_name = nsp_get_group_name,
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
+ .dt_free_map = pinctrl_utils_dt_free_map,
+};
+
+static int nsp_gpio_set_slew(struct nsp_gpio *chip, unsigned gpio, u16 slew)
+{
+ if (slew)
+ nsp_set_bit(chip, IO_CTRL, NSP_GPIO_SLEW_RATE_EN, gpio, true);
+ else
+ nsp_set_bit(chip, IO_CTRL, NSP_GPIO_SLEW_RATE_EN, gpio, false);
+
+ return 0;
+}
+
+static int nsp_gpio_set_pull(struct nsp_gpio *chip, unsigned gpio,
+ bool pull_up, bool pull_down)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ nsp_set_bit(chip, IO_CTRL, NSP_PULL_DOWN_EN, gpio, pull_down);
+ nsp_set_bit(chip, IO_CTRL, NSP_PULL_UP_EN, gpio, pull_up);
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ dev_dbg(chip->dev, "gpio:%u set pullup:%d pulldown: %d\n",
+ gpio, pull_up, pull_down);
+ return 0;
+}
+
+static void nsp_gpio_get_pull(struct nsp_gpio *chip, unsigned gpio,
+ bool *pull_up, bool *pull_down)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ *pull_up = nsp_get_bit(chip, IO_CTRL, NSP_PULL_UP_EN, gpio);
+ *pull_down = nsp_get_bit(chip, IO_CTRL, NSP_PULL_DOWN_EN, gpio);
+ spin_unlock_irqrestore(&chip->lock, flags);
+}
+
+static int nsp_gpio_set_strength(struct nsp_gpio *chip, unsigned gpio,
+ u16 strength)
+{
+ u32 offset, shift, i;
+ u32 val;
+ unsigned long flags;
+
+ /* make sure drive strength is supported */
+ if (strength < 2 || strength > 16 || (strength % 2))
+ return -ENOTSUPP;
+
+ shift = gpio;
+ offset = NSP_GPIO_DRV_CTRL;
+ dev_dbg(chip->dev, "gpio:%u set drive strength:%d mA\n", gpio,
+ strength);
+ spin_lock_irqsave(&chip->lock, flags);
+ strength = (strength / 2) - 1;
+ for (i = GPIO_DRV_STRENGTH_BITS; i > 0; i--) {
+ val = readl(chip->io_ctrl + offset);
+ val &= ~BIT(shift);
+ val |= ((strength >> (i-1)) & 0x1) << shift;
+ writel(val, chip->io_ctrl + offset);
+ offset += 4;
+ }
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return 0;
+}
+
+static int nsp_gpio_get_strength(struct nsp_gpio *chip, unsigned gpio,
+ u16 *strength)
+{
+ unsigned int offset, shift;
+ u32 val;
+ unsigned long flags;
+ int i;
+
+ offset = NSP_GPIO_DRV_CTRL;
+ shift = gpio;
+
+ spin_lock_irqsave(&chip->lock, flags);
+ *strength = 0;
+ for (i = (GPIO_DRV_STRENGTH_BITS - 1); i >= 0; i--) {
+ val = readl(chip->io_ctrl + offset) & BIT(shift);
+ val >>= shift;
+ *strength += (val << i);
+ offset += 4;
+ }
+
+ /* convert to mA */
+ *strength = (*strength + 1) * 2;
+ spin_unlock_irqrestore(&chip->lock, flags);
+
+ return 0;
+}
+
+int nsp_pin_config_group_get(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned long *config)
+{
+ return 0;
+}
+
+int nsp_pin_config_group_set(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned long *configs, unsigned num_configs)
+{
+ return 0;
+}
+
+static int nsp_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
+ unsigned long *config)
+{
+ struct nsp_gpio *chip = pinctrl_dev_get_drvdata(pctldev);
+ enum pin_config_param param = pinconf_to_config_param(*config);
+ unsigned int gpio;
+ u16 arg = 0;
+ bool pull_up, pull_down;
+ int ret;
+
+ gpio = nsp_pin_to_gpio(pin);
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ nsp_gpio_get_pull(chip, gpio, &pull_up, &pull_down);
+ if ((pull_up == false) && (pull_down == false))
+ return 0;
+ else
+ return -EINVAL;
+
+ case PIN_CONFIG_BIAS_PULL_UP:
+ nsp_gpio_get_pull(chip, gpio, &pull_up, &pull_down);
+ if (pull_up)
+ return 0;
+ else
+ return -EINVAL;
+
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ nsp_gpio_get_pull(chip, gpio, &pull_up, &pull_down);
+ if (pull_down)
+ return 0;
+ else
+ return -EINVAL;
+
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ ret = nsp_gpio_get_strength(chip, gpio, &arg);
+ if (ret)
+ return ret;
+ *config = pinconf_to_config_packed(param, arg);
+ return 0;
+
+ default:
+ return -ENOTSUPP;
+ }
+}
+
+static int nsp_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
+ unsigned long *configs, unsigned num_configs)
+{
+ struct nsp_gpio *chip = pinctrl_dev_get_drvdata(pctldev);
+ enum pin_config_param param;
+ u16 arg;
+ unsigned int i, gpio;
+ int ret = -ENOTSUPP;
+
+ gpio = nsp_pin_to_gpio(pin);
+ for (i = 0; i < num_configs; i++) {
+ param = pinconf_to_config_param(configs[i]);
+ arg = pinconf_to_config_argument(configs[i]);
+
+ switch (param) {
+ case PIN_CONFIG_BIAS_DISABLE:
+ ret = nsp_gpio_set_pull(chip, gpio, false, false);
+ if (ret < 0)
+ goto out;
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_UP:
+ ret = nsp_gpio_set_pull(chip, gpio, true, false);
+ if (ret < 0)
+ goto out;
+ break;
+
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ ret = nsp_gpio_set_pull(chip, gpio, false, true);
+ if (ret < 0)
+ goto out;
+ break;
+
+ case PIN_CONFIG_DRIVE_STRENGTH:
+ ret = nsp_gpio_set_strength(chip, gpio, arg);
+ if (ret < 0)
+ goto out;
+ break;
+
+ case PIN_CONFIG_SLEW_RATE:
+ ret = nsp_gpio_set_slew(chip, gpio, arg);
+ if (ret < 0)
+ goto out;
+ break;
+
+ default:
+ dev_err(chip->dev, "invalid configuration\n");
+ return -ENOTSUPP;
+ }
+ }
+
+out:
+ return ret;
+}
+
+static const struct pinconf_ops nsp_pconf_ops = {
+ .is_generic = true,
+ .pin_config_get = nsp_pin_config_get,
+ .pin_config_set = nsp_pin_config_set,
+ .pin_config_group_get = nsp_pin_config_group_get,
+ .pin_config_group_set = nsp_pin_config_group_set,
+};
+
+/*
+ * NSP GPIO controller supports some PINCONF related configurations such as
+ * pull up, pull down, slew and drive strength, when the pin is configured
+ * to GPIO.
+ *
+ * Here a local pinctrl device is created with simple 1-to-1 pin mapping to the
+ * local GPIO pins
+ */
+static int nsp_gpio_register_pinconf(struct nsp_gpio *chip)
+{
+ struct pinctrl_desc *pctldesc = &chip->pctldesc;
+ struct pinctrl_pin_desc *pins;
+ struct gpio_chip *gc = &chip->gc;
+ int i;
+
+ pins = devm_kcalloc(chip->dev, gc->ngpio, sizeof(*pins), GFP_KERNEL);
+ if (!pins)
+ return -ENOMEM;
+ for (i = 0; i < gc->ngpio; i++) {
+ pins[i].number = i;
+ pins[i].name = devm_kasprintf(chip->dev, GFP_KERNEL,
+ "gpio-%d", i);
+ if (!pins[i].name)
+ return -ENOMEM;
+ }
+ pctldesc->name = dev_name(chip->dev);
+ pctldesc->pctlops = &nsp_pctrl_ops;
+ pctldesc->pins = pins;
+ pctldesc->npins = gc->ngpio;
+ pctldesc->confops = &nsp_pconf_ops;
+
+ chip->pctl = pinctrl_register(pctldesc, chip->dev, chip);
+ if (IS_ERR(chip->pctl)) {
+ dev_err(chip->dev, "unable to register pinctrl device\n");
+ return PTR_ERR(chip->pctl);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id nsp_gpio_of_match[] = {
+ {.compatible = "brcm,nsp-gpio-a",},
+ {}
+};
+
+static int nsp_gpio_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct nsp_gpio *chip;
+ struct gpio_chip *gc;
+ u32 val, count;
+ int irq, ret;
+
+ if (of_property_read_u32(pdev->dev.of_node, "ngpios", &val)) {
+ dev_err(&pdev->dev, "Missing ngpios OF property\n");
+ return -ENODEV;
+ }
+
+ chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
+ if (!chip)
+ return -ENOMEM;
+
+ chip->dev = dev;
+ platform_set_drvdata(pdev, chip);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ chip->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(chip->base)) {
+ dev_err(dev, "unable to map I/O memory\n");
+ return PTR_ERR(chip->base);
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ chip->io_ctrl = devm_ioremap_resource(dev, res);
+ if (IS_ERR(chip->io_ctrl)) {
+ dev_err(dev, "unable to map I/O memory\n");
+ return PTR_ERR(chip->io_ctrl);
+ }
+
+ spin_lock_init(&chip->lock);
+ gc = &chip->gc;
+ gc->base = -1;
+ gc->can_sleep = false;
+ gc->ngpio = val;
+ gc->label = dev_name(dev);
+ gc->dev = dev;
+ gc->of_node = dev->of_node;
+ gc->request = nsp_gpio_request;
+ gc->free = nsp_gpio_free;
+ gc->direction_input = nsp_gpio_direction_input;
+ gc->direction_output = nsp_gpio_direction_output;
+ gc->set = nsp_gpio_set;
+ gc->get = nsp_gpio_get;
+ gc->to_irq = nsp_gpio_to_irq;
+
+ /* optional GPIO interrupt support */
+ irq = platform_get_irq(pdev, 0);
+ if (irq > 0) {
+ /* Create irq domain so that each pin can be assigned an IRQ.*/
+ chip->irq_domain = irq_domain_add_linear(gc->of_node, gc->ngpio,
+ &irq_domain_simple_ops,
+ chip);
+ if (!chip->irq_domain) {
+ dev_err(&pdev->dev, "Couldn't allocate IRQ domain\n");
+ return -ENXIO;
+ }
+
+ /* Map each gpio to an IRQ and set the handler for gpiolib. */
+ for (count = 0; count < gc->ngpio; count++) {
+ int irq = irq_create_mapping(chip->irq_domain, count);
+
+ irq_set_chip_and_handler(irq, &nsp_gpio_irq_chip,
+ handle_simple_irq);
+ irq_set_chip_data(irq, chip);
+ }
+
+ /* Install ISR for this GPIO controller. */
+ ret = devm_request_irq(&pdev->dev, irq, nsp_gpio_irq_handler,
+ IRQF_SHARED, "gpio-a", chip);
+ if (ret) {
+ dev_err(&pdev->dev, "Unable to request IRQ%d: %d\n",
+ irq, ret);
+ goto err_rm_gpiochip;
+ }
+
+ val = readl(chip->base + NSP_CHIP_A_INT_MASK);
+ val = val | NSP_CHIP_A_GPIO_INT_BIT;
+ writel(val, (chip->base + NSP_CHIP_A_INT_MASK));
+ }
+
+ ret = gpiochip_add(gc);
+ if (ret < 0) {
+ dev_err(dev, "unable to add GPIO chip\n");
+ return ret;
+ }
+
+ ret = nsp_gpio_register_pinconf(chip);
+ if (ret) {
+ dev_err(dev, "unable to register pinconf\n");
+ goto err_rm_gpiochip;
+ }
+
+ return 0;
+
+err_rm_gpiochip:
+ gpiochip_remove(gc);
+
+ return ret;
+}
+
+static struct platform_driver nsp_gpio_driver = {
+ .driver = {
+ .name = "nsp-gpio-a",
+ .of_match_table = nsp_gpio_of_match,
+ },
+ .probe = nsp_gpio_probe,
+};
+
+static int __init nsp_gpio_init(void)
+{
+ return platform_driver_probe(&nsp_gpio_driver, nsp_gpio_probe);
+}
+arch_initcall_sync(nsp_gpio_init);
diff --git a/drivers/pinctrl/berlin/Makefile b/drivers/pinctrl/berlin/Makefile
index 06f94029ad66..6f641ce2c830 100644
--- a/drivers/pinctrl/berlin/Makefile
+++ b/drivers/pinctrl/berlin/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_PINCTRL_BERLIN) += berlin.o
+obj-y += berlin.o
obj-$(CONFIG_PINCTRL_BERLIN_BG2) += berlin-bg2.o
obj-$(CONFIG_PINCTRL_BERLIN_BG2CD) += berlin-bg2cd.o
obj-$(CONFIG_PINCTRL_BERLIN_BG2Q) += berlin-bg2q.o
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8127.c b/drivers/pinctrl/mediatek/pinctrl-mt8127.c
index b317b0b664ea..98e0bebfdf92 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8127.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8127.c
@@ -351,7 +351,7 @@ static int __init mtk_pinctrl_init(void)
return platform_driver_register(&mtk_pinctrl_driver);
}
-module_init(mtk_pinctrl_init);
+arch_initcall(mtk_pinctrl_init);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("MediaTek MT8127 Pinctrl Driver");
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8135.c b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
index 404f1178511d..1c153b860f36 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8135.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8135.c
@@ -366,7 +366,7 @@ static int __init mtk_pinctrl_init(void)
return platform_driver_register(&mtk_pinctrl_driver);
}
-module_init(mtk_pinctrl_init);
+arch_initcall(mtk_pinctrl_init);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MediaTek Pinctrl Driver");
diff --git a/drivers/pinctrl/mediatek/pinctrl-mt8173.c b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
index ad271840d865..a62514eb2129 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mt8173.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mt8173.c
@@ -394,7 +394,7 @@ static int __init mtk_pinctrl_init(void)
return platform_driver_register(&mtk_pinctrl_driver);
}
-module_init(mtk_pinctrl_init);
+arch_initcall(mtk_pinctrl_init);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("MediaTek Pinctrl Driver");
diff --git a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
index 5c717275a7fa..e22cbaf9f9cf 100644
--- a/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
+++ b/drivers/pinctrl/mediatek/pinctrl-mtk-common.c
@@ -509,6 +509,9 @@ static int mtk_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
err = pinconf_generic_parse_dt_config(node, pctldev, &configs,
&num_configs);
+ if (err)
+ return err;
+
if (num_configs)
has_config = 1;
@@ -520,21 +523,23 @@ static int mtk_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
if (has_config && num_pins >= 1)
maps_per_pin++;
- if (!num_pins || !maps_per_pin)
- return -EINVAL;
+ if (!num_pins || !maps_per_pin) {
+ err = -EINVAL;
+ goto exit;
+ }
reserve = num_pins * maps_per_pin;
err = pinctrl_utils_reserve_map(pctldev, map,
reserved_maps, num_maps, reserve);
if (err < 0)
- goto fail;
+ goto exit;
for (i = 0; i < num_pins; i++) {
err = of_property_read_u32_index(node, "pinmux",
i, &pinfunc);
if (err)
- goto fail;
+ goto exit;
pin = MTK_GET_PIN_NO(pinfunc);
func = MTK_GET_PIN_FUNC(pinfunc);
@@ -543,20 +548,21 @@ static int mtk_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
func >= ARRAY_SIZE(mtk_gpio_functions)) {
dev_err(pctl->dev, "invalid pins value.\n");
err = -EINVAL;
- goto fail;
+ goto exit;
}
grp = mtk_pctrl_find_group_by_pin(pctl, pin);
if (!grp) {
dev_err(pctl->dev, "unable to match pin %d to group\n",
pin);
- return -EINVAL;
+ err = -EINVAL;
+ goto exit;
}
err = mtk_pctrl_dt_node_to_map_func(pctl, pin, func, grp, map,
reserved_maps, num_maps);
if (err < 0)
- goto fail;
+ goto exit;
if (has_config) {
err = pinctrl_utils_add_map_configs(pctldev, map,
@@ -564,13 +570,14 @@ static int mtk_pctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
configs, num_configs,
PIN_MAP_TYPE_CONFIGS_GROUP);
if (err < 0)
- goto fail;
+ goto exit;
}
}
- return 0;
+ err = 0;
-fail:
+exit:
+ kfree(configs);
return err;
}
@@ -591,6 +598,7 @@ static int mtk_pctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
&reserved_maps, num_maps);
if (ret < 0) {
pinctrl_utils_dt_free_map(pctldev, *map, *num_maps);
+ of_node_put(np);
return ret;
}
}
diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile
index 554d8af14eeb..18270cd5ea43 100644
--- a/drivers/pinctrl/mvebu/Makefile
+++ b/drivers/pinctrl/mvebu/Makefile
@@ -1,4 +1,4 @@
-obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o
+obj-y += pinctrl-mvebu.o
obj-$(CONFIG_PINCTRL_DOVE) += pinctrl-dove.o
obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o
obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
index 77d2221d379d..e4d473811bb3 100644
--- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c
+++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c
@@ -663,28 +663,20 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
/* assign mpp modes to groups */
for (n = 0; n < soc->nmodes; n++) {
struct mvebu_mpp_mode *mode = &soc->modes[n];
- struct mvebu_pinctrl_group *grp =
- mvebu_pinctrl_find_group_by_pid(pctl, mode->pid);
+ struct mvebu_mpp_ctrl_setting *set = &mode->settings[0];
+ struct mvebu_pinctrl_group *grp;
unsigned num_settings;
- if (!grp) {
- dev_warn(&pdev->dev, "unknown pinctrl group %d\n",
- mode->pid);
- continue;
- }
-
- for (num_settings = 0; ;) {
- struct mvebu_mpp_ctrl_setting *set =
- &mode->settings[num_settings];
-
+ for (num_settings = 0; ; set++) {
if (!set->name)
break;
- num_settings++;
/* skip unsupported settings for this variant */
if (pctl->variant && !(pctl->variant & set->variant))
continue;
+ num_settings++;
+
/* find gpio/gpo/gpi settings */
if (strcmp(set->name, "gpio") == 0)
set->flags = MVEBU_SETTING_GPI |
@@ -695,6 +687,17 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
set->flags = MVEBU_SETTING_GPI;
}
+ /* skip modes with no settings for this variant */
+ if (!num_settings)
+ continue;
+
+ grp = mvebu_pinctrl_find_group_by_pid(pctl, mode->pid);
+ if (!grp) {
+ dev_warn(&pdev->dev, "unknown pinctrl group %d\n",
+ mode->pid);
+ continue;
+ }
+
grp->settings = mode->settings;
grp->num_settings = num_settings;
}
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 099a3442ff42..79e6159712c2 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -220,6 +220,7 @@ static void parse_dt_cfg(struct device_node *np,
* parse the config properties into generic pinconfig values.
* @np: node containing the pinconfig properties
* @configs: array with nconfigs entries containing the generic pinconf values
+ * must be freed when no longer necessary.
* @nconfigs: umber of configurations
*/
int pinconf_generic_parse_dt_config(struct device_node *np,
diff --git a/drivers/pinctrl/pinctrl-adi2.c b/drivers/pinctrl/pinctrl-adi2.c
index fd342dffe4dc..8e9e8eab59ba 100644
--- a/drivers/pinctrl/pinctrl-adi2.c
+++ b/drivers/pinctrl/pinctrl-adi2.c
@@ -1102,32 +1102,24 @@ static struct platform_driver adi_gpio_driver = {
},
};
+static struct platform_driver * const drivers[] = {
+ &adi_pinctrl_driver,
+ &adi_gpio_pint_driver,
+ &adi_gpio_driver,
+};
+
static int __init adi_pinctrl_setup(void)
{
int ret;
- ret = platform_driver_register(&adi_pinctrl_driver);
+ ret = platform_register_drivers(drivers, ARRAY_SIZE(drivers));
if (ret)
return ret;
- ret = platform_driver_register(&adi_gpio_pint_driver);
- if (ret)
- goto pint_error;
-
- ret = platform_driver_register(&adi_gpio_driver);
- if (ret)
- goto gpio_error;
-
#ifdef CONFIG_PM
register_syscore_ops(&gpio_pm_syscore_ops);
#endif
- return ret;
-gpio_error:
- platform_driver_unregister(&adi_gpio_pint_driver);
-pint_error:
- platform_driver_unregister(&adi_pinctrl_driver);
-
- return ret;
+ return 0;
}
arch_initcall(adi_pinctrl_setup);
diff --git a/drivers/pinctrl/pinctrl-at91-pio4.c b/drivers/pinctrl/pinctrl-at91-pio4.c
index 33edd07d9149..d5bdcebc6aa6 100644
--- a/drivers/pinctrl/pinctrl-at91-pio4.c
+++ b/drivers/pinctrl/pinctrl-at91-pio4.c
@@ -500,7 +500,8 @@ static int atmel_pctl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
if (!num_pins) {
dev_err(pctldev->dev, "no pins found in node %s\n",
of_node_full_name(np));
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit;
}
/*
@@ -514,19 +515,19 @@ static int atmel_pctl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps,
reserve);
if (ret < 0)
- return ret;
+ goto exit;
for (i = 0; i < num_pins; i++) {
const char *group, *func;
ret = of_property_read_u32_index(np, "pinmux", i, &pinfunc);
if (ret)
- return ret;
+ goto exit;
ret = atmel_pctl_xlate_pinfunc(pctldev, np, pinfunc, &group,
&func);
if (ret)
- return ret;
+ goto exit;
pinctrl_utils_add_map_mux(pctldev, map, reserved_maps, num_maps,
group, func);
@@ -537,11 +538,13 @@ static int atmel_pctl_dt_subnode_to_map(struct pinctrl_dev *pctldev,
configs, num_configs,
PIN_MAP_TYPE_CONFIGS_GROUP);
if (ret < 0)
- return ret;
+ goto exit;
}
}
- return 0;
+exit:
+ kfree(configs);
+ return ret;
}
static int atmel_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
@@ -1000,7 +1003,7 @@ static int atmel_pinctrl_probe(struct platform_device *pdev)
atmel_pioctrl->irqs[i] = res->start;
irq_set_chained_handler(res->start, atmel_gpio_irq_handler);
irq_set_handler_data(res->start, atmel_pioctrl);
- dev_dbg(dev, "bank %i: hwirq=%u\n", i, res->start);
+ dev_dbg(dev, "bank %i: irq=%pr\n", i, res);
}
atmel_pioctrl->irq_domain = irq_domain_add_linear(dev->of_node,
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c
index 0d2fc0cff35e..47b625b1b789 100644
--- a/drivers/pinctrl/pinctrl-at91.c
+++ b/drivers/pinctrl/pinctrl-at91.c
@@ -1828,20 +1828,20 @@ static struct platform_driver at91_pinctrl_driver = {
.remove = at91_pinctrl_remove,
};
+static struct platform_driver * const drivers[] = {
+ &at91_gpio_driver,
+ &at91_pinctrl_driver,
+};
+
static int __init at91_pinctrl_init(void)
{
- int ret;
-
- ret = platform_driver_register(&at91_gpio_driver);
- if (ret)
- return ret;
- return platform_driver_register(&at91_pinctrl_driver);
+ return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
}
arch_initcall(at91_pinctrl_init);
static void __exit at91_pinctrl_exit(void)
{
- platform_driver_unregister(&at91_pinctrl_driver);
+ platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
}
module_exit(at91_pinctrl_exit);
diff --git a/drivers/pinctrl/pinctrl-lantiq.h b/drivers/pinctrl/pinctrl-lantiq.h
index eb89ba045228..e137d139e494 100644
--- a/drivers/pinctrl/pinctrl-lantiq.h
+++ b/drivers/pinctrl/pinctrl-lantiq.h
@@ -162,6 +162,14 @@ enum ltq_pin {
GPIO53,
GPIO54,
GPIO55,
+ GPIO56,
+ GPIO57,
+ GPIO58,
+ GPIO59,
+ GPIO60, /* 60 */
+ GPIO61,
+ GPIO62,
+ GPIO63,
GPIO64,
GPIO65,
diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c
index a0651128e23a..91288265e856 100644
--- a/drivers/pinctrl/pinctrl-rockchip.c
+++ b/drivers/pinctrl/pinctrl-rockchip.c
@@ -614,6 +614,40 @@ static void rk3288_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
}
}
+#define RK3228_PULL_OFFSET 0x100
+
+static void rk3228_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl *info = bank->drvdata;
+
+ *regmap = info->regmap_base;
+ *reg = RK3228_PULL_OFFSET;
+ *reg += bank->bank_num * RK3188_PULL_BANK_STRIDE;
+ *reg += ((pin_num / RK3188_PULL_PINS_PER_REG) * 4);
+
+ *bit = (pin_num % RK3188_PULL_PINS_PER_REG);
+ *bit *= RK3188_PULL_BITS_PER_PIN;
+}
+
+#define RK3228_DRV_GRF_OFFSET 0x200
+
+static void rk3228_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank,
+ int pin_num, struct regmap **regmap,
+ int *reg, u8 *bit)
+{
+ struct rockchip_pinctrl *info = bank->drvdata;
+
+ *regmap = info->regmap_base;
+ *reg = RK3228_DRV_GRF_OFFSET;
+ *reg += bank->bank_num * RK3288_DRV_BANK_STRIDE;
+ *reg += ((pin_num / RK3288_DRV_PINS_PER_REG) * 4);
+
+ *bit = (pin_num % RK3288_DRV_PINS_PER_REG);
+ *bit *= RK3288_DRV_BITS_PER_PIN;
+}
+
#define RK3368_PULL_GRF_OFFSET 0x100
#define RK3368_PULL_PMU_OFFSET 0x10
@@ -1258,8 +1292,10 @@ static int rockchip_pinctrl_parse_functions(struct device_node *np,
func->groups[i] = child->name;
grp = &info->groups[grp_index++];
ret = rockchip_pinctrl_parse_groups(child, grp, info, i++);
- if (ret)
+ if (ret) {
+ of_node_put(child);
return ret;
+ }
}
return 0;
@@ -1304,6 +1340,7 @@ static int rockchip_pinctrl_parse_dt(struct platform_device *pdev,
ret = rockchip_pinctrl_parse_functions(child, info, i++);
if (ret) {
dev_err(&pdev->dev, "failed to parse function\n");
+ of_node_put(child);
return ret;
}
}
@@ -2143,6 +2180,23 @@ static struct rockchip_pin_ctrl rk3188_pin_ctrl = {
.pull_calc_reg = rk3188_calc_pull_reg_and_bit,
};
+static struct rockchip_pin_bank rk3228_pin_banks[] = {
+ PIN_BANK(0, 32, "gpio0"),
+ PIN_BANK(1, 32, "gpio1"),
+ PIN_BANK(2, 32, "gpio2"),
+ PIN_BANK(3, 32, "gpio3"),
+};
+
+static struct rockchip_pin_ctrl rk3228_pin_ctrl = {
+ .pin_banks = rk3228_pin_banks,
+ .nr_banks = ARRAY_SIZE(rk3228_pin_banks),
+ .label = "RK3228-GPIO",
+ .type = RK3288,
+ .grf_mux_offset = 0x0,
+ .pull_calc_reg = rk3228_calc_pull_reg_and_bit,
+ .drv_calc_reg = rk3228_calc_drv_reg_and_bit,
+};
+
static struct rockchip_pin_bank rk3288_pin_banks[] = {
PIN_BANK_IOMUX_FLAGS(0, 24, "gpio0", IOMUX_SOURCE_PMU,
IOMUX_SOURCE_PMU,
@@ -2220,6 +2274,8 @@ static const struct of_device_id rockchip_pinctrl_dt_match[] = {
.data = (void *)&rk3066b_pin_ctrl },
{ .compatible = "rockchip,rk3188-pinctrl",
.data = (void *)&rk3188_pin_ctrl },
+ { .compatible = "rockchip,rk3228-pinctrl",
+ .data = (void *)&rk3228_pin_ctrl },
{ .compatible = "rockchip,rk3288-pinctrl",
.data = (void *)&rk3288_pin_ctrl },
{ .compatible = "rockchip,rk3368-pinctrl",
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index ef04b962c3d5..d24e5f1d1525 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -1484,10 +1484,7 @@ static void pcs_irq_free(struct pcs_device *pcs)
static void pcs_free_resources(struct pcs_device *pcs)
{
pcs_irq_free(pcs);
-
- if (pcs->pctl)
- pinctrl_unregister(pcs->pctl);
-
+ pinctrl_unregister(pcs->pctl);
pcs_free_funcs(pcs);
pcs_free_pingroups(pcs);
}
diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c
index 84a43e612952..bd3aa5a4fd6d 100644
--- a/drivers/pinctrl/pinctrl-tegra-xusb.c
+++ b/drivers/pinctrl/pinctrl-tegra-xusb.c
@@ -253,8 +253,10 @@ static int tegra_xusb_padctl_dt_node_to_map(struct pinctrl_dev *pinctrl,
err = tegra_xusb_padctl_parse_subnode(padctl, np, maps,
&reserved_maps,
num_maps);
- if (err < 0)
+ if (err < 0) {
+ of_node_put(np);
return err;
+ }
}
return 0;
diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c
index 0fd7fd2b0f72..9da4da219a07 100644
--- a/drivers/pinctrl/pinctrl-tegra.c
+++ b/drivers/pinctrl/pinctrl-tegra.c
@@ -217,6 +217,7 @@ static int tegra_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
if (ret < 0) {
pinctrl_utils_dt_free_map(pctldev, *map,
*num_maps);
+ of_node_put(np);
return ret;
}
}
diff --git a/drivers/pinctrl/pinctrl-xway.c b/drivers/pinctrl/pinctrl-xway.c
index ae724bdab3d3..7db74699fda4 100644
--- a/drivers/pinctrl/pinctrl-xway.c
+++ b/drivers/pinctrl/pinctrl-xway.c
@@ -7,6 +7,7 @@
* publishhed by the Free Software Foundation.
*
* Copyright (C) 2012 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2015 Martin Schiller <mschiller@tdt.de>
*/
#include <linux/err.h>
@@ -24,7 +25,7 @@
#include <lantiq_soc.h>
-/* we have 3 1/2 banks of 16 bit each */
+/* we have up to 4 banks of 16 bit each */
#define PINS 16
#define PORT3 3
#define PORT(x) (x / PINS)
@@ -35,7 +36,7 @@
#define MUX_ALT1 0x2
/*
- * each bank has this offset apart from the 1/2 bank that is mixed into the
+ * each bank has this offset apart from the 4th bank that is mixed into the
* other 3 ranges
*/
#define REG_OFF 0x30
@@ -51,7 +52,7 @@
#define GPIO_PUDSEL(p) (GPIO_BASE(p) + 0x1c)
#define GPIO_PUDEN(p) (GPIO_BASE(p) + 0x20)
-/* the 1/2 port needs special offsets for some registers */
+/* the 4th port needs special offsets for some registers */
#define GPIO3_OD (GPIO_BASE(0) + 0x24)
#define GPIO3_PUDSEL (GPIO_BASE(0) + 0x28)
#define GPIO3_PUDEN (GPIO_BASE(0) + 0x2C)
@@ -80,17 +81,18 @@
#define FUNC_MUX(f, m) \
{ .func = f, .mux = XWAY_MUX_##m, }
-#define XWAY_MAX_PIN 32
-#define XR9_MAX_PIN 56
-
enum xway_mux {
XWAY_MUX_GPIO = 0,
XWAY_MUX_SPI,
XWAY_MUX_ASC,
+ XWAY_MUX_USIF,
XWAY_MUX_PCI,
+ XWAY_MUX_CBUS,
XWAY_MUX_CGU,
XWAY_MUX_EBU,
+ XWAY_MUX_EBU2,
XWAY_MUX_JTAG,
+ XWAY_MUX_MCD,
XWAY_MUX_EXIN,
XWAY_MUX_TDM,
XWAY_MUX_STP,
@@ -103,9 +105,15 @@ enum xway_mux {
XWAY_MUX_DFE,
XWAY_MUX_SDIO,
XWAY_MUX_GPHY,
+ XWAY_MUX_SSI,
+ XWAY_MUX_WIFI,
XWAY_MUX_NONE = 0xffff,
};
+/* --------- DEPRECATED: xr9 related code --------- */
+/* ---------- use xrx100/xrx200 instead ---------- */
+#define XR9_MAX_PIN 56
+
static const struct ltq_mfp_pin xway_mfp[] = {
/* pin f0 f1 f2 f3 */
MFP_XWAY(GPIO0, GPIO, EXIN, NONE, TDM),
@@ -113,7 +121,7 @@ static const struct ltq_mfp_pin xway_mfp[] = {
MFP_XWAY(GPIO2, GPIO, CGU, EXIN, GPHY),
MFP_XWAY(GPIO3, GPIO, CGU, NONE, PCI),
MFP_XWAY(GPIO4, GPIO, STP, NONE, ASC),
- MFP_XWAY(GPIO5, GPIO, STP, NONE, GPHY),
+ MFP_XWAY(GPIO5, GPIO, STP, GPHY, NONE),
MFP_XWAY(GPIO6, GPIO, STP, GPT, ASC),
MFP_XWAY(GPIO7, GPIO, CGU, PCI, GPHY),
MFP_XWAY(GPIO8, GPIO, CGU, NMI, NONE),
@@ -152,10 +160,10 @@ static const struct ltq_mfp_pin xway_mfp[] = {
MFP_XWAY(GPIO41, GPIO, NONE, NONE, NONE),
MFP_XWAY(GPIO42, GPIO, MDIO, NONE, NONE),
MFP_XWAY(GPIO43, GPIO, MDIO, NONE, NONE),
- MFP_XWAY(GPIO44, GPIO, NONE, GPHY, SIN),
+ MFP_XWAY(GPIO44, GPIO, MII, SIN, GPHY),
MFP_XWAY(GPIO45, GPIO, NONE, GPHY, SIN),
MFP_XWAY(GPIO46, GPIO, NONE, NONE, EXIN),
- MFP_XWAY(GPIO47, GPIO, NONE, GPHY, SIN),
+ MFP_XWAY(GPIO47, GPIO, MII, GPHY, SIN),
MFP_XWAY(GPIO48, GPIO, EBU, NONE, NONE),
MFP_XWAY(GPIO49, GPIO, EBU, NONE, NONE),
MFP_XWAY(GPIO50, GPIO, NONE, NONE, NONE),
@@ -166,42 +174,6 @@ static const struct ltq_mfp_pin xway_mfp[] = {
MFP_XWAY(GPIO55, GPIO, NONE, NONE, NONE),
};
-static const struct ltq_mfp_pin ase_mfp[] = {
- /* pin f0 f1 f2 f3 */
- MFP_XWAY(GPIO0, GPIO, EXIN, MII, TDM),
- MFP_XWAY(GPIO1, GPIO, STP, DFE, EBU),
- MFP_XWAY(GPIO2, GPIO, STP, DFE, EPHY),
- MFP_XWAY(GPIO3, GPIO, STP, EPHY, EBU),
- MFP_XWAY(GPIO4, GPIO, GPT, EPHY, MII),
- MFP_XWAY(GPIO5, GPIO, MII, ASC, GPT),
- MFP_XWAY(GPIO6, GPIO, MII, ASC, EXIN),
- MFP_XWAY(GPIO7, GPIO, SPI, MII, JTAG),
- MFP_XWAY(GPIO8, GPIO, SPI, MII, JTAG),
- MFP_XWAY(GPIO9, GPIO, SPI, MII, JTAG),
- MFP_XWAY(GPIO10, GPIO, SPI, MII, JTAG),
- MFP_XWAY(GPIO11, GPIO, EBU, CGU, JTAG),
- MFP_XWAY(GPIO12, GPIO, EBU, MII, SDIO),
- MFP_XWAY(GPIO13, GPIO, EBU, MII, CGU),
- MFP_XWAY(GPIO14, GPIO, EBU, SPI, CGU),
- MFP_XWAY(GPIO15, GPIO, EBU, SPI, SDIO),
- MFP_XWAY(GPIO16, GPIO, NONE, NONE, NONE),
- MFP_XWAY(GPIO17, GPIO, NONE, NONE, NONE),
- MFP_XWAY(GPIO18, GPIO, NONE, NONE, NONE),
- MFP_XWAY(GPIO19, GPIO, EBU, MII, SDIO),
- MFP_XWAY(GPIO20, GPIO, EBU, MII, SDIO),
- MFP_XWAY(GPIO21, GPIO, EBU, MII, SDIO),
- MFP_XWAY(GPIO22, GPIO, EBU, MII, CGU),
- MFP_XWAY(GPIO23, GPIO, EBU, MII, CGU),
- MFP_XWAY(GPIO24, GPIO, EBU, NONE, MII),
- MFP_XWAY(GPIO25, GPIO, EBU, MII, GPT),
- MFP_XWAY(GPIO26, GPIO, EBU, MII, SDIO),
- MFP_XWAY(GPIO27, GPIO, EBU, NONE, MII),
- MFP_XWAY(GPIO28, GPIO, MII, EBU, SDIO),
- MFP_XWAY(GPIO29, GPIO, EBU, MII, EXIN),
- MFP_XWAY(GPIO30, GPIO, NONE, NONE, NONE),
- MFP_XWAY(GPIO31, GPIO, NONE, NONE, NONE),
-};
-
static const unsigned pins_jtag[] = {GPIO15, GPIO16, GPIO17, GPIO19, GPIO35};
static const unsigned pins_asc0[] = {GPIO11, GPIO12};
static const unsigned pins_asc0_cts_rts[] = {GPIO9, GPIO10};
@@ -231,6 +203,8 @@ static const unsigned pins_nand_cle[] = {GPIO24};
static const unsigned pins_nand_rdy[] = {GPIO48};
static const unsigned pins_nand_rd[] = {GPIO49};
+static const unsigned xway_exin_pin_map[] = {GPIO0, GPIO1, GPIO2, GPIO39, GPIO46, GPIO9};
+
static const unsigned pins_exin0[] = {GPIO0};
static const unsigned pins_exin1[] = {GPIO1};
static const unsigned pins_exin2[] = {GPIO2};
@@ -240,7 +214,7 @@ static const unsigned pins_exin5[] = {GPIO9};
static const unsigned pins_spi[] = {GPIO16, GPIO17, GPIO18};
static const unsigned pins_spi_cs1[] = {GPIO15};
-static const unsigned pins_spi_cs2[] = {GPIO21};
+static const unsigned pins_spi_cs2[] = {GPIO22};
static const unsigned pins_spi_cs3[] = {GPIO13};
static const unsigned pins_spi_cs4[] = {GPIO10};
static const unsigned pins_spi_cs5[] = {GPIO9};
@@ -264,25 +238,6 @@ static const unsigned pins_pci_req2[] = {GPIO31};
static const unsigned pins_pci_req3[] = {GPIO3};
static const unsigned pins_pci_req4[] = {GPIO37};
-static const unsigned ase_pins_jtag[] = {GPIO7, GPIO8, GPIO9, GPIO10, GPIO11};
-static const unsigned ase_pins_asc[] = {GPIO5, GPIO6};
-static const unsigned ase_pins_stp[] = {GPIO1, GPIO2, GPIO3};
-static const unsigned ase_pins_ephy[] = {GPIO2, GPIO3, GPIO4};
-static const unsigned ase_pins_dfe[] = {GPIO1, GPIO2};
-
-static const unsigned ase_pins_spi[] = {GPIO8, GPIO9, GPIO10};
-static const unsigned ase_pins_spi_cs1[] = {GPIO7};
-static const unsigned ase_pins_spi_cs2[] = {GPIO15};
-static const unsigned ase_pins_spi_cs3[] = {GPIO14};
-
-static const unsigned ase_pins_exin0[] = {GPIO6};
-static const unsigned ase_pins_exin1[] = {GPIO29};
-static const unsigned ase_pins_exin2[] = {GPIO0};
-
-static const unsigned ase_pins_gpt1[] = {GPIO5};
-static const unsigned ase_pins_gpt2[] = {GPIO4};
-static const unsigned ase_pins_gpt3[] = {GPIO25};
-
static const struct ltq_pin_group xway_grps[] = {
GRP_MUX("exin0", EXIN, pins_exin0),
GRP_MUX("exin1", EXIN, pins_exin1),
@@ -338,24 +293,6 @@ static const struct ltq_pin_group xway_grps[] = {
GRP_MUX("gphy1 led2", GPHY, pins_gphy1_led2),
};
-static const struct ltq_pin_group ase_grps[] = {
- GRP_MUX("exin0", EXIN, ase_pins_exin0),
- GRP_MUX("exin1", EXIN, ase_pins_exin1),
- GRP_MUX("exin2", EXIN, ase_pins_exin2),
- GRP_MUX("jtag", JTAG, ase_pins_jtag),
- GRP_MUX("stp", STP, ase_pins_stp),
- GRP_MUX("asc", ASC, ase_pins_asc),
- GRP_MUX("gpt1", GPT, ase_pins_gpt1),
- GRP_MUX("gpt2", GPT, ase_pins_gpt2),
- GRP_MUX("gpt3", GPT, ase_pins_gpt3),
- GRP_MUX("ephy", EPHY, ase_pins_ephy),
- GRP_MUX("dfe", DFE, ase_pins_dfe),
- GRP_MUX("spi", SPI, ase_pins_spi),
- GRP_MUX("spi_cs1", SPI, ase_pins_spi_cs1),
- GRP_MUX("spi_cs2", SPI, ase_pins_spi_cs2),
- GRP_MUX("spi_cs3", SPI, ase_pins_spi_cs3),
-};
-
static const char * const xway_pci_grps[] = {"gnt1", "gnt2",
"gnt3", "req1",
"req2", "req3"};
@@ -395,30 +332,6 @@ static const char * const xrx_pci_grps[] = {"gnt1", "gnt2",
"req1", "req2",
"req3", "req4"};
-/* ase */
-static const char * const ase_exin_grps[] = {"exin0", "exin1", "exin2"};
-static const char * const ase_gpt_grps[] = {"gpt1", "gpt2", "gpt3"};
-static const char * const ase_dfe_grps[] = {"dfe"};
-static const char * const ase_ephy_grps[] = {"ephy"};
-static const char * const ase_asc_grps[] = {"asc"};
-static const char * const ase_jtag_grps[] = {"jtag"};
-static const char * const ase_stp_grps[] = {"stp"};
-static const char * const ase_spi_grps[] = {"spi", "spi_cs1",
- "spi_cs2", "spi_cs3"};
-
-static const struct ltq_pmx_func danube_funcs[] = {
- {"spi", ARRAY_AND_SIZE(xway_spi_grps)},
- {"asc", ARRAY_AND_SIZE(xway_asc_grps)},
- {"cgu", ARRAY_AND_SIZE(xway_cgu_grps)},
- {"jtag", ARRAY_AND_SIZE(xway_jtag_grps)},
- {"exin", ARRAY_AND_SIZE(xway_exin_grps)},
- {"stp", ARRAY_AND_SIZE(xway_stp_grps)},
- {"gpt", ARRAY_AND_SIZE(xway_gpt_grps)},
- {"nmi", ARRAY_AND_SIZE(xway_nmi_grps)},
- {"pci", ARRAY_AND_SIZE(xway_pci_grps)},
- {"ebu", ARRAY_AND_SIZE(xway_ebu_grps)},
-};
-
static const struct ltq_pmx_func xrx_funcs[] = {
{"spi", ARRAY_AND_SIZE(xway_spi_grps)},
{"asc", ARRAY_AND_SIZE(xway_asc_grps)},
@@ -434,17 +347,991 @@ static const struct ltq_pmx_func xrx_funcs[] = {
{"gphy", ARRAY_AND_SIZE(xrx_gphy_grps)},
};
+/* --------- ase related code --------- */
+#define ASE_MAX_PIN 32
+
+static const struct ltq_mfp_pin ase_mfp[] = {
+ /* pin f0 f1 f2 f3 */
+ MFP_XWAY(GPIO0, GPIO, EXIN, MII, TDM),
+ MFP_XWAY(GPIO1, GPIO, STP, DFE, EBU),
+ MFP_XWAY(GPIO2, GPIO, STP, DFE, EPHY),
+ MFP_XWAY(GPIO3, GPIO, STP, EPHY, EBU),
+ MFP_XWAY(GPIO4, GPIO, GPT, EPHY, MII),
+ MFP_XWAY(GPIO5, GPIO, MII, ASC, GPT),
+ MFP_XWAY(GPIO6, GPIO, MII, ASC, EXIN),
+ MFP_XWAY(GPIO7, GPIO, SPI, MII, JTAG),
+ MFP_XWAY(GPIO8, GPIO, SPI, MII, JTAG),
+ MFP_XWAY(GPIO9, GPIO, SPI, MII, JTAG),
+ MFP_XWAY(GPIO10, GPIO, SPI, MII, JTAG),
+ MFP_XWAY(GPIO11, GPIO, EBU, CGU, JTAG),
+ MFP_XWAY(GPIO12, GPIO, EBU, MII, SDIO),
+ MFP_XWAY(GPIO13, GPIO, EBU, MII, CGU),
+ MFP_XWAY(GPIO14, GPIO, EBU, SPI, CGU),
+ MFP_XWAY(GPIO15, GPIO, EBU, SPI, SDIO),
+ MFP_XWAY(GPIO16, GPIO, NONE, NONE, NONE),
+ MFP_XWAY(GPIO17, GPIO, NONE, NONE, NONE),
+ MFP_XWAY(GPIO18, GPIO, NONE, NONE, NONE),
+ MFP_XWAY(GPIO19, GPIO, EBU, MII, SDIO),
+ MFP_XWAY(GPIO20, GPIO, EBU, MII, SDIO),
+ MFP_XWAY(GPIO21, GPIO, EBU, MII, EBU2),
+ MFP_XWAY(GPIO22, GPIO, EBU, MII, CGU),
+ MFP_XWAY(GPIO23, GPIO, EBU, MII, CGU),
+ MFP_XWAY(GPIO24, GPIO, EBU, EBU2, MDIO),
+ MFP_XWAY(GPIO25, GPIO, EBU, MII, GPT),
+ MFP_XWAY(GPIO26, GPIO, EBU, MII, SDIO),
+ MFP_XWAY(GPIO27, GPIO, EBU, NONE, MDIO),
+ MFP_XWAY(GPIO28, GPIO, MII, EBU, SDIO),
+ MFP_XWAY(GPIO29, GPIO, EBU, MII, EXIN),
+ MFP_XWAY(GPIO30, GPIO, NONE, NONE, NONE),
+ MFP_XWAY(GPIO31, GPIO, NONE, NONE, NONE),
+};
+
+static const unsigned ase_exin_pin_map[] = {GPIO6, GPIO29, GPIO0};
+
+static const unsigned ase_pins_exin0[] = {GPIO6};
+static const unsigned ase_pins_exin1[] = {GPIO29};
+static const unsigned ase_pins_exin2[] = {GPIO0};
+
+static const unsigned ase_pins_jtag[] = {GPIO7, GPIO8, GPIO9, GPIO10, GPIO11};
+static const unsigned ase_pins_asc[] = {GPIO5, GPIO6};
+static const unsigned ase_pins_stp[] = {GPIO1, GPIO2, GPIO3};
+static const unsigned ase_pins_mdio[] = {GPIO24, GPIO27};
+static const unsigned ase_pins_ephy_led0[] = {GPIO2};
+static const unsigned ase_pins_ephy_led1[] = {GPIO3};
+static const unsigned ase_pins_ephy_led2[] = {GPIO4};
+static const unsigned ase_pins_dfe_led0[] = {GPIO1};
+static const unsigned ase_pins_dfe_led1[] = {GPIO2};
+
+static const unsigned ase_pins_spi[] = {GPIO8, GPIO9, GPIO10}; /* DEPRECATED */
+static const unsigned ase_pins_spi_di[] = {GPIO8};
+static const unsigned ase_pins_spi_do[] = {GPIO9};
+static const unsigned ase_pins_spi_clk[] = {GPIO10};
+static const unsigned ase_pins_spi_cs1[] = {GPIO7};
+static const unsigned ase_pins_spi_cs2[] = {GPIO15};
+static const unsigned ase_pins_spi_cs3[] = {GPIO14};
+
+static const unsigned ase_pins_gpt1[] = {GPIO5};
+static const unsigned ase_pins_gpt2[] = {GPIO4};
+static const unsigned ase_pins_gpt3[] = {GPIO25};
+
+static const unsigned ase_pins_clkout0[] = {GPIO23};
+static const unsigned ase_pins_clkout1[] = {GPIO22};
+static const unsigned ase_pins_clkout2[] = {GPIO14};
+
+static const struct ltq_pin_group ase_grps[] = {
+ GRP_MUX("exin0", EXIN, ase_pins_exin0),
+ GRP_MUX("exin1", EXIN, ase_pins_exin1),
+ GRP_MUX("exin2", EXIN, ase_pins_exin2),
+ GRP_MUX("jtag", JTAG, ase_pins_jtag),
+ GRP_MUX("spi", SPI, ase_pins_spi), /* DEPRECATED */
+ GRP_MUX("spi_di", SPI, ase_pins_spi_di),
+ GRP_MUX("spi_do", SPI, ase_pins_spi_do),
+ GRP_MUX("spi_clk", SPI, ase_pins_spi_clk),
+ GRP_MUX("spi_cs1", SPI, ase_pins_spi_cs1),
+ GRP_MUX("spi_cs2", SPI, ase_pins_spi_cs2),
+ GRP_MUX("spi_cs3", SPI, ase_pins_spi_cs3),
+ GRP_MUX("asc", ASC, ase_pins_asc),
+ GRP_MUX("stp", STP, ase_pins_stp),
+ GRP_MUX("gpt1", GPT, ase_pins_gpt1),
+ GRP_MUX("gpt2", GPT, ase_pins_gpt2),
+ GRP_MUX("gpt3", GPT, ase_pins_gpt3),
+ GRP_MUX("clkout0", CGU, ase_pins_clkout0),
+ GRP_MUX("clkout1", CGU, ase_pins_clkout1),
+ GRP_MUX("clkout2", CGU, ase_pins_clkout2),
+ GRP_MUX("mdio", MDIO, ase_pins_mdio),
+ GRP_MUX("dfe led0", DFE, ase_pins_dfe_led0),
+ GRP_MUX("dfe led1", DFE, ase_pins_dfe_led1),
+ GRP_MUX("ephy led0", EPHY, ase_pins_ephy_led0),
+ GRP_MUX("ephy led1", EPHY, ase_pins_ephy_led1),
+ GRP_MUX("ephy led2", EPHY, ase_pins_ephy_led2),
+};
+
+static const char * const ase_exin_grps[] = {"exin0", "exin1", "exin2"};
+static const char * const ase_gpt_grps[] = {"gpt1", "gpt2", "gpt3"};
+static const char * const ase_cgu_grps[] = {"clkout0", "clkout1",
+ "clkout2"};
+static const char * const ase_mdio_grps[] = {"mdio"};
+static const char * const ase_dfe_grps[] = {"dfe led0", "dfe led1"};
+static const char * const ase_ephy_grps[] = {"ephy led0", "ephy led1",
+ "ephy led2"};
+static const char * const ase_asc_grps[] = {"asc"};
+static const char * const ase_jtag_grps[] = {"jtag"};
+static const char * const ase_stp_grps[] = {"stp"};
+static const char * const ase_spi_grps[] = {"spi", /* DEPRECATED */
+ "spi_di", "spi_do",
+ "spi_clk", "spi_cs1",
+ "spi_cs2", "spi_cs3"};
+
static const struct ltq_pmx_func ase_funcs[] = {
{"spi", ARRAY_AND_SIZE(ase_spi_grps)},
{"asc", ARRAY_AND_SIZE(ase_asc_grps)},
+ {"cgu", ARRAY_AND_SIZE(ase_cgu_grps)},
{"jtag", ARRAY_AND_SIZE(ase_jtag_grps)},
{"exin", ARRAY_AND_SIZE(ase_exin_grps)},
{"stp", ARRAY_AND_SIZE(ase_stp_grps)},
{"gpt", ARRAY_AND_SIZE(ase_gpt_grps)},
+ {"mdio", ARRAY_AND_SIZE(ase_mdio_grps)},
{"ephy", ARRAY_AND_SIZE(ase_ephy_grps)},
{"dfe", ARRAY_AND_SIZE(ase_dfe_grps)},
};
+/* --------- danube related code --------- */
+#define DANUBE_MAX_PIN 32
+
+static const struct ltq_mfp_pin danube_mfp[] = {
+ /* pin f0 f1 f2 f3 */
+ MFP_XWAY(GPIO0, GPIO, EXIN, SDIO, TDM),
+ MFP_XWAY(GPIO1, GPIO, EXIN, CBUS, MII),
+ MFP_XWAY(GPIO2, GPIO, CGU, EXIN, MII),
+ MFP_XWAY(GPIO3, GPIO, CGU, SDIO, PCI),
+ MFP_XWAY(GPIO4, GPIO, STP, DFE, ASC),
+ MFP_XWAY(GPIO5, GPIO, STP, MII, DFE),
+ MFP_XWAY(GPIO6, GPIO, STP, GPT, ASC),
+ MFP_XWAY(GPIO7, GPIO, CGU, CBUS, MII),
+ MFP_XWAY(GPIO8, GPIO, CGU, NMI, MII),
+ MFP_XWAY(GPIO9, GPIO, ASC, SPI, MII),
+ MFP_XWAY(GPIO10, GPIO, ASC, SPI, MII),
+ MFP_XWAY(GPIO11, GPIO, ASC, CBUS, SPI),
+ MFP_XWAY(GPIO12, GPIO, ASC, CBUS, MCD),
+ MFP_XWAY(GPIO13, GPIO, EBU, SPI, MII),
+ MFP_XWAY(GPIO14, GPIO, CGU, CBUS, MII),
+ MFP_XWAY(GPIO15, GPIO, SPI, SDIO, JTAG),
+ MFP_XWAY(GPIO16, GPIO, SPI, SDIO, JTAG),
+ MFP_XWAY(GPIO17, GPIO, SPI, SDIO, JTAG),
+ MFP_XWAY(GPIO18, GPIO, SPI, SDIO, JTAG),
+ MFP_XWAY(GPIO19, GPIO, PCI, SDIO, MII),
+ MFP_XWAY(GPIO20, GPIO, JTAG, SDIO, MII),
+ MFP_XWAY(GPIO21, GPIO, PCI, EBU, GPT),
+ MFP_XWAY(GPIO22, GPIO, SPI, MCD, MII),
+ MFP_XWAY(GPIO23, GPIO, EBU, PCI, STP),
+ MFP_XWAY(GPIO24, GPIO, EBU, TDM, PCI),
+ MFP_XWAY(GPIO25, GPIO, TDM, SDIO, ASC),
+ MFP_XWAY(GPIO26, GPIO, EBU, TDM, SDIO),
+ MFP_XWAY(GPIO27, GPIO, TDM, SDIO, ASC),
+ MFP_XWAY(GPIO28, GPIO, GPT, MII, SDIO),
+ MFP_XWAY(GPIO29, GPIO, PCI, CBUS, MII),
+ MFP_XWAY(GPIO30, GPIO, PCI, CBUS, MII),
+ MFP_XWAY(GPIO31, GPIO, EBU, PCI, MII),
+};
+
+static const unsigned danube_exin_pin_map[] = {GPIO0, GPIO1, GPIO2};
+
+static const unsigned danube_pins_exin0[] = {GPIO0};
+static const unsigned danube_pins_exin1[] = {GPIO1};
+static const unsigned danube_pins_exin2[] = {GPIO2};
+
+static const unsigned danube_pins_jtag[] = {GPIO15, GPIO16, GPIO17, GPIO18, GPIO20};
+static const unsigned danube_pins_asc0[] = {GPIO11, GPIO12};
+static const unsigned danube_pins_asc0_cts_rts[] = {GPIO9, GPIO10};
+static const unsigned danube_pins_stp[] = {GPIO4, GPIO5, GPIO6};
+static const unsigned danube_pins_nmi[] = {GPIO8};
+
+static const unsigned danube_pins_dfe_led0[] = {GPIO4};
+static const unsigned danube_pins_dfe_led1[] = {GPIO5};
+
+static const unsigned danube_pins_ebu_a24[] = {GPIO13};
+static const unsigned danube_pins_ebu_clk[] = {GPIO21};
+static const unsigned danube_pins_ebu_cs1[] = {GPIO23};
+static const unsigned danube_pins_ebu_a23[] = {GPIO24};
+static const unsigned danube_pins_ebu_wait[] = {GPIO26};
+static const unsigned danube_pins_ebu_a25[] = {GPIO31};
+
+static const unsigned danube_pins_nand_ale[] = {GPIO13};
+static const unsigned danube_pins_nand_cs1[] = {GPIO23};
+static const unsigned danube_pins_nand_cle[] = {GPIO24};
+
+static const unsigned danube_pins_spi[] = {GPIO16, GPIO17, GPIO18}; /* DEPRECATED */
+static const unsigned danube_pins_spi_di[] = {GPIO16};
+static const unsigned danube_pins_spi_do[] = {GPIO17};
+static const unsigned danube_pins_spi_clk[] = {GPIO18};
+static const unsigned danube_pins_spi_cs1[] = {GPIO15};
+static const unsigned danube_pins_spi_cs2[] = {GPIO21};
+static const unsigned danube_pins_spi_cs3[] = {GPIO13};
+static const unsigned danube_pins_spi_cs4[] = {GPIO10};
+static const unsigned danube_pins_spi_cs5[] = {GPIO9};
+static const unsigned danube_pins_spi_cs6[] = {GPIO11};
+
+static const unsigned danube_pins_gpt1[] = {GPIO28};
+static const unsigned danube_pins_gpt2[] = {GPIO21};
+static const unsigned danube_pins_gpt3[] = {GPIO6};
+
+static const unsigned danube_pins_clkout0[] = {GPIO8};
+static const unsigned danube_pins_clkout1[] = {GPIO7};
+static const unsigned danube_pins_clkout2[] = {GPIO3};
+static const unsigned danube_pins_clkout3[] = {GPIO2};
+
+static const unsigned danube_pins_pci_gnt1[] = {GPIO30};
+static const unsigned danube_pins_pci_gnt2[] = {GPIO23};
+static const unsigned danube_pins_pci_gnt3[] = {GPIO19};
+static const unsigned danube_pins_pci_req1[] = {GPIO29};
+static const unsigned danube_pins_pci_req2[] = {GPIO31};
+static const unsigned danube_pins_pci_req3[] = {GPIO3};
+
+static const struct ltq_pin_group danube_grps[] = {
+ GRP_MUX("exin0", EXIN, danube_pins_exin0),
+ GRP_MUX("exin1", EXIN, danube_pins_exin1),
+ GRP_MUX("exin2", EXIN, danube_pins_exin2),
+ GRP_MUX("jtag", JTAG, danube_pins_jtag),
+ GRP_MUX("ebu a23", EBU, danube_pins_ebu_a23),
+ GRP_MUX("ebu a24", EBU, danube_pins_ebu_a24),
+ GRP_MUX("ebu a25", EBU, danube_pins_ebu_a25),
+ GRP_MUX("ebu clk", EBU, danube_pins_ebu_clk),
+ GRP_MUX("ebu cs1", EBU, danube_pins_ebu_cs1),
+ GRP_MUX("ebu wait", EBU, danube_pins_ebu_wait),
+ GRP_MUX("nand ale", EBU, danube_pins_nand_ale),
+ GRP_MUX("nand cs1", EBU, danube_pins_nand_cs1),
+ GRP_MUX("nand cle", EBU, danube_pins_nand_cle),
+ GRP_MUX("spi", SPI, danube_pins_spi), /* DEPRECATED */
+ GRP_MUX("spi_di", SPI, danube_pins_spi_di),
+ GRP_MUX("spi_do", SPI, danube_pins_spi_do),
+ GRP_MUX("spi_clk", SPI, danube_pins_spi_clk),
+ GRP_MUX("spi_cs1", SPI, danube_pins_spi_cs1),
+ GRP_MUX("spi_cs2", SPI, danube_pins_spi_cs2),
+ GRP_MUX("spi_cs3", SPI, danube_pins_spi_cs3),
+ GRP_MUX("spi_cs4", SPI, danube_pins_spi_cs4),
+ GRP_MUX("spi_cs5", SPI, danube_pins_spi_cs5),
+ GRP_MUX("spi_cs6", SPI, danube_pins_spi_cs6),
+ GRP_MUX("asc0", ASC, danube_pins_asc0),
+ GRP_MUX("asc0 cts rts", ASC, danube_pins_asc0_cts_rts),
+ GRP_MUX("stp", STP, danube_pins_stp),
+ GRP_MUX("nmi", NMI, danube_pins_nmi),
+ GRP_MUX("gpt1", GPT, danube_pins_gpt1),
+ GRP_MUX("gpt2", GPT, danube_pins_gpt2),
+ GRP_MUX("gpt3", GPT, danube_pins_gpt3),
+ GRP_MUX("clkout0", CGU, danube_pins_clkout0),
+ GRP_MUX("clkout1", CGU, danube_pins_clkout1),
+ GRP_MUX("clkout2", CGU, danube_pins_clkout2),
+ GRP_MUX("clkout3", CGU, danube_pins_clkout3),
+ GRP_MUX("gnt1", PCI, danube_pins_pci_gnt1),
+ GRP_MUX("gnt2", PCI, danube_pins_pci_gnt2),
+ GRP_MUX("gnt3", PCI, danube_pins_pci_gnt3),
+ GRP_MUX("req1", PCI, danube_pins_pci_req1),
+ GRP_MUX("req2", PCI, danube_pins_pci_req2),
+ GRP_MUX("req3", PCI, danube_pins_pci_req3),
+ GRP_MUX("dfe led0", DFE, danube_pins_dfe_led0),
+ GRP_MUX("dfe led1", DFE, danube_pins_dfe_led1),
+};
+
+static const char * const danube_pci_grps[] = {"gnt1", "gnt2",
+ "gnt3", "req1",
+ "req2", "req3"};
+static const char * const danube_spi_grps[] = {"spi", /* DEPRECATED */
+ "spi_di", "spi_do",
+ "spi_clk", "spi_cs1",
+ "spi_cs2", "spi_cs3",
+ "spi_cs4", "spi_cs5",
+ "spi_cs6"};
+static const char * const danube_cgu_grps[] = {"clkout0", "clkout1",
+ "clkout2", "clkout3"};
+static const char * const danube_ebu_grps[] = {"ebu a23", "ebu a24",
+ "ebu a25", "ebu cs1",
+ "ebu wait", "ebu clk",
+ "nand ale", "nand cs1",
+ "nand cle"};
+static const char * const danube_dfe_grps[] = {"dfe led0", "dfe led1"};
+static const char * const danube_exin_grps[] = {"exin0", "exin1", "exin2"};
+static const char * const danube_gpt_grps[] = {"gpt1", "gpt2", "gpt3"};
+static const char * const danube_asc_grps[] = {"asc0", "asc0 cts rts"};
+static const char * const danube_jtag_grps[] = {"jtag"};
+static const char * const danube_stp_grps[] = {"stp"};
+static const char * const danube_nmi_grps[] = {"nmi"};
+
+static const struct ltq_pmx_func danube_funcs[] = {
+ {"spi", ARRAY_AND_SIZE(danube_spi_grps)},
+ {"asc", ARRAY_AND_SIZE(danube_asc_grps)},
+ {"cgu", ARRAY_AND_SIZE(danube_cgu_grps)},
+ {"jtag", ARRAY_AND_SIZE(danube_jtag_grps)},
+ {"exin", ARRAY_AND_SIZE(danube_exin_grps)},
+ {"stp", ARRAY_AND_SIZE(danube_stp_grps)},
+ {"gpt", ARRAY_AND_SIZE(danube_gpt_grps)},
+ {"nmi", ARRAY_AND_SIZE(danube_nmi_grps)},
+ {"pci", ARRAY_AND_SIZE(danube_pci_grps)},
+ {"ebu", ARRAY_AND_SIZE(danube_ebu_grps)},
+ {"dfe", ARRAY_AND_SIZE(danube_dfe_grps)},
+};
+
+/* --------- xrx100 related code --------- */
+#define XRX100_MAX_PIN 56
+
+static const struct ltq_mfp_pin xrx100_mfp[] = {
+ /* pin f0 f1 f2 f3 */
+ MFP_XWAY(GPIO0, GPIO, EXIN, SDIO, TDM),
+ MFP_XWAY(GPIO1, GPIO, EXIN, CBUS, SIN),
+ MFP_XWAY(GPIO2, GPIO, CGU, EXIN, NONE),
+ MFP_XWAY(GPIO3, GPIO, CGU, SDIO, PCI),
+ MFP_XWAY(GPIO4, GPIO, STP, DFE, ASC),
+ MFP_XWAY(GPIO5, GPIO, STP, NONE, DFE),
+ MFP_XWAY(GPIO6, GPIO, STP, GPT, ASC),
+ MFP_XWAY(GPIO7, GPIO, CGU, CBUS, NONE),
+ MFP_XWAY(GPIO8, GPIO, CGU, NMI, NONE),
+ MFP_XWAY(GPIO9, GPIO, ASC, SPI, EXIN),
+ MFP_XWAY(GPIO10, GPIO, ASC, SPI, EXIN),
+ MFP_XWAY(GPIO11, GPIO, ASC, CBUS, SPI),
+ MFP_XWAY(GPIO12, GPIO, ASC, CBUS, MCD),
+ MFP_XWAY(GPIO13, GPIO, EBU, SPI, NONE),
+ MFP_XWAY(GPIO14, GPIO, CGU, NONE, NONE),
+ MFP_XWAY(GPIO15, GPIO, SPI, SDIO, MCD),
+ MFP_XWAY(GPIO16, GPIO, SPI, SDIO, NONE),
+ MFP_XWAY(GPIO17, GPIO, SPI, SDIO, NONE),
+ MFP_XWAY(GPIO18, GPIO, SPI, SDIO, NONE),
+ MFP_XWAY(GPIO19, GPIO, PCI, SDIO, CGU),
+ MFP_XWAY(GPIO20, GPIO, NONE, SDIO, EBU),
+ MFP_XWAY(GPIO21, GPIO, PCI, EBU, GPT),
+ MFP_XWAY(GPIO22, GPIO, SPI, NONE, EBU),
+ MFP_XWAY(GPIO23, GPIO, EBU, PCI, STP),
+ MFP_XWAY(GPIO24, GPIO, EBU, TDM, PCI),
+ MFP_XWAY(GPIO25, GPIO, TDM, SDIO, ASC),
+ MFP_XWAY(GPIO26, GPIO, EBU, TDM, SDIO),
+ MFP_XWAY(GPIO27, GPIO, TDM, SDIO, ASC),
+ MFP_XWAY(GPIO28, GPIO, GPT, NONE, SDIO),
+ MFP_XWAY(GPIO29, GPIO, PCI, CBUS, NONE),
+ MFP_XWAY(GPIO30, GPIO, PCI, CBUS, NONE),
+ MFP_XWAY(GPIO31, GPIO, EBU, PCI, NONE),
+ MFP_XWAY(GPIO32, GPIO, MII, NONE, EBU),
+ MFP_XWAY(GPIO33, GPIO, MII, NONE, EBU),
+ MFP_XWAY(GPIO34, GPIO, SIN, SSI, NONE),
+ MFP_XWAY(GPIO35, GPIO, SIN, SSI, NONE),
+ MFP_XWAY(GPIO36, GPIO, SIN, SSI, NONE),
+ MFP_XWAY(GPIO37, GPIO, PCI, NONE, NONE),
+ MFP_XWAY(GPIO38, GPIO, PCI, NONE, NONE),
+ MFP_XWAY(GPIO39, GPIO, NONE, EXIN, NONE),
+ MFP_XWAY(GPIO40, GPIO, MII, TDM, NONE),
+ MFP_XWAY(GPIO41, GPIO, MII, TDM, NONE),
+ MFP_XWAY(GPIO42, GPIO, MDIO, NONE, NONE),
+ MFP_XWAY(GPIO43, GPIO, MDIO, NONE, NONE),
+ MFP_XWAY(GPIO44, GPIO, MII, SIN, NONE),
+ MFP_XWAY(GPIO45, GPIO, MII, NONE, SIN),
+ MFP_XWAY(GPIO46, GPIO, MII, NONE, EXIN),
+ MFP_XWAY(GPIO47, GPIO, MII, NONE, SIN),
+ MFP_XWAY(GPIO48, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO49, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO50, GPIO, NONE, NONE, NONE),
+ MFP_XWAY(GPIO51, GPIO, NONE, NONE, NONE),
+ MFP_XWAY(GPIO52, GPIO, NONE, NONE, NONE),
+ MFP_XWAY(GPIO53, GPIO, NONE, NONE, NONE),
+ MFP_XWAY(GPIO54, GPIO, NONE, NONE, NONE),
+ MFP_XWAY(GPIO55, GPIO, NONE, NONE, NONE),
+};
+
+static const unsigned xrx100_exin_pin_map[] = {GPIO0, GPIO1, GPIO2, GPIO39, GPIO10, GPIO9};
+
+static const unsigned xrx100_pins_exin0[] = {GPIO0};
+static const unsigned xrx100_pins_exin1[] = {GPIO1};
+static const unsigned xrx100_pins_exin2[] = {GPIO2};
+static const unsigned xrx100_pins_exin3[] = {GPIO39};
+static const unsigned xrx100_pins_exin4[] = {GPIO10};
+static const unsigned xrx100_pins_exin5[] = {GPIO9};
+
+static const unsigned xrx100_pins_asc0[] = {GPIO11, GPIO12};
+static const unsigned xrx100_pins_asc0_cts_rts[] = {GPIO9, GPIO10};
+static const unsigned xrx100_pins_stp[] = {GPIO4, GPIO5, GPIO6};
+static const unsigned xrx100_pins_nmi[] = {GPIO8};
+static const unsigned xrx100_pins_mdio[] = {GPIO42, GPIO43};
+
+static const unsigned xrx100_pins_dfe_led0[] = {GPIO4};
+static const unsigned xrx100_pins_dfe_led1[] = {GPIO5};
+
+static const unsigned xrx100_pins_ebu_a24[] = {GPIO13};
+static const unsigned xrx100_pins_ebu_clk[] = {GPIO21};
+static const unsigned xrx100_pins_ebu_cs1[] = {GPIO23};
+static const unsigned xrx100_pins_ebu_a23[] = {GPIO24};
+static const unsigned xrx100_pins_ebu_wait[] = {GPIO26};
+static const unsigned xrx100_pins_ebu_a25[] = {GPIO31};
+
+static const unsigned xrx100_pins_nand_ale[] = {GPIO13};
+static const unsigned xrx100_pins_nand_cs1[] = {GPIO23};
+static const unsigned xrx100_pins_nand_cle[] = {GPIO24};
+static const unsigned xrx100_pins_nand_rdy[] = {GPIO48};
+static const unsigned xrx100_pins_nand_rd[] = {GPIO49};
+
+static const unsigned xrx100_pins_spi_di[] = {GPIO16};
+static const unsigned xrx100_pins_spi_do[] = {GPIO17};
+static const unsigned xrx100_pins_spi_clk[] = {GPIO18};
+static const unsigned xrx100_pins_spi_cs1[] = {GPIO15};
+static const unsigned xrx100_pins_spi_cs2[] = {GPIO22};
+static const unsigned xrx100_pins_spi_cs3[] = {GPIO13};
+static const unsigned xrx100_pins_spi_cs4[] = {GPIO10};
+static const unsigned xrx100_pins_spi_cs5[] = {GPIO9};
+static const unsigned xrx100_pins_spi_cs6[] = {GPIO11};
+
+static const unsigned xrx100_pins_gpt1[] = {GPIO28};
+static const unsigned xrx100_pins_gpt2[] = {GPIO21};
+static const unsigned xrx100_pins_gpt3[] = {GPIO6};
+
+static const unsigned xrx100_pins_clkout0[] = {GPIO8};
+static const unsigned xrx100_pins_clkout1[] = {GPIO7};
+static const unsigned xrx100_pins_clkout2[] = {GPIO3};
+static const unsigned xrx100_pins_clkout3[] = {GPIO2};
+
+static const unsigned xrx100_pins_pci_gnt1[] = {GPIO30};
+static const unsigned xrx100_pins_pci_gnt2[] = {GPIO23};
+static const unsigned xrx100_pins_pci_gnt3[] = {GPIO19};
+static const unsigned xrx100_pins_pci_gnt4[] = {GPIO38};
+static const unsigned xrx100_pins_pci_req1[] = {GPIO29};
+static const unsigned xrx100_pins_pci_req2[] = {GPIO31};
+static const unsigned xrx100_pins_pci_req3[] = {GPIO3};
+static const unsigned xrx100_pins_pci_req4[] = {GPIO37};
+
+static const struct ltq_pin_group xrx100_grps[] = {
+ GRP_MUX("exin0", EXIN, xrx100_pins_exin0),
+ GRP_MUX("exin1", EXIN, xrx100_pins_exin1),
+ GRP_MUX("exin2", EXIN, xrx100_pins_exin2),
+ GRP_MUX("exin3", EXIN, xrx100_pins_exin3),
+ GRP_MUX("exin4", EXIN, xrx100_pins_exin4),
+ GRP_MUX("exin5", EXIN, xrx100_pins_exin5),
+ GRP_MUX("ebu a23", EBU, xrx100_pins_ebu_a23),
+ GRP_MUX("ebu a24", EBU, xrx100_pins_ebu_a24),
+ GRP_MUX("ebu a25", EBU, xrx100_pins_ebu_a25),
+ GRP_MUX("ebu clk", EBU, xrx100_pins_ebu_clk),
+ GRP_MUX("ebu cs1", EBU, xrx100_pins_ebu_cs1),
+ GRP_MUX("ebu wait", EBU, xrx100_pins_ebu_wait),
+ GRP_MUX("nand ale", EBU, xrx100_pins_nand_ale),
+ GRP_MUX("nand cs1", EBU, xrx100_pins_nand_cs1),
+ GRP_MUX("nand cle", EBU, xrx100_pins_nand_cle),
+ GRP_MUX("nand rdy", EBU, xrx100_pins_nand_rdy),
+ GRP_MUX("nand rd", EBU, xrx100_pins_nand_rd),
+ GRP_MUX("spi_di", SPI, xrx100_pins_spi_di),
+ GRP_MUX("spi_do", SPI, xrx100_pins_spi_do),
+ GRP_MUX("spi_clk", SPI, xrx100_pins_spi_clk),
+ GRP_MUX("spi_cs1", SPI, xrx100_pins_spi_cs1),
+ GRP_MUX("spi_cs2", SPI, xrx100_pins_spi_cs2),
+ GRP_MUX("spi_cs3", SPI, xrx100_pins_spi_cs3),
+ GRP_MUX("spi_cs4", SPI, xrx100_pins_spi_cs4),
+ GRP_MUX("spi_cs5", SPI, xrx100_pins_spi_cs5),
+ GRP_MUX("spi_cs6", SPI, xrx100_pins_spi_cs6),
+ GRP_MUX("asc0", ASC, xrx100_pins_asc0),
+ GRP_MUX("asc0 cts rts", ASC, xrx100_pins_asc0_cts_rts),
+ GRP_MUX("stp", STP, xrx100_pins_stp),
+ GRP_MUX("nmi", NMI, xrx100_pins_nmi),
+ GRP_MUX("gpt1", GPT, xrx100_pins_gpt1),
+ GRP_MUX("gpt2", GPT, xrx100_pins_gpt2),
+ GRP_MUX("gpt3", GPT, xrx100_pins_gpt3),
+ GRP_MUX("clkout0", CGU, xrx100_pins_clkout0),
+ GRP_MUX("clkout1", CGU, xrx100_pins_clkout1),
+ GRP_MUX("clkout2", CGU, xrx100_pins_clkout2),
+ GRP_MUX("clkout3", CGU, xrx100_pins_clkout3),
+ GRP_MUX("gnt1", PCI, xrx100_pins_pci_gnt1),
+ GRP_MUX("gnt2", PCI, xrx100_pins_pci_gnt2),
+ GRP_MUX("gnt3", PCI, xrx100_pins_pci_gnt3),
+ GRP_MUX("gnt4", PCI, xrx100_pins_pci_gnt4),
+ GRP_MUX("req1", PCI, xrx100_pins_pci_req1),
+ GRP_MUX("req2", PCI, xrx100_pins_pci_req2),
+ GRP_MUX("req3", PCI, xrx100_pins_pci_req3),
+ GRP_MUX("req4", PCI, xrx100_pins_pci_req4),
+ GRP_MUX("mdio", MDIO, xrx100_pins_mdio),
+ GRP_MUX("dfe led0", DFE, xrx100_pins_dfe_led0),
+ GRP_MUX("dfe led1", DFE, xrx100_pins_dfe_led1),
+};
+
+static const char * const xrx100_pci_grps[] = {"gnt1", "gnt2",
+ "gnt3", "gnt4",
+ "req1", "req2",
+ "req3", "req4"};
+static const char * const xrx100_spi_grps[] = {"spi_di", "spi_do",
+ "spi_clk", "spi_cs1",
+ "spi_cs2", "spi_cs3",
+ "spi_cs4", "spi_cs5",
+ "spi_cs6"};
+static const char * const xrx100_cgu_grps[] = {"clkout0", "clkout1",
+ "clkout2", "clkout3"};
+static const char * const xrx100_ebu_grps[] = {"ebu a23", "ebu a24",
+ "ebu a25", "ebu cs1",
+ "ebu wait", "ebu clk",
+ "nand ale", "nand cs1",
+ "nand cle", "nand rdy",
+ "nand rd"};
+static const char * const xrx100_exin_grps[] = {"exin0", "exin1", "exin2",
+ "exin3", "exin4", "exin5"};
+static const char * const xrx100_gpt_grps[] = {"gpt1", "gpt2", "gpt3"};
+static const char * const xrx100_asc_grps[] = {"asc0", "asc0 cts rts"};
+static const char * const xrx100_stp_grps[] = {"stp"};
+static const char * const xrx100_nmi_grps[] = {"nmi"};
+static const char * const xrx100_mdio_grps[] = {"mdio"};
+static const char * const xrx100_dfe_grps[] = {"dfe led0", "dfe led1"};
+
+static const struct ltq_pmx_func xrx100_funcs[] = {
+ {"spi", ARRAY_AND_SIZE(xrx100_spi_grps)},
+ {"asc", ARRAY_AND_SIZE(xrx100_asc_grps)},
+ {"cgu", ARRAY_AND_SIZE(xrx100_cgu_grps)},
+ {"exin", ARRAY_AND_SIZE(xrx100_exin_grps)},
+ {"stp", ARRAY_AND_SIZE(xrx100_stp_grps)},
+ {"gpt", ARRAY_AND_SIZE(xrx100_gpt_grps)},
+ {"nmi", ARRAY_AND_SIZE(xrx100_nmi_grps)},
+ {"pci", ARRAY_AND_SIZE(xrx100_pci_grps)},
+ {"ebu", ARRAY_AND_SIZE(xrx100_ebu_grps)},
+ {"mdio", ARRAY_AND_SIZE(xrx100_mdio_grps)},
+ {"dfe", ARRAY_AND_SIZE(xrx100_dfe_grps)},
+};
+
+/* --------- xrx200 related code --------- */
+#define XRX200_MAX_PIN 50
+
+static const struct ltq_mfp_pin xrx200_mfp[] = {
+ /* pin f0 f1 f2 f3 */
+ MFP_XWAY(GPIO0, GPIO, EXIN, SDIO, TDM),
+ MFP_XWAY(GPIO1, GPIO, EXIN, CBUS, SIN),
+ MFP_XWAY(GPIO2, GPIO, CGU, EXIN, GPHY),
+ MFP_XWAY(GPIO3, GPIO, CGU, SDIO, PCI),
+ MFP_XWAY(GPIO4, GPIO, STP, DFE, USIF),
+ MFP_XWAY(GPIO5, GPIO, STP, GPHY, DFE),
+ MFP_XWAY(GPIO6, GPIO, STP, GPT, USIF),
+ MFP_XWAY(GPIO7, GPIO, CGU, CBUS, GPHY),
+ MFP_XWAY(GPIO8, GPIO, CGU, NMI, NONE),
+ MFP_XWAY(GPIO9, GPIO, USIF, SPI, EXIN),
+ MFP_XWAY(GPIO10, GPIO, USIF, SPI, EXIN),
+ MFP_XWAY(GPIO11, GPIO, USIF, CBUS, SPI),
+ MFP_XWAY(GPIO12, GPIO, USIF, CBUS, MCD),
+ MFP_XWAY(GPIO13, GPIO, EBU, SPI, NONE),
+ MFP_XWAY(GPIO14, GPIO, CGU, CBUS, USIF),
+ MFP_XWAY(GPIO15, GPIO, SPI, SDIO, MCD),
+ MFP_XWAY(GPIO16, GPIO, SPI, SDIO, NONE),
+ MFP_XWAY(GPIO17, GPIO, SPI, SDIO, NONE),
+ MFP_XWAY(GPIO18, GPIO, SPI, SDIO, NONE),
+ MFP_XWAY(GPIO19, GPIO, PCI, SDIO, CGU),
+ MFP_XWAY(GPIO20, GPIO, NONE, SDIO, EBU),
+ MFP_XWAY(GPIO21, GPIO, PCI, EBU, GPT),
+ MFP_XWAY(GPIO22, GPIO, SPI, CGU, EBU),
+ MFP_XWAY(GPIO23, GPIO, EBU, PCI, STP),
+ MFP_XWAY(GPIO24, GPIO, EBU, TDM, PCI),
+ MFP_XWAY(GPIO25, GPIO, TDM, SDIO, USIF),
+ MFP_XWAY(GPIO26, GPIO, EBU, TDM, SDIO),
+ MFP_XWAY(GPIO27, GPIO, TDM, SDIO, USIF),
+ MFP_XWAY(GPIO28, GPIO, GPT, PCI, SDIO),
+ MFP_XWAY(GPIO29, GPIO, PCI, CBUS, EXIN),
+ MFP_XWAY(GPIO30, GPIO, PCI, CBUS, NONE),
+ MFP_XWAY(GPIO31, GPIO, EBU, PCI, NONE),
+ MFP_XWAY(GPIO32, GPIO, MII, NONE, EBU),
+ MFP_XWAY(GPIO33, GPIO, MII, NONE, EBU),
+ MFP_XWAY(GPIO34, GPIO, SIN, SSI, NONE),
+ MFP_XWAY(GPIO35, GPIO, SIN, SSI, NONE),
+ MFP_XWAY(GPIO36, GPIO, SIN, SSI, EXIN),
+ MFP_XWAY(GPIO37, GPIO, USIF, NONE, PCI),
+ MFP_XWAY(GPIO38, GPIO, PCI, USIF, NONE),
+ MFP_XWAY(GPIO39, GPIO, USIF, EXIN, NONE),
+ MFP_XWAY(GPIO40, GPIO, MII, TDM, NONE),
+ MFP_XWAY(GPIO41, GPIO, MII, TDM, NONE),
+ MFP_XWAY(GPIO42, GPIO, MDIO, NONE, NONE),
+ MFP_XWAY(GPIO43, GPIO, MDIO, NONE, NONE),
+ MFP_XWAY(GPIO44, GPIO, MII, SIN, GPHY),
+ MFP_XWAY(GPIO45, GPIO, MII, GPHY, SIN),
+ MFP_XWAY(GPIO46, GPIO, MII, NONE, EXIN),
+ MFP_XWAY(GPIO47, GPIO, MII, GPHY, SIN),
+ MFP_XWAY(GPIO48, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO49, GPIO, EBU, NONE, NONE),
+};
+
+static const unsigned xrx200_exin_pin_map[] = {GPIO0, GPIO1, GPIO2, GPIO39, GPIO10, GPIO9};
+
+static const unsigned xrx200_pins_exin0[] = {GPIO0};
+static const unsigned xrx200_pins_exin1[] = {GPIO1};
+static const unsigned xrx200_pins_exin2[] = {GPIO2};
+static const unsigned xrx200_pins_exin3[] = {GPIO39};
+static const unsigned xrx200_pins_exin4[] = {GPIO10};
+static const unsigned xrx200_pins_exin5[] = {GPIO9};
+
+static const unsigned xrx200_pins_usif_uart_rx[] = {GPIO11};
+static const unsigned xrx200_pins_usif_uart_tx[] = {GPIO12};
+static const unsigned xrx200_pins_usif_uart_rts[] = {GPIO9};
+static const unsigned xrx200_pins_usif_uart_cts[] = {GPIO10};
+static const unsigned xrx200_pins_usif_uart_dtr[] = {GPIO4};
+static const unsigned xrx200_pins_usif_uart_dsr[] = {GPIO6};
+static const unsigned xrx200_pins_usif_uart_dcd[] = {GPIO25};
+static const unsigned xrx200_pins_usif_uart_ri[] = {GPIO27};
+
+static const unsigned xrx200_pins_usif_spi_di[] = {GPIO11};
+static const unsigned xrx200_pins_usif_spi_do[] = {GPIO12};
+static const unsigned xrx200_pins_usif_spi_clk[] = {GPIO38};
+static const unsigned xrx200_pins_usif_spi_cs0[] = {GPIO37};
+static const unsigned xrx200_pins_usif_spi_cs1[] = {GPIO39};
+static const unsigned xrx200_pins_usif_spi_cs2[] = {GPIO14};
+
+static const unsigned xrx200_pins_stp[] = {GPIO4, GPIO5, GPIO6};
+static const unsigned xrx200_pins_nmi[] = {GPIO8};
+static const unsigned xrx200_pins_mdio[] = {GPIO42, GPIO43};
+
+static const unsigned xrx200_pins_dfe_led0[] = {GPIO4};
+static const unsigned xrx200_pins_dfe_led1[] = {GPIO5};
+
+static const unsigned xrx200_pins_gphy0_led0[] = {GPIO5};
+static const unsigned xrx200_pins_gphy0_led1[] = {GPIO7};
+static const unsigned xrx200_pins_gphy0_led2[] = {GPIO2};
+static const unsigned xrx200_pins_gphy1_led0[] = {GPIO44};
+static const unsigned xrx200_pins_gphy1_led1[] = {GPIO45};
+static const unsigned xrx200_pins_gphy1_led2[] = {GPIO47};
+
+static const unsigned xrx200_pins_ebu_a24[] = {GPIO13};
+static const unsigned xrx200_pins_ebu_clk[] = {GPIO21};
+static const unsigned xrx200_pins_ebu_cs1[] = {GPIO23};
+static const unsigned xrx200_pins_ebu_a23[] = {GPIO24};
+static const unsigned xrx200_pins_ebu_wait[] = {GPIO26};
+static const unsigned xrx200_pins_ebu_a25[] = {GPIO31};
+
+static const unsigned xrx200_pins_nand_ale[] = {GPIO13};
+static const unsigned xrx200_pins_nand_cs1[] = {GPIO23};
+static const unsigned xrx200_pins_nand_cle[] = {GPIO24};
+static const unsigned xrx200_pins_nand_rdy[] = {GPIO48};
+static const unsigned xrx200_pins_nand_rd[] = {GPIO49};
+
+static const unsigned xrx200_pins_spi_di[] = {GPIO16};
+static const unsigned xrx200_pins_spi_do[] = {GPIO17};
+static const unsigned xrx200_pins_spi_clk[] = {GPIO18};
+static const unsigned xrx200_pins_spi_cs1[] = {GPIO15};
+static const unsigned xrx200_pins_spi_cs2[] = {GPIO22};
+static const unsigned xrx200_pins_spi_cs3[] = {GPIO13};
+static const unsigned xrx200_pins_spi_cs4[] = {GPIO10};
+static const unsigned xrx200_pins_spi_cs5[] = {GPIO9};
+static const unsigned xrx200_pins_spi_cs6[] = {GPIO11};
+
+static const unsigned xrx200_pins_gpt1[] = {GPIO28};
+static const unsigned xrx200_pins_gpt2[] = {GPIO21};
+static const unsigned xrx200_pins_gpt3[] = {GPIO6};
+
+static const unsigned xrx200_pins_clkout0[] = {GPIO8};
+static const unsigned xrx200_pins_clkout1[] = {GPIO7};
+static const unsigned xrx200_pins_clkout2[] = {GPIO3};
+static const unsigned xrx200_pins_clkout3[] = {GPIO2};
+
+static const unsigned xrx200_pins_pci_gnt1[] = {GPIO28};
+static const unsigned xrx200_pins_pci_gnt2[] = {GPIO23};
+static const unsigned xrx200_pins_pci_gnt3[] = {GPIO19};
+static const unsigned xrx200_pins_pci_gnt4[] = {GPIO38};
+static const unsigned xrx200_pins_pci_req1[] = {GPIO29};
+static const unsigned xrx200_pins_pci_req2[] = {GPIO31};
+static const unsigned xrx200_pins_pci_req3[] = {GPIO3};
+static const unsigned xrx200_pins_pci_req4[] = {GPIO37};
+
+static const struct ltq_pin_group xrx200_grps[] = {
+ GRP_MUX("exin0", EXIN, xrx200_pins_exin0),
+ GRP_MUX("exin1", EXIN, xrx200_pins_exin1),
+ GRP_MUX("exin2", EXIN, xrx200_pins_exin2),
+ GRP_MUX("exin3", EXIN, xrx200_pins_exin3),
+ GRP_MUX("exin4", EXIN, xrx200_pins_exin4),
+ GRP_MUX("exin5", EXIN, xrx200_pins_exin5),
+ GRP_MUX("ebu a23", EBU, xrx200_pins_ebu_a23),
+ GRP_MUX("ebu a24", EBU, xrx200_pins_ebu_a24),
+ GRP_MUX("ebu a25", EBU, xrx200_pins_ebu_a25),
+ GRP_MUX("ebu clk", EBU, xrx200_pins_ebu_clk),
+ GRP_MUX("ebu cs1", EBU, xrx200_pins_ebu_cs1),
+ GRP_MUX("ebu wait", EBU, xrx200_pins_ebu_wait),
+ GRP_MUX("nand ale", EBU, xrx200_pins_nand_ale),
+ GRP_MUX("nand cs1", EBU, xrx200_pins_nand_cs1),
+ GRP_MUX("nand cle", EBU, xrx200_pins_nand_cle),
+ GRP_MUX("nand rdy", EBU, xrx200_pins_nand_rdy),
+ GRP_MUX("nand rd", EBU, xrx200_pins_nand_rd),
+ GRP_MUX("spi_di", SPI, xrx200_pins_spi_di),
+ GRP_MUX("spi_do", SPI, xrx200_pins_spi_do),
+ GRP_MUX("spi_clk", SPI, xrx200_pins_spi_clk),
+ GRP_MUX("spi_cs1", SPI, xrx200_pins_spi_cs1),
+ GRP_MUX("spi_cs2", SPI, xrx200_pins_spi_cs2),
+ GRP_MUX("spi_cs3", SPI, xrx200_pins_spi_cs3),
+ GRP_MUX("spi_cs4", SPI, xrx200_pins_spi_cs4),
+ GRP_MUX("spi_cs5", SPI, xrx200_pins_spi_cs5),
+ GRP_MUX("spi_cs6", SPI, xrx200_pins_spi_cs6),
+ GRP_MUX("usif uart_rx", USIF, xrx200_pins_usif_uart_rx),
+ GRP_MUX("usif uart_rx", USIF, xrx200_pins_usif_uart_tx),
+ GRP_MUX("usif uart_rts", USIF, xrx200_pins_usif_uart_rts),
+ GRP_MUX("usif uart_cts", USIF, xrx200_pins_usif_uart_cts),
+ GRP_MUX("usif uart_dtr", USIF, xrx200_pins_usif_uart_dtr),
+ GRP_MUX("usif uart_dsr", USIF, xrx200_pins_usif_uart_dsr),
+ GRP_MUX("usif uart_dcd", USIF, xrx200_pins_usif_uart_dcd),
+ GRP_MUX("usif uart_ri", USIF, xrx200_pins_usif_uart_ri),
+ GRP_MUX("usif spi_di", USIF, xrx200_pins_usif_spi_di),
+ GRP_MUX("usif spi_do", USIF, xrx200_pins_usif_spi_do),
+ GRP_MUX("usif spi_clk", USIF, xrx200_pins_usif_spi_clk),
+ GRP_MUX("usif spi_cs0", USIF, xrx200_pins_usif_spi_cs0),
+ GRP_MUX("usif spi_cs1", USIF, xrx200_pins_usif_spi_cs1),
+ GRP_MUX("usif spi_cs2", USIF, xrx200_pins_usif_spi_cs2),
+ GRP_MUX("stp", STP, xrx200_pins_stp),
+ GRP_MUX("nmi", NMI, xrx200_pins_nmi),
+ GRP_MUX("gpt1", GPT, xrx200_pins_gpt1),
+ GRP_MUX("gpt2", GPT, xrx200_pins_gpt2),
+ GRP_MUX("gpt3", GPT, xrx200_pins_gpt3),
+ GRP_MUX("clkout0", CGU, xrx200_pins_clkout0),
+ GRP_MUX("clkout1", CGU, xrx200_pins_clkout1),
+ GRP_MUX("clkout2", CGU, xrx200_pins_clkout2),
+ GRP_MUX("clkout3", CGU, xrx200_pins_clkout3),
+ GRP_MUX("gnt1", PCI, xrx200_pins_pci_gnt1),
+ GRP_MUX("gnt2", PCI, xrx200_pins_pci_gnt2),
+ GRP_MUX("gnt3", PCI, xrx200_pins_pci_gnt3),
+ GRP_MUX("gnt4", PCI, xrx200_pins_pci_gnt4),
+ GRP_MUX("req1", PCI, xrx200_pins_pci_req1),
+ GRP_MUX("req2", PCI, xrx200_pins_pci_req2),
+ GRP_MUX("req3", PCI, xrx200_pins_pci_req3),
+ GRP_MUX("req4", PCI, xrx200_pins_pci_req4),
+ GRP_MUX("mdio", MDIO, xrx200_pins_mdio),
+ GRP_MUX("dfe led0", DFE, xrx200_pins_dfe_led0),
+ GRP_MUX("dfe led1", DFE, xrx200_pins_dfe_led1),
+ GRP_MUX("gphy0 led0", GPHY, xrx200_pins_gphy0_led0),
+ GRP_MUX("gphy0 led1", GPHY, xrx200_pins_gphy0_led1),
+ GRP_MUX("gphy0 led2", GPHY, xrx200_pins_gphy0_led2),
+ GRP_MUX("gphy1 led0", GPHY, xrx200_pins_gphy1_led0),
+ GRP_MUX("gphy1 led1", GPHY, xrx200_pins_gphy1_led1),
+ GRP_MUX("gphy1 led2", GPHY, xrx200_pins_gphy1_led2),
+};
+
+static const char * const xrx200_pci_grps[] = {"gnt1", "gnt2",
+ "gnt3", "gnt4",
+ "req1", "req2",
+ "req3", "req4"};
+static const char * const xrx200_spi_grps[] = {"spi_di", "spi_do",
+ "spi_clk", "spi_cs1",
+ "spi_cs2", "spi_cs3",
+ "spi_cs4", "spi_cs5",
+ "spi_cs6"};
+static const char * const xrx200_cgu_grps[] = {"clkout0", "clkout1",
+ "clkout2", "clkout3"};
+static const char * const xrx200_ebu_grps[] = {"ebu a23", "ebu a24",
+ "ebu a25", "ebu cs1",
+ "ebu wait", "ebu clk",
+ "nand ale", "nand cs1",
+ "nand cle", "nand rdy",
+ "nand rd"};
+static const char * const xrx200_exin_grps[] = {"exin0", "exin1", "exin2",
+ "exin3", "exin4", "exin5"};
+static const char * const xrx200_gpt_grps[] = {"gpt1", "gpt2", "gpt3"};
+static const char * const xrx200_usif_grps[] = {"usif uart_rx", "usif uart_tx",
+ "usif uart_rts", "usif uart_cts",
+ "usif uart_dtr", "usif uart_dsr",
+ "usif uart_dcd", "usif uart_ri",
+ "usif spi_di", "usif spi_do",
+ "usif spi_clk", "usif spi_cs0",
+ "usif spi_cs1", "usif spi_cs2"};
+static const char * const xrx200_stp_grps[] = {"stp"};
+static const char * const xrx200_nmi_grps[] = {"nmi"};
+static const char * const xrx200_mdio_grps[] = {"mdio"};
+static const char * const xrx200_dfe_grps[] = {"dfe led0", "dfe led1"};
+static const char * const xrx200_gphy_grps[] = {"gphy0 led0", "gphy0 led1",
+ "gphy0 led2", "gphy1 led0",
+ "gphy1 led1", "gphy1 led2"};
+
+static const struct ltq_pmx_func xrx200_funcs[] = {
+ {"spi", ARRAY_AND_SIZE(xrx200_spi_grps)},
+ {"usif", ARRAY_AND_SIZE(xrx200_usif_grps)},
+ {"cgu", ARRAY_AND_SIZE(xrx200_cgu_grps)},
+ {"exin", ARRAY_AND_SIZE(xrx200_exin_grps)},
+ {"stp", ARRAY_AND_SIZE(xrx200_stp_grps)},
+ {"gpt", ARRAY_AND_SIZE(xrx200_gpt_grps)},
+ {"nmi", ARRAY_AND_SIZE(xrx200_nmi_grps)},
+ {"pci", ARRAY_AND_SIZE(xrx200_pci_grps)},
+ {"ebu", ARRAY_AND_SIZE(xrx200_ebu_grps)},
+ {"mdio", ARRAY_AND_SIZE(xrx200_mdio_grps)},
+ {"dfe", ARRAY_AND_SIZE(xrx200_dfe_grps)},
+ {"gphy", ARRAY_AND_SIZE(xrx200_gphy_grps)},
+};
+
+/* --------- xrx300 related code --------- */
+#define XRX300_MAX_PIN 64
+
+static const struct ltq_mfp_pin xrx300_mfp[] = {
+ /* pin f0 f1 f2 f3 */
+ MFP_XWAY(GPIO0, GPIO, EXIN, EPHY, NONE),
+ MFP_XWAY(GPIO1, GPIO, NONE, EXIN, NONE),
+ MFP_XWAY(GPIO2, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO3, GPIO, CGU, NONE, NONE),
+ MFP_XWAY(GPIO4, GPIO, STP, DFE, NONE),
+ MFP_XWAY(GPIO5, GPIO, STP, EPHY, DFE),
+ MFP_XWAY(GPIO6, GPIO, STP, NONE, NONE),
+ MFP_XWAY(GPIO7, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO8, GPIO, CGU, GPHY, EPHY),
+ MFP_XWAY(GPIO9, GPIO, WIFI, NONE, EXIN),
+ MFP_XWAY(GPIO10, GPIO, USIF, SPI, EXIN),
+ MFP_XWAY(GPIO11, GPIO, USIF, WIFI, SPI),
+ MFP_XWAY(GPIO12, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO13, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO14, GPIO, CGU, USIF, EPHY),
+ MFP_XWAY(GPIO15, GPIO, SPI, NONE, MCD),
+ MFP_XWAY(GPIO16, GPIO, SPI, EXIN, NONE),
+ MFP_XWAY(GPIO17, GPIO, SPI, NONE, NONE),
+ MFP_XWAY(GPIO18, GPIO, SPI, NONE, NONE),
+ MFP_XWAY(GPIO19, GPIO, USIF, NONE, EPHY),
+ MFP_XWAY(GPIO20, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO21, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO22, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO23, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO24, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO25, GPIO, TDM, NONE, NONE),
+ MFP_XWAY(GPIO26, GPIO, TDM, NONE, NONE),
+ MFP_XWAY(GPIO27, GPIO, TDM, NONE, NONE),
+ MFP_XWAY(GPIO28, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO29, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO30, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO31, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO32, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO33, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO34, GPIO, NONE, SSI, NONE),
+ MFP_XWAY(GPIO35, GPIO, NONE, SSI, NONE),
+ MFP_XWAY(GPIO36, GPIO, NONE, SSI, NONE),
+ MFP_XWAY(GPIO37, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO38, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO39, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO40, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO41, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO42, GPIO, MDIO, NONE, NONE),
+ MFP_XWAY(GPIO43, GPIO, MDIO, NONE, NONE),
+ MFP_XWAY(GPIO44, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO45, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO46, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO47, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO48, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO49, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO50, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO51, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO52, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO53, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO54, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO55, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO56, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO57, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO58, GPIO, EBU, TDM, NONE),
+ MFP_XWAY(GPIO59, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO60, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO61, GPIO, EBU, NONE, NONE),
+ MFP_XWAY(GPIO62, NONE, NONE, NONE, NONE),
+ MFP_XWAY(GPIO63, NONE, NONE, NONE, NONE),
+};
+
+static const unsigned xrx300_exin_pin_map[] = {GPIO0, GPIO1, GPIO16, GPIO10, GPIO9};
+
+static const unsigned xrx300_pins_exin0[] = {GPIO0};
+static const unsigned xrx300_pins_exin1[] = {GPIO1};
+static const unsigned xrx300_pins_exin2[] = {GPIO16};
+/* EXIN3 is not available on xrX300 */
+static const unsigned xrx300_pins_exin4[] = {GPIO10};
+static const unsigned xrx300_pins_exin5[] = {GPIO9};
+
+static const unsigned xrx300_pins_usif_uart_rx[] = {GPIO11};
+static const unsigned xrx300_pins_usif_uart_tx[] = {GPIO10};
+
+static const unsigned xrx300_pins_usif_spi_di[] = {GPIO11};
+static const unsigned xrx300_pins_usif_spi_do[] = {GPIO10};
+static const unsigned xrx300_pins_usif_spi_clk[] = {GPIO19};
+static const unsigned xrx300_pins_usif_spi_cs0[] = {GPIO14};
+
+static const unsigned xrx300_pins_stp[] = {GPIO4, GPIO5, GPIO6};
+static const unsigned xrx300_pins_mdio[] = {GPIO42, GPIO43};
+
+static const unsigned xrx300_pins_dfe_led0[] = {GPIO4};
+static const unsigned xrx300_pins_dfe_led1[] = {GPIO5};
+
+static const unsigned xrx300_pins_ephy0_led0[] = {GPIO5};
+static const unsigned xrx300_pins_ephy0_led1[] = {GPIO8};
+static const unsigned xrx300_pins_ephy1_led0[] = {GPIO14};
+static const unsigned xrx300_pins_ephy1_led1[] = {GPIO19};
+
+static const unsigned xrx300_pins_nand_ale[] = {GPIO13};
+static const unsigned xrx300_pins_nand_cs1[] = {GPIO23};
+static const unsigned xrx300_pins_nand_cle[] = {GPIO24};
+static const unsigned xrx300_pins_nand_rdy[] = {GPIO48};
+static const unsigned xrx300_pins_nand_rd[] = {GPIO49};
+static const unsigned xrx300_pins_nand_d1[] = {GPIO50};
+static const unsigned xrx300_pins_nand_d0[] = {GPIO51};
+static const unsigned xrx300_pins_nand_d2[] = {GPIO52};
+static const unsigned xrx300_pins_nand_d7[] = {GPIO53};
+static const unsigned xrx300_pins_nand_d6[] = {GPIO54};
+static const unsigned xrx300_pins_nand_d5[] = {GPIO55};
+static const unsigned xrx300_pins_nand_d4[] = {GPIO56};
+static const unsigned xrx300_pins_nand_d3[] = {GPIO57};
+static const unsigned xrx300_pins_nand_cs0[] = {GPIO58};
+static const unsigned xrx300_pins_nand_wr[] = {GPIO59};
+static const unsigned xrx300_pins_nand_wp[] = {GPIO60};
+static const unsigned xrx300_pins_nand_se[] = {GPIO61};
+
+static const unsigned xrx300_pins_spi_di[] = {GPIO16};
+static const unsigned xrx300_pins_spi_do[] = {GPIO17};
+static const unsigned xrx300_pins_spi_clk[] = {GPIO18};
+static const unsigned xrx300_pins_spi_cs1[] = {GPIO15};
+/* SPI_CS2 is not available on xrX300 */
+/* SPI_CS3 is not available on xrX300 */
+static const unsigned xrx300_pins_spi_cs4[] = {GPIO10};
+/* SPI_CS5 is not available on xrX300 */
+static const unsigned xrx300_pins_spi_cs6[] = {GPIO11};
+
+/* CLKOUT0 is not available on xrX300 */
+/* CLKOUT1 is not available on xrX300 */
+static const unsigned xrx300_pins_clkout2[] = {GPIO3};
+
+static const struct ltq_pin_group xrx300_grps[] = {
+ GRP_MUX("exin0", EXIN, xrx300_pins_exin0),
+ GRP_MUX("exin1", EXIN, xrx300_pins_exin1),
+ GRP_MUX("exin2", EXIN, xrx300_pins_exin2),
+ GRP_MUX("exin4", EXIN, xrx300_pins_exin4),
+ GRP_MUX("exin5", EXIN, xrx300_pins_exin5),
+ GRP_MUX("nand ale", EBU, xrx300_pins_nand_ale),
+ GRP_MUX("nand cs1", EBU, xrx300_pins_nand_cs1),
+ GRP_MUX("nand cle", EBU, xrx300_pins_nand_cle),
+ GRP_MUX("nand rdy", EBU, xrx300_pins_nand_rdy),
+ GRP_MUX("nand rd", EBU, xrx300_pins_nand_rd),
+ GRP_MUX("nand d1", EBU, xrx300_pins_nand_d1),
+ GRP_MUX("nand d0", EBU, xrx300_pins_nand_d0),
+ GRP_MUX("nand d2", EBU, xrx300_pins_nand_d2),
+ GRP_MUX("nand d7", EBU, xrx300_pins_nand_d7),
+ GRP_MUX("nand d6", EBU, xrx300_pins_nand_d6),
+ GRP_MUX("nand d5", EBU, xrx300_pins_nand_d5),
+ GRP_MUX("nand d4", EBU, xrx300_pins_nand_d4),
+ GRP_MUX("nand d3", EBU, xrx300_pins_nand_d3),
+ GRP_MUX("nand cs0", EBU, xrx300_pins_nand_cs0),
+ GRP_MUX("nand wr", EBU, xrx300_pins_nand_wr),
+ GRP_MUX("nand wp", EBU, xrx300_pins_nand_wp),
+ GRP_MUX("nand se", EBU, xrx300_pins_nand_se),
+ GRP_MUX("spi_di", SPI, xrx300_pins_spi_di),
+ GRP_MUX("spi_do", SPI, xrx300_pins_spi_do),
+ GRP_MUX("spi_clk", SPI, xrx300_pins_spi_clk),
+ GRP_MUX("spi_cs1", SPI, xrx300_pins_spi_cs1),
+ GRP_MUX("spi_cs4", SPI, xrx300_pins_spi_cs4),
+ GRP_MUX("spi_cs6", SPI, xrx300_pins_spi_cs6),
+ GRP_MUX("usif uart_rx", USIF, xrx300_pins_usif_uart_rx),
+ GRP_MUX("usif uart_tx", USIF, xrx300_pins_usif_uart_tx),
+ GRP_MUX("usif spi_di", USIF, xrx300_pins_usif_spi_di),
+ GRP_MUX("usif spi_do", USIF, xrx300_pins_usif_spi_do),
+ GRP_MUX("usif spi_clk", USIF, xrx300_pins_usif_spi_clk),
+ GRP_MUX("usif spi_cs0", USIF, xrx300_pins_usif_spi_cs0),
+ GRP_MUX("stp", STP, xrx300_pins_stp),
+ GRP_MUX("clkout2", CGU, xrx300_pins_clkout2),
+ GRP_MUX("mdio", MDIO, xrx300_pins_mdio),
+ GRP_MUX("dfe led0", DFE, xrx300_pins_dfe_led0),
+ GRP_MUX("dfe led1", DFE, xrx300_pins_dfe_led1),
+ GRP_MUX("ephy0 led0", GPHY, xrx300_pins_ephy0_led0),
+ GRP_MUX("ephy0 led1", GPHY, xrx300_pins_ephy0_led1),
+ GRP_MUX("ephy1 led0", GPHY, xrx300_pins_ephy1_led0),
+ GRP_MUX("ephy1 led1", GPHY, xrx300_pins_ephy1_led1),
+};
+
+static const char * const xrx300_spi_grps[] = {"spi_di", "spi_do",
+ "spi_clk", "spi_cs1",
+ "spi_cs4", "spi_cs6"};
+static const char * const xrx300_cgu_grps[] = {"clkout2"};
+static const char * const xrx300_ebu_grps[] = {"nand ale", "nand cs1",
+ "nand cle", "nand rdy",
+ "nand rd", "nand d1",
+ "nand d0", "nand d2",
+ "nand d7", "nand d6",
+ "nand d5", "nand d4",
+ "nand d3", "nand cs0",
+ "nand wr", "nand wp",
+ "nand se"};
+static const char * const xrx300_exin_grps[] = {"exin0", "exin1", "exin2",
+ "exin4", "exin5"};
+static const char * const xrx300_usif_grps[] = {"usif uart_rx", "usif uart_tx",
+ "usif spi_di", "usif spi_do",
+ "usif spi_clk", "usif spi_cs0"};
+static const char * const xrx300_stp_grps[] = {"stp"};
+static const char * const xrx300_mdio_grps[] = {"mdio"};
+static const char * const xrx300_dfe_grps[] = {"dfe led0", "dfe led1"};
+static const char * const xrx300_gphy_grps[] = {"ephy0 led0", "ephy0 led1",
+ "ephy1 led0", "ephy1 led1"};
+
+static const struct ltq_pmx_func xrx300_funcs[] = {
+ {"spi", ARRAY_AND_SIZE(xrx300_spi_grps)},
+ {"usif", ARRAY_AND_SIZE(xrx300_usif_grps)},
+ {"cgu", ARRAY_AND_SIZE(xrx300_cgu_grps)},
+ {"exin", ARRAY_AND_SIZE(xrx300_exin_grps)},
+ {"stp", ARRAY_AND_SIZE(xrx300_stp_grps)},
+ {"ebu", ARRAY_AND_SIZE(xrx300_ebu_grps)},
+ {"mdio", ARRAY_AND_SIZE(xrx300_mdio_grps)},
+ {"dfe", ARRAY_AND_SIZE(xrx300_dfe_grps)},
+ {"ephy", ARRAY_AND_SIZE(xrx300_gphy_grps)},
+};
+
/* --------- pinconf related code --------- */
static int xway_pinconf_get(struct pinctrl_dev *pctldev,
unsigned pin,
@@ -676,6 +1563,10 @@ static int xway_gpio_dir_out(struct gpio_chip *chip, unsigned int pin, int val)
{
struct ltq_pinmux_info *info = dev_get_drvdata(chip->dev);
+ if (PORT(pin) == PORT3)
+ gpio_setbit(info->membase[0], GPIO3_OD, PORT_PIN(pin));
+ else
+ gpio_setbit(info->membase[0], GPIO_OD(pin), PORT_PIN(pin));
gpio_setbit(info->membase[0], GPIO_DIR(pin), PORT_PIN(pin));
xway_gpio_set(chip, pin, val);
@@ -695,10 +1586,7 @@ static struct gpio_chip xway_chip = {
/* --------- register the pinctrl layer --------- */
-static const unsigned xway_exin_pin_map[] = {GPIO0, GPIO1, GPIO2, GPIO39, GPIO46, GPIO9};
-static const unsigned ase_exin_pins_map[] = {GPIO6, GPIO29, GPIO0};
-
-static struct pinctrl_xway_soc {
+struct pinctrl_xway_soc {
int pin_count;
const struct ltq_mfp_pin *mfp;
const struct ltq_pin_group *grps;
@@ -707,22 +1595,54 @@ static struct pinctrl_xway_soc {
unsigned int num_funcs;
const unsigned *exin;
unsigned int num_exin;
-} soc_cfg[] = {
- /* legacy xway */
- {XWAY_MAX_PIN, xway_mfp,
- xway_grps, ARRAY_SIZE(xway_grps),
- danube_funcs, ARRAY_SIZE(danube_funcs),
- xway_exin_pin_map, 3},
- /* xway xr9 series */
- {XR9_MAX_PIN, xway_mfp,
- xway_grps, ARRAY_SIZE(xway_grps),
- xrx_funcs, ARRAY_SIZE(xrx_funcs),
- xway_exin_pin_map, 6},
- /* xway ase series */
- {XWAY_MAX_PIN, ase_mfp,
- ase_grps, ARRAY_SIZE(ase_grps),
- ase_funcs, ARRAY_SIZE(ase_funcs),
- ase_exin_pins_map, 3},
+};
+
+/* xway xr9 series (DEPRECATED: Use XWAY xRX100/xRX200 Family) */
+static struct pinctrl_xway_soc xr9_pinctrl = {
+ XR9_MAX_PIN, xway_mfp,
+ xway_grps, ARRAY_SIZE(xway_grps),
+ xrx_funcs, ARRAY_SIZE(xrx_funcs),
+ xway_exin_pin_map, 6
+};
+
+/* XWAY AMAZON Family */
+static struct pinctrl_xway_soc ase_pinctrl = {
+ ASE_MAX_PIN, ase_mfp,
+ ase_grps, ARRAY_SIZE(ase_grps),
+ ase_funcs, ARRAY_SIZE(ase_funcs),
+ ase_exin_pin_map, 3
+};
+
+/* XWAY DANUBE Family */
+static struct pinctrl_xway_soc danube_pinctrl = {
+ DANUBE_MAX_PIN, danube_mfp,
+ danube_grps, ARRAY_SIZE(danube_grps),
+ danube_funcs, ARRAY_SIZE(danube_funcs),
+ danube_exin_pin_map, 3
+};
+
+/* XWAY xRX100 Family */
+static struct pinctrl_xway_soc xrx100_pinctrl = {
+ XRX100_MAX_PIN, xrx100_mfp,
+ xrx100_grps, ARRAY_SIZE(xrx100_grps),
+ xrx100_funcs, ARRAY_SIZE(xrx100_funcs),
+ xrx100_exin_pin_map, 6
+};
+
+/* XWAY xRX200 Family */
+static struct pinctrl_xway_soc xrx200_pinctrl = {
+ XRX200_MAX_PIN, xrx200_mfp,
+ xrx200_grps, ARRAY_SIZE(xrx200_grps),
+ xrx200_funcs, ARRAY_SIZE(xrx200_funcs),
+ xrx200_exin_pin_map, 6
+};
+
+/* XWAY xRX300 Family */
+static struct pinctrl_xway_soc xrx300_pinctrl = {
+ XRX300_MAX_PIN, xrx300_mfp,
+ xrx300_grps, ARRAY_SIZE(xrx300_grps),
+ xrx300_funcs, ARRAY_SIZE(xrx300_funcs),
+ xrx300_exin_pin_map, 5
};
static struct pinctrl_gpio_range xway_gpio_range = {
@@ -731,9 +1651,14 @@ static struct pinctrl_gpio_range xway_gpio_range = {
};
static const struct of_device_id xway_match[] = {
- { .compatible = "lantiq,pinctrl-xway", .data = &soc_cfg[0]},
- { .compatible = "lantiq,pinctrl-xr9", .data = &soc_cfg[1]},
- { .compatible = "lantiq,pinctrl-ase", .data = &soc_cfg[2]},
+ { .compatible = "lantiq,pinctrl-xway", .data = &danube_pinctrl}, /*DEPRECATED*/
+ { .compatible = "lantiq,pinctrl-xr9", .data = &xr9_pinctrl}, /*DEPRECATED*/
+ { .compatible = "lantiq,pinctrl-ase", .data = &ase_pinctrl}, /*DEPRECATED*/
+ { .compatible = "lantiq,ase-pinctrl", .data = &ase_pinctrl},
+ { .compatible = "lantiq,danube-pinctrl", .data = &danube_pinctrl},
+ { .compatible = "lantiq,xrx100-pinctrl", .data = &xrx100_pinctrl},
+ { .compatible = "lantiq,xrx200-pinctrl", .data = &xrx200_pinctrl},
+ { .compatible = "lantiq,xrx300-pinctrl", .data = &xrx300_pinctrl},
{},
};
MODULE_DEVICE_TABLE(of, xway_match);
@@ -755,7 +1680,7 @@ static int pinmux_xway_probe(struct platform_device *pdev)
if (match)
xway_soc = (const struct pinctrl_xway_soc *) match->data;
else
- xway_soc = &soc_cfg[0];
+ xway_soc = &danube_pinctrl;
/* find out how many pads we have */
xway_chip.ngpio = xway_soc->pin_count;
diff --git a/drivers/pinctrl/pxa/Kconfig b/drivers/pinctrl/pxa/Kconfig
new file mode 100644
index 000000000000..990667ff772c
--- /dev/null
+++ b/drivers/pinctrl/pxa/Kconfig
@@ -0,0 +1,17 @@
+if (ARCH_PXA || COMPILE_TEST)
+
+config PINCTRL_PXA
+ bool
+ select PINMUX
+ select PINCONF
+ select GENERIC_PINCONF
+
+config PINCTRL_PXA27X
+ tristate "Marvell PXA27x pin controller driver"
+ select PINCTRL_PXA
+ default y if PXA27x
+ help
+ This is the pinctrl, pinmux, pinconf driver for the Marvell
+ PXA2xx block found in the pxa25x and pxa27x platforms.
+
+endif
diff --git a/drivers/pinctrl/pxa/Makefile b/drivers/pinctrl/pxa/Makefile
new file mode 100644
index 000000000000..f1d56af2bfc0
--- /dev/null
+++ b/drivers/pinctrl/pxa/Makefile
@@ -0,0 +1,2 @@
+# Marvell PXA pin control drivers
+obj-$(CONFIG_PINCTRL_PXA27X) += pinctrl-pxa2xx.o pinctrl-pxa27x.o
diff --git a/drivers/pinctrl/pxa/pinctrl-pxa27x.c b/drivers/pinctrl/pxa/pinctrl-pxa27x.c
new file mode 100644
index 000000000000..2e2c3709ef05
--- /dev/null
+++ b/drivers/pinctrl/pxa/pinctrl-pxa27x.c
@@ -0,0 +1,566 @@
+/*
+ * Marvell PXA27x family pin control
+ *
+ * Copyright (C) 2015 Robert Jarzmik
+ *
+ * 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; version 2 of the License.
+ *
+ */
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-pxa2xx.h"
+
+static const struct pxa_desc_pin pxa27x_pins[] = {
+ PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(0)),
+ PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(1)),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(9),
+ PXA_FUNCTION(0, 3, "FFCTS"),
+ PXA_FUNCTION(1, 1, "HZ_CLK"),
+ PXA_FUNCTION(1, 3, "CHOUT<0>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(10),
+ PXA_FUNCTION(0, 1, "FFDCD"),
+ PXA_FUNCTION(0, 3, "USB_P3_5"),
+ PXA_FUNCTION(1, 1, "HZ_CLK"),
+ PXA_FUNCTION(1, 3, "CHOUT<1>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(11),
+ PXA_FUNCTION(0, 1, "EXT_SYNC<0>"),
+ PXA_FUNCTION(0, 2, "SSPRXD2"),
+ PXA_FUNCTION(0, 3, "USB_P3_1"),
+ PXA_FUNCTION(1, 1, "CHOUT<0>"),
+ PXA_FUNCTION(1, 1, "PWM_OUT<2>"),
+ PXA_FUNCTION(1, 3, "48_MHz")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(12),
+ PXA_FUNCTION(0, 1, "EXT_SYNC<1>"),
+ PXA_FUNCTION(0, 2, "CIF_DD<7>"),
+ PXA_FUNCTION(1, 1, "CHOUT<1>"),
+ PXA_FUNCTION(1, 1, "PWM_OUT<3>"),
+ PXA_FUNCTION(1, 3, "48_MHz")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(13),
+ PXA_FUNCTION(0, 1, "CLK_EXT"),
+ PXA_FUNCTION(0, 2, "KP_DKIN<7>"),
+ PXA_FUNCTION(0, 3, "KP_MKIN<7>"),
+ PXA_FUNCTION(1, 1, "SSPTXD2")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(14),
+ PXA_FUNCTION(0, 1, "L_VSYNC"),
+ PXA_FUNCTION(0, 2, "SSPSFRM2"),
+ PXA_FUNCTION(1, 1, "SSPSFRM2"),
+ PXA_FUNCTION(1, 3, "UCLK")),
+ PXA_GPIO_ONLY_PIN(PXA_PINCTRL_PIN(15)),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(16),
+ PXA_FUNCTION(0, 1, "KP_MKIN<5>"),
+ PXA_FUNCTION(1, 2, "PWM_OUT<0>"),
+ PXA_FUNCTION(1, 3, "FFTXD")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(17),
+ PXA_FUNCTION(0, 1, "KP_MKIN<6>"),
+ PXA_FUNCTION(0, 2, "CIF_DD<6>"),
+ PXA_FUNCTION(1, 2, "PWM_OUT<1>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(18),
+ PXA_FUNCTION(0, 1, "RDY")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(19),
+ PXA_FUNCTION(0, 1, "SSPSCLK2"),
+ PXA_FUNCTION(0, 3, "FFRXD"),
+ PXA_FUNCTION(1, 1, "SSPSCLK2"),
+ PXA_FUNCTION(1, 2, "L_CS"),
+ PXA_FUNCTION(1, 3, "nURST")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(20),
+ PXA_FUNCTION(0, 1, "DREQ<0>"),
+ PXA_FUNCTION(0, 2, "MBREQ"),
+ PXA_FUNCTION(1, 1, "nSDCS<2>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(21),
+ PXA_FUNCTION(1, 1, "nSDCS<3>"),
+ PXA_FUNCTION(1, 2, "DVAL<0>"),
+ PXA_FUNCTION(1, 3, "MBGNT")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(22),
+ PXA_FUNCTION(0, 1, "SSPEXTCLK2"),
+ PXA_FUNCTION(0, 2, "SSPSCLKEN2"),
+ PXA_FUNCTION(0, 3, "SSPSCLK2"),
+ PXA_FUNCTION(1, 1, "KP_MKOUT<7>"),
+ PXA_FUNCTION(1, 2, "SSPSYSCLK2"),
+ PXA_FUNCTION(1, 3, "SSPSCLK2")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(23),
+ PXA_FUNCTION(0, 2, "SSPSCLK"),
+ PXA_FUNCTION(1, 1, "CIF_MCLK"),
+ PXA_FUNCTION(1, 1, "SSPSCLK")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(24),
+ PXA_FUNCTION(0, 1, "CIF_FV"),
+ PXA_FUNCTION(0, 2, "SSPSFRM"),
+ PXA_FUNCTION(1, 1, "CIF_FV"),
+ PXA_FUNCTION(1, 2, "SSPSFRM")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(25),
+ PXA_FUNCTION(0, 1, "CIF_LV"),
+ PXA_FUNCTION(1, 1, "CIF_LV"),
+ PXA_FUNCTION(1, 2, "SSPTXD")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(26),
+ PXA_FUNCTION(0, 1, "SSPRXD"),
+ PXA_FUNCTION(0, 2, "CIF_PCLK"),
+ PXA_FUNCTION(0, 3, "FFCTS")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(27),
+ PXA_FUNCTION(0, 1, "SSPEXTCLK"),
+ PXA_FUNCTION(0, 2, "SSPSCLKEN"),
+ PXA_FUNCTION(0, 3, "CIF_DD<0>"),
+ PXA_FUNCTION(1, 1, "SSPSYSCLK"),
+ PXA_FUNCTION(1, 3, "FFRTS")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(28),
+ PXA_FUNCTION(0, 1, "AC97_BITCLK"),
+ PXA_FUNCTION(0, 2, "I2S_BITCLK"),
+ PXA_FUNCTION(0, 3, "SSPSFRM"),
+ PXA_FUNCTION(1, 1, "I2S_BITCLK"),
+ PXA_FUNCTION(1, 3, "SSPSFRM")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(29),
+ PXA_FUNCTION(0, 1, "AC97_SDATA_IN_0"),
+ PXA_FUNCTION(0, 2, "I2S_SDATA_IN"),
+ PXA_FUNCTION(0, 3, "SSPSCLK"),
+ PXA_FUNCTION(1, 1, "SSPRXD2"),
+ PXA_FUNCTION(1, 3, "SSPSCLK")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(30),
+ PXA_FUNCTION(1, 1, "I2S_SDATA_OUT"),
+ PXA_FUNCTION(1, 2, "AC97_SDATA_OUT"),
+ PXA_FUNCTION(1, 3, "USB_P3_2")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(31),
+ PXA_FUNCTION(1, 1, "I2S_SYNC"),
+ PXA_FUNCTION(1, 2, "AC97_SYNC"),
+ PXA_FUNCTION(1, 3, "USB_P3_6")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(32),
+ PXA_FUNCTION(1, 1, "MSSCLK"),
+ PXA_FUNCTION(1, 2, "MMCLK")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(33),
+ PXA_FUNCTION(0, 1, "FFRXD"),
+ PXA_FUNCTION(0, 2, "FFDSR"),
+ PXA_FUNCTION(1, 1, "DVAL<1>"),
+ PXA_FUNCTION(1, 2, "nCS<5>"),
+ PXA_FUNCTION(1, 3, "MBGNT")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(34),
+ PXA_FUNCTION(0, 1, "FFRXD"),
+ PXA_FUNCTION(0, 2, "KP_MKIN<3>"),
+ PXA_FUNCTION(0, 3, "SSPSCLK3"),
+ PXA_FUNCTION(1, 1, "USB_P2_2"),
+ PXA_FUNCTION(1, 3, "SSPSCLK3")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(35),
+ PXA_FUNCTION(0, 1, "FFCTS"),
+ PXA_FUNCTION(0, 2, "USB_P2_1"),
+ PXA_FUNCTION(0, 3, "SSPSFRM3"),
+ PXA_FUNCTION(1, 2, "KP_MKOUT<6>"),
+ PXA_FUNCTION(1, 3, "SSPTXD3")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(36),
+ PXA_FUNCTION(0, 1, "FFDCD"),
+ PXA_FUNCTION(0, 2, "SSPSCLK2"),
+ PXA_FUNCTION(0, 3, "KP_MKIN<7>"),
+ PXA_FUNCTION(1, 1, "USB_P2_4"),
+ PXA_FUNCTION(1, 2, "SSPSCLK2")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(37),
+ PXA_FUNCTION(0, 1, "FFDSR"),
+ PXA_FUNCTION(0, 2, "SSPSFRM2"),
+ PXA_FUNCTION(0, 3, "KP_MKIN<3>"),
+ PXA_FUNCTION(1, 1, "USB_P2_8"),
+ PXA_FUNCTION(1, 2, "SSPSFRM2"),
+ PXA_FUNCTION(1, 3, "FFTXD")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(38),
+ PXA_FUNCTION(0, 1, "FFRI"),
+ PXA_FUNCTION(0, 2, "KP_MKIN<4>"),
+ PXA_FUNCTION(0, 3, "USB_P2_3"),
+ PXA_FUNCTION(1, 1, "SSPTXD3"),
+ PXA_FUNCTION(1, 2, "SSPTXD2"),
+ PXA_FUNCTION(1, 3, "PWM_OUT<0>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(39),
+ PXA_FUNCTION(0, 1, "KP_MKIN<4>"),
+ PXA_FUNCTION(0, 3, "SSPSFRM3"),
+ PXA_FUNCTION(1, 1, "USB_P2_6"),
+ PXA_FUNCTION(1, 2, "FFTXD"),
+ PXA_FUNCTION(1, 3, "SSPSFRM3")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(40),
+ PXA_FUNCTION(0, 1, "SSPRXD2"),
+ PXA_FUNCTION(0, 3, "USB_P2_5"),
+ PXA_FUNCTION(1, 1, "KP_MKOUT<6>"),
+ PXA_FUNCTION(1, 2, "FFDTR"),
+ PXA_FUNCTION(1, 3, "SSPSCLK3")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(41),
+ PXA_FUNCTION(0, 1, "FFRXD"),
+ PXA_FUNCTION(0, 2, "USB_P2_7"),
+ PXA_FUNCTION(0, 3, "SSPRXD3"),
+ PXA_FUNCTION(1, 1, "KP_MKOUT<7>"),
+ PXA_FUNCTION(1, 2, "FFRTS")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(42),
+ PXA_FUNCTION(0, 1, "BTRXD"),
+ PXA_FUNCTION(0, 2, "ICP_RXD"),
+ PXA_FUNCTION(1, 3, "CIF_MCLK")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(43),
+ PXA_FUNCTION(0, 3, "CIF_FV"),
+ PXA_FUNCTION(1, 1, "ICP_TXD"),
+ PXA_FUNCTION(1, 2, "BTTXD"),
+ PXA_FUNCTION(1, 3, "CIF_FV")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(44),
+ PXA_FUNCTION(0, 1, "BTCTS"),
+ PXA_FUNCTION(0, 3, "CIF_LV"),
+ PXA_FUNCTION(1, 3, "CIF_LV")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(45),
+ PXA_FUNCTION(0, 3, "CIF_PCLK"),
+ PXA_FUNCTION(1, 1, "AC97_SYSCLK"),
+ PXA_FUNCTION(1, 2, "BTRTS"),
+ PXA_FUNCTION(1, 3, "SSPSYSCLK3")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(46),
+ PXA_FUNCTION(0, 1, "ICP_RXD"),
+ PXA_FUNCTION(0, 2, "STD_RXD"),
+ PXA_FUNCTION(1, 2, "PWM_OUT<2>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(47),
+ PXA_FUNCTION(0, 1, "CIF_DD<0>"),
+ PXA_FUNCTION(1, 1, "STD_TXD"),
+ PXA_FUNCTION(1, 2, "ICP_TXD"),
+ PXA_FUNCTION(1, 3, "PWM_OUT<3>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(48),
+ PXA_FUNCTION(0, 1, "CIF_DD<5>"),
+ PXA_FUNCTION(1, 1, "BB_OB_DAT<1>"),
+ PXA_FUNCTION(1, 2, "nPOE")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(49),
+ PXA_FUNCTION(1, 2, "nPWE")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(50),
+ PXA_FUNCTION(0, 1, "CIF_DD<3>"),
+ PXA_FUNCTION(0, 3, "SSPSCLK2"),
+ PXA_FUNCTION(1, 1, "BB_OB_DAT<2>"),
+ PXA_FUNCTION(1, 2, "nPIOR"),
+ PXA_FUNCTION(1, 3, "SSPSCLK2")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(51),
+ PXA_FUNCTION(0, 1, "CIF_DD<2>"),
+ PXA_FUNCTION(1, 1, "BB_OB_DAT<3>"),
+ PXA_FUNCTION(1, 2, "nPIOW")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(52),
+ PXA_FUNCTION(0, 1, "CIF_DD<4>"),
+ PXA_FUNCTION(0, 2, "SSPSCLK3"),
+ PXA_FUNCTION(1, 1, "BB_OB_CLK"),
+ PXA_FUNCTION(1, 2, "SSPSCLK3")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(53),
+ PXA_FUNCTION(0, 1, "FFRXD"),
+ PXA_FUNCTION(0, 2, "USB_P2_3"),
+ PXA_FUNCTION(1, 1, "BB_OB_STB"),
+ PXA_FUNCTION(1, 2, "CIF_MCLK"),
+ PXA_FUNCTION(1, 3, "SSPSYSCLK")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(54),
+ PXA_FUNCTION(0, 2, "BB_OB_WAIT"),
+ PXA_FUNCTION(0, 3, "CIF_PCLK"),
+ PXA_FUNCTION(1, 2, "nPCE<2>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(55),
+ PXA_FUNCTION(0, 1, "CIF_DD<1>"),
+ PXA_FUNCTION(0, 2, "BB_IB_DAT<1>"),
+ PXA_FUNCTION(1, 2, "nPREG")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(56),
+ PXA_FUNCTION(0, 1, "nPWAIT"),
+ PXA_FUNCTION(0, 2, "BB_IB_DAT<2>"),
+ PXA_FUNCTION(1, 1, "USB_P3_4")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(57),
+ PXA_FUNCTION(0, 1, "nIOS16"),
+ PXA_FUNCTION(0, 2, "BB_IB_DAT<3>"),
+ PXA_FUNCTION(1, 3, "SSPTXD")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(58),
+ PXA_FUNCTION(0, 2, "LDD<0>"),
+ PXA_FUNCTION(1, 2, "LDD<0>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(59),
+ PXA_FUNCTION(0, 2, "LDD<1>"),
+ PXA_FUNCTION(1, 2, "LDD<1>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(60),
+ PXA_FUNCTION(0, 2, "LDD<2>"),
+ PXA_FUNCTION(1, 2, "LDD<2>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(61),
+ PXA_FUNCTION(0, 2, "LDD<3>"),
+ PXA_FUNCTION(1, 2, "LDD<3>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(62),
+ PXA_FUNCTION(0, 2, "LDD<4>"),
+ PXA_FUNCTION(1, 2, "LDD<4>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(63),
+ PXA_FUNCTION(0, 2, "LDD<5>"),
+ PXA_FUNCTION(1, 2, "LDD<5>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(64),
+ PXA_FUNCTION(0, 2, "LDD<6>"),
+ PXA_FUNCTION(1, 2, "LDD<6>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(65),
+ PXA_FUNCTION(0, 2, "LDD<7>"),
+ PXA_FUNCTION(1, 2, "LDD<7>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(66),
+ PXA_FUNCTION(0, 2, "LDD<8>"),
+ PXA_FUNCTION(1, 2, "LDD<8>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(67),
+ PXA_FUNCTION(0, 2, "LDD<9>"),
+ PXA_FUNCTION(1, 2, "LDD<9>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(68),
+ PXA_FUNCTION(0, 2, "LDD<10>"),
+ PXA_FUNCTION(1, 2, "LDD<10>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(69),
+ PXA_FUNCTION(0, 2, "LDD<11>"),
+ PXA_FUNCTION(1, 2, "LDD<11>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(70),
+ PXA_FUNCTION(0, 2, "LDD<12>"),
+ PXA_FUNCTION(1, 2, "LDD<12>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(71),
+ PXA_FUNCTION(0, 2, "LDD<13>"),
+ PXA_FUNCTION(1, 2, "LDD<13>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(72),
+ PXA_FUNCTION(0, 2, "LDD<14>"),
+ PXA_FUNCTION(1, 2, "LDD<14>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(73),
+ PXA_FUNCTION(0, 2, "LDD<15>"),
+ PXA_FUNCTION(1, 2, "LDD<15>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(74),
+ PXA_FUNCTION(1, 2, "L_FCLK_RD")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(75),
+ PXA_FUNCTION(1, 2, "L_LCLK_A0")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(76),
+ PXA_FUNCTION(1, 2, "L_PCLK_WR")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(77),
+ PXA_FUNCTION(1, 2, "L_BIAS")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(78),
+ PXA_FUNCTION(1, 1, "nPCE<2>"),
+ PXA_FUNCTION(1, 2, "nCS<2>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(79),
+ PXA_FUNCTION(1, 1, "PSKTSEL"),
+ PXA_FUNCTION(1, 2, "nCS<3>"),
+ PXA_FUNCTION(1, 3, "PWM_OUT<2>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(80),
+ PXA_FUNCTION(0, 1, "DREQ<1>"),
+ PXA_FUNCTION(0, 2, "MBREQ"),
+ PXA_FUNCTION(1, 2, "nCS<4>"),
+ PXA_FUNCTION(1, 3, "PWM_OUT<3>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(81),
+ PXA_FUNCTION(0, 2, "CIF_DD<0>"),
+ PXA_FUNCTION(1, 1, "SSPTXD3"),
+ PXA_FUNCTION(1, 2, "BB_OB_DAT<0>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(82),
+ PXA_FUNCTION(0, 1, "SSPRXD3"),
+ PXA_FUNCTION(0, 2, "BB_IB_DAT<0>"),
+ PXA_FUNCTION(0, 3, "CIF_DD<5>"),
+ PXA_FUNCTION(1, 3, "FFDTR")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(83),
+ PXA_FUNCTION(0, 1, "SSPSFRM3"),
+ PXA_FUNCTION(0, 2, "BB_IB_CLK"),
+ PXA_FUNCTION(0, 3, "CIF_DD<5>"),
+ PXA_FUNCTION(1, 1, "SSPSFRM3"),
+ PXA_FUNCTION(1, 2, "FFTXD"),
+ PXA_FUNCTION(1, 3, "FFRTS")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(84),
+ PXA_FUNCTION(0, 1, "SSPCLK3"),
+ PXA_FUNCTION(0, 2, "BB_IB_STB"),
+ PXA_FUNCTION(0, 3, "CIF_FV"),
+ PXA_FUNCTION(1, 1, "SSPCLK3"),
+ PXA_FUNCTION(1, 3, "CIF_FV")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(85),
+ PXA_FUNCTION(0, 1, "FFRXD"),
+ PXA_FUNCTION(0, 2, "DREQ<2>"),
+ PXA_FUNCTION(0, 3, "CIF_LV"),
+ PXA_FUNCTION(1, 1, "nPCE<1>"),
+ PXA_FUNCTION(1, 2, "BB_IB_WAIT"),
+ PXA_FUNCTION(1, 3, "CIF_LV")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(86),
+ PXA_FUNCTION(0, 1, "SSPRXD2"),
+ PXA_FUNCTION(0, 2, "LDD<16>"),
+ PXA_FUNCTION(0, 3, "USB_P3_5"),
+ PXA_FUNCTION(1, 1, "nPCE<1>"),
+ PXA_FUNCTION(1, 2, "LDD<16>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(87),
+ PXA_FUNCTION(0, 1, "nPCE<2>"),
+ PXA_FUNCTION(0, 2, "LDD<17>"),
+ PXA_FUNCTION(0, 3, "USB_P3_1"),
+ PXA_FUNCTION(1, 1, "SSPTXD2"),
+ PXA_FUNCTION(1, 2, "LDD<17>"),
+ PXA_FUNCTION(1, 3, "SSPSFRM2")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(88),
+ PXA_FUNCTION(0, 1, "USBHPWR<1>"),
+ PXA_FUNCTION(0, 2, "SSPRXD2"),
+ PXA_FUNCTION(0, 3, "SSPSFRM2"),
+ PXA_FUNCTION(1, 2, "SSPTXD2"),
+ PXA_FUNCTION(1, 3, "SSPSFRM2")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(89),
+ PXA_FUNCTION(0, 1, "SSPRXD3"),
+ PXA_FUNCTION(0, 3, "FFRI"),
+ PXA_FUNCTION(1, 1, "AC97_SYSCLK"),
+ PXA_FUNCTION(1, 2, "USBHPEN<1>"),
+ PXA_FUNCTION(1, 3, "SSPTXD2")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(90),
+ PXA_FUNCTION(0, 1, "KP_MKIN<5>"),
+ PXA_FUNCTION(0, 3, "USB_P3_5"),
+ PXA_FUNCTION(1, 1, "CIF_DD<4>"),
+ PXA_FUNCTION(1, 2, "nURST")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(91),
+ PXA_FUNCTION(0, 1, "KP_MKIN<6>"),
+ PXA_FUNCTION(0, 3, "USB_P3_1"),
+ PXA_FUNCTION(1, 1, "CIF_DD<5>"),
+ PXA_FUNCTION(1, 2, "UCLK")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(92),
+ PXA_FUNCTION(0, 1, "MMDAT<0>"),
+ PXA_FUNCTION(1, 1, "MMDAT<0>"),
+ PXA_FUNCTION(1, 2, "MSBS")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(93),
+ PXA_FUNCTION(0, 1, "KP_DKIN<0>"),
+ PXA_FUNCTION(0, 2, "CIF_DD<6>"),
+ PXA_FUNCTION(1, 1, "AC97_SDATA_OUT")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(94),
+ PXA_FUNCTION(0, 1, "KP_DKIN<1>"),
+ PXA_FUNCTION(0, 2, "CIF_DD<5>"),
+ PXA_FUNCTION(1, 1, "AC97_SYNC")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(95),
+ PXA_FUNCTION(0, 1, "KP_DKIN<2>"),
+ PXA_FUNCTION(0, 2, "CIF_DD<4>"),
+ PXA_FUNCTION(0, 3, "KP_MKIN<6>"),
+ PXA_FUNCTION(1, 1, "AC97_RESET_n")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(96),
+ PXA_FUNCTION(0, 1, "KP_DKIN<3>"),
+ PXA_FUNCTION(0, 2, "MBREQ"),
+ PXA_FUNCTION(0, 3, "FFRXD"),
+ PXA_FUNCTION(1, 2, "DVAL<1>"),
+ PXA_FUNCTION(1, 3, "KP_MKOUT<6>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(97),
+ PXA_FUNCTION(0, 1, "KP_DKIN<4>"),
+ PXA_FUNCTION(0, 2, "DREQ<1>"),
+ PXA_FUNCTION(0, 3, "KP_MKIN<3>"),
+ PXA_FUNCTION(1, 2, "MBGNT")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(98),
+ PXA_FUNCTION(0, 1, "KP_DKIN<5>"),
+ PXA_FUNCTION(0, 2, "CIF_DD<0>"),
+ PXA_FUNCTION(0, 3, "KP_MKIN<4>"),
+ PXA_FUNCTION(1, 1, "AC97_SYSCLK"),
+ PXA_FUNCTION(1, 3, "FFRTS")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(99),
+ PXA_FUNCTION(0, 1, "KP_DKIN<6>"),
+ PXA_FUNCTION(0, 2, "AC97_SDATA_IN_1"),
+ PXA_FUNCTION(0, 3, "KP_MKIN<5>"),
+ PXA_FUNCTION(1, 3, "FFTXD")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(100),
+ PXA_FUNCTION(0, 1, "KP_MKIN<0>"),
+ PXA_FUNCTION(0, 2, "DREQ<2>"),
+ PXA_FUNCTION(0, 3, "FFCTS")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(101),
+ PXA_FUNCTION(0, 1, "KP_MKIN<1>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(102),
+ PXA_FUNCTION(0, 1, "KP_MKIN<2>"),
+ PXA_FUNCTION(0, 3, "FFRXD"),
+ PXA_FUNCTION(1, 1, "nPCE<1>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(103),
+ PXA_FUNCTION(0, 1, "CIF_DD<3>"),
+ PXA_FUNCTION(1, 2, "KP_MKOUT<0>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(104),
+ PXA_FUNCTION(0, 1, "CIF_DD<2>"),
+ PXA_FUNCTION(1, 1, "PSKTSEL"),
+ PXA_FUNCTION(1, 2, "KP_MKOUT<1>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(105),
+ PXA_FUNCTION(0, 1, "CIF_DD<1>"),
+ PXA_FUNCTION(1, 1, "nPCE<2>"),
+ PXA_FUNCTION(1, 2, "KP_MKOUT<2>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(106),
+ PXA_FUNCTION(0, 1, "CIF_DD<9>"),
+ PXA_FUNCTION(1, 2, "KP_MKOUT<3>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(107),
+ PXA_FUNCTION(0, 1, "CIF_DD<8>"),
+ PXA_FUNCTION(1, 2, "KP_MKOUT<4>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(108),
+ PXA_FUNCTION(0, 1, "CIF_DD<7>"),
+ PXA_FUNCTION(1, 1, "CHOUT<0>"),
+ PXA_FUNCTION(1, 2, "KP_MKOUT<5>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(109),
+ PXA_FUNCTION(0, 1, "MMDAT<1>"),
+ PXA_FUNCTION(0, 2, "MSSDIO"),
+ PXA_FUNCTION(1, 1, "MMDAT<1>"),
+ PXA_FUNCTION(1, 2, "MSSDIO")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(110),
+ PXA_FUNCTION(0, 1, "MMDAT<2>"),
+ PXA_FUNCTION(1, 1, "MMDAT<2>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(111),
+ PXA_FUNCTION(0, 1, "MMDAT<3>"),
+ PXA_FUNCTION(1, 1, "MMDAT<3>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(112),
+ PXA_FUNCTION(0, 1, "MMCMD"),
+ PXA_FUNCTION(0, 2, "nMSINS"),
+ PXA_FUNCTION(1, 1, "MMCMD")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(113),
+ PXA_FUNCTION(0, 3, "USB_P3_3"),
+ PXA_FUNCTION(1, 1, "I2S_SYSCLK"),
+ PXA_FUNCTION(1, 2, "AC97_RESET_n")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(114),
+ PXA_FUNCTION(0, 1, "CIF_DD<1>"),
+ PXA_FUNCTION(1, 1, "UEN"),
+ PXA_FUNCTION(1, 2, "UVS0")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(115),
+ PXA_FUNCTION(0, 1, "DREQ<0>"),
+ PXA_FUNCTION(0, 2, "CIF_DD<3>"),
+ PXA_FUNCTION(0, 3, "MBREQ"),
+ PXA_FUNCTION(1, 1, "UEN"),
+ PXA_FUNCTION(1, 2, "nUVS1"),
+ PXA_FUNCTION(1, 3, "PWM_OUT<1>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(116),
+ PXA_FUNCTION(0, 1, "CIF_DD<2>"),
+ PXA_FUNCTION(0, 2, "AC97_SDATA_IN_0"),
+ PXA_FUNCTION(0, 3, "UDET"),
+ PXA_FUNCTION(1, 1, "DVAL<0>"),
+ PXA_FUNCTION(1, 2, "nUVS2"),
+ PXA_FUNCTION(1, 3, "MBGNT")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(117),
+ PXA_FUNCTION(0, 1, "SCL"),
+ PXA_FUNCTION(1, 1, "SCL")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(118),
+ PXA_FUNCTION(0, 1, "SDA"),
+ PXA_FUNCTION(1, 1, "SDA")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(119),
+ PXA_FUNCTION(0, 1, "USBHPWR<2>")),
+ PXA_GPIO_PIN(PXA_PINCTRL_PIN(120),
+ PXA_FUNCTION(1, 2, "USBHPEN<2>")),
+};
+
+static int pxa27x_pinctrl_probe(struct platform_device *pdev)
+{
+ int ret, i;
+ void __iomem *base_af[8];
+ void __iomem *base_dir[4];
+ void __iomem *base_sleep[4];
+ struct resource *res;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base_af[0] = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base_af[0]))
+ return PTR_ERR(base_af[0]);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ base_dir[0] = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base_dir[0]))
+ return PTR_ERR(base_dir[0]);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ base_dir[3] = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base_dir[3]))
+ return PTR_ERR(base_dir[3]);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+ base_sleep[0] = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base_sleep[0]))
+ return PTR_ERR(base_sleep[0]);
+
+ for (i = 0; i < ARRAY_SIZE(base_af); i++)
+ base_af[i] = base_af[0] + sizeof(base_af[0]) * i;
+ for (i = 0; i < 3; i++)
+ base_dir[i] = base_dir[0] + sizeof(base_dir[0]) * i;
+ for (i = 0; i < ARRAY_SIZE(base_sleep); i++)
+ base_sleep[i] = base_sleep[0] + sizeof(base_af[0]) * i;
+
+ ret = pxa2xx_pinctrl_init(pdev, pxa27x_pins, ARRAY_SIZE(pxa27x_pins),
+ base_af, base_dir, base_sleep);
+ return ret;
+}
+
+static const struct of_device_id pxa27x_pinctrl_match[] = {
+ { .compatible = "marvell,pxa27x-pinctrl", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, pxa27x_pinctrl_match);
+
+static struct platform_driver pxa27x_pinctrl_driver = {
+ .probe = pxa27x_pinctrl_probe,
+ .driver = {
+ .name = "pxa27x-pinctrl",
+ .of_match_table = pxa27x_pinctrl_match,
+ },
+};
+module_platform_driver(pxa27x_pinctrl_driver);
+
+MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>");
+MODULE_DESCRIPTION("Marvell PXA27x pinctrl driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pinctrl/pxa/pinctrl-pxa2xx.c b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c
new file mode 100644
index 000000000000..d90e205cf809
--- /dev/null
+++ b/drivers/pinctrl/pxa/pinctrl-pxa2xx.c
@@ -0,0 +1,436 @@
+/*
+ * Marvell PXA2xx family pin control
+ *
+ * Copyright (C) 2015 Robert Jarzmik
+ *
+ * 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; version 2 of the License.
+ *
+ */
+
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "../pinctrl-utils.h"
+#include "pinctrl-pxa2xx.h"
+
+static int pxa2xx_pctrl_get_groups_count(struct pinctrl_dev *pctldev)
+{
+ struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ return pctl->ngroups;
+}
+
+static const char *pxa2xx_pctrl_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned tgroup)
+{
+ struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct pxa_pinctrl_group *group = pctl->groups + tgroup;
+
+ return group->name;
+}
+
+static int pxa2xx_pctrl_get_group_pins(struct pinctrl_dev *pctldev,
+ unsigned tgroup,
+ const unsigned **pins,
+ unsigned *num_pins)
+{
+ struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct pxa_pinctrl_group *group = pctl->groups + tgroup;
+
+ *pins = (unsigned *)&group->pin;
+ *num_pins = 1;
+
+ return 0;
+}
+
+static const struct pinctrl_ops pxa2xx_pctl_ops = {
+#ifdef CONFIG_OF
+ .dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+ .dt_free_map = pinctrl_utils_dt_free_map,
+#endif
+ .get_groups_count = pxa2xx_pctrl_get_groups_count,
+ .get_group_name = pxa2xx_pctrl_get_group_name,
+ .get_group_pins = pxa2xx_pctrl_get_group_pins,
+};
+
+static struct pxa_desc_function *
+pxa_desc_by_func_group(struct pxa_pinctrl *pctl, const char *pin_name,
+ const char *func_name)
+{
+ int i;
+ struct pxa_desc_function *df;
+
+ for (i = 0; i < pctl->npins; i++) {
+ const struct pxa_desc_pin *pin = pctl->ppins + i;
+
+ if (!strcmp(pin->pin.name, pin_name))
+ for (df = pin->functions; df->name; df++)
+ if (!strcmp(df->name, func_name))
+ return df;
+ }
+
+ return NULL;
+}
+
+static int pxa2xx_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
+ struct pinctrl_gpio_range *range,
+ unsigned pin,
+ bool input)
+{
+ struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ unsigned long flags;
+ uint32_t val;
+ void __iomem *gpdr;
+
+ gpdr = pctl->base_gpdr[pin / 32];
+ dev_dbg(pctl->dev, "set_direction(pin=%d): dir=%d\n",
+ pin, !input);
+
+ spin_lock_irqsave(&pctl->lock, flags);
+
+ val = readl_relaxed(gpdr);
+ val = (val & ~BIT(pin % 32)) | (input ? 0 : BIT(pin % 32));
+ writel_relaxed(val, gpdr);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+
+ return 0;
+}
+
+static const char *pxa2xx_pmx_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned function)
+{
+ struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct pxa_pinctrl_function *pf = pctl->functions + function;
+
+ return pf->name;
+}
+
+static int pxa2xx_get_functions_count(struct pinctrl_dev *pctldev)
+{
+ struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+
+ return pctl->nfuncs;
+}
+
+static int pxa2xx_pmx_get_func_groups(struct pinctrl_dev *pctldev,
+ unsigned function,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct pxa_pinctrl_function *pf = pctl->functions + function;
+
+ *groups = pf->groups;
+ *num_groups = pf->ngroups;
+
+ return 0;
+}
+
+static int pxa2xx_pmx_set_mux(struct pinctrl_dev *pctldev, unsigned function,
+ unsigned tgroup)
+{
+ struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct pxa_pinctrl_group *group = pctl->groups + tgroup;
+ struct pxa_desc_function *df;
+ int pin, shift;
+ unsigned long flags;
+ void __iomem *gafr, *gpdr;
+ u32 val;
+
+
+ df = pxa_desc_by_func_group(pctl, group->name,
+ (pctl->functions + function)->name);
+ if (!df)
+ return -EINVAL;
+
+ pin = group->pin;
+ gafr = pctl->base_gafr[pin / 16];
+ gpdr = pctl->base_gpdr[pin / 32];
+ shift = (pin % 16) << 1;
+ dev_dbg(pctl->dev, "set_mux(pin=%d): af=%d dir=%d\n",
+ pin, df->muxval >> 1, df->muxval & 0x1);
+
+ spin_lock_irqsave(&pctl->lock, flags);
+
+ val = readl_relaxed(gafr);
+ val = (val & ~(0x3 << shift)) | ((df->muxval >> 1) << shift);
+ writel_relaxed(val, gafr);
+
+ val = readl_relaxed(gpdr);
+ val = (val & ~BIT(pin % 32)) | ((df->muxval & 1) ? BIT(pin % 32) : 0);
+ writel_relaxed(val, gpdr);
+
+ spin_unlock_irqrestore(&pctl->lock, flags);
+
+ return 0;
+}
+static const struct pinmux_ops pxa2xx_pinmux_ops = {
+ .get_functions_count = pxa2xx_get_functions_count,
+ .get_function_name = pxa2xx_pmx_get_func_name,
+ .get_function_groups = pxa2xx_pmx_get_func_groups,
+ .set_mux = pxa2xx_pmx_set_mux,
+ .gpio_set_direction = pxa2xx_pmx_gpio_set_direction,
+};
+
+static int pxa2xx_pconf_group_get(struct pinctrl_dev *pctldev,
+ unsigned group,
+ unsigned long *config)
+{
+ struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct pxa_pinctrl_group *g = pctl->groups + group;
+ unsigned long flags;
+ unsigned pin = g->pin;
+ void __iomem *pgsr = pctl->base_pgsr[pin / 32];
+ u32 val;
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ val = readl_relaxed(pgsr) & BIT(pin % 32);
+ *config = val ? PIN_CONFIG_LOW_POWER_MODE : 0;
+ spin_unlock_irqrestore(&pctl->lock, flags);
+
+ dev_dbg(pctl->dev, "get sleep gpio state(pin=%d) %d\n",
+ pin, !!val);
+ return 0;
+}
+
+static int pxa2xx_pconf_group_set(struct pinctrl_dev *pctldev,
+ unsigned group,
+ unsigned long *configs,
+ unsigned num_configs)
+{
+ struct pxa_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
+ struct pxa_pinctrl_group *g = pctl->groups + group;
+ unsigned long flags;
+ unsigned pin = g->pin;
+ void __iomem *pgsr = pctl->base_pgsr[pin / 32];
+ int i, is_set = 0;
+ u32 val;
+
+ for (i = 0; i < num_configs; i++) {
+ switch (pinconf_to_config_param(configs[i])) {
+ case PIN_CONFIG_LOW_POWER_MODE:
+ is_set = pinconf_to_config_argument(configs[i]);
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ dev_dbg(pctl->dev, "set sleep gpio state(pin=%d) %d\n",
+ pin, is_set);
+
+ spin_lock_irqsave(&pctl->lock, flags);
+ val = readl_relaxed(pgsr);
+ val = (val & ~BIT(pin % 32)) | (is_set ? BIT(pin % 32) : 0);
+ writel_relaxed(val, pgsr);
+ spin_unlock_irqrestore(&pctl->lock, flags);
+
+ return 0;
+}
+
+static const struct pinconf_ops pxa2xx_pconf_ops = {
+ .pin_config_group_get = pxa2xx_pconf_group_get,
+ .pin_config_group_set = pxa2xx_pconf_group_set,
+ .is_generic = true,
+};
+
+static struct pinctrl_desc pxa2xx_pinctrl_desc = {
+ .confops = &pxa2xx_pconf_ops,
+ .pctlops = &pxa2xx_pctl_ops,
+ .pmxops = &pxa2xx_pinmux_ops,
+};
+
+static const struct pxa_pinctrl_function *
+pxa2xx_find_function(struct pxa_pinctrl *pctl, const char *fname,
+ const struct pxa_pinctrl_function *functions)
+{
+ const struct pxa_pinctrl_function *func;
+
+ for (func = functions; func->name; func++)
+ if (!strcmp(fname, func->name))
+ return func;
+
+ return NULL;
+}
+
+static int pxa2xx_build_functions(struct pxa_pinctrl *pctl)
+{
+ int i;
+ struct pxa_pinctrl_function *functions;
+ struct pxa_desc_function *df;
+
+ /*
+ * Each pin can have at most 6 alternate functions, and 2 gpio functions
+ * which are common to each pin. As there are more than 2 pins without
+ * alternate function, 6 * npins is an absolute high limit of the number
+ * of functions.
+ */
+ functions = devm_kcalloc(pctl->dev, pctl->npins * 6,
+ sizeof(*functions), GFP_KERNEL);
+ if (!functions)
+ return -ENOMEM;
+
+ for (i = 0; i < pctl->npins; i++)
+ for (df = pctl->ppins[i].functions; df->name; df++)
+ if (!pxa2xx_find_function(pctl, df->name, functions))
+ (functions + pctl->nfuncs++)->name = df->name;
+ pctl->functions = devm_kmemdup(pctl->dev, functions,
+ pctl->nfuncs * sizeof(*functions),
+ GFP_KERNEL);
+ if (!pctl->functions)
+ return -ENOMEM;
+
+ devm_kfree(pctl->dev, functions);
+ return 0;
+}
+
+static int pxa2xx_build_groups(struct pxa_pinctrl *pctl)
+{
+ int i, j, ngroups;
+ struct pxa_pinctrl_function *func;
+ struct pxa_desc_function *df;
+ char **gtmp;
+
+ gtmp = devm_kmalloc_array(pctl->dev, pctl->npins, sizeof(*gtmp),
+ GFP_KERNEL);
+ if (!gtmp)
+ return -ENOMEM;
+
+ for (i = 0; i < pctl->nfuncs; i++) {
+ ngroups = 0;
+ for (j = 0; j < pctl->npins; j++)
+ for (df = pctl->ppins[j].functions; df->name;
+ df++)
+ if (!strcmp(pctl->functions[i].name,
+ df->name))
+ gtmp[ngroups++] = (char *)
+ pctl->ppins[j].pin.name;
+ func = pctl->functions + i;
+ func->ngroups = ngroups;
+ func->groups =
+ devm_kmalloc_array(pctl->dev, ngroups,
+ sizeof(char *), GFP_KERNEL);
+ if (!func->groups)
+ return -ENOMEM;
+
+ memcpy(func->groups, gtmp, ngroups * sizeof(*gtmp));
+ }
+
+ devm_kfree(pctl->dev, gtmp);
+ return 0;
+}
+
+static int pxa2xx_build_state(struct pxa_pinctrl *pctl,
+ const struct pxa_desc_pin *ppins, int npins)
+{
+ struct pxa_pinctrl_group *group;
+ struct pinctrl_pin_desc *pins;
+ int ret, i;
+
+ pctl->npins = npins;
+ pctl->ppins = ppins;
+ pctl->ngroups = npins;
+
+ pctl->desc.npins = npins;
+ pins = devm_kcalloc(pctl->dev, npins, sizeof(*pins), GFP_KERNEL);
+ if (!pins)
+ return -ENOMEM;
+
+ pctl->desc.pins = pins;
+ for (i = 0; i < npins; i++)
+ pins[i] = ppins[i].pin;
+
+ pctl->groups = devm_kmalloc_array(pctl->dev, pctl->ngroups,
+ sizeof(*pctl->groups), GFP_KERNEL);
+ if (!pctl->groups)
+ return -ENOMEM;
+
+ for (i = 0; i < npins; i++) {
+ group = pctl->groups + i;
+ group->name = ppins[i].pin.name;
+ group->pin = ppins[i].pin.number;
+ }
+
+ ret = pxa2xx_build_functions(pctl);
+ if (ret)
+ return ret;
+
+ ret = pxa2xx_build_groups(pctl);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int pxa2xx_pinctrl_init(struct platform_device *pdev,
+ const struct pxa_desc_pin *ppins, int npins,
+ void __iomem *base_gafr[], void __iomem *base_gpdr[],
+ void __iomem *base_pgsr[])
+{
+ struct pxa_pinctrl *pctl;
+ int ret, i, maxpin = 0;
+
+ for (i = 0; i < npins; i++)
+ maxpin = max_t(int, ppins[i].pin.number, maxpin);
+
+ pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
+ if (!pctl)
+ return -ENOMEM;
+ pctl->base_gafr = devm_kcalloc(&pdev->dev, roundup(maxpin, 16),
+ sizeof(*pctl->base_gafr), GFP_KERNEL);
+ pctl->base_gpdr = devm_kcalloc(&pdev->dev, roundup(maxpin, 32),
+ sizeof(*pctl->base_gpdr), GFP_KERNEL);
+ pctl->base_pgsr = devm_kcalloc(&pdev->dev, roundup(maxpin, 32),
+ sizeof(*pctl->base_pgsr), GFP_KERNEL);
+ if (!pctl->base_gafr || !pctl->base_gpdr || !pctl->base_pgsr)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, pctl);
+ spin_lock_init(&pctl->lock);
+
+ pctl->dev = &pdev->dev;
+ pctl->desc = pxa2xx_pinctrl_desc;
+ pctl->desc.name = dev_name(&pdev->dev);
+ pctl->desc.owner = THIS_MODULE;
+
+ for (i = 0; i < roundup(maxpin, 16); i += 16)
+ pctl->base_gafr[i / 16] = base_gafr[i / 16];
+ for (i = 0; i < roundup(maxpin, 32); i += 32) {
+ pctl->base_gpdr[i / 32] = base_gpdr[i / 32];
+ pctl->base_pgsr[i / 32] = base_pgsr[i / 32];
+ }
+
+ ret = pxa2xx_build_state(pctl, ppins, npins);
+ if (ret)
+ return ret;
+
+ pctl->pctl_dev = pinctrl_register(&pctl->desc, &pdev->dev, pctl);
+ if (IS_ERR(pctl->pctl_dev)) {
+ dev_err(&pdev->dev, "couldn't register pinctrl driver\n");
+ return PTR_ERR(pctl->pctl_dev);
+ }
+
+ dev_info(&pdev->dev, "initialized pxa2xx pinctrl driver\n");
+
+ return 0;
+}
+
+int pxa2xx_pinctrl_exit(struct platform_device *pdev)
+{
+ struct pxa_pinctrl *pctl = platform_get_drvdata(pdev);
+
+ pinctrl_unregister(pctl->pctl_dev);
+ return 0;
+}
diff --git a/drivers/pinctrl/pxa/pinctrl-pxa2xx.h b/drivers/pinctrl/pxa/pinctrl-pxa2xx.h
new file mode 100644
index 000000000000..8be1e0b79751
--- /dev/null
+++ b/drivers/pinctrl/pxa/pinctrl-pxa2xx.h
@@ -0,0 +1,92 @@
+/*
+ * Marvell PXA2xx family pin control
+ *
+ * Copyright (C) 2015 Robert Jarzmik
+ *
+ * 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; version 2 of the License.
+ *
+ */
+
+#ifndef __PINCTRL_PXA_H
+#define __PINCTRL_PXA_H
+
+#define PXA_FUNCTION(_dir, _af, _name) \
+ { \
+ .name = _name, \
+ .muxval = (_dir | (_af << 1)), \
+ }
+
+#define PXA_PIN(_pin, funcs...) \
+ { \
+ .pin = _pin, \
+ .functions = (struct pxa_desc_function[]){ \
+ funcs, { } }, \
+ }
+
+#define PXA_GPIO_PIN(_pin, funcs...) \
+ { \
+ .pin = _pin, \
+ .functions = (struct pxa_desc_function[]){ \
+ PXA_FUNCTION(0, 0, "gpio_in"), \
+ PXA_FUNCTION(1, 0, "gpio_out"), \
+ funcs, { } }, \
+ }
+
+#define PXA_GPIO_ONLY_PIN(_pin) \
+ { \
+ .pin = _pin, \
+ .functions = (struct pxa_desc_function[]){ \
+ PXA_FUNCTION(0, 0, "gpio_in"), \
+ PXA_FUNCTION(1, 0, "gpio_out"), \
+ { } }, \
+ }
+
+#define PXA_PINCTRL_PIN(pin) \
+ PINCTRL_PIN(pin, "P" #pin)
+
+struct pxa_desc_function {
+ const char *name;
+ u8 muxval;
+};
+
+struct pxa_desc_pin {
+ struct pinctrl_pin_desc pin;
+ struct pxa_desc_function *functions;
+};
+
+struct pxa_pinctrl_group {
+ const char *name;
+ unsigned pin;
+};
+
+struct pxa_pinctrl_function {
+ const char *name;
+ const char **groups;
+ unsigned ngroups;
+};
+
+struct pxa_pinctrl {
+ spinlock_t lock;
+ void __iomem **base_gafr;
+ void __iomem **base_gpdr;
+ void __iomem **base_pgsr;
+ struct device *dev;
+ struct pinctrl_desc desc;
+ struct pinctrl_dev *pctl_dev;
+ unsigned npins;
+ const struct pxa_desc_pin *ppins;
+ unsigned ngroups;
+ struct pxa_pinctrl_group *groups;
+ unsigned nfuncs;
+ struct pxa_pinctrl_function *functions;
+ char *name;
+};
+
+int pxa2xx_pinctrl_init(struct platform_device *pdev,
+ const struct pxa_desc_pin *ppins, int npins,
+ void __iomem *base_gafr[], void __iomem *base_gpdr[],
+ void __iomem *base_gpsr[]);
+
+#endif /* __PINCTRL_PXA_H */
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index 383263a92e59..eeac8cba8a21 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -63,6 +63,14 @@ config PINCTRL_MSM8916
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm TLMM block found on the Qualcomm 8916 platform.
+config PINCTRL_MSM8996
+ tristate "Qualcomm MSM8996 pin controller driver"
+ depends on GPIOLIB && OF
+ select PINCTRL_MSM
+ help
+ This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+ Qualcomm TLMM block found in the Qualcomm MSM8996 platform.
+
config PINCTRL_QDF2XXX
tristate "Qualcomm Technologies QDF2xxx pin controller driver"
depends on GPIOLIB && ACPI
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index 13b190e72c21..dfb50a9fe04a 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_PINCTRL_MSM8660) += pinctrl-msm8660.o
obj-$(CONFIG_PINCTRL_MSM8960) += pinctrl-msm8960.o
obj-$(CONFIG_PINCTRL_MSM8X74) += pinctrl-msm8x74.o
obj-$(CONFIG_PINCTRL_MSM8916) += pinctrl-msm8916.o
+obj-$(CONFIG_PINCTRL_MSM8996) += pinctrl-msm8996.o
obj-$(CONFIG_PINCTRL_QDF2XXX) += pinctrl-qdf2xxx.o
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-gpio.o
obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-mpp.o
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8996.c b/drivers/pinctrl/qcom/pinctrl-msm8996.c
new file mode 100644
index 000000000000..c257927bea05
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-msm8996.c
@@ -0,0 +1,1942 @@
+/*
+ * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+#define FUNCTION(fname) \
+ [msm_mux_##fname] = { \
+ .name = #fname, \
+ .groups = fname##_groups, \
+ .ngroups = ARRAY_SIZE(fname##_groups), \
+ }
+
+#define REG_BASE 0x0
+#define REG_SIZE 0x1000
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9) \
+ { \
+ .name = "gpio" #id, \
+ .pins = gpio##id##_pins, \
+ .npins = (unsigned)ARRAY_SIZE(gpio##id##_pins), \
+ .funcs = (int[]){ \
+ msm_mux_gpio, /* gpio mode */ \
+ msm_mux_##f1, \
+ msm_mux_##f2, \
+ msm_mux_##f3, \
+ msm_mux_##f4, \
+ msm_mux_##f5, \
+ msm_mux_##f6, \
+ msm_mux_##f7, \
+ msm_mux_##f8, \
+ msm_mux_##f9 \
+ }, \
+ .nfuncs = 10, \
+ .ctl_reg = REG_BASE + REG_SIZE * id, \
+ .io_reg = REG_BASE + 0x4 + REG_SIZE * id, \
+ .intr_cfg_reg = REG_BASE + 0x8 + REG_SIZE * id, \
+ .intr_status_reg = REG_BASE + 0xc + REG_SIZE * id, \
+ .intr_target_reg = REG_BASE + 0x8 + REG_SIZE * id, \
+ .mux_bit = 2, \
+ .pull_bit = 0, \
+ .drv_bit = 6, \
+ .oe_bit = 9, \
+ .in_bit = 0, \
+ .out_bit = 1, \
+ .intr_enable_bit = 0, \
+ .intr_status_bit = 0, \
+ .intr_target_bit = 5, \
+ .intr_target_kpss_val = 3, \
+ .intr_raw_status_bit = 4, \
+ .intr_polarity_bit = 1, \
+ .intr_detection_bit = 2, \
+ .intr_detection_width = 2, \
+ }
+
+#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv) \
+ { \
+ .name = #pg_name, \
+ .pins = pg_name##_pins, \
+ .npins = (unsigned)ARRAY_SIZE(pg_name##_pins), \
+ .ctl_reg = ctl, \
+ .io_reg = 0, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = pull, \
+ .drv_bit = drv, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = -1, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
+static const struct pinctrl_pin_desc msm8996_pins[] = {
+ PINCTRL_PIN(0, "GPIO_0"),
+ PINCTRL_PIN(1, "GPIO_1"),
+ PINCTRL_PIN(2, "GPIO_2"),
+ PINCTRL_PIN(3, "GPIO_3"),
+ PINCTRL_PIN(4, "GPIO_4"),
+ PINCTRL_PIN(5, "GPIO_5"),
+ PINCTRL_PIN(6, "GPIO_6"),
+ PINCTRL_PIN(7, "GPIO_7"),
+ PINCTRL_PIN(8, "GPIO_8"),
+ PINCTRL_PIN(9, "GPIO_9"),
+ PINCTRL_PIN(10, "GPIO_10"),
+ PINCTRL_PIN(11, "GPIO_11"),
+ PINCTRL_PIN(12, "GPIO_12"),
+ PINCTRL_PIN(13, "GPIO_13"),
+ PINCTRL_PIN(14, "GPIO_14"),
+ PINCTRL_PIN(15, "GPIO_15"),
+ PINCTRL_PIN(16, "GPIO_16"),
+ PINCTRL_PIN(17, "GPIO_17"),
+ PINCTRL_PIN(18, "GPIO_18"),
+ PINCTRL_PIN(19, "GPIO_19"),
+ PINCTRL_PIN(20, "GPIO_20"),
+ PINCTRL_PIN(21, "GPIO_21"),
+ PINCTRL_PIN(22, "GPIO_22"),
+ PINCTRL_PIN(23, "GPIO_23"),
+ PINCTRL_PIN(24, "GPIO_24"),
+ PINCTRL_PIN(25, "GPIO_25"),
+ PINCTRL_PIN(26, "GPIO_26"),
+ PINCTRL_PIN(27, "GPIO_27"),
+ PINCTRL_PIN(28, "GPIO_28"),
+ PINCTRL_PIN(29, "GPIO_29"),
+ PINCTRL_PIN(30, "GPIO_30"),
+ PINCTRL_PIN(31, "GPIO_31"),
+ PINCTRL_PIN(32, "GPIO_32"),
+ PINCTRL_PIN(33, "GPIO_33"),
+ PINCTRL_PIN(34, "GPIO_34"),
+ PINCTRL_PIN(35, "GPIO_35"),
+ PINCTRL_PIN(36, "GPIO_36"),
+ PINCTRL_PIN(37, "GPIO_37"),
+ PINCTRL_PIN(38, "GPIO_38"),
+ PINCTRL_PIN(39, "GPIO_39"),
+ PINCTRL_PIN(40, "GPIO_40"),
+ PINCTRL_PIN(41, "GPIO_41"),
+ PINCTRL_PIN(42, "GPIO_42"),
+ PINCTRL_PIN(43, "GPIO_43"),
+ PINCTRL_PIN(44, "GPIO_44"),
+ PINCTRL_PIN(45, "GPIO_45"),
+ PINCTRL_PIN(46, "GPIO_46"),
+ PINCTRL_PIN(47, "GPIO_47"),
+ PINCTRL_PIN(48, "GPIO_48"),
+ PINCTRL_PIN(49, "GPIO_49"),
+ PINCTRL_PIN(50, "GPIO_50"),
+ PINCTRL_PIN(51, "GPIO_51"),
+ PINCTRL_PIN(52, "GPIO_52"),
+ PINCTRL_PIN(53, "GPIO_53"),
+ PINCTRL_PIN(54, "GPIO_54"),
+ PINCTRL_PIN(55, "GPIO_55"),
+ PINCTRL_PIN(56, "GPIO_56"),
+ PINCTRL_PIN(57, "GPIO_57"),
+ PINCTRL_PIN(58, "GPIO_58"),
+ PINCTRL_PIN(59, "GPIO_59"),
+ PINCTRL_PIN(60, "GPIO_60"),
+ PINCTRL_PIN(61, "GPIO_61"),
+ PINCTRL_PIN(62, "GPIO_62"),
+ PINCTRL_PIN(63, "GPIO_63"),
+ PINCTRL_PIN(64, "GPIO_64"),
+ PINCTRL_PIN(65, "GPIO_65"),
+ PINCTRL_PIN(66, "GPIO_66"),
+ PINCTRL_PIN(67, "GPIO_67"),
+ PINCTRL_PIN(68, "GPIO_68"),
+ PINCTRL_PIN(69, "GPIO_69"),
+ PINCTRL_PIN(70, "GPIO_70"),
+ PINCTRL_PIN(71, "GPIO_71"),
+ PINCTRL_PIN(72, "GPIO_72"),
+ PINCTRL_PIN(73, "GPIO_73"),
+ PINCTRL_PIN(74, "GPIO_74"),
+ PINCTRL_PIN(75, "GPIO_75"),
+ PINCTRL_PIN(76, "GPIO_76"),
+ PINCTRL_PIN(77, "GPIO_77"),
+ PINCTRL_PIN(78, "GPIO_78"),
+ PINCTRL_PIN(79, "GPIO_79"),
+ PINCTRL_PIN(80, "GPIO_80"),
+ PINCTRL_PIN(81, "GPIO_81"),
+ PINCTRL_PIN(82, "GPIO_82"),
+ PINCTRL_PIN(83, "GPIO_83"),
+ PINCTRL_PIN(84, "GPIO_84"),
+ PINCTRL_PIN(85, "GPIO_85"),
+ PINCTRL_PIN(86, "GPIO_86"),
+ PINCTRL_PIN(87, "GPIO_87"),
+ PINCTRL_PIN(88, "GPIO_88"),
+ PINCTRL_PIN(89, "GPIO_89"),
+ PINCTRL_PIN(90, "GPIO_90"),
+ PINCTRL_PIN(91, "GPIO_91"),
+ PINCTRL_PIN(92, "GPIO_92"),
+ PINCTRL_PIN(93, "GPIO_93"),
+ PINCTRL_PIN(94, "GPIO_94"),
+ PINCTRL_PIN(95, "GPIO_95"),
+ PINCTRL_PIN(96, "GPIO_96"),
+ PINCTRL_PIN(97, "GPIO_97"),
+ PINCTRL_PIN(98, "GPIO_98"),
+ PINCTRL_PIN(99, "GPIO_99"),
+ PINCTRL_PIN(100, "GPIO_100"),
+ PINCTRL_PIN(101, "GPIO_101"),
+ PINCTRL_PIN(102, "GPIO_102"),
+ PINCTRL_PIN(103, "GPIO_103"),
+ PINCTRL_PIN(104, "GPIO_104"),
+ PINCTRL_PIN(105, "GPIO_105"),
+ PINCTRL_PIN(106, "GPIO_106"),
+ PINCTRL_PIN(107, "GPIO_107"),
+ PINCTRL_PIN(108, "GPIO_108"),
+ PINCTRL_PIN(109, "GPIO_109"),
+ PINCTRL_PIN(110, "GPIO_110"),
+ PINCTRL_PIN(111, "GPIO_111"),
+ PINCTRL_PIN(112, "GPIO_112"),
+ PINCTRL_PIN(113, "GPIO_113"),
+ PINCTRL_PIN(114, "GPIO_114"),
+ PINCTRL_PIN(115, "GPIO_115"),
+ PINCTRL_PIN(116, "GPIO_116"),
+ PINCTRL_PIN(117, "GPIO_117"),
+ PINCTRL_PIN(118, "GPIO_118"),
+ PINCTRL_PIN(119, "GPIO_119"),
+ PINCTRL_PIN(120, "GPIO_120"),
+ PINCTRL_PIN(121, "GPIO_121"),
+ PINCTRL_PIN(122, "GPIO_122"),
+ PINCTRL_PIN(123, "GPIO_123"),
+ PINCTRL_PIN(124, "GPIO_124"),
+ PINCTRL_PIN(125, "GPIO_125"),
+ PINCTRL_PIN(126, "GPIO_126"),
+ PINCTRL_PIN(127, "GPIO_127"),
+ PINCTRL_PIN(128, "GPIO_128"),
+ PINCTRL_PIN(129, "GPIO_129"),
+ PINCTRL_PIN(130, "GPIO_130"),
+ PINCTRL_PIN(131, "GPIO_131"),
+ PINCTRL_PIN(132, "GPIO_132"),
+ PINCTRL_PIN(133, "GPIO_133"),
+ PINCTRL_PIN(134, "GPIO_134"),
+ PINCTRL_PIN(135, "GPIO_135"),
+ PINCTRL_PIN(136, "GPIO_136"),
+ PINCTRL_PIN(137, "GPIO_137"),
+ PINCTRL_PIN(138, "GPIO_138"),
+ PINCTRL_PIN(139, "GPIO_139"),
+ PINCTRL_PIN(140, "GPIO_140"),
+ PINCTRL_PIN(141, "GPIO_141"),
+ PINCTRL_PIN(142, "GPIO_142"),
+ PINCTRL_PIN(143, "GPIO_143"),
+ PINCTRL_PIN(144, "GPIO_144"),
+ PINCTRL_PIN(145, "GPIO_145"),
+ PINCTRL_PIN(146, "GPIO_146"),
+ PINCTRL_PIN(147, "GPIO_147"),
+ PINCTRL_PIN(148, "GPIO_148"),
+ PINCTRL_PIN(149, "GPIO_149"),
+ PINCTRL_PIN(150, "SDC1_CLK"),
+ PINCTRL_PIN(151, "SDC1_CMD"),
+ PINCTRL_PIN(152, "SDC1_DATA"),
+ PINCTRL_PIN(153, "SDC2_CLK"),
+ PINCTRL_PIN(154, "SDC2_CMD"),
+ PINCTRL_PIN(155, "SDC2_DATA"),
+ PINCTRL_PIN(156, "SDC1_RCLK"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+ static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+DECLARE_MSM_GPIO_PINS(113);
+DECLARE_MSM_GPIO_PINS(114);
+DECLARE_MSM_GPIO_PINS(115);
+DECLARE_MSM_GPIO_PINS(116);
+DECLARE_MSM_GPIO_PINS(117);
+DECLARE_MSM_GPIO_PINS(118);
+DECLARE_MSM_GPIO_PINS(119);
+DECLARE_MSM_GPIO_PINS(120);
+DECLARE_MSM_GPIO_PINS(121);
+DECLARE_MSM_GPIO_PINS(122);
+DECLARE_MSM_GPIO_PINS(123);
+DECLARE_MSM_GPIO_PINS(124);
+DECLARE_MSM_GPIO_PINS(125);
+DECLARE_MSM_GPIO_PINS(126);
+DECLARE_MSM_GPIO_PINS(127);
+DECLARE_MSM_GPIO_PINS(128);
+DECLARE_MSM_GPIO_PINS(129);
+DECLARE_MSM_GPIO_PINS(130);
+DECLARE_MSM_GPIO_PINS(131);
+DECLARE_MSM_GPIO_PINS(132);
+DECLARE_MSM_GPIO_PINS(133);
+DECLARE_MSM_GPIO_PINS(134);
+DECLARE_MSM_GPIO_PINS(135);
+DECLARE_MSM_GPIO_PINS(136);
+DECLARE_MSM_GPIO_PINS(137);
+DECLARE_MSM_GPIO_PINS(138);
+DECLARE_MSM_GPIO_PINS(139);
+DECLARE_MSM_GPIO_PINS(140);
+DECLARE_MSM_GPIO_PINS(141);
+DECLARE_MSM_GPIO_PINS(142);
+DECLARE_MSM_GPIO_PINS(143);
+DECLARE_MSM_GPIO_PINS(144);
+DECLARE_MSM_GPIO_PINS(145);
+DECLARE_MSM_GPIO_PINS(146);
+DECLARE_MSM_GPIO_PINS(147);
+DECLARE_MSM_GPIO_PINS(148);
+DECLARE_MSM_GPIO_PINS(149);
+
+static const unsigned int sdc1_clk_pins[] = { 150 };
+static const unsigned int sdc1_cmd_pins[] = { 151 };
+static const unsigned int sdc1_data_pins[] = { 152 };
+static const unsigned int sdc2_clk_pins[] = { 153 };
+static const unsigned int sdc2_cmd_pins[] = { 154 };
+static const unsigned int sdc2_data_pins[] = { 155 };
+static const unsigned int sdc1_rclk_pins[] = { 156 };
+
+enum msm8996_functions {
+ msm_mux_adsp_ext,
+ msm_mux_atest_bbrx0,
+ msm_mux_atest_bbrx1,
+ msm_mux_atest_char,
+ msm_mux_atest_char0,
+ msm_mux_atest_char1,
+ msm_mux_atest_char2,
+ msm_mux_atest_char3,
+ msm_mux_atest_gpsadc0,
+ msm_mux_atest_gpsadc1,
+ msm_mux_atest_tsens,
+ msm_mux_atest_tsens2,
+ msm_mux_atest_usb1,
+ msm_mux_atest_usb10,
+ msm_mux_atest_usb11,
+ msm_mux_atest_usb12,
+ msm_mux_atest_usb13,
+ msm_mux_atest_usb2,
+ msm_mux_atest_usb20,
+ msm_mux_atest_usb21,
+ msm_mux_atest_usb22,
+ msm_mux_atest_usb23,
+ msm_mux_audio_ref,
+ msm_mux_bimc_dte0,
+ msm_mux_bimc_dte1,
+ msm_mux_blsp10_spi,
+ msm_mux_blsp11_i2c_scl_b,
+ msm_mux_blsp11_i2c_sda_b,
+ msm_mux_blsp11_uart_rx_b,
+ msm_mux_blsp11_uart_tx_b,
+ msm_mux_blsp1_spi,
+ msm_mux_blsp2_spi,
+ msm_mux_blsp_i2c1,
+ msm_mux_blsp_i2c10,
+ msm_mux_blsp_i2c11,
+ msm_mux_blsp_i2c12,
+ msm_mux_blsp_i2c2,
+ msm_mux_blsp_i2c3,
+ msm_mux_blsp_i2c4,
+ msm_mux_blsp_i2c5,
+ msm_mux_blsp_i2c6,
+ msm_mux_blsp_i2c7,
+ msm_mux_blsp_i2c8,
+ msm_mux_blsp_i2c9,
+ msm_mux_blsp_spi1,
+ msm_mux_blsp_spi10,
+ msm_mux_blsp_spi11,
+ msm_mux_blsp_spi12,
+ msm_mux_blsp_spi2,
+ msm_mux_blsp_spi3,
+ msm_mux_blsp_spi4,
+ msm_mux_blsp_spi5,
+ msm_mux_blsp_spi6,
+ msm_mux_blsp_spi7,
+ msm_mux_blsp_spi8,
+ msm_mux_blsp_spi9,
+ msm_mux_blsp_uart1,
+ msm_mux_blsp_uart10,
+ msm_mux_blsp_uart11,
+ msm_mux_blsp_uart12,
+ msm_mux_blsp_uart2,
+ msm_mux_blsp_uart3,
+ msm_mux_blsp_uart4,
+ msm_mux_blsp_uart5,
+ msm_mux_blsp_uart6,
+ msm_mux_blsp_uart7,
+ msm_mux_blsp_uart8,
+ msm_mux_blsp_uart9,
+ msm_mux_blsp_uim1,
+ msm_mux_blsp_uim10,
+ msm_mux_blsp_uim11,
+ msm_mux_blsp_uim12,
+ msm_mux_blsp_uim2,
+ msm_mux_blsp_uim3,
+ msm_mux_blsp_uim4,
+ msm_mux_blsp_uim5,
+ msm_mux_blsp_uim6,
+ msm_mux_blsp_uim7,
+ msm_mux_blsp_uim8,
+ msm_mux_blsp_uim9,
+ msm_mux_btfm_slimbus,
+ msm_mux_cam_mclk,
+ msm_mux_cci_async,
+ msm_mux_cci_i2c,
+ msm_mux_cci_timer0,
+ msm_mux_cci_timer1,
+ msm_mux_cci_timer2,
+ msm_mux_cci_timer3,
+ msm_mux_cci_timer4,
+ msm_mux_cri_trng,
+ msm_mux_cri_trng0,
+ msm_mux_cri_trng1,
+ msm_mux_dac_calib0,
+ msm_mux_dac_calib1,
+ msm_mux_dac_calib10,
+ msm_mux_dac_calib11,
+ msm_mux_dac_calib12,
+ msm_mux_dac_calib13,
+ msm_mux_dac_calib14,
+ msm_mux_dac_calib15,
+ msm_mux_dac_calib16,
+ msm_mux_dac_calib17,
+ msm_mux_dac_calib18,
+ msm_mux_dac_calib19,
+ msm_mux_dac_calib2,
+ msm_mux_dac_calib20,
+ msm_mux_dac_calib21,
+ msm_mux_dac_calib22,
+ msm_mux_dac_calib23,
+ msm_mux_dac_calib24,
+ msm_mux_dac_calib25,
+ msm_mux_dac_calib26,
+ msm_mux_dac_calib3,
+ msm_mux_dac_calib4,
+ msm_mux_dac_calib5,
+ msm_mux_dac_calib6,
+ msm_mux_dac_calib7,
+ msm_mux_dac_calib8,
+ msm_mux_dac_calib9,
+ msm_mux_dac_gpio,
+ msm_mux_dbg_out,
+ msm_mux_ddr_bist,
+ msm_mux_edp_hot,
+ msm_mux_edp_lcd,
+ msm_mux_gcc_gp1_clk_a,
+ msm_mux_gcc_gp1_clk_b,
+ msm_mux_gcc_gp2_clk_a,
+ msm_mux_gcc_gp2_clk_b,
+ msm_mux_gcc_gp3_clk_a,
+ msm_mux_gcc_gp3_clk_b,
+ msm_mux_gsm_tx,
+ msm_mux_hdmi_cec,
+ msm_mux_hdmi_ddc,
+ msm_mux_hdmi_hot,
+ msm_mux_hdmi_rcv,
+ msm_mux_isense_dbg,
+ msm_mux_ldo_en,
+ msm_mux_ldo_update,
+ msm_mux_lpass_slimbus,
+ msm_mux_m_voc,
+ msm_mux_mdp_vsync,
+ msm_mux_mdp_vsync_p_b,
+ msm_mux_mdp_vsync_s_b,
+ msm_mux_modem_tsync,
+ msm_mux_mss_lte,
+ msm_mux_nav_dr,
+ msm_mux_nav_pps,
+ msm_mux_pa_indicator,
+ msm_mux_pci_e0,
+ msm_mux_pci_e1,
+ msm_mux_pci_e2,
+ msm_mux_pll_bypassnl,
+ msm_mux_pll_reset,
+ msm_mux_pri_mi2s,
+ msm_mux_prng_rosc,
+ msm_mux_pwr_crypto,
+ msm_mux_pwr_modem,
+ msm_mux_pwr_nav,
+ msm_mux_qdss_cti,
+ msm_mux_qdss_cti_trig_in_a,
+ msm_mux_qdss_cti_trig_in_b,
+ msm_mux_qdss_cti_trig_out_a,
+ msm_mux_qdss_cti_trig_out_b,
+ msm_mux_qdss_stm0,
+ msm_mux_qdss_stm1,
+ msm_mux_qdss_stm10,
+ msm_mux_qdss_stm11,
+ msm_mux_qdss_stm12,
+ msm_mux_qdss_stm13,
+ msm_mux_qdss_stm14,
+ msm_mux_qdss_stm15,
+ msm_mux_qdss_stm16,
+ msm_mux_qdss_stm17,
+ msm_mux_qdss_stm18,
+ msm_mux_qdss_stm19,
+ msm_mux_qdss_stm2,
+ msm_mux_qdss_stm20,
+ msm_mux_qdss_stm21,
+ msm_mux_qdss_stm22,
+ msm_mux_qdss_stm23,
+ msm_mux_qdss_stm24,
+ msm_mux_qdss_stm25,
+ msm_mux_qdss_stm26,
+ msm_mux_qdss_stm27,
+ msm_mux_qdss_stm28,
+ msm_mux_qdss_stm29,
+ msm_mux_qdss_stm3,
+ msm_mux_qdss_stm30,
+ msm_mux_qdss_stm31,
+ msm_mux_qdss_stm4,
+ msm_mux_qdss_stm5,
+ msm_mux_qdss_stm6,
+ msm_mux_qdss_stm7,
+ msm_mux_qdss_stm8,
+ msm_mux_qdss_stm9,
+ msm_mux_qdss_traceclk_a,
+ msm_mux_qdss_traceclk_b,
+ msm_mux_qdss_tracectl_a,
+ msm_mux_qdss_tracectl_b,
+ msm_mux_qdss_tracedata_11,
+ msm_mux_qdss_tracedata_12,
+ msm_mux_qdss_tracedata_a,
+ msm_mux_qdss_tracedata_b,
+ msm_mux_qspi0,
+ msm_mux_qspi1,
+ msm_mux_qspi2,
+ msm_mux_qspi3,
+ msm_mux_qspi_clk,
+ msm_mux_qspi_cs,
+ msm_mux_qua_mi2s,
+ msm_mux_sd_card,
+ msm_mux_sd_write,
+ msm_mux_sdc40,
+ msm_mux_sdc41,
+ msm_mux_sdc42,
+ msm_mux_sdc43,
+ msm_mux_sdc4_clk,
+ msm_mux_sdc4_cmd,
+ msm_mux_sec_mi2s,
+ msm_mux_spkr_i2s,
+ msm_mux_ssbi1,
+ msm_mux_ssbi2,
+ msm_mux_ssc_irq,
+ msm_mux_ter_mi2s,
+ msm_mux_tsense_pwm1,
+ msm_mux_tsense_pwm2,
+ msm_mux_tsif1_clk,
+ msm_mux_tsif1_data,
+ msm_mux_tsif1_en,
+ msm_mux_tsif1_error,
+ msm_mux_tsif1_sync,
+ msm_mux_tsif2_clk,
+ msm_mux_tsif2_data,
+ msm_mux_tsif2_en,
+ msm_mux_tsif2_error,
+ msm_mux_tsif2_sync,
+ msm_mux_uim1,
+ msm_mux_uim2,
+ msm_mux_uim3,
+ msm_mux_uim4,
+ msm_mux_uim_batt,
+ msm_mux_vfr_1,
+ msm_mux_gpio,
+ msm_mux_NA,
+};
+
+static const char * const gpio_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+ "gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+ "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+ "gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+ "gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+ "gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+ "gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+ "gpio50", "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+ "gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+ "gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+ "gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+ "gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+ "gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+ "gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+ "gpio111", "gpio112", "gpio113", "gpio114", "gpio115", "gpio116",
+ "gpio117", "gpio118", "gpio119", "gpio120", "gpio121", "gpio122",
+ "gpio123", "gpio124", "gpio125", "gpio126", "gpio127", "gpio128",
+ "gpio129", "gpio130", "gpio131", "gpio132", "gpio133", "gpio134",
+ "gpio135", "gpio136", "gpio137", "gpio138", "gpio139", "gpio140",
+ "gpio141", "gpio142", "gpio143", "gpio144", "gpio145", "gpio146",
+ "gpio147", "gpio148", "gpio149"
+};
+
+
+static const char * const blsp_uart1_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+static const char * const blsp_spi1_groups[] = {
+ "gpio0", "gpio1", "gpio2", "gpio3",
+};
+static const char * const blsp_i2c1_groups[] = {
+ "gpio2", "gpio3",
+};
+static const char * const blsp_uim1_groups[] = {
+ "gpio0", "gpio1",
+};
+static const char * const atest_tsens_groups[] = {
+ "gpio3",
+};
+static const char * const bimc_dte1_groups[] = {
+ "gpio3", "gpio5",
+};
+static const char * const blsp_spi8_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7",
+};
+static const char * const blsp_uart8_groups[] = {
+ "gpio4", "gpio5", "gpio6", "gpio7",
+};
+static const char * const blsp_uim8_groups[] = {
+ "gpio4", "gpio5",
+};
+static const char * const qdss_cti_trig_out_b_groups[] = {
+ "gpio4",
+};
+static const char * const dac_calib0_groups[] = {
+ "gpio4", "gpio41",
+};
+static const char * const bimc_dte0_groups[] = {
+ "gpio4", "gpio6",
+};
+static const char * const qdss_cti_trig_in_b_groups[] = {
+ "gpio5",
+};
+static const char * const dac_calib1_groups[] = {
+ "gpio5", "gpio42",
+};
+static const char * const dac_calib2_groups[] = {
+ "gpio6", "gpio43",
+};
+static const char * const atest_tsens2_groups[] = {
+ "gpio7",
+};
+static const char * const blsp_spi10_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const blsp_uart10_groups[] = {
+ "gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const blsp_uim10_groups[] = {
+ "gpio8", "gpio9",
+};
+static const char * const atest_bbrx1_groups[] = {
+ "gpio8",
+};
+static const char * const atest_usb12_groups[] = {
+ "gpio9",
+};
+static const char * const mdp_vsync_groups[] = {
+ "gpio10", "gpio11", "gpio12",
+};
+static const char * const edp_lcd_groups[] = {
+ "gpio10",
+};
+static const char * const blsp_i2c10_groups[] = {
+ "gpio10", "gpio11",
+};
+static const char * const atest_usb11_groups[] = {
+ "gpio10",
+};
+static const char * const atest_gpsadc0_groups[] = {
+ "gpio11",
+};
+static const char * const edp_hot_groups[] = {
+ "gpio11",
+};
+static const char * const atest_usb10_groups[] = {
+ "gpio11",
+};
+static const char * const m_voc_groups[] = {
+ "gpio12",
+};
+static const char * const dac_gpio_groups[] = {
+ "gpio12",
+};
+static const char * const atest_char_groups[] = {
+ "gpio12",
+};
+static const char * const cam_mclk_groups[] = {
+ "gpio13", "gpio14", "gpio15", "gpio16",
+};
+static const char * const pll_bypassnl_groups[] = {
+ "gpio13",
+};
+static const char * const qdss_stm7_groups[] = {
+ "gpio13",
+};
+static const char * const blsp_i2c8_groups[] = {
+ "gpio6", "gpio7",
+};
+static const char * const atest_usb1_groups[] = {
+ "gpio7",
+};
+static const char * const atest_usb13_groups[] = {
+ "gpio8",
+};
+static const char * const atest_bbrx0_groups[] = {
+ "gpio9",
+};
+static const char * const atest_gpsadc1_groups[] = {
+ "gpio10",
+};
+static const char * const qdss_tracedata_b_groups[] = {
+ "gpio13", "gpio14", "gpio15", "gpio16", "gpio17", "gpio18", "gpio19",
+ "gpio21", "gpio22", "gpio23", "gpio26", "gpio29", "gpio57", "gpio58",
+ "gpio92", "gpio93",
+};
+static const char * const pll_reset_groups[] = {
+ "gpio14",
+};
+static const char * const qdss_stm6_groups[] = {
+ "gpio14",
+};
+static const char * const qdss_stm5_groups[] = {
+ "gpio15",
+};
+static const char * const qdss_stm4_groups[] = {
+ "gpio16",
+};
+static const char * const atest_usb2_groups[] = {
+ "gpio16",
+};
+static const char * const dac_calib3_groups[] = {
+ "gpio17", "gpio44",
+};
+static const char * const cci_i2c_groups[] = {
+ "gpio17", "gpio18", "gpio19", "gpio20",
+};
+static const char * const qdss_stm3_groups[] = {
+ "gpio17",
+};
+static const char * const atest_usb23_groups[] = {
+ "gpio17",
+};
+static const char * const atest_char3_groups[] = {
+ "gpio17",
+};
+static const char * const dac_calib4_groups[] = {
+ "gpio18", "gpio45",
+};
+static const char * const qdss_stm2_groups[] = {
+ "gpio18",
+};
+static const char * const atest_usb22_groups[] = {
+ "gpio18",
+};
+static const char * const atest_char2_groups[] = {
+ "gpio18",
+};
+static const char * const dac_calib5_groups[] = {
+ "gpio19", "gpio46",
+};
+static const char * const qdss_stm1_groups[] = {
+ "gpio19",
+};
+static const char * const atest_usb21_groups[] = {
+ "gpio19",
+};
+static const char * const atest_char1_groups[] = {
+ "gpio19",
+};
+static const char * const dac_calib6_groups[] = {
+ "gpio20", "gpio47",
+};
+static const char * const dbg_out_groups[] = {
+ "gpio20",
+};
+static const char * const qdss_stm0_groups[] = {
+ "gpio20",
+};
+static const char * const atest_usb20_groups[] = {
+ "gpio20",
+};
+static const char * const atest_char0_groups[] = {
+ "gpio20",
+};
+static const char * const dac_calib7_groups[] = {
+ "gpio21", "gpio48",
+};
+static const char * const cci_timer0_groups[] = {
+ "gpio21",
+};
+static const char * const qdss_stm13_groups[] = {
+ "gpio21",
+};
+static const char * const dac_calib8_groups[] = {
+ "gpio22", "gpio49",
+};
+static const char * const cci_timer1_groups[] = {
+ "gpio22",
+};
+static const char * const qdss_stm12_groups[] = {
+ "gpio22",
+};
+static const char * const dac_calib9_groups[] = {
+ "gpio23", "gpio50",
+};
+static const char * const cci_timer2_groups[] = {
+ "gpio23",
+};
+static const char * const qdss_stm11_groups[] = {
+ "gpio23",
+};
+static const char * const dac_calib10_groups[] = {
+ "gpio24", "gpio51",
+};
+static const char * const cci_timer3_groups[] = {
+ "gpio24",
+};
+static const char * const cci_async_groups[] = {
+ "gpio24", "gpio25", "gpio26",
+};
+static const char * const blsp1_spi_groups[] = {
+ "gpio24", "gpio27", "gpio28", "gpio90",
+};
+static const char * const qdss_stm10_groups[] = {
+ "gpio24",
+};
+static const char * const qdss_cti_trig_in_a_groups[] = {
+ "gpio24",
+};
+static const char * const dac_calib11_groups[] = {
+ "gpio25", "gpio52",
+};
+static const char * const cci_timer4_groups[] = {
+ "gpio25",
+};
+static const char * const blsp_spi6_groups[] = {
+ "gpio25", "gpio26", "gpio27", "gpio28",
+};
+static const char * const blsp_uart6_groups[] = {
+ "gpio25", "gpio26", "gpio27", "gpio28",
+};
+static const char * const blsp_uim6_groups[] = {
+ "gpio25", "gpio26",
+};
+static const char * const blsp2_spi_groups[] = {
+ "gpio25", "gpio29", "gpio30",
+};
+static const char * const qdss_stm9_groups[] = {
+ "gpio25",
+};
+static const char * const qdss_cti_trig_out_a_groups[] = {
+ "gpio25",
+};
+static const char * const dac_calib12_groups[] = {
+ "gpio26", "gpio53",
+};
+static const char * const qdss_stm8_groups[] = {
+ "gpio26",
+};
+static const char * const dac_calib13_groups[] = {
+ "gpio27", "gpio54",
+};
+static const char * const blsp_i2c6_groups[] = {
+ "gpio27", "gpio28",
+};
+static const char * const qdss_tracectl_a_groups[] = {
+ "gpio27",
+};
+static const char * const dac_calib14_groups[] = {
+ "gpio28", "gpio55",
+};
+static const char * const qdss_traceclk_a_groups[] = {
+ "gpio28",
+};
+static const char * const dac_calib15_groups[] = {
+ "gpio29", "gpio56",
+};
+static const char * const dac_calib16_groups[] = {
+ "gpio30", "gpio57",
+};
+static const char * const hdmi_rcv_groups[] = {
+ "gpio30",
+};
+static const char * const dac_calib17_groups[] = {
+ "gpio31", "gpio58",
+};
+static const char * const pwr_modem_groups[] = {
+ "gpio31",
+};
+static const char * const hdmi_cec_groups[] = {
+ "gpio31",
+};
+static const char * const pwr_nav_groups[] = {
+ "gpio32",
+};
+static const char * const dac_calib18_groups[] = {
+ "gpio32", "gpio59",
+};
+static const char * const hdmi_ddc_groups[] = {
+ "gpio32", "gpio33",
+};
+static const char * const pwr_crypto_groups[] = {
+ "gpio33",
+};
+static const char * const dac_calib19_groups[] = {
+ "gpio33", "gpio60",
+};
+static const char * const dac_calib20_groups[] = {
+ "gpio34", "gpio61",
+};
+static const char * const hdmi_hot_groups[] = {
+ "gpio34",
+};
+static const char * const dac_calib21_groups[] = {
+ "gpio35", "gpio62",
+};
+static const char * const pci_e0_groups[] = {
+ "gpio35", "gpio36",
+};
+static const char * const dac_calib22_groups[] = {
+ "gpio36", "gpio63",
+};
+static const char * const dac_calib23_groups[] = {
+ "gpio37", "gpio64",
+};
+static const char * const blsp_i2c2_groups[] = {
+ "gpio43", "gpio44",
+};
+static const char * const blsp_spi3_groups[] = {
+ "gpio45", "gpio46", "gpio47", "gpio48",
+};
+static const char * const blsp_uart3_groups[] = {
+ "gpio45", "gpio46", "gpio47", "gpio48",
+};
+static const char * const blsp_uim3_groups[] = {
+ "gpio45", "gpio46",
+};
+static const char * const blsp_i2c3_groups[] = {
+ "gpio47", "gpio48",
+};
+static const char * const dac_calib24_groups[] = {
+ "gpio38", "gpio65",
+};
+static const char * const dac_calib25_groups[] = {
+ "gpio39", "gpio66",
+};
+static const char * const tsif1_sync_groups[] = {
+ "gpio39",
+};
+static const char * const sd_write_groups[] = {
+ "gpio40",
+};
+static const char * const tsif1_error_groups[] = {
+ "gpio40",
+};
+static const char * const blsp_spi2_groups[] = {
+ "gpio41", "gpio42", "gpio43", "gpio44",
+};
+static const char * const blsp_uart2_groups[] = {
+ "gpio41", "gpio42", "gpio43", "gpio44",
+};
+static const char * const blsp_uim2_groups[] = {
+ "gpio41", "gpio42",
+};
+static const char * const qdss_cti_groups[] = {
+ "gpio41", "gpio42", "gpio100", "gpio101",
+};
+static const char * const uim3_groups[] = {
+ "gpio49", "gpio50", "gpio51", "gpio52",
+};
+static const char * const blsp_spi9_groups[] = {
+ "gpio49", "gpio50", "gpio51", "gpio52",
+};
+static const char * const blsp_uart9_groups[] = {
+ "gpio49", "gpio50", "gpio51", "gpio52",
+};
+static const char * const blsp_uim9_groups[] = {
+ "gpio49", "gpio50",
+};
+static const char * const blsp10_spi_groups[] = {
+ "gpio49", "gpio50", "gpio51", "gpio52", "gpio88",
+};
+static const char * const blsp_i2c9_groups[] = {
+ "gpio51", "gpio52",
+};
+static const char * const blsp_spi7_groups[] = {
+ "gpio53", "gpio54", "gpio55", "gpio56",
+};
+static const char * const blsp_uart7_groups[] = {
+ "gpio53", "gpio54", "gpio55", "gpio56",
+};
+static const char * const blsp_uim7_groups[] = {
+ "gpio53", "gpio54",
+};
+static const char * const qdss_tracedata_a_groups[] = {
+ "gpio53", "gpio54", "gpio63", "gpio64", "gpio65", "gpio66", "gpio67",
+ "gpio74", "gpio75", "gpio76", "gpio77", "gpio85", "gpio86", "gpio87",
+ "gpio89", "gpio90",
+};
+static const char * const blsp_i2c7_groups[] = {
+ "gpio55", "gpio56",
+};
+static const char * const qua_mi2s_groups[] = {
+ "gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+};
+static const char * const gcc_gp1_clk_a_groups[] = {
+ "gpio57",
+};
+static const char * const uim4_groups[] = {
+ "gpio58", "gpio59", "gpio60", "gpio61",
+};
+static const char * const blsp_spi11_groups[] = {
+ "gpio58", "gpio59", "gpio60", "gpio61",
+};
+static const char * const blsp_uart11_groups[] = {
+ "gpio58", "gpio59", "gpio60", "gpio61",
+};
+static const char * const blsp_uim11_groups[] = {
+ "gpio58", "gpio59",
+};
+static const char * const gcc_gp2_clk_a_groups[] = {
+ "gpio58",
+};
+static const char * const gcc_gp3_clk_a_groups[] = {
+ "gpio59",
+};
+static const char * const blsp_i2c11_groups[] = {
+ "gpio60", "gpio61",
+};
+static const char * const cri_trng0_groups[] = {
+ "gpio60",
+};
+static const char * const cri_trng1_groups[] = {
+ "gpio61",
+};
+static const char * const cri_trng_groups[] = {
+ "gpio62",
+};
+static const char * const qdss_stm18_groups[] = {
+ "gpio63",
+};
+static const char * const pri_mi2s_groups[] = {
+ "gpio64", "gpio65", "gpio66", "gpio67", "gpio68",
+};
+static const char * const qdss_stm17_groups[] = {
+ "gpio64",
+};
+static const char * const blsp_spi4_groups[] = {
+ "gpio65", "gpio66", "gpio67", "gpio68",
+};
+static const char * const blsp_uart4_groups[] = {
+ "gpio65", "gpio66", "gpio67", "gpio68",
+};
+static const char * const blsp_uim4_groups[] = {
+ "gpio65", "gpio66",
+};
+static const char * const qdss_stm16_groups[] = {
+ "gpio65",
+};
+static const char * const qdss_stm15_groups[] = {
+ "gpio66",
+};
+static const char * const dac_calib26_groups[] = {
+ "gpio67",
+};
+static const char * const blsp_i2c4_groups[] = {
+ "gpio67", "gpio68",
+};
+static const char * const qdss_stm14_groups[] = {
+ "gpio67",
+};
+static const char * const spkr_i2s_groups[] = {
+ "gpio69", "gpio70", "gpio71", "gpio72",
+};
+static const char * const audio_ref_groups[] = {
+ "gpio69",
+};
+static const char * const lpass_slimbus_groups[] = {
+ "gpio70", "gpio71", "gpio72",
+};
+static const char * const isense_dbg_groups[] = {
+ "gpio70",
+};
+static const char * const tsense_pwm1_groups[] = {
+ "gpio71",
+};
+static const char * const tsense_pwm2_groups[] = {
+ "gpio71",
+};
+static const char * const btfm_slimbus_groups[] = {
+ "gpio73", "gpio74",
+};
+static const char * const ter_mi2s_groups[] = {
+ "gpio74", "gpio75", "gpio76", "gpio77", "gpio78",
+};
+static const char * const qdss_stm22_groups[] = {
+ "gpio74",
+};
+static const char * const qdss_stm21_groups[] = {
+ "gpio75",
+};
+static const char * const qdss_stm20_groups[] = {
+ "gpio76",
+};
+static const char * const qdss_stm19_groups[] = {
+ "gpio77",
+};
+static const char * const ssc_irq_groups[] = {
+ "gpio78", "gpio79", "gpio80", "gpio117", "gpio118", "gpio119",
+ "gpio120", "gpio121", "gpio122", "gpio123", "gpio124", "gpio125",
+};
+static const char * const gcc_gp1_clk_b_groups[] = {
+ "gpio78",
+};
+static const char * const sec_mi2s_groups[] = {
+ "gpio79", "gpio80", "gpio81", "gpio82", "gpio83",
+};
+static const char * const blsp_spi5_groups[] = {
+ "gpio81", "gpio82", "gpio83", "gpio84",
+};
+static const char * const blsp_uart5_groups[] = {
+ "gpio81", "gpio82", "gpio83", "gpio84",
+};
+static const char * const blsp_uim5_groups[] = {
+ "gpio81", "gpio82",
+};
+static const char * const gcc_gp2_clk_b_groups[] = {
+ "gpio81",
+};
+static const char * const gcc_gp3_clk_b_groups[] = {
+ "gpio82",
+};
+static const char * const blsp_i2c5_groups[] = {
+ "gpio83", "gpio84",
+};
+static const char * const blsp_spi12_groups[] = {
+ "gpio85", "gpio86", "gpio87", "gpio88",
+};
+static const char * const blsp_uart12_groups[] = {
+ "gpio85", "gpio86", "gpio87", "gpio88",
+};
+static const char * const blsp_uim12_groups[] = {
+ "gpio85", "gpio86",
+};
+static const char * const qdss_stm25_groups[] = {
+ "gpio85",
+};
+static const char * const qdss_stm31_groups[] = {
+ "gpio86",
+};
+static const char * const blsp_i2c12_groups[] = {
+ "gpio87", "gpio88",
+};
+static const char * const qdss_stm30_groups[] = {
+ "gpio87",
+};
+static const char * const qdss_stm29_groups[] = {
+ "gpio88",
+};
+static const char * const tsif1_clk_groups[] = {
+ "gpio89",
+};
+static const char * const qdss_stm28_groups[] = {
+ "gpio89",
+};
+static const char * const tsif1_en_groups[] = {
+ "gpio90",
+};
+static const char * const tsif1_data_groups[] = {
+ "gpio91",
+};
+static const char * const sdc4_cmd_groups[] = {
+ "gpio91",
+};
+static const char * const qdss_stm27_groups[] = {
+ "gpio91",
+};
+static const char * const qdss_traceclk_b_groups[] = {
+ "gpio91",
+};
+static const char * const tsif2_error_groups[] = {
+ "gpio92",
+};
+static const char * const sdc43_groups[] = {
+ "gpio92",
+};
+static const char * const vfr_1_groups[] = {
+ "gpio92",
+};
+static const char * const qdss_stm26_groups[] = {
+ "gpio92",
+};
+static const char * const tsif2_clk_groups[] = {
+ "gpio93",
+};
+static const char * const sdc4_clk_groups[] = {
+ "gpio93",
+};
+static const char * const qdss_stm24_groups[] = {
+ "gpio93",
+};
+static const char * const tsif2_en_groups[] = {
+ "gpio94",
+};
+static const char * const sdc42_groups[] = {
+ "gpio94",
+};
+static const char * const qdss_stm23_groups[] = {
+ "gpio94",
+};
+static const char * const qdss_tracectl_b_groups[] = {
+ "gpio94",
+};
+static const char * const sd_card_groups[] = {
+ "gpio95",
+};
+static const char * const tsif2_data_groups[] = {
+ "gpio95",
+};
+static const char * const sdc41_groups[] = {
+ "gpio95",
+};
+static const char * const tsif2_sync_groups[] = {
+ "gpio96",
+};
+static const char * const sdc40_groups[] = {
+ "gpio96",
+};
+static const char * const mdp_vsync_p_b_groups[] = {
+ "gpio97",
+};
+static const char * const ldo_en_groups[] = {
+ "gpio97",
+};
+static const char * const mdp_vsync_s_b_groups[] = {
+ "gpio98",
+};
+static const char * const ldo_update_groups[] = {
+ "gpio98",
+};
+static const char * const blsp11_uart_tx_b_groups[] = {
+ "gpio100",
+};
+static const char * const blsp11_uart_rx_b_groups[] = {
+ "gpio101",
+};
+static const char * const blsp11_i2c_sda_b_groups[] = {
+ "gpio102",
+};
+static const char * const prng_rosc_groups[] = {
+ "gpio102",
+};
+static const char * const blsp11_i2c_scl_b_groups[] = {
+ "gpio103",
+};
+static const char * const uim2_groups[] = {
+ "gpio105", "gpio106", "gpio107", "gpio108",
+};
+static const char * const uim1_groups[] = {
+ "gpio109", "gpio110", "gpio111", "gpio112",
+};
+static const char * const uim_batt_groups[] = {
+ "gpio113",
+};
+static const char * const pci_e2_groups[] = {
+ "gpio114", "gpio115", "gpio116",
+};
+static const char * const pa_indicator_groups[] = {
+ "gpio116",
+};
+static const char * const adsp_ext_groups[] = {
+ "gpio118",
+};
+static const char * const ddr_bist_groups[] = {
+ "gpio121", "gpio122", "gpio123", "gpio124",
+};
+static const char * const qdss_tracedata_11_groups[] = {
+ "gpio123",
+};
+static const char * const qdss_tracedata_12_groups[] = {
+ "gpio124",
+};
+static const char * const modem_tsync_groups[] = {
+ "gpio128",
+};
+static const char * const nav_dr_groups[] = {
+ "gpio128",
+};
+static const char * const nav_pps_groups[] = {
+ "gpio128",
+};
+static const char * const pci_e1_groups[] = {
+ "gpio130", "gpio131", "gpio132",
+};
+static const char * const gsm_tx_groups[] = {
+ "gpio134", "gpio135",
+};
+static const char * const qspi_cs_groups[] = {
+ "gpio138", "gpio141",
+};
+static const char * const ssbi2_groups[] = {
+ "gpio139",
+};
+static const char * const ssbi1_groups[] = {
+ "gpio140",
+};
+static const char * const mss_lte_groups[] = {
+ "gpio144", "gpio145",
+};
+static const char * const qspi_clk_groups[] = {
+ "gpio145",
+};
+static const char * const qspi0_groups[] = {
+ "gpio146",
+};
+static const char * const qspi1_groups[] = {
+ "gpio147",
+};
+static const char * const qspi2_groups[] = {
+ "gpio148",
+};
+static const char * const qspi3_groups[] = {
+ "gpio149",
+};
+
+static const struct msm_function msm8996_functions[] = {
+ FUNCTION(adsp_ext),
+ FUNCTION(atest_bbrx0),
+ FUNCTION(atest_bbrx1),
+ FUNCTION(atest_char),
+ FUNCTION(atest_char0),
+ FUNCTION(atest_char1),
+ FUNCTION(atest_char2),
+ FUNCTION(atest_char3),
+ FUNCTION(atest_gpsadc0),
+ FUNCTION(atest_gpsadc1),
+ FUNCTION(atest_tsens),
+ FUNCTION(atest_tsens2),
+ FUNCTION(atest_usb1),
+ FUNCTION(atest_usb10),
+ FUNCTION(atest_usb11),
+ FUNCTION(atest_usb12),
+ FUNCTION(atest_usb13),
+ FUNCTION(atest_usb2),
+ FUNCTION(atest_usb20),
+ FUNCTION(atest_usb21),
+ FUNCTION(atest_usb22),
+ FUNCTION(atest_usb23),
+ FUNCTION(audio_ref),
+ FUNCTION(bimc_dte0),
+ FUNCTION(bimc_dte1),
+ FUNCTION(blsp10_spi),
+ FUNCTION(blsp11_i2c_scl_b),
+ FUNCTION(blsp11_i2c_sda_b),
+ FUNCTION(blsp11_uart_rx_b),
+ FUNCTION(blsp11_uart_tx_b),
+ FUNCTION(blsp1_spi),
+ FUNCTION(blsp2_spi),
+ FUNCTION(blsp_i2c1),
+ FUNCTION(blsp_i2c10),
+ FUNCTION(blsp_i2c11),
+ FUNCTION(blsp_i2c12),
+ FUNCTION(blsp_i2c2),
+ FUNCTION(blsp_i2c3),
+ FUNCTION(blsp_i2c4),
+ FUNCTION(blsp_i2c5),
+ FUNCTION(blsp_i2c6),
+ FUNCTION(blsp_i2c7),
+ FUNCTION(blsp_i2c8),
+ FUNCTION(blsp_i2c9),
+ FUNCTION(blsp_spi1),
+ FUNCTION(blsp_spi10),
+ FUNCTION(blsp_spi11),
+ FUNCTION(blsp_spi12),
+ FUNCTION(blsp_spi2),
+ FUNCTION(blsp_spi3),
+ FUNCTION(blsp_spi4),
+ FUNCTION(blsp_spi5),
+ FUNCTION(blsp_spi6),
+ FUNCTION(blsp_spi7),
+ FUNCTION(blsp_spi8),
+ FUNCTION(blsp_spi9),
+ FUNCTION(blsp_uart1),
+ FUNCTION(blsp_uart10),
+ FUNCTION(blsp_uart11),
+ FUNCTION(blsp_uart12),
+ FUNCTION(blsp_uart2),
+ FUNCTION(blsp_uart3),
+ FUNCTION(blsp_uart4),
+ FUNCTION(blsp_uart5),
+ FUNCTION(blsp_uart6),
+ FUNCTION(blsp_uart7),
+ FUNCTION(blsp_uart8),
+ FUNCTION(blsp_uart9),
+ FUNCTION(blsp_uim1),
+ FUNCTION(blsp_uim10),
+ FUNCTION(blsp_uim11),
+ FUNCTION(blsp_uim12),
+ FUNCTION(blsp_uim2),
+ FUNCTION(blsp_uim3),
+ FUNCTION(blsp_uim4),
+ FUNCTION(blsp_uim5),
+ FUNCTION(blsp_uim6),
+ FUNCTION(blsp_uim7),
+ FUNCTION(blsp_uim8),
+ FUNCTION(blsp_uim9),
+ FUNCTION(btfm_slimbus),
+ FUNCTION(cam_mclk),
+ FUNCTION(cci_async),
+ FUNCTION(cci_i2c),
+ FUNCTION(cci_timer0),
+ FUNCTION(cci_timer1),
+ FUNCTION(cci_timer2),
+ FUNCTION(cci_timer3),
+ FUNCTION(cci_timer4),
+ FUNCTION(cri_trng),
+ FUNCTION(cri_trng0),
+ FUNCTION(cri_trng1),
+ FUNCTION(dac_calib0),
+ FUNCTION(dac_calib1),
+ FUNCTION(dac_calib10),
+ FUNCTION(dac_calib11),
+ FUNCTION(dac_calib12),
+ FUNCTION(dac_calib13),
+ FUNCTION(dac_calib14),
+ FUNCTION(dac_calib15),
+ FUNCTION(dac_calib16),
+ FUNCTION(dac_calib17),
+ FUNCTION(dac_calib18),
+ FUNCTION(dac_calib19),
+ FUNCTION(dac_calib2),
+ FUNCTION(dac_calib20),
+ FUNCTION(dac_calib21),
+ FUNCTION(dac_calib22),
+ FUNCTION(dac_calib23),
+ FUNCTION(dac_calib24),
+ FUNCTION(dac_calib25),
+ FUNCTION(dac_calib26),
+ FUNCTION(dac_calib3),
+ FUNCTION(dac_calib4),
+ FUNCTION(dac_calib5),
+ FUNCTION(dac_calib6),
+ FUNCTION(dac_calib7),
+ FUNCTION(dac_calib8),
+ FUNCTION(dac_calib9),
+ FUNCTION(dac_gpio),
+ FUNCTION(dbg_out),
+ FUNCTION(ddr_bist),
+ FUNCTION(edp_hot),
+ FUNCTION(edp_lcd),
+ FUNCTION(gcc_gp1_clk_a),
+ FUNCTION(gcc_gp1_clk_b),
+ FUNCTION(gcc_gp2_clk_a),
+ FUNCTION(gcc_gp2_clk_b),
+ FUNCTION(gcc_gp3_clk_a),
+ FUNCTION(gcc_gp3_clk_b),
+ FUNCTION(gpio),
+ FUNCTION(gsm_tx),
+ FUNCTION(hdmi_cec),
+ FUNCTION(hdmi_ddc),
+ FUNCTION(hdmi_hot),
+ FUNCTION(hdmi_rcv),
+ FUNCTION(isense_dbg),
+ FUNCTION(ldo_en),
+ FUNCTION(ldo_update),
+ FUNCTION(lpass_slimbus),
+ FUNCTION(m_voc),
+ FUNCTION(mdp_vsync),
+ FUNCTION(mdp_vsync_p_b),
+ FUNCTION(mdp_vsync_s_b),
+ FUNCTION(modem_tsync),
+ FUNCTION(mss_lte),
+ FUNCTION(nav_dr),
+ FUNCTION(nav_pps),
+ FUNCTION(pa_indicator),
+ FUNCTION(pci_e0),
+ FUNCTION(pci_e1),
+ FUNCTION(pci_e2),
+ FUNCTION(pll_bypassnl),
+ FUNCTION(pll_reset),
+ FUNCTION(pri_mi2s),
+ FUNCTION(prng_rosc),
+ FUNCTION(pwr_crypto),
+ FUNCTION(pwr_modem),
+ FUNCTION(pwr_nav),
+ FUNCTION(qdss_cti),
+ FUNCTION(qdss_cti_trig_in_a),
+ FUNCTION(qdss_cti_trig_in_b),
+ FUNCTION(qdss_cti_trig_out_a),
+ FUNCTION(qdss_cti_trig_out_b),
+ FUNCTION(qdss_stm0),
+ FUNCTION(qdss_stm1),
+ FUNCTION(qdss_stm10),
+ FUNCTION(qdss_stm11),
+ FUNCTION(qdss_stm12),
+ FUNCTION(qdss_stm13),
+ FUNCTION(qdss_stm14),
+ FUNCTION(qdss_stm15),
+ FUNCTION(qdss_stm16),
+ FUNCTION(qdss_stm17),
+ FUNCTION(qdss_stm18),
+ FUNCTION(qdss_stm19),
+ FUNCTION(qdss_stm2),
+ FUNCTION(qdss_stm20),
+ FUNCTION(qdss_stm21),
+ FUNCTION(qdss_stm22),
+ FUNCTION(qdss_stm23),
+ FUNCTION(qdss_stm24),
+ FUNCTION(qdss_stm25),
+ FUNCTION(qdss_stm26),
+ FUNCTION(qdss_stm27),
+ FUNCTION(qdss_stm28),
+ FUNCTION(qdss_stm29),
+ FUNCTION(qdss_stm3),
+ FUNCTION(qdss_stm30),
+ FUNCTION(qdss_stm31),
+ FUNCTION(qdss_stm4),
+ FUNCTION(qdss_stm5),
+ FUNCTION(qdss_stm6),
+ FUNCTION(qdss_stm7),
+ FUNCTION(qdss_stm8),
+ FUNCTION(qdss_stm9),
+ FUNCTION(qdss_traceclk_a),
+ FUNCTION(qdss_traceclk_b),
+ FUNCTION(qdss_tracectl_a),
+ FUNCTION(qdss_tracectl_b),
+ FUNCTION(qdss_tracedata_11),
+ FUNCTION(qdss_tracedata_12),
+ FUNCTION(qdss_tracedata_a),
+ FUNCTION(qdss_tracedata_b),
+ FUNCTION(qspi0),
+ FUNCTION(qspi1),
+ FUNCTION(qspi2),
+ FUNCTION(qspi3),
+ FUNCTION(qspi_clk),
+ FUNCTION(qspi_cs),
+ FUNCTION(qua_mi2s),
+ FUNCTION(sd_card),
+ FUNCTION(sd_write),
+ FUNCTION(sdc40),
+ FUNCTION(sdc41),
+ FUNCTION(sdc42),
+ FUNCTION(sdc43),
+ FUNCTION(sdc4_clk),
+ FUNCTION(sdc4_cmd),
+ FUNCTION(sec_mi2s),
+ FUNCTION(spkr_i2s),
+ FUNCTION(ssbi1),
+ FUNCTION(ssbi2),
+ FUNCTION(ssc_irq),
+ FUNCTION(ter_mi2s),
+ FUNCTION(tsense_pwm1),
+ FUNCTION(tsense_pwm2),
+ FUNCTION(tsif1_clk),
+ FUNCTION(tsif1_data),
+ FUNCTION(tsif1_en),
+ FUNCTION(tsif1_error),
+ FUNCTION(tsif1_sync),
+ FUNCTION(tsif2_clk),
+ FUNCTION(tsif2_data),
+ FUNCTION(tsif2_en),
+ FUNCTION(tsif2_error),
+ FUNCTION(tsif2_sync),
+ FUNCTION(uim1),
+ FUNCTION(uim2),
+ FUNCTION(uim3),
+ FUNCTION(uim4),
+ FUNCTION(uim_batt),
+ FUNCTION(vfr_1),
+};
+
+static const struct msm_pingroup msm8996_groups[] = {
+ PINGROUP(0, blsp_spi1, blsp_uart1, blsp_uim1, NA, NA, NA, NA, NA, NA),
+ PINGROUP(1, blsp_spi1, blsp_uart1, blsp_uim1, NA, NA, NA, NA, NA, NA),
+ PINGROUP(2, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA, NA),
+ PINGROUP(3, blsp_spi1, blsp_uart1, blsp_i2c1, NA, atest_tsens,
+ bimc_dte1, NA, NA, NA),
+ PINGROUP(4, blsp_spi8, blsp_uart8, blsp_uim8, NA, qdss_cti_trig_out_b,
+ dac_calib0, bimc_dte0, NA, NA),
+ PINGROUP(5, blsp_spi8, blsp_uart8, blsp_uim8, NA, qdss_cti_trig_in_b,
+ dac_calib1, bimc_dte1, NA, NA),
+ PINGROUP(6, blsp_spi8, blsp_uart8, blsp_i2c8, NA, dac_calib2,
+ bimc_dte0, NA, NA, NA),
+ PINGROUP(7, blsp_spi8, blsp_uart8, blsp_i2c8, NA, atest_tsens2,
+ atest_usb1, NA, NA, NA),
+ PINGROUP(8, blsp_spi10, blsp_uart10, blsp_uim10, NA, atest_bbrx1,
+ atest_usb13, NA, NA, NA),
+ PINGROUP(9, blsp_spi10, blsp_uart10, blsp_uim10, atest_bbrx0,
+ atest_usb12, NA, NA, NA, NA),
+ PINGROUP(10, mdp_vsync, blsp_spi10, blsp_uart10, blsp_i2c10,
+ atest_gpsadc1, atest_usb11, NA, NA, NA),
+ PINGROUP(11, mdp_vsync, blsp_spi10, blsp_uart10, blsp_i2c10,
+ atest_gpsadc0, atest_usb10, NA, NA, NA),
+ PINGROUP(12, mdp_vsync, m_voc, dac_gpio, atest_char, NA, NA, NA, NA,
+ NA),
+ PINGROUP(13, cam_mclk, pll_bypassnl, qdss_stm7, qdss_tracedata_b, NA,
+ NA, NA, NA, NA),
+ PINGROUP(14, cam_mclk, pll_reset, qdss_stm6, qdss_tracedata_b, NA, NA,
+ NA, NA, NA),
+ PINGROUP(15, cam_mclk, qdss_stm5, qdss_tracedata_b, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(16, cam_mclk, qdss_stm4, qdss_tracedata_b, NA, atest_usb2, NA,
+ NA, NA, NA),
+ PINGROUP(17, cci_i2c, qdss_stm3, qdss_tracedata_b, dac_calib3,
+ atest_usb23, atest_char3, NA, NA, NA),
+ PINGROUP(18, cci_i2c, qdss_stm2, qdss_tracedata_b, dac_calib4,
+ atest_usb22, atest_char2, NA, NA, NA),
+ PINGROUP(19, cci_i2c, qdss_stm1, qdss_tracedata_b, dac_calib5,
+ atest_usb21, atest_char1, NA, NA, NA),
+ PINGROUP(20, cci_i2c, dbg_out, qdss_stm0, dac_calib6, atest_usb20,
+ atest_char0, NA, NA, NA),
+ PINGROUP(21, cci_timer0, qdss_stm13, qdss_tracedata_b, dac_calib7, NA,
+ NA, NA, NA, NA),
+ PINGROUP(22, cci_timer1, qdss_stm12, qdss_tracedata_b, dac_calib8, NA,
+ NA, NA, NA, NA),
+ PINGROUP(23, cci_timer2, blsp1_spi, qdss_stm11, qdss_tracedata_b,
+ dac_calib9, NA, NA, NA, NA),
+ PINGROUP(24, cci_timer3, cci_async, blsp1_spi, qdss_stm10,
+ qdss_cti_trig_in_a, dac_calib10, NA, NA, NA),
+ PINGROUP(25, cci_timer4, cci_async, blsp_spi6, blsp_uart6, blsp_uim6,
+ blsp2_spi, qdss_stm9, qdss_cti_trig_out_a, dac_calib11),
+ PINGROUP(26, cci_async, blsp_spi6, blsp_uart6, blsp_uim6, qdss_stm8,
+ qdss_tracedata_b, dac_calib12, NA, NA),
+ PINGROUP(27, blsp_spi6, blsp_uart6, blsp_i2c6, blsp1_spi,
+ qdss_tracectl_a, dac_calib13, NA, NA, NA),
+ PINGROUP(28, blsp_spi6, blsp_uart6, blsp_i2c6, blsp1_spi,
+ qdss_traceclk_a, dac_calib14, NA, NA, NA),
+ PINGROUP(29, blsp2_spi, NA, qdss_tracedata_b, dac_calib15, NA, NA, NA,
+ NA, NA),
+ PINGROUP(30, hdmi_rcv, blsp2_spi, dac_calib16, NA, NA, NA, NA, NA, NA),
+ PINGROUP(31, hdmi_cec, pwr_modem, dac_calib17, NA, NA, NA, NA, NA, NA),
+ PINGROUP(32, hdmi_ddc, pwr_nav, NA, dac_calib18, NA, NA, NA, NA, NA),
+ PINGROUP(33, hdmi_ddc, pwr_crypto, NA, dac_calib19, NA, NA, NA, NA, NA),
+ PINGROUP(34, hdmi_hot, NA, dac_calib20, NA, NA, NA, NA, NA, NA),
+ PINGROUP(35, pci_e0, NA, dac_calib21, NA, NA, NA, NA, NA, NA),
+ PINGROUP(36, pci_e0, NA, dac_calib22, NA, NA, NA, NA, NA, NA),
+ PINGROUP(37, NA, dac_calib23, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(38, NA, dac_calib24, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(39, tsif1_sync, NA, dac_calib25, NA, NA, NA, NA, NA, NA),
+ PINGROUP(40, sd_write, tsif1_error, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(41, blsp_spi2, blsp_uart2, blsp_uim2, NA, qdss_cti,
+ dac_calib0, NA, NA, NA),
+ PINGROUP(42, blsp_spi2, blsp_uart2, blsp_uim2, NA, qdss_cti,
+ dac_calib1, NA, NA, NA),
+ PINGROUP(43, blsp_spi2, blsp_uart2, blsp_i2c2, NA, dac_calib2, NA, NA,
+ NA, NA),
+ PINGROUP(44, blsp_spi2, blsp_uart2, blsp_i2c2, NA, dac_calib3, NA, NA,
+ NA, NA),
+ PINGROUP(45, blsp_spi3, blsp_uart3, blsp_uim3, NA, dac_calib4, NA, NA,
+ NA, NA),
+ PINGROUP(46, blsp_spi3, blsp_uart3, blsp_uim3, NA, dac_calib5, NA, NA,
+ NA, NA),
+ PINGROUP(47, blsp_spi3, blsp_uart3, blsp_i2c3, dac_calib6, NA, NA, NA,
+ NA, NA),
+ PINGROUP(48, blsp_spi3, blsp_uart3, blsp_i2c3, dac_calib7, NA, NA, NA,
+ NA, NA),
+ PINGROUP(49, uim3, blsp_spi9, blsp_uart9, blsp_uim9, blsp10_spi,
+ dac_calib8, NA, NA, NA),
+ PINGROUP(50, uim3, blsp_spi9, blsp_uart9, blsp_uim9, blsp10_spi,
+ dac_calib9, NA, NA, NA),
+ PINGROUP(51, uim3, blsp_spi9, blsp_uart9, blsp_i2c9, blsp10_spi,
+ dac_calib10, NA, NA, NA),
+ PINGROUP(52, uim3, blsp_spi9, blsp_uart9, blsp_i2c9,
+ blsp10_spi, dac_calib11, NA, NA, NA),
+ PINGROUP(53, blsp_spi7, blsp_uart7, blsp_uim7, NA, qdss_tracedata_a,
+ dac_calib12, NA, NA, NA),
+ PINGROUP(54, blsp_spi7, blsp_uart7, blsp_uim7, NA, NA,
+ qdss_tracedata_a, dac_calib13, NA, NA),
+ PINGROUP(55, blsp_spi7, blsp_uart7, blsp_i2c7, NA, dac_calib14, NA, NA,
+ NA, NA),
+ PINGROUP(56, blsp_spi7, blsp_uart7, blsp_i2c7, NA, dac_calib15, NA, NA,
+ NA, NA),
+ PINGROUP(57, qua_mi2s, gcc_gp1_clk_a, NA, qdss_tracedata_b,
+ dac_calib16, NA, NA, NA, NA),
+ PINGROUP(58, qua_mi2s, uim4, blsp_spi11, blsp_uart11, blsp_uim11,
+ gcc_gp2_clk_a, NA, qdss_tracedata_b, dac_calib17),
+ PINGROUP(59, qua_mi2s, uim4, blsp_spi11, blsp_uart11, blsp_uim11,
+ gcc_gp3_clk_a, NA, dac_calib18, NA),
+ PINGROUP(60, qua_mi2s, uim4, blsp_spi11, blsp_uart11, blsp_i2c11,
+ cri_trng0, NA, dac_calib19, NA),
+ PINGROUP(61, qua_mi2s, uim4, blsp_spi11, blsp_uart11,
+ blsp_i2c11, cri_trng1, NA, dac_calib20, NA),
+ PINGROUP(62, qua_mi2s, cri_trng, NA, dac_calib21, NA, NA, NA, NA, NA),
+ PINGROUP(63, qua_mi2s, NA, NA, qdss_stm18, qdss_tracedata_a,
+ dac_calib22, NA, NA, NA),
+ PINGROUP(64, pri_mi2s, NA, qdss_stm17, qdss_tracedata_a, dac_calib23,
+ NA, NA, NA, NA),
+ PINGROUP(65, pri_mi2s, blsp_spi4, blsp_uart4, blsp_uim4, NA,
+ qdss_stm16, qdss_tracedata_a, dac_calib24, NA),
+ PINGROUP(66, pri_mi2s, blsp_spi4, blsp_uart4, blsp_uim4, NA,
+ qdss_stm15, qdss_tracedata_a, dac_calib25, NA),
+ PINGROUP(67, pri_mi2s, blsp_spi4, blsp_uart4, blsp_i2c4, qdss_stm14,
+ qdss_tracedata_a, dac_calib26, NA, NA),
+ PINGROUP(68, pri_mi2s, blsp_spi4, blsp_uart4, blsp_i2c4, NA, NA, NA,
+ NA, NA),
+ PINGROUP(69, spkr_i2s, audio_ref, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(70, lpass_slimbus, spkr_i2s, isense_dbg, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(71, lpass_slimbus, spkr_i2s, tsense_pwm1, tsense_pwm2, NA, NA,
+ NA, NA, NA),
+ PINGROUP(72, lpass_slimbus, spkr_i2s, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(73, btfm_slimbus, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(74, btfm_slimbus, ter_mi2s, qdss_stm22, qdss_tracedata_a, NA,
+ NA, NA, NA, NA),
+ PINGROUP(75, ter_mi2s, qdss_stm21, qdss_tracedata_a, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(76, ter_mi2s, qdss_stm20, qdss_tracedata_a, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(77, ter_mi2s, qdss_stm19, qdss_tracedata_a, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(78, ter_mi2s, gcc_gp1_clk_b, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(79, sec_mi2s, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(80, sec_mi2s, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(81, sec_mi2s, blsp_spi5, blsp_uart5, blsp_uim5, gcc_gp2_clk_b,
+ NA, NA, NA, NA),
+ PINGROUP(82, sec_mi2s, blsp_spi5, blsp_uart5, blsp_uim5, gcc_gp3_clk_b,
+ NA, NA, NA, NA),
+ PINGROUP(83, sec_mi2s, blsp_spi5, blsp_uart5, blsp_i2c5, NA, NA, NA,
+ NA, NA),
+ PINGROUP(84, blsp_spi5, blsp_uart5, blsp_i2c5, NA, NA, NA, NA, NA, NA),
+ PINGROUP(85, blsp_spi12, blsp_uart12, blsp_uim12, NA, qdss_stm25,
+ qdss_tracedata_a, NA, NA, NA),
+ PINGROUP(86, blsp_spi12, blsp_uart12, blsp_uim12, NA, NA, qdss_stm31,
+ qdss_tracedata_a, NA, NA),
+ PINGROUP(87, blsp_spi12, blsp_uart12, blsp_i2c12, NA, qdss_stm30,
+ qdss_tracedata_a, NA, NA, NA),
+ PINGROUP(88, blsp_spi12, blsp_uart12, blsp_i2c12, blsp10_spi, NA,
+ qdss_stm29, NA, NA, NA),
+ PINGROUP(89, tsif1_clk, qdss_stm28, qdss_tracedata_a, NA, NA, NA, NA,
+ NA, NA),
+ PINGROUP(90, tsif1_en, blsp1_spi, qdss_tracedata_a, NA, NA, NA, NA, NA,
+ NA),
+ PINGROUP(91, tsif1_data, sdc4_cmd, qdss_stm27, qdss_traceclk_b, NA, NA,
+ NA, NA, NA),
+ PINGROUP(92, tsif2_error, sdc43, vfr_1, qdss_stm26, qdss_tracedata_b,
+ NA, NA, NA, NA),
+ PINGROUP(93, tsif2_clk, sdc4_clk, NA, qdss_stm24, qdss_tracedata_b, NA,
+ NA, NA, NA),
+ PINGROUP(94, tsif2_en, sdc42, NA, qdss_stm23, qdss_tracectl_b, NA, NA,
+ NA, NA),
+ PINGROUP(95, tsif2_data, sdc41, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(96, tsif2_sync, sdc40, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(97, NA, NA, mdp_vsync_p_b, ldo_en, NA, NA, NA, NA, NA),
+ PINGROUP(98, NA, NA, mdp_vsync_s_b, ldo_update, NA, NA, NA, NA, NA),
+ PINGROUP(99, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(100, NA, NA, blsp11_uart_tx_b, qdss_cti, NA, NA, NA, NA, NA),
+ PINGROUP(101, NA, blsp11_uart_rx_b, qdss_cti, NA, NA, NA, NA, NA, NA),
+ PINGROUP(102, NA, blsp11_i2c_sda_b, prng_rosc, NA, NA, NA, NA, NA, NA),
+ PINGROUP(103, NA, blsp11_i2c_scl_b, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(104, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(105, uim2, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(106, uim2, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(107, uim2, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(108, uim2, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(109, uim1, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(110, uim1, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(111, uim1, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(112, uim1, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(113, uim_batt, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(114, NA, pci_e2, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(115, NA, pci_e2, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(116, NA, pa_indicator, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(117, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(118, adsp_ext, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(119, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(120, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(121, ddr_bist, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(122, ddr_bist, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(123, ddr_bist, qdss_tracedata_11, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(124, ddr_bist, qdss_tracedata_12, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(125, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(126, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(127, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(128, NA, modem_tsync, nav_dr, nav_pps, NA, NA, NA, NA, NA),
+ PINGROUP(129, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(130, pci_e1, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(131, pci_e1, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(132, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(133, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(134, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(135, gsm_tx, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(136, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(137, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(138, NA, qspi_cs, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(139, NA, ssbi2, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(140, NA, ssbi1, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(141, NA, qspi_cs, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(142, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(143, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(144, mss_lte, NA, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(145, mss_lte, qspi_clk, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(146, NA, qspi0, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(147, NA, qspi1, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(148, NA, qspi2, NA, NA, NA, NA, NA, NA, NA),
+ PINGROUP(149, NA, qspi3, NA, NA, NA, NA, NA, NA, NA),
+ SDC_QDSD_PINGROUP(sdc1_clk, 0x12c000, 13, 6),
+ SDC_QDSD_PINGROUP(sdc1_cmd, 0x12c000, 11, 3),
+ SDC_QDSD_PINGROUP(sdc1_data, 0x12c000, 9, 0),
+ SDC_QDSD_PINGROUP(sdc2_clk, 0x12d000, 14, 6),
+ SDC_QDSD_PINGROUP(sdc2_cmd, 0x12d000, 11, 3),
+ SDC_QDSD_PINGROUP(sdc2_data, 0x12d000, 9, 0),
+ SDC_QDSD_PINGROUP(sdc1_rclk, 0x12c000, 15, 0),
+};
+
+static const struct msm_pinctrl_soc_data msm8996_pinctrl = {
+ .pins = msm8996_pins,
+ .npins = ARRAY_SIZE(msm8996_pins),
+ .functions = msm8996_functions,
+ .nfunctions = ARRAY_SIZE(msm8996_functions),
+ .groups = msm8996_groups,
+ .ngroups = ARRAY_SIZE(msm8996_groups),
+ .ngpios = 150,
+};
+
+static int msm8996_pinctrl_probe(struct platform_device *pdev)
+{
+ return msm_pinctrl_probe(pdev, &msm8996_pinctrl);
+}
+
+static const struct of_device_id msm8996_pinctrl_of_match[] = {
+ { .compatible = "qcom,msm8996-pinctrl", },
+ { }
+};
+
+static struct platform_driver msm8996_pinctrl_driver = {
+ .driver = {
+ .name = "msm8996-pinctrl",
+ .of_match_table = msm8996_pinctrl_of_match,
+ },
+ .probe = msm8996_pinctrl_probe,
+ .remove = msm_pinctrl_remove,
+};
+
+static int __init msm8996_pinctrl_init(void)
+{
+ return platform_driver_register(&msm8996_pinctrl_driver);
+}
+arch_initcall(msm8996_pinctrl_init);
+
+static void __exit msm8996_pinctrl_exit(void)
+{
+ platform_driver_unregister(&msm8996_pinctrl_driver);
+}
+module_exit(msm8996_pinctrl_exit);
+
+MODULE_DESCRIPTION("Qualcomm msm8996 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, msm8996_pinctrl_of_match);
diff --git a/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c b/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c
index e9ff3bc150bb..f448534edf46 100644
--- a/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c
+++ b/drivers/pinctrl/qcom/pinctrl-qdf2xxx.c
@@ -32,6 +32,9 @@
static struct msm_pinctrl_soc_data qdf2xxx_pinctrl;
+/* A reasonable limit to the number of GPIOS */
+#define MAX_GPIOS 256
+
static int qdf2xxx_pinctrl_probe(struct platform_device *pdev)
{
struct pinctrl_pin_desc *pins;
@@ -42,11 +45,13 @@ static int qdf2xxx_pinctrl_probe(struct platform_device *pdev)
/* Query the number of GPIOs from ACPI */
ret = device_property_read_u32(&pdev->dev, "num-gpios", &num_gpios);
- if (ret < 0)
+ if (ret < 0) {
+ dev_warn(&pdev->dev, "missing num-gpios property\n");
return ret;
+ }
- if (!num_gpios) {
- dev_warn(&pdev->dev, "missing num-gpios property\n");
+ if (!num_gpios || num_gpios > MAX_GPIOS) {
+ dev_warn(&pdev->dev, "invalid num-gpios property\n");
return -ENODEV;
}
@@ -55,6 +60,9 @@ static int qdf2xxx_pinctrl_probe(struct platform_device *pdev)
groups = devm_kcalloc(&pdev->dev, num_gpios,
sizeof(struct msm_pingroup), GFP_KERNEL);
+ if (!pins || !groups)
+ return -ENOMEM;
+
for (i = 0; i < num_gpios; i++) {
pins[i].number = i;
diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
index 6c42ca14d2fd..77f6a5cb1008 100644
--- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
+++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
@@ -14,6 +14,7 @@
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_irq.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinmux.h>
@@ -693,18 +694,19 @@ static int pmic_gpio_probe(struct platform_device *pdev)
struct pmic_gpio_pad *pad, *pads;
struct pmic_gpio_state *state;
int ret, npins, i;
- u32 res[2];
+ u32 reg;
- ret = of_property_read_u32_array(dev->of_node, "reg", res, 2);
+ ret = of_property_read_u32(dev->of_node, "reg", &reg);
if (ret < 0) {
- dev_err(dev, "missing base address and/or range");
+ dev_err(dev, "missing base address");
return ret;
}
- npins = res[1] / PMIC_GPIO_ADDRESS_RANGE;
-
+ npins = platform_irq_count(pdev);
if (!npins)
return -EINVAL;
+ if (npins < 0)
+ return npins;
BUG_ON(npins > ARRAY_SIZE(pmic_gpio_groups));
@@ -752,7 +754,7 @@ static int pmic_gpio_probe(struct platform_device *pdev)
if (pad->irq < 0)
return pad->irq;
- pad->base = res[0] + i * PMIC_GPIO_ADDRESS_RANGE;
+ pad->base = reg + i * PMIC_GPIO_ADDRESS_RANGE;
ret = pmic_gpio_populate(state, pad);
if (ret < 0)
@@ -804,6 +806,7 @@ static int pmic_gpio_remove(struct platform_device *pdev)
static const struct of_device_id pmic_gpio_of_match[] = {
{ .compatible = "qcom,pm8916-gpio" }, /* 4 GPIO's */
{ .compatible = "qcom,pm8941-gpio" }, /* 36 GPIO's */
+ { .compatible = "qcom,pm8994-gpio" }, /* 22 GPIO's */
{ .compatible = "qcom,pma8084-gpio" }, /* 22 GPIO's */
{ },
};
diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
index 9ce0e30e33e8..2df4f29175ae 100644
--- a/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
+++ b/drivers/pinctrl/qcom/pinctrl-spmi-mpp.c
@@ -14,6 +14,7 @@
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/of_irq.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinmux.h>
@@ -795,17 +796,19 @@ static int pmic_mpp_probe(struct platform_device *pdev)
struct pmic_mpp_pad *pad, *pads;
struct pmic_mpp_state *state;
int ret, npins, i;
- u32 res[2];
+ u32 reg;
- ret = of_property_read_u32_array(dev->of_node, "reg", res, 2);
+ ret = of_property_read_u32(dev->of_node, "reg", &reg);
if (ret < 0) {
- dev_err(dev, "missing base address and/or range");
+ dev_err(dev, "missing base address");
return ret;
}
- npins = res[1] / PMIC_MPP_ADDRESS_RANGE;
+ npins = platform_irq_count(pdev);
if (!npins)
return -EINVAL;
+ if (npins < 0)
+ return npins;
BUG_ON(npins > ARRAY_SIZE(pmic_mpp_groups));
@@ -854,7 +857,7 @@ static int pmic_mpp_probe(struct platform_device *pdev)
if (pad->irq < 0)
return pad->irq;
- pad->base = res[0] + i * PMIC_MPP_ADDRESS_RANGE;
+ pad->base = reg + i * PMIC_MPP_ADDRESS_RANGE;
ret = pmic_mpp_populate(state, pad);
if (ret < 0)
@@ -907,6 +910,7 @@ static const struct of_device_id pmic_mpp_of_match[] = {
{ .compatible = "qcom,pm8841-mpp" }, /* 4 MPP's */
{ .compatible = "qcom,pm8916-mpp" }, /* 4 MPP's */
{ .compatible = "qcom,pm8941-mpp" }, /* 8 MPP's */
+ { .compatible = "qcom,pm8994-mpp" }, /* 8 MPP's */
{ .compatible = "qcom,pma8084-mpp" }, /* 8 MPP's */
{ },
};
diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
index 19a3c3bc2f1f..e51176ec83d2 100644
--- a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
+++ b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c
@@ -23,6 +23,7 @@
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/of_device.h>
+#include <linux/of_irq.h>
#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
@@ -650,11 +651,12 @@ static int pm8xxx_pin_populate(struct pm8xxx_gpio *pctrl,
}
static const struct of_device_id pm8xxx_gpio_of_match[] = {
- { .compatible = "qcom,pm8018-gpio", .data = (void *)6 },
- { .compatible = "qcom,pm8038-gpio", .data = (void *)12 },
- { .compatible = "qcom,pm8058-gpio", .data = (void *)40 },
- { .compatible = "qcom,pm8917-gpio", .data = (void *)38 },
- { .compatible = "qcom,pm8921-gpio", .data = (void *)44 },
+ { .compatible = "qcom,pm8018-gpio" },
+ { .compatible = "qcom,pm8038-gpio" },
+ { .compatible = "qcom,pm8058-gpio" },
+ { .compatible = "qcom,pm8917-gpio" },
+ { .compatible = "qcom,pm8921-gpio" },
+ { .compatible = "qcom,ssbi-gpio" },
{ },
};
MODULE_DEVICE_TABLE(of, pm8xxx_gpio_of_match);
@@ -665,14 +667,19 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev)
struct pinctrl_pin_desc *pins;
struct pm8xxx_gpio *pctrl;
int ret;
- int i;
+ int i, npins;
pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
if (!pctrl)
return -ENOMEM;
pctrl->dev = &pdev->dev;
- pctrl->npins = (unsigned long)of_device_get_match_data(&pdev->dev);
+ npins = platform_irq_count(pdev);
+ if (!npins)
+ return -EINVAL;
+ if (npins < 0)
+ return npins;
+ pctrl->npins = npins;
pctrl->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!pctrl->regmap) {
diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c b/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
index b868ef1766a0..e9f01de51e18 100644
--- a/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
+++ b/drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c
@@ -23,6 +23,7 @@
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/of_device.h>
+#include <linux/of_irq.h>
#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
@@ -741,11 +742,12 @@ static int pm8xxx_pin_populate(struct pm8xxx_mpp *pctrl,
}
static const struct of_device_id pm8xxx_mpp_of_match[] = {
- { .compatible = "qcom,pm8018-mpp", .data = (void *)6 },
- { .compatible = "qcom,pm8038-mpp", .data = (void *)6 },
- { .compatible = "qcom,pm8917-mpp", .data = (void *)10 },
- { .compatible = "qcom,pm8821-mpp", .data = (void *)4 },
- { .compatible = "qcom,pm8921-mpp", .data = (void *)12 },
+ { .compatible = "qcom,pm8018-mpp" },
+ { .compatible = "qcom,pm8038-mpp" },
+ { .compatible = "qcom,pm8917-mpp" },
+ { .compatible = "qcom,pm8821-mpp" },
+ { .compatible = "qcom,pm8921-mpp" },
+ { .compatible = "qcom,ssbi-mpp" },
{ },
};
MODULE_DEVICE_TABLE(of, pm8xxx_mpp_of_match);
@@ -756,14 +758,19 @@ static int pm8xxx_mpp_probe(struct platform_device *pdev)
struct pinctrl_pin_desc *pins;
struct pm8xxx_mpp *pctrl;
int ret;
- int i;
+ int i, npins;
pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
if (!pctrl)
return -ENOMEM;
pctrl->dev = &pdev->dev;
- pctrl->npins = (unsigned long)of_device_get_match_data(&pdev->dev);
+ npins = platform_irq_count(pdev);
+ if (!npins)
+ return -EINVAL;
+ if (npins < 0)
+ return npins;
+ pctrl->npins = npins;
pctrl->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!pctrl->regmap) {
diff --git a/drivers/pinctrl/samsung/pinctrl-exynos.c b/drivers/pinctrl/samsung/pinctrl-exynos.c
index 71ccf6a90b22..16e2293cc2bc 100644
--- a/drivers/pinctrl/samsung/pinctrl-exynos.c
+++ b/drivers/pinctrl/samsung/pinctrl-exynos.c
@@ -1150,6 +1150,109 @@ const struct samsung_pin_ctrl exynos5260_pin_ctrl[] __initconst = {
},
};
+/* pin banks of exynos5410 pin-controller 0 */
+static const struct samsung_pin_bank_data exynos5410_pin_banks0[] __initconst = {
+ EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
+ EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
+ EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08),
+ EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpb0", 0x0c),
+ EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpb1", 0x10),
+ EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpb2", 0x14),
+ EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpb3", 0x18),
+ EXYNOS_PIN_BANK_EINTG(7, 0x0E0, "gpc0", 0x1c),
+ EXYNOS_PIN_BANK_EINTG(4, 0x100, "gpc3", 0x20),
+ EXYNOS_PIN_BANK_EINTG(7, 0x120, "gpc1", 0x24),
+ EXYNOS_PIN_BANK_EINTG(7, 0x140, "gpc2", 0x28),
+ EXYNOS_PIN_BANK_EINTN(2, 0x160, "gpm5"),
+ EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpd1", 0x2c),
+ EXYNOS_PIN_BANK_EINTG(8, 0x1A0, "gpe0", 0x30),
+ EXYNOS_PIN_BANK_EINTG(2, 0x1C0, "gpe1", 0x34),
+ EXYNOS_PIN_BANK_EINTG(6, 0x1E0, "gpf0", 0x38),
+ EXYNOS_PIN_BANK_EINTG(8, 0x200, "gpf1", 0x3c),
+ EXYNOS_PIN_BANK_EINTG(8, 0x220, "gpg0", 0x40),
+ EXYNOS_PIN_BANK_EINTG(8, 0x240, "gpg1", 0x44),
+ EXYNOS_PIN_BANK_EINTG(2, 0x260, "gpg2", 0x48),
+ EXYNOS_PIN_BANK_EINTG(4, 0x280, "gph0", 0x4c),
+ EXYNOS_PIN_BANK_EINTG(8, 0x2A0, "gph1", 0x50),
+ EXYNOS_PIN_BANK_EINTN(8, 0x2C0, "gpm7"),
+ EXYNOS_PIN_BANK_EINTN(6, 0x2E0, "gpy0"),
+ EXYNOS_PIN_BANK_EINTN(4, 0x300, "gpy1"),
+ EXYNOS_PIN_BANK_EINTN(6, 0x320, "gpy2"),
+ EXYNOS_PIN_BANK_EINTN(8, 0x340, "gpy3"),
+ EXYNOS_PIN_BANK_EINTN(8, 0x360, "gpy4"),
+ EXYNOS_PIN_BANK_EINTN(8, 0x380, "gpy5"),
+ EXYNOS_PIN_BANK_EINTN(8, 0x3A0, "gpy6"),
+ EXYNOS_PIN_BANK_EINTN(8, 0x3C0, "gpy7"),
+ EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
+ EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
+ EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
+ EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
+};
+
+/* pin banks of exynos5410 pin-controller 1 */
+static const struct samsung_pin_bank_data exynos5410_pin_banks1[] __initconst = {
+ EXYNOS_PIN_BANK_EINTG(5, 0x000, "gpj0", 0x00),
+ EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpj1", 0x04),
+ EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpj2", 0x08),
+ EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpj3", 0x0c),
+ EXYNOS_PIN_BANK_EINTG(2, 0x080, "gpj4", 0x10),
+ EXYNOS_PIN_BANK_EINTG(8, 0x0A0, "gpk0", 0x14),
+ EXYNOS_PIN_BANK_EINTG(8, 0x0C0, "gpk1", 0x18),
+ EXYNOS_PIN_BANK_EINTG(8, 0x0E0, "gpk2", 0x1c),
+ EXYNOS_PIN_BANK_EINTG(7, 0x100, "gpk3", 0x20),
+};
+
+/* pin banks of exynos5410 pin-controller 2 */
+static const struct samsung_pin_bank_data exynos5410_pin_banks2[] __initconst = {
+ EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpv0", 0x00),
+ EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpv1", 0x04),
+ EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpv2", 0x08),
+ EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpv3", 0x0c),
+ EXYNOS_PIN_BANK_EINTG(2, 0x0C0, "gpv4", 0x10),
+};
+
+/* pin banks of exynos5410 pin-controller 3 */
+static const struct samsung_pin_bank_data exynos5410_pin_banks3[] __initconst = {
+ EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
+};
+
+/*
+ * Samsung pinctrl driver data for Exynos5410 SoC. Exynos5410 SoC includes
+ * four gpio/pin-mux/pinconfig controllers.
+ */
+const struct samsung_pin_ctrl exynos5410_pin_ctrl[] __initconst = {
+ {
+ /* pin-controller instance 0 data */
+ .pin_banks = exynos5410_pin_banks0,
+ .nr_banks = ARRAY_SIZE(exynos5410_pin_banks0),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .eint_wkup_init = exynos_eint_wkup_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 1 data */
+ .pin_banks = exynos5410_pin_banks1,
+ .nr_banks = ARRAY_SIZE(exynos5410_pin_banks1),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 2 data */
+ .pin_banks = exynos5410_pin_banks2,
+ .nr_banks = ARRAY_SIZE(exynos5410_pin_banks2),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ }, {
+ /* pin-controller instance 3 data */
+ .pin_banks = exynos5410_pin_banks3,
+ .nr_banks = ARRAY_SIZE(exynos5410_pin_banks3),
+ .eint_gpio_init = exynos_eint_gpio_init,
+ .suspend = exynos_pinctrl_suspend,
+ .resume = exynos_pinctrl_resume,
+ },
+};
+
/* pin banks of exynos5420 pin-controller 0 */
static const struct samsung_pin_bank_data exynos5420_pin_banks0[] __initconst = {
EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpy7", 0x00),
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 3f622ccd8eab..48294e7449a4 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -1222,6 +1222,8 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = {
.data = (void *)exynos5250_pin_ctrl },
{ .compatible = "samsung,exynos5260-pinctrl",
.data = (void *)exynos5260_pin_ctrl },
+ { .compatible = "samsung,exynos5410-pinctrl",
+ .data = (void *)exynos5410_pin_ctrl },
{ .compatible = "samsung,exynos5420-pinctrl",
.data = (void *)exynos5420_pin_ctrl },
{ .compatible = "samsung,exynos5433-pinctrl",
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.h b/drivers/pinctrl/samsung/pinctrl-samsung.h
index c1239ff6157d..cd31bfaf62cb 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.h
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.h
@@ -270,6 +270,7 @@ extern const struct samsung_pin_ctrl exynos4x12_pin_ctrl[];
extern const struct samsung_pin_ctrl exynos4415_pin_ctrl[];
extern const struct samsung_pin_ctrl exynos5250_pin_ctrl[];
extern const struct samsung_pin_ctrl exynos5260_pin_ctrl[];
+extern const struct samsung_pin_ctrl exynos5410_pin_ctrl[];
extern const struct samsung_pin_ctrl exynos5420_pin_ctrl[];
extern const struct samsung_pin_ctrl exynos5433_pin_ctrl[];
extern const struct samsung_pin_ctrl exynos7_pin_ctrl[];
diff --git a/drivers/pinctrl/sh-pfc/pfc-emev2.c b/drivers/pinctrl/sh-pfc/pfc-emev2.c
index 02118ab336fc..1cbbe04d7df6 100644
--- a/drivers/pinctrl/sh-pfc/pfc-emev2.c
+++ b/drivers/pinctrl/sh-pfc/pfc-emev2.c
@@ -258,18 +258,18 @@ static const u16 pinmux_data[] = {
/* GPSR0 */
/* V9 */
- PINMUX_DATA(JT_SEL_MARK, FN_JT_SEL),
+ PINMUX_SINGLE(JT_SEL),
/* U9 */
- PINMUX_DATA(ERR_RST_REQB_MARK, FN_ERR_RST_REQB),
+ PINMUX_SINGLE(ERR_RST_REQB),
/* V8 */
- PINMUX_DATA(REF_CLKO_MARK, FN_REF_CLKO),
+ PINMUX_SINGLE(REF_CLKO),
/* U8 */
- PINMUX_DATA(EXT_CLKI_MARK, FN_EXT_CLKI),
+ PINMUX_SINGLE(EXT_CLKI),
/* B22*/
PINMUX_IPSR_NOFN(LCD3_1_0_PORT18, LCD3_PXCLK, SEL_LCD3_1_0_00),
PINMUX_IPSR_NOFN(LCD3_1_0_PORT18, YUV3_CLK_O, SEL_LCD3_1_0_01),
/* C21 */
- PINMUX_DATA(LCD3_PXCLKB_MARK, FN_LCD3_PXCLKB),
+ PINMUX_SINGLE(LCD3_PXCLKB),
/* A21 */
PINMUX_IPSR_NOFN(LCD3_1_0_PORT20, LCD3_CLK_I, SEL_LCD3_1_0_00),
PINMUX_IPSR_NOFN(LCD3_1_0_PORT20, YUV3_CLK_I, SEL_LCD3_1_0_01),
@@ -285,17 +285,17 @@ static const u16 pinmux_data[] = {
/* GPSR1 */
/* A20 */
- PINMUX_DATA(LCD3_R0_MARK, FN_LCD3_R0),
+ PINMUX_SINGLE(LCD3_R0),
/* B20 */
- PINMUX_DATA(LCD3_R1_MARK, FN_LCD3_R1),
+ PINMUX_SINGLE(LCD3_R1),
/* A19 */
- PINMUX_DATA(LCD3_R2_MARK, FN_LCD3_R2),
+ PINMUX_SINGLE(LCD3_R2),
/* B19 */
- PINMUX_DATA(LCD3_R3_MARK, FN_LCD3_R3),
+ PINMUX_SINGLE(LCD3_R3),
/* C19 */
- PINMUX_DATA(LCD3_R4_MARK, FN_LCD3_R4),
+ PINMUX_SINGLE(LCD3_R4),
/* B18 */
- PINMUX_DATA(LCD3_R5_MARK, FN_LCD3_R5),
+ PINMUX_SINGLE(LCD3_R5),
/* C18 */
PINMUX_IPSR_NOFN(LCD3_9_8_PORT38, LCD3_R6, SEL_LCD3_9_8_00),
PINMUX_IPSR_NOFN(LCD3_9_8_PORT38, TP33_CLK, SEL_LCD3_9_8_10),
@@ -367,9 +367,9 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_NOFN(LCD3_11_10_PORT43, YUV3_D15, SEL_LCD3_11_10_01),
PINMUX_IPSR_NOFN(LCD3_11_10_PORT43, TP33_DATA15, SEL_LCD3_11_10_10),
/* AA9 */
- PINMUX_DATA(IIC0_SCL_MARK, FN_IIC0_SCL),
+ PINMUX_SINGLE(IIC0_SCL),
/* AA8 */
- PINMUX_DATA(IIC0_SDA_MARK, FN_IIC0_SDA),
+ PINMUX_SINGLE(IIC0_SDA),
/* Y9 */
PINMUX_IPSR_NOFN(IIC_1_0_PORT46, IIC1_SCL, SEL_IIC_1_0_00),
PINMUX_IPSR_NOFN(IIC_1_0_PORT46, UART3_RX, SEL_IIC_1_0_01),
@@ -377,51 +377,51 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_NOFN(IIC_1_0_PORT47, IIC1_SDA, SEL_IIC_1_0_00),
PINMUX_IPSR_NOFN(IIC_1_0_PORT47, UART3_TX, SEL_IIC_1_0_01),
/* AC19 */
- PINMUX_DATA(SD_CKI_MARK, FN_SD_CKI),
+ PINMUX_SINGLE(SD_CKI),
/* AB18 */
- PINMUX_DATA(SDI0_CKO_MARK, FN_SDI0_CKO),
+ PINMUX_SINGLE(SDI0_CKO),
/* AC18 */
- PINMUX_DATA(SDI0_CKI_MARK, FN_SDI0_CKI),
+ PINMUX_SINGLE(SDI0_CKI),
/* Y12 */
- PINMUX_DATA(SDI0_CMD_MARK, FN_SDI0_CMD),
+ PINMUX_SINGLE(SDI0_CMD),
/* AA13 */
- PINMUX_DATA(SDI0_DATA0_MARK, FN_SDI0_DATA0),
+ PINMUX_SINGLE(SDI0_DATA0),
/* Y13 */
- PINMUX_DATA(SDI0_DATA1_MARK, FN_SDI0_DATA1),
+ PINMUX_SINGLE(SDI0_DATA1),
/* AA14 */
- PINMUX_DATA(SDI0_DATA2_MARK, FN_SDI0_DATA2),
+ PINMUX_SINGLE(SDI0_DATA2),
/* Y14 */
- PINMUX_DATA(SDI0_DATA3_MARK, FN_SDI0_DATA3),
+ PINMUX_SINGLE(SDI0_DATA3),
/* AA15 */
- PINMUX_DATA(SDI0_DATA4_MARK, FN_SDI0_DATA4),
+ PINMUX_SINGLE(SDI0_DATA4),
/* Y15 */
- PINMUX_DATA(SDI0_DATA5_MARK, FN_SDI0_DATA5),
+ PINMUX_SINGLE(SDI0_DATA5),
/* AA16 */
- PINMUX_DATA(SDI0_DATA6_MARK, FN_SDI0_DATA6),
+ PINMUX_SINGLE(SDI0_DATA6),
/* Y16 */
- PINMUX_DATA(SDI0_DATA7_MARK, FN_SDI0_DATA7),
+ PINMUX_SINGLE(SDI0_DATA7),
/* AB22 */
- PINMUX_DATA(SDI1_CKO_MARK, FN_SDI1_CKO),
+ PINMUX_SINGLE(SDI1_CKO),
/* AA23 */
- PINMUX_DATA(SDI1_CKI_MARK, FN_SDI1_CKI),
+ PINMUX_SINGLE(SDI1_CKI),
/* AC21 */
- PINMUX_DATA(SDI1_CMD_MARK, FN_SDI1_CMD),
+ PINMUX_SINGLE(SDI1_CMD),
/* GPSR2 */
/* AB21 */
- PINMUX_DATA(SDI1_DATA0_MARK, FN_SDI1_DATA0),
+ PINMUX_SINGLE(SDI1_DATA0),
/* AB20 */
- PINMUX_DATA(SDI1_DATA1_MARK, FN_SDI1_DATA1),
+ PINMUX_SINGLE(SDI1_DATA1),
/* AB19 */
- PINMUX_DATA(SDI1_DATA2_MARK, FN_SDI1_DATA2),
+ PINMUX_SINGLE(SDI1_DATA2),
/* AA19 */
- PINMUX_DATA(SDI1_DATA3_MARK, FN_SDI1_DATA3),
+ PINMUX_SINGLE(SDI1_DATA3),
/* J23 */
- PINMUX_DATA(AB_CLK_MARK, FN_AB_CLK),
+ PINMUX_SINGLE(AB_CLK),
/* D21 */
- PINMUX_DATA(AB_CSB0_MARK, FN_AB_CSB0),
+ PINMUX_SINGLE(AB_CSB0),
/* E21 */
- PINMUX_DATA(AB_CSB1_MARK, FN_AB_CSB1),
+ PINMUX_SINGLE(AB_CSB1),
/* F20 */
PINMUX_IPSR_NOFN(AB_1_0_PORT71, AB_CSB2, SEL_AB_1_0_00),
PINMUX_IPSR_NOFN(AB_1_0_PORT71, CF_CSB0, SEL_AB_1_0_10),
@@ -514,7 +514,7 @@ static const u16 pinmux_data[] = {
/* GPSR3 */
/* M21 */
- PINMUX_DATA(AB_A20_MARK, FN_AB_A20),
+ PINMUX_SINGLE(AB_A20),
/* N21 */
PINMUX_IPSR_NOFN(AB_9_8_PORT97, AB_A21, SEL_AB_9_8_00),
PINMUX_IPSR_NOFN(AB_9_8_PORT97, SDI2_CKO, SEL_AB_9_8_01),
@@ -541,13 +541,13 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_NOFN(AB_13_12_PORT104, AB_A28, SEL_AB_13_12_00),
PINMUX_IPSR_NOFN(AB_13_12_PORT104, AB_BEN1, SEL_AB_13_12_10),
/* B8 */
- PINMUX_DATA(USI0_CS1_MARK, FN_USI0_CS1),
+ PINMUX_SINGLE(USI0_CS1),
/* B9 */
- PINMUX_DATA(USI0_CS2_MARK, FN_USI0_CS2),
+ PINMUX_SINGLE(USI0_CS2),
/* C10 */
- PINMUX_DATA(USI1_DI_MARK, FN_USI1_DI),
+ PINMUX_SINGLE(USI1_DI),
/* D10 */
- PINMUX_DATA(USI1_DO_MARK, FN_USI1_DO),
+ PINMUX_SINGLE(USI1_DO),
/* AB5 */
PINMUX_IPSR_NOFN(USI_1_0_PORT109, USI2_CLK, SEL_USI_1_0_00),
PINMUX_IPSR_NOFN(USI_1_0_PORT109, DTV_BCLK_B, SEL_USI_1_0_01),
@@ -587,49 +587,49 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_NOFN(USI_9_8_PORT121, PWM1, SEL_USI_9_8_00),
PINMUX_IPSR_NOFN(USI_9_8_PORT121, USI4_DO, SEL_USI_9_8_01),
/* V20 */
- PINMUX_DATA(NTSC_CLK_MARK, FN_NTSC_CLK),
+ PINMUX_SINGLE(NTSC_CLK),
/* P20 */
- PINMUX_DATA(NTSC_DATA0_MARK, FN_NTSC_DATA0),
+ PINMUX_SINGLE(NTSC_DATA0),
/* P18 */
- PINMUX_DATA(NTSC_DATA1_MARK, FN_NTSC_DATA1),
+ PINMUX_SINGLE(NTSC_DATA1),
/* R20 */
- PINMUX_DATA(NTSC_DATA2_MARK, FN_NTSC_DATA2),
+ PINMUX_SINGLE(NTSC_DATA2),
/* R18 */
- PINMUX_DATA(NTSC_DATA3_MARK, FN_NTSC_DATA3),
+ PINMUX_SINGLE(NTSC_DATA3),
/* T20 */
- PINMUX_DATA(NTSC_DATA4_MARK, FN_NTSC_DATA4),
+ PINMUX_SINGLE(NTSC_DATA4),
/* GPRS3 */
/* T18 */
- PINMUX_DATA(NTSC_DATA5_MARK, FN_NTSC_DATA5),
+ PINMUX_SINGLE(NTSC_DATA5),
/* U20 */
- PINMUX_DATA(NTSC_DATA6_MARK, FN_NTSC_DATA6),
+ PINMUX_SINGLE(NTSC_DATA6),
/* U18 */
- PINMUX_DATA(NTSC_DATA7_MARK, FN_NTSC_DATA7),
+ PINMUX_SINGLE(NTSC_DATA7),
/* W23 */
- PINMUX_DATA(CAM_CLKO_MARK, FN_CAM_CLKO),
+ PINMUX_SINGLE(CAM_CLKO),
/* Y23 */
- PINMUX_DATA(CAM_CLKI_MARK, FN_CAM_CLKI),
+ PINMUX_SINGLE(CAM_CLKI),
/* W22 */
- PINMUX_DATA(CAM_VS_MARK, FN_CAM_VS),
+ PINMUX_SINGLE(CAM_VS),
/* V21 */
- PINMUX_DATA(CAM_HS_MARK, FN_CAM_HS),
+ PINMUX_SINGLE(CAM_HS),
/* T21 */
- PINMUX_DATA(CAM_YUV0_MARK, FN_CAM_YUV0),
+ PINMUX_SINGLE(CAM_YUV0),
/* T22 */
- PINMUX_DATA(CAM_YUV1_MARK, FN_CAM_YUV1),
+ PINMUX_SINGLE(CAM_YUV1),
/* T23 */
- PINMUX_DATA(CAM_YUV2_MARK, FN_CAM_YUV2),
+ PINMUX_SINGLE(CAM_YUV2),
/* U21 */
- PINMUX_DATA(CAM_YUV3_MARK, FN_CAM_YUV3),
+ PINMUX_SINGLE(CAM_YUV3),
/* U22 */
- PINMUX_DATA(CAM_YUV4_MARK, FN_CAM_YUV4),
+ PINMUX_SINGLE(CAM_YUV4),
/* U23 */
- PINMUX_DATA(CAM_YUV5_MARK, FN_CAM_YUV5),
+ PINMUX_SINGLE(CAM_YUV5),
/* V22 */
- PINMUX_DATA(CAM_YUV6_MARK, FN_CAM_YUV6),
+ PINMUX_SINGLE(CAM_YUV6),
/* V23 */
- PINMUX_DATA(CAM_YUV7_MARK, FN_CAM_YUV7),
+ PINMUX_SINGLE(CAM_YUV7),
/* K22 */
PINMUX_IPSR_NOFN(HSI_1_0_PORT143, USI5_CLK_B, SEL_HSI_1_0_01),
/* K23 */
@@ -647,17 +647,17 @@ static const u16 pinmux_data[] = {
/* M22 */
PINMUX_IPSR_NOFN(HSI_1_0_PORT150, USI5_DI_B, SEL_HSI_1_0_01),
/* D13 */
- PINMUX_DATA(JT_TDO_MARK, FN_JT_TDO),
+ PINMUX_SINGLE(JT_TDO),
/* F13 */
- PINMUX_DATA(JT_TDOEN_MARK, FN_JT_TDOEN),
+ PINMUX_SINGLE(JT_TDOEN),
/* AA12 */
- PINMUX_DATA(USB_VBUS_MARK, FN_USB_VBUS),
+ PINMUX_SINGLE(USB_VBUS),
/* A12 */
- PINMUX_DATA(LOWPWR_MARK, FN_LOWPWR),
+ PINMUX_SINGLE(LOWPWR),
/* Y11 */
- PINMUX_DATA(UART1_RX_MARK, FN_UART1_RX),
+ PINMUX_SINGLE(UART1_RX),
/* Y10 */
- PINMUX_DATA(UART1_TX_MARK, FN_UART1_TX),
+ PINMUX_SINGLE(UART1_TX),
/* AA10 */
PINMUX_IPSR_NOFN(UART_1_0_PORT157, UART1_CTSB, SEL_UART_1_0_00),
PINMUX_IPSR_NOFN(UART_1_0_PORT157, UART2_RX, SEL_UART_1_0_01),
@@ -749,7 +749,7 @@ static const unsigned int cf_ctrl_mux[] = {
};
static const unsigned int cf_data8_pins[] = {
- /* CF_D[0:8] */
+ /* CF_D[0:7] */
77, 78, 79, 80,
81, 82, 83, 84,
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c
index 279e9dd442e4..7f7c8a6e76e8 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7740.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7740.c
@@ -2214,7 +2214,7 @@ static const unsigned int lcd1_data9_mux[] = {
LCD1_D8_MARK,
};
static const unsigned int lcd1_data12_pins[] = {
- /* D[0:12] */
+ /* D[0:11] */
4, 3, 2, 1, 0, 91, 92, 23,
93, 94, 21, 201,
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
index bbd35dc1a0c4..ad09a670c2ff 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7778.c
@@ -548,17 +548,17 @@ enum {
static const u16 pinmux_data[] = {
PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */
- PINMUX_DATA(PENC0_MARK, FN_PENC0),
- PINMUX_DATA(PENC1_MARK, FN_PENC1),
- PINMUX_DATA(A1_MARK, FN_A1),
- PINMUX_DATA(A2_MARK, FN_A2),
- PINMUX_DATA(A3_MARK, FN_A3),
- PINMUX_DATA(WE0_MARK, FN_WE0),
- PINMUX_DATA(AUDIO_CLKA_MARK, FN_AUDIO_CLKA),
- PINMUX_DATA(AUDIO_CLKB_MARK, FN_AUDIO_CLKB),
- PINMUX_DATA(SSI_SCK34_MARK, FN_SSI_SCK34),
- PINMUX_DATA(AVS1_MARK, FN_AVS1),
- PINMUX_DATA(AVS2_MARK, FN_AVS2),
+ PINMUX_SINGLE(PENC0),
+ PINMUX_SINGLE(PENC1),
+ PINMUX_SINGLE(A1),
+ PINMUX_SINGLE(A2),
+ PINMUX_SINGLE(A3),
+ PINMUX_SINGLE(WE0),
+ PINMUX_SINGLE(AUDIO_CLKA),
+ PINMUX_SINGLE(AUDIO_CLKB),
+ PINMUX_SINGLE(SSI_SCK34),
+ PINMUX_SINGLE(AVS1),
+ PINMUX_SINGLE(AVS2),
/* IPSR0 */
PINMUX_IPSR_DATA(IP0_1_0, PRESETOUT),
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7779.c b/drivers/pinctrl/sh-pfc/pfc-r8a7779.c
index ed4e0788035c..bd17eccb6a89 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7779.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7779.c
@@ -23,13 +23,6 @@
#include "sh_pfc.h"
-#define PORT_GP_9(bank, fn, sfx) \
- PORT_GP_1(bank, 0, fn, sfx), PORT_GP_1(bank, 1, fn, sfx), \
- PORT_GP_1(bank, 2, fn, sfx), PORT_GP_1(bank, 3, fn, sfx), \
- PORT_GP_1(bank, 4, fn, sfx), PORT_GP_1(bank, 5, fn, sfx), \
- PORT_GP_1(bank, 6, fn, sfx), PORT_GP_1(bank, 7, fn, sfx), \
- PORT_GP_1(bank, 8, fn, sfx)
-
#define CPU_ALL_PORT(fn, sfx) \
PORT_GP_32(0, fn, sfx), \
PORT_GP_32(1, fn, sfx), \
@@ -609,14 +602,14 @@ enum {
static const u16 pinmux_data[] = {
PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */
- PINMUX_DATA(AVS1_MARK, FN_AVS1),
- PINMUX_DATA(AVS1_MARK, FN_AVS1),
- PINMUX_DATA(A17_MARK, FN_A17),
- PINMUX_DATA(A18_MARK, FN_A18),
- PINMUX_DATA(A19_MARK, FN_A19),
+ PINMUX_SINGLE(AVS1),
+ PINMUX_SINGLE(AVS1),
+ PINMUX_SINGLE(A17),
+ PINMUX_SINGLE(A18),
+ PINMUX_SINGLE(A19),
- PINMUX_DATA(USB_PENC0_MARK, FN_USB_PENC0),
- PINMUX_DATA(USB_PENC1_MARK, FN_USB_PENC1),
+ PINMUX_SINGLE(USB_PENC0),
+ PINMUX_SINGLE(USB_PENC1),
PINMUX_IPSR_DATA(IP0_2_0, USB_PENC2),
PINMUX_IPSR_MSEL(IP0_2_0, SCK0, SEL_SCIF0_0),
@@ -2289,6 +2282,35 @@ static const unsigned int scif5_clk_d_pins[] = {
static const unsigned int scif5_clk_d_mux[] = {
SCK5_D_MARK,
};
+/* - SCIF Clock ------------------------------------------------------------- */
+static const unsigned int scif_clk_pins[] = {
+ /* SCIF_CLK */
+ RCAR_GP_PIN(4, 28),
+};
+static const unsigned int scif_clk_mux[] = {
+ SCIF_CLK_MARK,
+};
+static const unsigned int scif_clk_b_pins[] = {
+ /* SCIF_CLK */
+ RCAR_GP_PIN(4, 5),
+};
+static const unsigned int scif_clk_b_mux[] = {
+ SCIF_CLK_B_MARK,
+};
+static const unsigned int scif_clk_c_pins[] = {
+ /* SCIF_CLK */
+ RCAR_GP_PIN(4, 18),
+};
+static const unsigned int scif_clk_c_mux[] = {
+ SCIF_CLK_C_MARK,
+};
+static const unsigned int scif_clk_d_pins[] = {
+ /* SCIF_CLK */
+ RCAR_GP_PIN(2, 29),
+};
+static const unsigned int scif_clk_d_mux[] = {
+ SCIF_CLK_D_MARK,
+};
/* - SDHI0 ------------------------------------------------------------------ */
static const unsigned int sdhi0_data1_pins[] = {
/* D0 */
@@ -2700,6 +2722,10 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(scif5_clk_c),
SH_PFC_PIN_GROUP(scif5_data_d),
SH_PFC_PIN_GROUP(scif5_clk_d),
+ SH_PFC_PIN_GROUP(scif_clk),
+ SH_PFC_PIN_GROUP(scif_clk_b),
+ SH_PFC_PIN_GROUP(scif_clk_c),
+ SH_PFC_PIN_GROUP(scif_clk_d),
SH_PFC_PIN_GROUP(sdhi0_data1),
SH_PFC_PIN_GROUP(sdhi0_data4),
SH_PFC_PIN_GROUP(sdhi0_ctrl),
@@ -2909,6 +2935,13 @@ static const char * const scif5_groups[] = {
"scif5_clk_d",
};
+static const char * const scif_clk_groups[] = {
+ "scif_clk",
+ "scif_clk_b",
+ "scif_clk_c",
+ "scif_clk_d",
+};
+
static const char * const sdhi0_groups[] = {
"sdhi0_data1",
"sdhi0_data4",
@@ -3004,6 +3037,7 @@ static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(scif3),
SH_PFC_FUNCTION(scif4),
SH_PFC_FUNCTION(scif5),
+ SH_PFC_FUNCTION(scif_clk),
SH_PFC_FUNCTION(usb0),
SH_PFC_FUNCTION(usb1),
SH_PFC_FUNCTION(usb2),
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
index d9924b0d53b7..a8b629bc7a55 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
@@ -26,23 +26,6 @@
#include "core.h"
#include "sh_pfc.h"
-#define PORT_GP_30(bank, fn, sfx) \
- PORT_GP_1(bank, 0, fn, sfx), PORT_GP_1(bank, 1, fn, sfx), \
- PORT_GP_1(bank, 2, fn, sfx), PORT_GP_1(bank, 3, fn, sfx), \
- PORT_GP_1(bank, 4, fn, sfx), PORT_GP_1(bank, 5, fn, sfx), \
- PORT_GP_1(bank, 6, fn, sfx), PORT_GP_1(bank, 7, fn, sfx), \
- PORT_GP_1(bank, 8, fn, sfx), PORT_GP_1(bank, 9, fn, sfx), \
- PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx), \
- PORT_GP_1(bank, 12, fn, sfx), PORT_GP_1(bank, 13, fn, sfx), \
- PORT_GP_1(bank, 14, fn, sfx), PORT_GP_1(bank, 15, fn, sfx), \
- PORT_GP_1(bank, 16, fn, sfx), PORT_GP_1(bank, 17, fn, sfx), \
- PORT_GP_1(bank, 18, fn, sfx), PORT_GP_1(bank, 19, fn, sfx), \
- PORT_GP_1(bank, 20, fn, sfx), PORT_GP_1(bank, 21, fn, sfx), \
- PORT_GP_1(bank, 22, fn, sfx), PORT_GP_1(bank, 23, fn, sfx), \
- PORT_GP_1(bank, 24, fn, sfx), PORT_GP_1(bank, 25, fn, sfx), \
- PORT_GP_1(bank, 26, fn, sfx), PORT_GP_1(bank, 27, fn, sfx), \
- PORT_GP_1(bank, 28, fn, sfx), PORT_GP_1(bank, 29, fn, sfx)
-
#define CPU_ALL_PORT(fn, sfx) \
PORT_GP_32(0, fn, sfx), \
PORT_GP_30(1, fn, sfx), \
@@ -806,15 +789,15 @@ enum {
static const u16 pinmux_data[] = {
PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */
- PINMUX_DATA(VI1_DATA7_VI1_B7_MARK, FN_VI1_DATA7_VI1_B7),
- PINMUX_DATA(USB0_PWEN_MARK, FN_USB0_PWEN),
- PINMUX_DATA(USB0_OVC_VBUS_MARK, FN_USB0_OVC_VBUS),
- PINMUX_DATA(USB2_PWEN_MARK, FN_USB2_PWEN),
- PINMUX_DATA(USB2_OVC_MARK, FN_USB2_OVC),
- PINMUX_DATA(AVS1_MARK, FN_AVS1),
- PINMUX_DATA(AVS2_MARK, FN_AVS2),
- PINMUX_DATA(DU_DOTCLKIN0_MARK, FN_DU_DOTCLKIN0),
- PINMUX_DATA(DU_DOTCLKIN2_MARK, FN_DU_DOTCLKIN2),
+ PINMUX_SINGLE(VI1_DATA7_VI1_B7),
+ PINMUX_SINGLE(USB0_PWEN),
+ PINMUX_SINGLE(USB0_OVC_VBUS),
+ PINMUX_SINGLE(USB2_PWEN),
+ PINMUX_SINGLE(USB2_OVC),
+ PINMUX_SINGLE(AVS1),
+ PINMUX_SINGLE(AVS2),
+ PINMUX_SINGLE(DU_DOTCLKIN0),
+ PINMUX_SINGLE(DU_DOTCLKIN2),
PINMUX_IPSR_DATA(IP0_2_0, D0),
PINMUX_IPSR_MSEL(IP0_2_0, MSIOF3_SCK_B, SEL_SOF3_1),
@@ -3236,6 +3219,21 @@ static const unsigned int scifb2_data_c_pins[] = {
static const unsigned int scifb2_data_c_mux[] = {
SCIFB2_RXD_C_MARK, SCIFB2_TXD_C_MARK,
};
+/* - SCIF Clock ------------------------------------------------------------- */
+static const unsigned int scif_clk_pins[] = {
+ /* SCIF_CLK */
+ RCAR_GP_PIN(4, 26),
+};
+static const unsigned int scif_clk_mux[] = {
+ SCIF_CLK_MARK,
+};
+static const unsigned int scif_clk_b_pins[] = {
+ /* SCIF_CLK */
+ RCAR_GP_PIN(5, 4),
+};
+static const unsigned int scif_clk_b_mux[] = {
+ SCIF_CLK_B_MARK,
+};
/* - SDHI0 ------------------------------------------------------------------ */
static const unsigned int sdhi0_data1_pins[] = {
/* D0 */
@@ -4139,6 +4137,8 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(scifb2_clk_b),
SH_PFC_PIN_GROUP(scifb2_ctrl_b),
SH_PFC_PIN_GROUP(scifb2_data_c),
+ SH_PFC_PIN_GROUP(scif_clk),
+ SH_PFC_PIN_GROUP(scif_clk_b),
SH_PFC_PIN_GROUP(sdhi0_data1),
SH_PFC_PIN_GROUP(sdhi0_data4),
SH_PFC_PIN_GROUP(sdhi0_ctrl),
@@ -4555,6 +4555,11 @@ static const char * const scifb2_groups[] = {
"scifb2_data_c",
};
+static const char * const scif_clk_groups[] = {
+ "scif_clk",
+ "scif_clk_b",
+};
+
static const char * const sdhi0_groups[] = {
"sdhi0_data1",
"sdhi0_data4",
@@ -4729,6 +4734,7 @@ static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(scifb0),
SH_PFC_FUNCTION(scifb1),
SH_PFC_FUNCTION(scifb2),
+ SH_PFC_FUNCTION(scif_clk),
SH_PFC_FUNCTION(sdhi0),
SH_PFC_FUNCTION(sdhi1),
SH_PFC_FUNCTION(sdhi2),
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
index 87a4f44147c1..4cfbb94ad5d0 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7791.c
@@ -2,6 +2,7 @@
* r8a7791 processor support - PFC hardware block.
*
* Copyright (C) 2013 Renesas Electronics Corporation
+ * Copyright (C) 2014-2015 Cogent Embedded, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
@@ -13,21 +14,6 @@
#include "core.h"
#include "sh_pfc.h"
-#define PORT_GP_26(bank, fn, sfx) \
- PORT_GP_1(bank, 0, fn, sfx), PORT_GP_1(bank, 1, fn, sfx), \
- PORT_GP_1(bank, 2, fn, sfx), PORT_GP_1(bank, 3, fn, sfx), \
- PORT_GP_1(bank, 4, fn, sfx), PORT_GP_1(bank, 5, fn, sfx), \
- PORT_GP_1(bank, 6, fn, sfx), PORT_GP_1(bank, 7, fn, sfx), \
- PORT_GP_1(bank, 8, fn, sfx), PORT_GP_1(bank, 9, fn, sfx), \
- PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx), \
- PORT_GP_1(bank, 12, fn, sfx), PORT_GP_1(bank, 13, fn, sfx), \
- PORT_GP_1(bank, 14, fn, sfx), PORT_GP_1(bank, 15, fn, sfx), \
- PORT_GP_1(bank, 16, fn, sfx), PORT_GP_1(bank, 17, fn, sfx), \
- PORT_GP_1(bank, 18, fn, sfx), PORT_GP_1(bank, 19, fn, sfx), \
- PORT_GP_1(bank, 20, fn, sfx), PORT_GP_1(bank, 21, fn, sfx), \
- PORT_GP_1(bank, 22, fn, sfx), PORT_GP_1(bank, 23, fn, sfx), \
- PORT_GP_1(bank, 24, fn, sfx), PORT_GP_1(bank, 25, fn, sfx)
-
#define CPU_ALL_PORT(fn, sfx) \
PORT_GP_32(0, fn, sfx), \
PORT_GP_26(1, fn, sfx), \
@@ -787,23 +773,23 @@ enum {
static const u16 pinmux_data[] = {
PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */
- PINMUX_DATA(EX_CS0_N_MARK, FN_EX_CS0_N),
- PINMUX_DATA(RD_N_MARK, FN_RD_N),
- PINMUX_DATA(AUDIO_CLKA_MARK, FN_AUDIO_CLKA),
- PINMUX_DATA(VI0_CLK_MARK, FN_VI0_CLK),
- PINMUX_DATA(VI0_DATA0_VI0_B0_MARK, FN_VI0_DATA0_VI0_B0),
- PINMUX_DATA(VI0_DATA1_VI0_B1_MARK, FN_VI0_DATA1_VI0_B1),
- PINMUX_DATA(VI0_DATA2_VI0_B2_MARK, FN_VI0_DATA2_VI0_B2),
- PINMUX_DATA(VI0_DATA4_VI0_B4_MARK, FN_VI0_DATA4_VI0_B4),
- PINMUX_DATA(VI0_DATA5_VI0_B5_MARK, FN_VI0_DATA5_VI0_B5),
- PINMUX_DATA(VI0_DATA6_VI0_B6_MARK, FN_VI0_DATA6_VI0_B6),
- PINMUX_DATA(VI0_DATA7_VI0_B7_MARK, FN_VI0_DATA7_VI0_B7),
- PINMUX_DATA(USB0_PWEN_MARK, FN_USB0_PWEN),
- PINMUX_DATA(USB0_OVC_MARK, FN_USB0_OVC),
- PINMUX_DATA(USB1_PWEN_MARK, FN_USB1_PWEN),
- PINMUX_DATA(USB1_OVC_MARK, FN_USB1_OVC),
- PINMUX_DATA(DU0_DOTCLKIN_MARK, FN_DU0_DOTCLKIN),
- PINMUX_DATA(SD1_CLK_MARK, FN_SD1_CLK),
+ PINMUX_SINGLE(EX_CS0_N),
+ PINMUX_SINGLE(RD_N),
+ PINMUX_SINGLE(AUDIO_CLKA),
+ PINMUX_SINGLE(VI0_CLK),
+ PINMUX_SINGLE(VI0_DATA0_VI0_B0),
+ PINMUX_SINGLE(VI0_DATA1_VI0_B1),
+ PINMUX_SINGLE(VI0_DATA2_VI0_B2),
+ PINMUX_SINGLE(VI0_DATA4_VI0_B4),
+ PINMUX_SINGLE(VI0_DATA5_VI0_B5),
+ PINMUX_SINGLE(VI0_DATA6_VI0_B6),
+ PINMUX_SINGLE(VI0_DATA7_VI0_B7),
+ PINMUX_SINGLE(USB0_PWEN),
+ PINMUX_SINGLE(USB0_OVC),
+ PINMUX_SINGLE(USB1_PWEN),
+ PINMUX_SINGLE(USB1_OVC),
+ PINMUX_SINGLE(DU0_DOTCLKIN),
+ PINMUX_SINGLE(SD1_CLK),
/* IPSR0 */
PINMUX_IPSR_DATA(IP0_0, D0),
@@ -1740,6 +1726,82 @@ static const unsigned int audio_clkout_mux[] = {
AUDIO_CLKOUT_MARK,
};
+/* - AVB -------------------------------------------------------------------- */
+static const unsigned int avb_link_pins[] = {
+ RCAR_GP_PIN(5, 14),
+};
+static const unsigned int avb_link_mux[] = {
+ AVB_LINK_MARK,
+};
+static const unsigned int avb_magic_pins[] = {
+ RCAR_GP_PIN(5, 11),
+};
+static const unsigned int avb_magic_mux[] = {
+ AVB_MAGIC_MARK,
+};
+static const unsigned int avb_phy_int_pins[] = {
+ RCAR_GP_PIN(5, 16),
+};
+static const unsigned int avb_phy_int_mux[] = {
+ AVB_PHY_INT_MARK,
+};
+static const unsigned int avb_mdio_pins[] = {
+ RCAR_GP_PIN(5, 12), RCAR_GP_PIN(5, 9),
+};
+static const unsigned int avb_mdio_mux[] = {
+ AVB_MDC_MARK, AVB_MDIO_MARK,
+};
+static const unsigned int avb_mii_pins[] = {
+ RCAR_GP_PIN(5, 18), RCAR_GP_PIN(5, 19), RCAR_GP_PIN(5, 20),
+ RCAR_GP_PIN(5, 21),
+
+ RCAR_GP_PIN(5, 0), RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 2),
+ RCAR_GP_PIN(5, 3),
+
+ RCAR_GP_PIN(5, 8), RCAR_GP_PIN(5, 13), RCAR_GP_PIN(5, 10),
+ RCAR_GP_PIN(5, 15), RCAR_GP_PIN(5, 26), RCAR_GP_PIN(5, 27),
+ RCAR_GP_PIN(5, 28), RCAR_GP_PIN(5, 29),
+};
+static const unsigned int avb_mii_mux[] = {
+ AVB_TXD0_MARK, AVB_TXD1_MARK, AVB_TXD2_MARK,
+ AVB_TXD3_MARK,
+
+ AVB_RXD0_MARK, AVB_RXD1_MARK, AVB_RXD2_MARK,
+ AVB_RXD3_MARK,
+
+ AVB_RX_ER_MARK, AVB_RX_CLK_MARK, AVB_RX_DV_MARK,
+ AVB_CRS_MARK, AVB_TX_EN_MARK, AVB_TX_ER_MARK,
+ AVB_TX_CLK_MARK, AVB_COL_MARK,
+};
+static const unsigned int avb_gmii_pins[] = {
+ RCAR_GP_PIN(5, 18), RCAR_GP_PIN(5, 19), RCAR_GP_PIN(5, 20),
+ RCAR_GP_PIN(5, 21), RCAR_GP_PIN(5, 22), RCAR_GP_PIN(5, 23),
+ RCAR_GP_PIN(5, 24), RCAR_GP_PIN(5, 25),
+
+ RCAR_GP_PIN(5, 0), RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 2),
+ RCAR_GP_PIN(5, 3), RCAR_GP_PIN(5, 4), RCAR_GP_PIN(5, 5),
+ RCAR_GP_PIN(5, 6), RCAR_GP_PIN(5, 7),
+
+ RCAR_GP_PIN(5, 8), RCAR_GP_PIN(5, 13), RCAR_GP_PIN(5, 10),
+ RCAR_GP_PIN(5, 15), RCAR_GP_PIN(5, 30), RCAR_GP_PIN(5, 17),
+ RCAR_GP_PIN(5, 26), RCAR_GP_PIN(5, 27), RCAR_GP_PIN(5, 28),
+ RCAR_GP_PIN(5, 29),
+};
+static const unsigned int avb_gmii_mux[] = {
+ AVB_TXD0_MARK, AVB_TXD1_MARK, AVB_TXD2_MARK,
+ AVB_TXD3_MARK, AVB_TXD4_MARK, AVB_TXD5_MARK,
+ AVB_TXD6_MARK, AVB_TXD7_MARK,
+
+ AVB_RXD0_MARK, AVB_RXD1_MARK, AVB_RXD2_MARK,
+ AVB_RXD3_MARK, AVB_RXD4_MARK, AVB_RXD5_MARK,
+ AVB_RXD6_MARK, AVB_RXD7_MARK,
+
+ AVB_RX_ER_MARK, AVB_RX_CLK_MARK, AVB_RX_DV_MARK,
+ AVB_CRS_MARK, AVB_GTX_CLK_MARK, AVB_GTXREFCLK_MARK,
+ AVB_TX_EN_MARK, AVB_TX_ER_MARK, AVB_TX_CLK_MARK,
+ AVB_COL_MARK,
+};
+
/* - CAN -------------------------------------------------------------------- */
static const unsigned int can0_data_pins[] = {
@@ -3602,6 +3664,23 @@ static const unsigned int scifb2_data_d_pins[] = {
static const unsigned int scifb2_data_d_mux[] = {
SCIFB2_RXD_D_MARK, SCIFB2_TXD_D_MARK,
};
+
+/* - SCIF Clock ------------------------------------------------------------- */
+static const unsigned int scif_clk_pins[] = {
+ /* SCIF_CLK */
+ RCAR_GP_PIN(2, 29),
+};
+static const unsigned int scif_clk_mux[] = {
+ SCIF_CLK_MARK,
+};
+static const unsigned int scif_clk_b_pins[] = {
+ /* SCIF_CLK */
+ RCAR_GP_PIN(7, 19),
+};
+static const unsigned int scif_clk_b_mux[] = {
+ SCIF_CLK_B_MARK,
+};
+
/* - SDHI0 ------------------------------------------------------------------ */
static const unsigned int sdhi0_data1_pins[] = {
/* D0 */
@@ -4258,6 +4337,12 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(audio_clk_b_b),
SH_PFC_PIN_GROUP(audio_clk_c),
SH_PFC_PIN_GROUP(audio_clkout),
+ SH_PFC_PIN_GROUP(avb_link),
+ SH_PFC_PIN_GROUP(avb_magic),
+ SH_PFC_PIN_GROUP(avb_phy_int),
+ SH_PFC_PIN_GROUP(avb_mdio),
+ SH_PFC_PIN_GROUP(avb_mii),
+ SH_PFC_PIN_GROUP(avb_gmii),
SH_PFC_PIN_GROUP(can0_data),
SH_PFC_PIN_GROUP(can0_data_b),
SH_PFC_PIN_GROUP(can0_data_c),
@@ -4510,6 +4595,8 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(scifb2_data_c),
SH_PFC_PIN_GROUP(scifb2_clk_c),
SH_PFC_PIN_GROUP(scifb2_data_d),
+ SH_PFC_PIN_GROUP(scif_clk),
+ SH_PFC_PIN_GROUP(scif_clk_b),
SH_PFC_PIN_GROUP(sdhi0_data1),
SH_PFC_PIN_GROUP(sdhi0_data4),
SH_PFC_PIN_GROUP(sdhi0_ctrl),
@@ -4597,6 +4684,15 @@ static const char * const audio_clk_groups[] = {
"audio_clkout",
};
+static const char * const avb_groups[] = {
+ "avb_link",
+ "avb_magic",
+ "avb_phy_int",
+ "avb_mdio",
+ "avb_mii",
+ "avb_gmii",
+};
+
static const char * const can0_groups[] = {
"can0_data",
"can0_data_b",
@@ -4976,6 +5072,11 @@ static const char * const scifb2_groups[] = {
"scifb2_data_d",
};
+static const char * const scif_clk_groups[] = {
+ "scif_clk",
+ "scif_clk_b",
+};
+
static const char * const sdhi0_groups[] = {
"sdhi0_data1",
"sdhi0_data4",
@@ -5081,6 +5182,7 @@ static const char * const vin2_groups[] = {
static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(audio_clk),
+ SH_PFC_FUNCTION(avb),
SH_PFC_FUNCTION(can0),
SH_PFC_FUNCTION(can1),
SH_PFC_FUNCTION(du),
@@ -5126,6 +5228,7 @@ static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(scifb0),
SH_PFC_FUNCTION(scifb1),
SH_PFC_FUNCTION(scifb2),
+ SH_PFC_FUNCTION(scif_clk),
SH_PFC_FUNCTION(sdhi0),
SH_PFC_FUNCTION(sdhi1),
SH_PFC_FUNCTION(sdhi2),
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c
index 086f6798b129..3718c7846bfd 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7794.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7794.c
@@ -15,25 +15,6 @@
#include "core.h"
#include "sh_pfc.h"
-#define PORT_GP_26(bank, fn, sfx) \
- PORT_GP_1(bank, 0, fn, sfx), PORT_GP_1(bank, 1, fn, sfx), \
- PORT_GP_1(bank, 2, fn, sfx), PORT_GP_1(bank, 3, fn, sfx), \
- PORT_GP_1(bank, 4, fn, sfx), PORT_GP_1(bank, 5, fn, sfx), \
- PORT_GP_1(bank, 6, fn, sfx), PORT_GP_1(bank, 7, fn, sfx), \
- PORT_GP_1(bank, 8, fn, sfx), PORT_GP_1(bank, 9, fn, sfx), \
- PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx), \
- PORT_GP_1(bank, 12, fn, sfx), PORT_GP_1(bank, 13, fn, sfx), \
- PORT_GP_1(bank, 14, fn, sfx), PORT_GP_1(bank, 15, fn, sfx), \
- PORT_GP_1(bank, 16, fn, sfx), PORT_GP_1(bank, 17, fn, sfx), \
- PORT_GP_1(bank, 18, fn, sfx), PORT_GP_1(bank, 19, fn, sfx), \
- PORT_GP_1(bank, 20, fn, sfx), PORT_GP_1(bank, 21, fn, sfx), \
- PORT_GP_1(bank, 22, fn, sfx), PORT_GP_1(bank, 23, fn, sfx), \
- PORT_GP_1(bank, 24, fn, sfx), PORT_GP_1(bank, 25, fn, sfx)
-
-#define PORT_GP_28(bank, fn, sfx) \
- PORT_GP_26(bank, fn, sfx), \
- PORT_GP_1(bank, 26, fn, sfx), PORT_GP_1(bank, 27, fn, sfx)
-
#define CPU_ALL_PORT(fn, sfx) \
PORT_GP_32(0, fn, sfx), \
PORT_GP_26(1, fn, sfx), \
@@ -618,28 +599,28 @@ enum {
static const u16 pinmux_data[] = {
PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */
- PINMUX_DATA(A2_MARK, FN_A2),
- PINMUX_DATA(WE0_N_MARK, FN_WE0_N),
- PINMUX_DATA(WE1_N_MARK, FN_WE1_N),
- PINMUX_DATA(DACK0_MARK, FN_DACK0),
- PINMUX_DATA(USB0_PWEN_MARK, FN_USB0_PWEN),
- PINMUX_DATA(USB0_OVC_MARK, FN_USB0_OVC),
- PINMUX_DATA(USB1_PWEN_MARK, FN_USB1_PWEN),
- PINMUX_DATA(USB1_OVC_MARK, FN_USB1_OVC),
- PINMUX_DATA(SD0_CLK_MARK, FN_SD0_CLK),
- PINMUX_DATA(SD0_CMD_MARK, FN_SD0_CMD),
- PINMUX_DATA(SD0_DATA0_MARK, FN_SD0_DATA0),
- PINMUX_DATA(SD0_DATA1_MARK, FN_SD0_DATA1),
- PINMUX_DATA(SD0_DATA2_MARK, FN_SD0_DATA2),
- PINMUX_DATA(SD0_DATA3_MARK, FN_SD0_DATA3),
- PINMUX_DATA(SD0_CD_MARK, FN_SD0_CD),
- PINMUX_DATA(SD0_WP_MARK, FN_SD0_WP),
- PINMUX_DATA(SD1_CLK_MARK, FN_SD1_CLK),
- PINMUX_DATA(SD1_CMD_MARK, FN_SD1_CMD),
- PINMUX_DATA(SD1_DATA0_MARK, FN_SD1_DATA0),
- PINMUX_DATA(SD1_DATA1_MARK, FN_SD1_DATA1),
- PINMUX_DATA(SD1_DATA2_MARK, FN_SD1_DATA2),
- PINMUX_DATA(SD1_DATA3_MARK, FN_SD1_DATA3),
+ PINMUX_SINGLE(A2),
+ PINMUX_SINGLE(WE0_N),
+ PINMUX_SINGLE(WE1_N),
+ PINMUX_SINGLE(DACK0),
+ PINMUX_SINGLE(USB0_PWEN),
+ PINMUX_SINGLE(USB0_OVC),
+ PINMUX_SINGLE(USB1_PWEN),
+ PINMUX_SINGLE(USB1_OVC),
+ PINMUX_SINGLE(SD0_CLK),
+ PINMUX_SINGLE(SD0_CMD),
+ PINMUX_SINGLE(SD0_DATA0),
+ PINMUX_SINGLE(SD0_DATA1),
+ PINMUX_SINGLE(SD0_DATA2),
+ PINMUX_SINGLE(SD0_DATA3),
+ PINMUX_SINGLE(SD0_CD),
+ PINMUX_SINGLE(SD0_WP),
+ PINMUX_SINGLE(SD1_CLK),
+ PINMUX_SINGLE(SD1_CMD),
+ PINMUX_SINGLE(SD1_DATA0),
+ PINMUX_SINGLE(SD1_DATA1),
+ PINMUX_SINGLE(SD1_DATA2),
+ PINMUX_SINGLE(SD1_DATA3),
/* IPSR0 */
PINMUX_IPSR_DATA(IP0_0, SD1_CD),
@@ -2644,6 +2625,21 @@ static const unsigned int scifb2_ctrl_pins[] = {
static const unsigned int scifb2_ctrl_mux[] = {
SCIFB2_RTS_N_MARK, SCIFB2_CTS_N_MARK,
};
+/* - SCIF Clock ------------------------------------------------------------- */
+static const unsigned int scif_clk_pins[] = {
+ /* SCIF_CLK */
+ RCAR_GP_PIN(1, 23),
+};
+static const unsigned int scif_clk_mux[] = {
+ SCIF_CLK_MARK,
+};
+static const unsigned int scif_clk_b_pins[] = {
+ /* SCIF_CLK */
+ RCAR_GP_PIN(3, 29),
+};
+static const unsigned int scif_clk_b_mux[] = {
+ SCIF_CLK_B_MARK,
+};
/* - SDHI0 ------------------------------------------------------------------ */
static const unsigned int sdhi0_data1_pins[] = {
/* D0 */
@@ -3071,6 +3067,8 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(scifb2_data),
SH_PFC_PIN_GROUP(scifb2_clk),
SH_PFC_PIN_GROUP(scifb2_ctrl),
+ SH_PFC_PIN_GROUP(scif_clk),
+ SH_PFC_PIN_GROUP(scif_clk_b),
SH_PFC_PIN_GROUP(sdhi0_data1),
SH_PFC_PIN_GROUP(sdhi0_data4),
SH_PFC_PIN_GROUP(sdhi0_ctrl),
@@ -3354,6 +3352,11 @@ static const char * const scifb2_groups[] = {
"scifb2_ctrl",
};
+static const char * const scif_clk_groups[] = {
+ "scif_clk",
+ "scif_clk_b",
+};
+
static const char * const sdhi0_groups[] = {
"sdhi0_data1",
"sdhi0_data4",
@@ -3441,6 +3444,7 @@ static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(scifb0),
SH_PFC_FUNCTION(scifb1),
SH_PFC_FUNCTION(scifb2),
+ SH_PFC_FUNCTION(scif_clk),
SH_PFC_FUNCTION(sdhi0),
SH_PFC_FUNCTION(sdhi1),
SH_PFC_FUNCTION(sdhi2),
diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
index 7ddb2adfc5a5..ce4f5cdb0579 100644
--- a/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
+++ b/drivers/pinctrl/sh-pfc/pfc-r8a7795.c
@@ -13,46 +13,15 @@
#include "core.h"
#include "sh_pfc.h"
-#define PORT_GP_3(bank, fn, sfx) \
- PORT_GP_1(bank, 0, fn, sfx), PORT_GP_1(bank, 1, fn, sfx), \
- PORT_GP_1(bank, 2, fn, sfx), PORT_GP_1(bank, 3, fn, sfx)
-
-#define PORT_GP_14(bank, fn, sfx) \
- PORT_GP_3(bank, fn, sfx), \
- PORT_GP_1(bank, 4, fn, sfx), PORT_GP_1(bank, 5, fn, sfx), \
- PORT_GP_1(bank, 6, fn, sfx), PORT_GP_1(bank, 7, fn, sfx), \
- PORT_GP_1(bank, 8, fn, sfx), PORT_GP_1(bank, 9, fn, sfx), \
- PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx), \
- PORT_GP_1(bank, 12, fn, sfx), PORT_GP_1(bank, 13, fn, sfx), \
- PORT_GP_1(bank, 14, fn, sfx)
-
-#define PORT_GP_15(bank, fn, sfx) \
- PORT_GP_14(bank, fn, sfx), PORT_GP_1(bank, 15, fn, sfx)
-
-#define PORT_GP_17(bank, fn, sfx) \
- PORT_GP_15(bank, fn, sfx), \
- PORT_GP_1(bank, 16, fn, sfx), PORT_GP_1(bank, 17, fn, sfx)
-
-#define PORT_GP_25(bank, fn, sfx) \
- PORT_GP_17(bank, fn, sfx), \
- PORT_GP_1(bank, 18, fn, sfx), PORT_GP_1(bank, 19, fn, sfx), \
- PORT_GP_1(bank, 20, fn, sfx), PORT_GP_1(bank, 21, fn, sfx), \
- PORT_GP_1(bank, 22, fn, sfx), PORT_GP_1(bank, 23, fn, sfx), \
- PORT_GP_1(bank, 24, fn, sfx), PORT_GP_1(bank, 25, fn, sfx)
-
-#define PORT_GP_27(bank, fn, sfx) \
- PORT_GP_25(bank, fn, sfx), \
- PORT_GP_1(bank, 26, fn, sfx), PORT_GP_1(bank, 27, fn, sfx)
-
#define CPU_ALL_PORT(fn, sfx) \
- PORT_GP_15(0, fn, sfx), \
- PORT_GP_27(1, fn, sfx), \
- PORT_GP_14(2, fn, sfx), \
- PORT_GP_15(3, fn, sfx), \
- PORT_GP_17(4, fn, sfx), \
- PORT_GP_25(5, fn, sfx), \
+ PORT_GP_16(0, fn, sfx), \
+ PORT_GP_28(1, fn, sfx), \
+ PORT_GP_15(2, fn, sfx), \
+ PORT_GP_16(3, fn, sfx), \
+ PORT_GP_18(4, fn, sfx), \
+ PORT_GP_26(5, fn, sfx), \
PORT_GP_32(6, fn, sfx), \
- PORT_GP_3(7, fn, sfx)
+ PORT_GP_4(7, fn, sfx)
/*
* F_() : just information
* FM() : macro for FN_xxx / xxx_MARK
@@ -495,7 +464,7 @@ FM(IP16_31_28) IP16_31_28
#define MOD_SEL1_13 FM(SEL_SCIF3_0) FM(SEL_SCIF3_1)
#define MOD_SEL1_12 FM(SEL_SCIF2_0) FM(SEL_SCIF2_1)
#define MOD_SEL1_11 FM(SEL_SCIF1_0) FM(SEL_SCIF1_1)
-#define MOD_SEL1_10 FM(SEL_SCIF_0) FM(SEL_SCIF_1)
+#define MOD_SEL1_10 FM(SEL_SATA_0) FM(SEL_SATA_1)
#define MOD_SEL1_9 FM(SEL_REMOCON_0) FM(SEL_REMOCON_1)
#define MOD_SEL1_6 FM(SEL_RCAN0_0) FM(SEL_RCAN0_1)
#define MOD_SEL1_5 FM(SEL_PWM6_0) FM(SEL_PWM6_1)
@@ -580,6 +549,25 @@ enum {
static const u16 pinmux_data[] = {
PINMUX_DATA_GP_ALL(),
+ PINMUX_SINGLE(AVS1),
+ PINMUX_SINGLE(AVS2),
+ PINMUX_SINGLE(HDMI0_CEC),
+ PINMUX_SINGLE(HDMI1_CEC),
+ PINMUX_SINGLE(MSIOF0_RXD),
+ PINMUX_SINGLE(MSIOF0_SCK),
+ PINMUX_SINGLE(MSIOF0_TXD),
+ PINMUX_SINGLE(SD2_CMD),
+ PINMUX_SINGLE(SD3_CLK),
+ PINMUX_SINGLE(SD3_CMD),
+ PINMUX_SINGLE(SD3_DAT0),
+ PINMUX_SINGLE(SD3_DAT1),
+ PINMUX_SINGLE(SD3_DAT2),
+ PINMUX_SINGLE(SD3_DAT3),
+ PINMUX_SINGLE(SD3_DS),
+ PINMUX_SINGLE(SSI_SCK5),
+ PINMUX_SINGLE(SSI_SDATA5),
+ PINMUX_SINGLE(SSI_WS5),
+
/* IPSR0 */
PINMUX_IPSR_DATA(IP0_3_0, AVB_MDC),
PINMUX_IPSR_MSEL(IP0_3_0, MSIOF2_SS2_C, SEL_MSIOF2_2),
@@ -1033,7 +1021,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP9_19_16, SD2_DAT3),
PINMUX_IPSR_DATA(IP9_23_20, SD2_DS),
- PINMUX_IPSR_MSEL(IP9_23_20, SATA_DEVSLP_B, SEL_SCIF_1),
+ PINMUX_IPSR_MSEL(IP9_23_20, SATA_DEVSLP_B, SEL_SATA_1),
PINMUX_IPSR_DATA(IP9_27_24, SD3_DAT4),
PINMUX_IPSR_MSEL(IP9_27_24, SD2_CD_A, SEL_SDHI2_0),
@@ -1293,7 +1281,7 @@ static const u16 pinmux_data[] = {
PINMUX_IPSR_DATA(IP15_11_8, SSI_SDATA6),
PINMUX_IPSR_MSEL(IP15_11_8, SIM0_CLK_D, SEL_SIMCARD_3),
- PINMUX_IPSR_MSEL(IP15_11_8, SATA_DEVSLP_A, SEL_SCIF_0),
+ PINMUX_IPSR_MSEL(IP15_11_8, SATA_DEVSLP_A, SEL_SATA_0),
PINMUX_IPSR_DATA(IP15_15_12, SSI_SCK78),
PINMUX_IPSR_MSEL(IP15_15_12, HRX2_B, SEL_HSCIF2_1),
@@ -1612,6 +1600,191 @@ static const unsigned int avb_avtp_capture_b_mux[] = {
AVB_AVTP_CAPTURE_B_MARK,
};
+/* - HSCIF0 ----------------------------------------------------------------- */
+static const unsigned int hscif0_data_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(5, 13), RCAR_GP_PIN(5, 14),
+};
+static const unsigned int hscif0_data_mux[] = {
+ HRX0_MARK, HTX0_MARK,
+};
+static const unsigned int hscif0_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(5, 12),
+};
+static const unsigned int hscif0_clk_mux[] = {
+ HSCK0_MARK,
+};
+static const unsigned int hscif0_ctrl_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(5, 16), RCAR_GP_PIN(5, 15),
+};
+static const unsigned int hscif0_ctrl_mux[] = {
+ HRTS0_N_MARK, HCTS0_N_MARK,
+};
+/* - HSCIF1 ----------------------------------------------------------------- */
+static const unsigned int hscif1_data_a_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(5, 5), RCAR_GP_PIN(5, 6),
+};
+static const unsigned int hscif1_data_a_mux[] = {
+ HRX1_A_MARK, HTX1_A_MARK,
+};
+static const unsigned int hscif1_clk_a_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(6, 21),
+};
+static const unsigned int hscif1_clk_a_mux[] = {
+ HSCK1_A_MARK,
+};
+static const unsigned int hscif1_ctrl_a_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(5, 8), RCAR_GP_PIN(5, 7),
+};
+static const unsigned int hscif1_ctrl_a_mux[] = {
+ HRTS1_N_A_MARK, HCTS1_N_A_MARK,
+};
+
+static const unsigned int hscif1_data_b_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(5, 1), RCAR_GP_PIN(5, 2),
+};
+static const unsigned int hscif1_data_b_mux[] = {
+ HRX1_B_MARK, HTX1_B_MARK,
+};
+static const unsigned int hscif1_clk_b_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(5, 0),
+};
+static const unsigned int hscif1_clk_b_mux[] = {
+ HSCK1_B_MARK,
+};
+static const unsigned int hscif1_ctrl_b_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(5, 4), RCAR_GP_PIN(5, 3),
+};
+static const unsigned int hscif1_ctrl_b_mux[] = {
+ HRTS1_N_B_MARK, HCTS1_N_B_MARK,
+};
+/* - HSCIF2 ----------------------------------------------------------------- */
+static const unsigned int hscif2_data_a_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(6, 8), RCAR_GP_PIN(6, 9),
+};
+static const unsigned int hscif2_data_a_mux[] = {
+ HRX2_A_MARK, HTX2_A_MARK,
+};
+static const unsigned int hscif2_clk_a_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(6, 10),
+};
+static const unsigned int hscif2_clk_a_mux[] = {
+ HSCK2_A_MARK,
+};
+static const unsigned int hscif2_ctrl_a_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(6, 7), RCAR_GP_PIN(6, 6),
+};
+static const unsigned int hscif2_ctrl_a_mux[] = {
+ HRTS2_N_A_MARK, HCTS2_N_A_MARK,
+};
+
+static const unsigned int hscif2_data_b_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(6, 17), RCAR_GP_PIN(6, 18),
+};
+static const unsigned int hscif2_data_b_mux[] = {
+ HRX2_B_MARK, HTX2_B_MARK,
+};
+static const unsigned int hscif2_clk_b_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(6, 21),
+};
+static const unsigned int hscif2_clk_b_mux[] = {
+ HSCK1_B_MARK,
+};
+static const unsigned int hscif2_ctrl_b_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(6, 20), RCAR_GP_PIN(6, 19),
+};
+static const unsigned int hscif2_ctrl_b_mux[] = {
+ HRTS2_N_B_MARK, HCTS2_N_B_MARK,
+};
+/* - HSCIF3 ----------------------------------------------------------------- */
+static const unsigned int hscif3_data_a_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(1, 23), RCAR_GP_PIN(1, 24),
+};
+static const unsigned int hscif3_data_a_mux[] = {
+ HRX3_A_MARK, HTX3_A_MARK,
+};
+static const unsigned int hscif3_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(1, 22),
+};
+static const unsigned int hscif3_clk_mux[] = {
+ HSCK3_MARK,
+};
+static const unsigned int hscif3_ctrl_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(1, 26), RCAR_GP_PIN(1, 25),
+};
+static const unsigned int hscif3_ctrl_mux[] = {
+ HRTS3_N_MARK, HCTS3_N_MARK,
+};
+
+static const unsigned int hscif3_data_b_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(0, 10), RCAR_GP_PIN(0, 11),
+};
+static const unsigned int hscif3_data_b_mux[] = {
+ HRX3_B_MARK, HTX3_B_MARK,
+};
+static const unsigned int hscif3_data_c_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(0, 14), RCAR_GP_PIN(0, 15),
+};
+static const unsigned int hscif3_data_c_mux[] = {
+ HRX3_C_MARK, HTX3_C_MARK,
+};
+static const unsigned int hscif3_data_d_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(2, 7), RCAR_GP_PIN(2, 8),
+};
+static const unsigned int hscif3_data_d_mux[] = {
+ HRX3_D_MARK, HTX3_D_MARK,
+};
+/* - HSCIF4 ----------------------------------------------------------------- */
+static const unsigned int hscif4_data_a_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(1, 12), RCAR_GP_PIN(1, 13),
+};
+static const unsigned int hscif4_data_a_mux[] = {
+ HRX4_A_MARK, HTX4_A_MARK,
+};
+static const unsigned int hscif4_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(1, 11),
+};
+static const unsigned int hscif4_clk_mux[] = {
+ HSCK4_MARK,
+};
+static const unsigned int hscif4_ctrl_pins[] = {
+ /* RTS, CTS */
+ RCAR_GP_PIN(1, 15), RCAR_GP_PIN(1, 14),
+};
+static const unsigned int hscif4_ctrl_mux[] = {
+ HRTS4_N_MARK, HCTS3_N_MARK,
+};
+
+static const unsigned int hscif4_data_b_pins[] = {
+ /* RX, TX */
+ RCAR_GP_PIN(1, 8), RCAR_GP_PIN(1, 11),
+};
+static const unsigned int hscif4_data_b_mux[] = {
+ HRX4_B_MARK, HTX4_B_MARK,
+};
+
/* - I2C -------------------------------------------------------------------- */
static const unsigned int i2c1_a_pins[] = {
/* SDA, SCL */
@@ -1663,6 +1836,678 @@ static const unsigned int i2c6_c_mux[] = {
SDA6_C_MARK, SCL6_C_MARK,
};
+/* - MSIOF0 ----------------------------------------------------------------- */
+static const unsigned int msiof0_clk_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(5, 17),
+};
+static const unsigned int msiof0_clk_mux[] = {
+ MSIOF0_SCK_MARK,
+};
+static const unsigned int msiof0_sync_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(5, 18),
+};
+static const unsigned int msiof0_sync_mux[] = {
+ MSIOF0_SYNC_MARK,
+};
+static const unsigned int msiof0_ss1_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(5, 19),
+};
+static const unsigned int msiof0_ss1_mux[] = {
+ MSIOF0_SS1_MARK,
+};
+static const unsigned int msiof0_ss2_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(5, 21),
+};
+static const unsigned int msiof0_ss2_mux[] = {
+ MSIOF0_SS2_MARK,
+};
+static const unsigned int msiof0_txd_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(5, 20),
+};
+static const unsigned int msiof0_txd_mux[] = {
+ MSIOF0_TXD_MARK,
+};
+static const unsigned int msiof0_rxd_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(5, 22),
+};
+static const unsigned int msiof0_rxd_mux[] = {
+ MSIOF0_RXD_MARK,
+};
+/* - MSIOF1 ----------------------------------------------------------------- */
+static const unsigned int msiof1_clk_a_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(6, 8),
+};
+static const unsigned int msiof1_clk_a_mux[] = {
+ MSIOF1_SCK_A_MARK,
+};
+static const unsigned int msiof1_sync_a_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(6, 9),
+};
+static const unsigned int msiof1_sync_a_mux[] = {
+ MSIOF1_SYNC_A_MARK,
+};
+static const unsigned int msiof1_ss1_a_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(6, 5),
+};
+static const unsigned int msiof1_ss1_a_mux[] = {
+ MSIOF1_SS1_A_MARK,
+};
+static const unsigned int msiof1_ss2_a_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(6, 6),
+};
+static const unsigned int msiof1_ss2_a_mux[] = {
+ MSIOF1_SS2_A_MARK,
+};
+static const unsigned int msiof1_txd_a_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(6, 7),
+};
+static const unsigned int msiof1_txd_a_mux[] = {
+ MSIOF1_TXD_A_MARK,
+};
+static const unsigned int msiof1_rxd_a_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(6, 10),
+};
+static const unsigned int msiof1_rxd_a_mux[] = {
+ MSIOF1_RXD_A_MARK,
+};
+static const unsigned int msiof1_clk_b_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(5, 9),
+};
+static const unsigned int msiof1_clk_b_mux[] = {
+ MSIOF1_SCK_B_MARK,
+};
+static const unsigned int msiof1_sync_b_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(5, 3),
+};
+static const unsigned int msiof1_sync_b_mux[] = {
+ MSIOF1_SYNC_B_MARK,
+};
+static const unsigned int msiof1_ss1_b_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(5, 4),
+};
+static const unsigned int msiof1_ss1_b_mux[] = {
+ MSIOF1_SS1_B_MARK,
+};
+static const unsigned int msiof1_ss2_b_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(5, 0),
+};
+static const unsigned int msiof1_ss2_b_mux[] = {
+ MSIOF1_SS2_B_MARK,
+};
+static const unsigned int msiof1_txd_b_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(5, 8),
+};
+static const unsigned int msiof1_txd_b_mux[] = {
+ MSIOF1_TXD_B_MARK,
+};
+static const unsigned int msiof1_rxd_b_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(5, 7),
+};
+static const unsigned int msiof1_rxd_b_mux[] = {
+ MSIOF1_RXD_B_MARK,
+};
+static const unsigned int msiof1_clk_c_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(6, 17),
+};
+static const unsigned int msiof1_clk_c_mux[] = {
+ MSIOF1_SCK_C_MARK,
+};
+static const unsigned int msiof1_sync_c_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(6, 18),
+};
+static const unsigned int msiof1_sync_c_mux[] = {
+ MSIOF1_SYNC_C_MARK,
+};
+static const unsigned int msiof1_ss1_c_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(6, 21),
+};
+static const unsigned int msiof1_ss1_c_mux[] = {
+ MSIOF1_SS1_C_MARK,
+};
+static const unsigned int msiof1_ss2_c_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(6, 27),
+};
+static const unsigned int msiof1_ss2_c_mux[] = {
+ MSIOF1_SS2_C_MARK,
+};
+static const unsigned int msiof1_txd_c_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(6, 20),
+};
+static const unsigned int msiof1_txd_c_mux[] = {
+ MSIOF1_TXD_C_MARK,
+};
+static const unsigned int msiof1_rxd_c_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(6, 19),
+};
+static const unsigned int msiof1_rxd_c_mux[] = {
+ MSIOF1_RXD_C_MARK,
+};
+static const unsigned int msiof1_clk_d_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(5, 12),
+};
+static const unsigned int msiof1_clk_d_mux[] = {
+ MSIOF1_SCK_D_MARK,
+};
+static const unsigned int msiof1_sync_d_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(5, 15),
+};
+static const unsigned int msiof1_sync_d_mux[] = {
+ MSIOF1_SYNC_D_MARK,
+};
+static const unsigned int msiof1_ss1_d_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(5, 16),
+};
+static const unsigned int msiof1_ss1_d_mux[] = {
+ MSIOF1_SS1_D_MARK,
+};
+static const unsigned int msiof1_ss2_d_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(5, 21),
+};
+static const unsigned int msiof1_ss2_d_mux[] = {
+ MSIOF1_SS2_D_MARK,
+};
+static const unsigned int msiof1_txd_d_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(5, 14),
+};
+static const unsigned int msiof1_txd_d_mux[] = {
+ MSIOF1_TXD_D_MARK,
+};
+static const unsigned int msiof1_rxd_d_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(5, 13),
+};
+static const unsigned int msiof1_rxd_d_mux[] = {
+ MSIOF1_RXD_D_MARK,
+};
+static const unsigned int msiof1_clk_e_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(3, 0),
+};
+static const unsigned int msiof1_clk_e_mux[] = {
+ MSIOF1_SCK_E_MARK,
+};
+static const unsigned int msiof1_sync_e_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(3, 1),
+};
+static const unsigned int msiof1_sync_e_mux[] = {
+ MSIOF1_SYNC_E_MARK,
+};
+static const unsigned int msiof1_ss1_e_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(3, 4),
+};
+static const unsigned int msiof1_ss1_e_mux[] = {
+ MSIOF1_SS1_E_MARK,
+};
+static const unsigned int msiof1_ss2_e_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(3, 5),
+};
+static const unsigned int msiof1_ss2_e_mux[] = {
+ MSIOF1_SS2_E_MARK,
+};
+static const unsigned int msiof1_txd_e_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(3, 3),
+};
+static const unsigned int msiof1_txd_e_mux[] = {
+ MSIOF1_TXD_E_MARK,
+};
+static const unsigned int msiof1_rxd_e_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(3, 2),
+};
+static const unsigned int msiof1_rxd_e_mux[] = {
+ MSIOF1_RXD_E_MARK,
+};
+static const unsigned int msiof1_clk_f_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(5, 23),
+};
+static const unsigned int msiof1_clk_f_mux[] = {
+ MSIOF1_SCK_F_MARK,
+};
+static const unsigned int msiof1_sync_f_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(5, 24),
+};
+static const unsigned int msiof1_sync_f_mux[] = {
+ MSIOF1_SYNC_F_MARK,
+};
+static const unsigned int msiof1_ss1_f_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(6, 1),
+};
+static const unsigned int msiof1_ss1_f_mux[] = {
+ MSIOF1_SS1_F_MARK,
+};
+static const unsigned int msiof1_ss2_f_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(6, 2),
+};
+static const unsigned int msiof1_ss2_f_mux[] = {
+ MSIOF1_SS2_F_MARK,
+};
+static const unsigned int msiof1_txd_f_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(6, 0),
+};
+static const unsigned int msiof1_txd_f_mux[] = {
+ MSIOF1_TXD_F_MARK,
+};
+static const unsigned int msiof1_rxd_f_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(5, 25),
+};
+static const unsigned int msiof1_rxd_f_mux[] = {
+ MSIOF1_RXD_F_MARK,
+};
+static const unsigned int msiof1_clk_g_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(3, 6),
+};
+static const unsigned int msiof1_clk_g_mux[] = {
+ MSIOF1_SCK_G_MARK,
+};
+static const unsigned int msiof1_sync_g_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(3, 7),
+};
+static const unsigned int msiof1_sync_g_mux[] = {
+ MSIOF1_SYNC_G_MARK,
+};
+static const unsigned int msiof1_ss1_g_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(3, 10),
+};
+static const unsigned int msiof1_ss1_g_mux[] = {
+ MSIOF1_SS1_G_MARK,
+};
+static const unsigned int msiof1_ss2_g_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(3, 11),
+};
+static const unsigned int msiof1_ss2_g_mux[] = {
+ MSIOF1_SS2_G_MARK,
+};
+static const unsigned int msiof1_txd_g_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(3, 9),
+};
+static const unsigned int msiof1_txd_g_mux[] = {
+ MSIOF1_TXD_G_MARK,
+};
+static const unsigned int msiof1_rxd_g_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(3, 8),
+};
+static const unsigned int msiof1_rxd_g_mux[] = {
+ MSIOF1_RXD_G_MARK,
+};
+/* - MSIOF2 ----------------------------------------------------------------- */
+static const unsigned int msiof2_clk_a_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(1, 9),
+};
+static const unsigned int msiof2_clk_a_mux[] = {
+ MSIOF2_SCK_A_MARK,
+};
+static const unsigned int msiof2_sync_a_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(1, 8),
+};
+static const unsigned int msiof2_sync_a_mux[] = {
+ MSIOF2_SYNC_A_MARK,
+};
+static const unsigned int msiof2_ss1_a_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(1, 6),
+};
+static const unsigned int msiof2_ss1_a_mux[] = {
+ MSIOF2_SS1_A_MARK,
+};
+static const unsigned int msiof2_ss2_a_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(1, 7),
+};
+static const unsigned int msiof2_ss2_a_mux[] = {
+ MSIOF2_SS2_A_MARK,
+};
+static const unsigned int msiof2_txd_a_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(1, 11),
+};
+static const unsigned int msiof2_txd_a_mux[] = {
+ MSIOF2_TXD_A_MARK,
+};
+static const unsigned int msiof2_rxd_a_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(1, 10),
+};
+static const unsigned int msiof2_rxd_a_mux[] = {
+ MSIOF2_RXD_A_MARK,
+};
+static const unsigned int msiof2_clk_b_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(0, 4),
+};
+static const unsigned int msiof2_clk_b_mux[] = {
+ MSIOF2_SCK_B_MARK,
+};
+static const unsigned int msiof2_sync_b_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(0, 5),
+};
+static const unsigned int msiof2_sync_b_mux[] = {
+ MSIOF2_SYNC_B_MARK,
+};
+static const unsigned int msiof2_ss1_b_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(0, 0),
+};
+static const unsigned int msiof2_ss1_b_mux[] = {
+ MSIOF2_SS1_B_MARK,
+};
+static const unsigned int msiof2_ss2_b_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(0, 1),
+};
+static const unsigned int msiof2_ss2_b_mux[] = {
+ MSIOF2_SS2_B_MARK,
+};
+static const unsigned int msiof2_txd_b_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(0, 7),
+};
+static const unsigned int msiof2_txd_b_mux[] = {
+ MSIOF2_TXD_B_MARK,
+};
+static const unsigned int msiof2_rxd_b_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(0, 6),
+};
+static const unsigned int msiof2_rxd_b_mux[] = {
+ MSIOF2_RXD_B_MARK,
+};
+static const unsigned int msiof2_clk_c_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(2, 12),
+};
+static const unsigned int msiof2_clk_c_mux[] = {
+ MSIOF2_SCK_C_MARK,
+};
+static const unsigned int msiof2_sync_c_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(2, 11),
+};
+static const unsigned int msiof2_sync_c_mux[] = {
+ MSIOF2_SYNC_C_MARK,
+};
+static const unsigned int msiof2_ss1_c_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(2, 10),
+};
+static const unsigned int msiof2_ss1_c_mux[] = {
+ MSIOF2_SS1_C_MARK,
+};
+static const unsigned int msiof2_ss2_c_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(2, 9),
+};
+static const unsigned int msiof2_ss2_c_mux[] = {
+ MSIOF2_SS2_C_MARK,
+};
+static const unsigned int msiof2_txd_c_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(2, 14),
+};
+static const unsigned int msiof2_txd_c_mux[] = {
+ MSIOF2_TXD_C_MARK,
+};
+static const unsigned int msiof2_rxd_c_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(2, 13),
+};
+static const unsigned int msiof2_rxd_c_mux[] = {
+ MSIOF2_RXD_C_MARK,
+};
+static const unsigned int msiof2_clk_d_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(0, 8),
+};
+static const unsigned int msiof2_clk_d_mux[] = {
+ MSIOF2_SCK_D_MARK,
+};
+static const unsigned int msiof2_sync_d_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(0, 9),
+};
+static const unsigned int msiof2_sync_d_mux[] = {
+ MSIOF2_SYNC_D_MARK,
+};
+static const unsigned int msiof2_ss1_d_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(0, 12),
+};
+static const unsigned int msiof2_ss1_d_mux[] = {
+ MSIOF2_SS1_D_MARK,
+};
+static const unsigned int msiof2_ss2_d_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(0, 13),
+};
+static const unsigned int msiof2_ss2_d_mux[] = {
+ MSIOF2_SS2_D_MARK,
+};
+static const unsigned int msiof2_txd_d_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(0, 11),
+};
+static const unsigned int msiof2_txd_d_mux[] = {
+ MSIOF2_TXD_D_MARK,
+};
+static const unsigned int msiof2_rxd_d_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(0, 10),
+};
+static const unsigned int msiof2_rxd_d_mux[] = {
+ MSIOF2_RXD_D_MARK,
+};
+/* - MSIOF3 ----------------------------------------------------------------- */
+static const unsigned int msiof3_clk_a_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(0, 0),
+};
+static const unsigned int msiof3_clk_a_mux[] = {
+ MSIOF3_SCK_A_MARK,
+};
+static const unsigned int msiof3_sync_a_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(0, 1),
+};
+static const unsigned int msiof3_sync_a_mux[] = {
+ MSIOF3_SYNC_A_MARK,
+};
+static const unsigned int msiof3_ss1_a_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(0, 14),
+};
+static const unsigned int msiof3_ss1_a_mux[] = {
+ MSIOF3_SS1_A_MARK,
+};
+static const unsigned int msiof3_ss2_a_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(0, 15),
+};
+static const unsigned int msiof3_ss2_a_mux[] = {
+ MSIOF3_SS2_A_MARK,
+};
+static const unsigned int msiof3_txd_a_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(0, 3),
+};
+static const unsigned int msiof3_txd_a_mux[] = {
+ MSIOF3_TXD_A_MARK,
+};
+static const unsigned int msiof3_rxd_a_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(0, 2),
+};
+static const unsigned int msiof3_rxd_a_mux[] = {
+ MSIOF3_RXD_A_MARK,
+};
+static const unsigned int msiof3_clk_b_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(1, 2),
+};
+static const unsigned int msiof3_clk_b_mux[] = {
+ MSIOF3_SCK_B_MARK,
+};
+static const unsigned int msiof3_sync_b_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(1, 0),
+};
+static const unsigned int msiof3_sync_b_mux[] = {
+ MSIOF3_SYNC_B_MARK,
+};
+static const unsigned int msiof3_ss1_b_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(1, 4),
+};
+static const unsigned int msiof3_ss1_b_mux[] = {
+ MSIOF3_SS1_B_MARK,
+};
+static const unsigned int msiof3_ss2_b_pins[] = {
+ /* SS2 */
+ RCAR_GP_PIN(1, 5),
+};
+static const unsigned int msiof3_ss2_b_mux[] = {
+ MSIOF3_SS2_B_MARK,
+};
+static const unsigned int msiof3_txd_b_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(1, 1),
+};
+static const unsigned int msiof3_txd_b_mux[] = {
+ MSIOF3_TXD_B_MARK,
+};
+static const unsigned int msiof3_rxd_b_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(1, 3),
+};
+static const unsigned int msiof3_rxd_b_mux[] = {
+ MSIOF3_RXD_B_MARK,
+};
+static const unsigned int msiof3_clk_c_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(1, 12),
+};
+static const unsigned int msiof3_clk_c_mux[] = {
+ MSIOF3_SCK_C_MARK,
+};
+static const unsigned int msiof3_sync_c_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(1, 13),
+};
+static const unsigned int msiof3_sync_c_mux[] = {
+ MSIOF3_SYNC_C_MARK,
+};
+static const unsigned int msiof3_txd_c_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(1, 15),
+};
+static const unsigned int msiof3_txd_c_mux[] = {
+ MSIOF3_TXD_C_MARK,
+};
+static const unsigned int msiof3_rxd_c_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(1, 14),
+};
+static const unsigned int msiof3_rxd_c_mux[] = {
+ MSIOF3_RXD_C_MARK,
+};
+static const unsigned int msiof3_clk_d_pins[] = {
+ /* SCK */
+ RCAR_GP_PIN(1, 22),
+};
+static const unsigned int msiof3_clk_d_mux[] = {
+ MSIOF3_SCK_D_MARK,
+};
+static const unsigned int msiof3_sync_d_pins[] = {
+ /* SYNC */
+ RCAR_GP_PIN(1, 23),
+};
+static const unsigned int msiof3_sync_d_mux[] = {
+ MSIOF3_SYNC_D_MARK,
+};
+static const unsigned int msiof3_ss1_d_pins[] = {
+ /* SS1 */
+ RCAR_GP_PIN(1, 26),
+};
+static const unsigned int msiof3_ss1_d_mux[] = {
+ MSIOF3_SS1_D_MARK,
+};
+static const unsigned int msiof3_txd_d_pins[] = {
+ /* TXD */
+ RCAR_GP_PIN(1, 25),
+};
+static const unsigned int msiof3_txd_d_mux[] = {
+ MSIOF3_TXD_D_MARK,
+};
+static const unsigned int msiof3_rxd_d_pins[] = {
+ /* RXD */
+ RCAR_GP_PIN(1, 24),
+};
+static const unsigned int msiof3_rxd_d_mux[] = {
+ MSIOF3_RXD_D_MARK,
+};
+
+/* - SATA --------------------------------------------------------------------*/
+static const unsigned int sata0_devslp_a_pins[] = {
+ /* DEVSLP */
+ RCAR_GP_PIN(6, 16),
+};
+static const unsigned int sata0_devslp_a_mux[] = {
+ SATA_DEVSLP_A_MARK,
+};
+static const unsigned int sata0_devslp_b_pins[] = {
+ /* DEVSLP */
+ RCAR_GP_PIN(4, 6),
+};
+static const unsigned int sata0_devslp_b_mux[] = {
+ SATA_DEVSLP_B_MARK,
+};
+
/* - SCIF0 ------------------------------------------------------------------ */
static const unsigned int scif0_data_pins[] = {
/* RX, TX */
@@ -1845,6 +2690,228 @@ static const unsigned int scif5_clk_pins[] = {
static const unsigned int scif5_clk_mux[] = {
SCK5_MARK,
};
+/* - SDHI0 ------------------------------------------------------------------ */
+static const unsigned int sdhi0_data1_pins[] = {
+ /* D0 */
+ RCAR_GP_PIN(3, 2),
+};
+static const unsigned int sdhi0_data1_mux[] = {
+ SD0_DAT0_MARK,
+};
+static const unsigned int sdhi0_data4_pins[] = {
+ /* D[0:3] */
+ RCAR_GP_PIN(3, 2), RCAR_GP_PIN(3, 3),
+ RCAR_GP_PIN(3, 4), RCAR_GP_PIN(3, 5),
+};
+static const unsigned int sdhi0_data4_mux[] = {
+ SD0_DAT0_MARK, SD0_DAT1_MARK,
+ SD0_DAT2_MARK, SD0_DAT3_MARK,
+};
+static const unsigned int sdhi0_ctrl_pins[] = {
+ /* CLK, CMD */
+ RCAR_GP_PIN(3, 0), RCAR_GP_PIN(3, 1),
+};
+static const unsigned int sdhi0_ctrl_mux[] = {
+ SD0_CLK_MARK, SD0_CMD_MARK,
+};
+static const unsigned int sdhi0_cd_pins[] = {
+ /* CD */
+ RCAR_GP_PIN(3, 12),
+};
+static const unsigned int sdhi0_cd_mux[] = {
+ SD0_CD_MARK,
+};
+static const unsigned int sdhi0_wp_pins[] = {
+ /* WP */
+ RCAR_GP_PIN(3, 13),
+};
+static const unsigned int sdhi0_wp_mux[] = {
+ SD0_WP_MARK,
+};
+/* - SDHI1 ------------------------------------------------------------------ */
+static const unsigned int sdhi1_data1_pins[] = {
+ /* D0 */
+ RCAR_GP_PIN(3, 8),
+};
+static const unsigned int sdhi1_data1_mux[] = {
+ SD1_DAT0_MARK,
+};
+static const unsigned int sdhi1_data4_pins[] = {
+ /* D[0:3] */
+ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9),
+ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11),
+};
+static const unsigned int sdhi1_data4_mux[] = {
+ SD1_DAT0_MARK, SD1_DAT1_MARK,
+ SD1_DAT2_MARK, SD1_DAT3_MARK,
+};
+static const unsigned int sdhi1_ctrl_pins[] = {
+ /* CLK, CMD */
+ RCAR_GP_PIN(3, 6), RCAR_GP_PIN(3, 7),
+};
+static const unsigned int sdhi1_ctrl_mux[] = {
+ SD1_CLK_MARK, SD1_CMD_MARK,
+};
+static const unsigned int sdhi1_cd_pins[] = {
+ /* CD */
+ RCAR_GP_PIN(3, 14),
+};
+static const unsigned int sdhi1_cd_mux[] = {
+ SD1_CD_MARK,
+};
+static const unsigned int sdhi1_wp_pins[] = {
+ /* WP */
+ RCAR_GP_PIN(3, 15),
+};
+static const unsigned int sdhi1_wp_mux[] = {
+ SD1_WP_MARK,
+};
+/* - SDHI2 ------------------------------------------------------------------ */
+static const unsigned int sdhi2_data1_pins[] = {
+ /* D0 */
+ RCAR_GP_PIN(4, 2),
+};
+static const unsigned int sdhi2_data1_mux[] = {
+ SD2_DAT0_MARK,
+};
+static const unsigned int sdhi2_data4_pins[] = {
+ /* D[0:3] */
+ RCAR_GP_PIN(4, 2), RCAR_GP_PIN(4, 3),
+ RCAR_GP_PIN(4, 4), RCAR_GP_PIN(4, 5),
+};
+static const unsigned int sdhi2_data4_mux[] = {
+ SD2_DAT0_MARK, SD2_DAT1_MARK,
+ SD2_DAT2_MARK, SD2_DAT3_MARK,
+};
+static const unsigned int sdhi2_data8_pins[] = {
+ /* D[0:7] */
+ RCAR_GP_PIN(4, 2), RCAR_GP_PIN(4, 3),
+ RCAR_GP_PIN(4, 4), RCAR_GP_PIN(4, 5),
+ RCAR_GP_PIN(3, 8), RCAR_GP_PIN(3, 9),
+ RCAR_GP_PIN(3, 10), RCAR_GP_PIN(3, 11),
+};
+static const unsigned int sdhi2_data8_mux[] = {
+ SD2_DAT0_MARK, SD2_DAT1_MARK,
+ SD2_DAT2_MARK, SD2_DAT3_MARK,
+ SD2_DAT4_MARK, SD2_DAT5_MARK,
+ SD2_DAT6_MARK, SD2_DAT7_MARK,
+};
+static const unsigned int sdhi2_ctrl_pins[] = {
+ /* CLK, CMD */
+ RCAR_GP_PIN(4, 0), RCAR_GP_PIN(4, 1),
+};
+static const unsigned int sdhi2_ctrl_mux[] = {
+ SD2_CLK_MARK, SD2_CMD_MARK,
+};
+static const unsigned int sdhi2_cd_a_pins[] = {
+ /* CD */
+ RCAR_GP_PIN(4, 13),
+};
+static const unsigned int sdhi2_cd_a_mux[] = {
+ SD2_CD_A_MARK,
+};
+static const unsigned int sdhi2_cd_b_pins[] = {
+ /* CD */
+ RCAR_GP_PIN(5, 10),
+};
+static const unsigned int sdhi2_cd_b_mux[] = {
+ SD2_CD_B_MARK,
+};
+static const unsigned int sdhi2_wp_a_pins[] = {
+ /* WP */
+ RCAR_GP_PIN(4, 14),
+};
+static const unsigned int sdhi2_wp_a_mux[] = {
+ SD2_WP_A_MARK,
+};
+static const unsigned int sdhi2_wp_b_pins[] = {
+ /* WP */
+ RCAR_GP_PIN(5, 11),
+};
+static const unsigned int sdhi2_wp_b_mux[] = {
+ SD2_WP_B_MARK,
+};
+static const unsigned int sdhi2_ds_pins[] = {
+ /* DS */
+ RCAR_GP_PIN(4, 6),
+};
+static const unsigned int sdhi2_ds_mux[] = {
+ SD2_DS_MARK,
+};
+/* - SDHI3 ------------------------------------------------------------------ */
+static const unsigned int sdhi3_data1_pins[] = {
+ /* D0 */
+ RCAR_GP_PIN(4, 9),
+};
+static const unsigned int sdhi3_data1_mux[] = {
+ SD3_DAT0_MARK,
+};
+static const unsigned int sdhi3_data4_pins[] = {
+ /* D[0:3] */
+ RCAR_GP_PIN(4, 9), RCAR_GP_PIN(4, 10),
+ RCAR_GP_PIN(4, 11), RCAR_GP_PIN(4, 12),
+};
+static const unsigned int sdhi3_data4_mux[] = {
+ SD3_DAT0_MARK, SD3_DAT1_MARK,
+ SD3_DAT2_MARK, SD3_DAT3_MARK,
+};
+static const unsigned int sdhi3_data8_pins[] = {
+ /* D[0:7] */
+ RCAR_GP_PIN(4, 9), RCAR_GP_PIN(4, 10),
+ RCAR_GP_PIN(4, 11), RCAR_GP_PIN(4, 12),
+ RCAR_GP_PIN(4, 13), RCAR_GP_PIN(4, 14),
+ RCAR_GP_PIN(4, 15), RCAR_GP_PIN(4, 16),
+};
+static const unsigned int sdhi3_data8_mux[] = {
+ SD3_DAT0_MARK, SD3_DAT1_MARK,
+ SD3_DAT2_MARK, SD3_DAT3_MARK,
+ SD3_DAT4_MARK, SD3_DAT5_MARK,
+ SD3_DAT6_MARK, SD3_DAT7_MARK,
+};
+static const unsigned int sdhi3_ctrl_pins[] = {
+ /* CLK, CMD */
+ RCAR_GP_PIN(4, 7), RCAR_GP_PIN(4, 8),
+};
+static const unsigned int sdhi3_ctrl_mux[] = {
+ SD3_CLK_MARK, SD3_CMD_MARK,
+};
+static const unsigned int sdhi3_cd_pins[] = {
+ /* CD */
+ RCAR_GP_PIN(4, 15),
+};
+static const unsigned int sdhi3_cd_mux[] = {
+ SD3_CD_MARK,
+};
+static const unsigned int sdhi3_wp_pins[] = {
+ /* WP */
+ RCAR_GP_PIN(4, 16),
+};
+static const unsigned int sdhi3_wp_mux[] = {
+ SD3_WP_MARK,
+};
+static const unsigned int sdhi3_ds_pins[] = {
+ /* DS */
+ RCAR_GP_PIN(4, 17),
+};
+static const unsigned int sdhi3_ds_mux[] = {
+ SD3_DS_MARK,
+};
+
+/* - SCIF Clock ------------------------------------------------------------- */
+static const unsigned int scif_clk_a_pins[] = {
+ /* SCIF_CLK */
+ RCAR_GP_PIN(6, 23),
+};
+static const unsigned int scif_clk_a_mux[] = {
+ SCIF_CLK_A_MARK,
+};
+static const unsigned int scif_clk_b_pins[] = {
+ /* SCIF_CLK */
+ RCAR_GP_PIN(5, 9),
+};
+static const unsigned int scif_clk_b_mux[] = {
+ SCIF_CLK_B_MARK,
+};
/* - SSI -------------------------------------------------------------------- */
static const unsigned int ssi0_data_pins[] = {
@@ -2050,6 +3117,31 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(avb_avtp_capture_a),
SH_PFC_PIN_GROUP(avb_avtp_match_b),
SH_PFC_PIN_GROUP(avb_avtp_capture_b),
+ SH_PFC_PIN_GROUP(hscif0_data),
+ SH_PFC_PIN_GROUP(hscif0_clk),
+ SH_PFC_PIN_GROUP(hscif0_ctrl),
+ SH_PFC_PIN_GROUP(hscif1_data_a),
+ SH_PFC_PIN_GROUP(hscif1_clk_a),
+ SH_PFC_PIN_GROUP(hscif1_ctrl_a),
+ SH_PFC_PIN_GROUP(hscif1_data_b),
+ SH_PFC_PIN_GROUP(hscif1_clk_b),
+ SH_PFC_PIN_GROUP(hscif1_ctrl_b),
+ SH_PFC_PIN_GROUP(hscif2_data_a),
+ SH_PFC_PIN_GROUP(hscif2_clk_a),
+ SH_PFC_PIN_GROUP(hscif2_ctrl_a),
+ SH_PFC_PIN_GROUP(hscif2_data_b),
+ SH_PFC_PIN_GROUP(hscif2_clk_b),
+ SH_PFC_PIN_GROUP(hscif2_ctrl_b),
+ SH_PFC_PIN_GROUP(hscif3_data_a),
+ SH_PFC_PIN_GROUP(hscif3_clk),
+ SH_PFC_PIN_GROUP(hscif3_ctrl),
+ SH_PFC_PIN_GROUP(hscif3_data_b),
+ SH_PFC_PIN_GROUP(hscif3_data_c),
+ SH_PFC_PIN_GROUP(hscif3_data_d),
+ SH_PFC_PIN_GROUP(hscif4_data_a),
+ SH_PFC_PIN_GROUP(hscif4_clk),
+ SH_PFC_PIN_GROUP(hscif4_ctrl),
+ SH_PFC_PIN_GROUP(hscif4_data_b),
SH_PFC_PIN_GROUP(i2c1_a),
SH_PFC_PIN_GROUP(i2c1_b),
SH_PFC_PIN_GROUP(i2c2_a),
@@ -2057,6 +3149,101 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(i2c6_a),
SH_PFC_PIN_GROUP(i2c6_b),
SH_PFC_PIN_GROUP(i2c6_c),
+ SH_PFC_PIN_GROUP(msiof0_clk),
+ SH_PFC_PIN_GROUP(msiof0_sync),
+ SH_PFC_PIN_GROUP(msiof0_ss1),
+ SH_PFC_PIN_GROUP(msiof0_ss2),
+ SH_PFC_PIN_GROUP(msiof0_txd),
+ SH_PFC_PIN_GROUP(msiof0_rxd),
+ SH_PFC_PIN_GROUP(msiof1_clk_a),
+ SH_PFC_PIN_GROUP(msiof1_sync_a),
+ SH_PFC_PIN_GROUP(msiof1_ss1_a),
+ SH_PFC_PIN_GROUP(msiof1_ss2_a),
+ SH_PFC_PIN_GROUP(msiof1_txd_a),
+ SH_PFC_PIN_GROUP(msiof1_rxd_a),
+ SH_PFC_PIN_GROUP(msiof1_clk_b),
+ SH_PFC_PIN_GROUP(msiof1_sync_b),
+ SH_PFC_PIN_GROUP(msiof1_ss1_b),
+ SH_PFC_PIN_GROUP(msiof1_ss2_b),
+ SH_PFC_PIN_GROUP(msiof1_txd_b),
+ SH_PFC_PIN_GROUP(msiof1_rxd_b),
+ SH_PFC_PIN_GROUP(msiof1_clk_c),
+ SH_PFC_PIN_GROUP(msiof1_sync_c),
+ SH_PFC_PIN_GROUP(msiof1_ss1_c),
+ SH_PFC_PIN_GROUP(msiof1_ss2_c),
+ SH_PFC_PIN_GROUP(msiof1_txd_c),
+ SH_PFC_PIN_GROUP(msiof1_rxd_c),
+ SH_PFC_PIN_GROUP(msiof1_clk_d),
+ SH_PFC_PIN_GROUP(msiof1_sync_d),
+ SH_PFC_PIN_GROUP(msiof1_ss1_d),
+ SH_PFC_PIN_GROUP(msiof1_ss2_d),
+ SH_PFC_PIN_GROUP(msiof1_txd_d),
+ SH_PFC_PIN_GROUP(msiof1_rxd_d),
+ SH_PFC_PIN_GROUP(msiof1_clk_e),
+ SH_PFC_PIN_GROUP(msiof1_sync_e),
+ SH_PFC_PIN_GROUP(msiof1_ss1_e),
+ SH_PFC_PIN_GROUP(msiof1_ss2_e),
+ SH_PFC_PIN_GROUP(msiof1_txd_e),
+ SH_PFC_PIN_GROUP(msiof1_rxd_e),
+ SH_PFC_PIN_GROUP(msiof1_clk_f),
+ SH_PFC_PIN_GROUP(msiof1_sync_f),
+ SH_PFC_PIN_GROUP(msiof1_ss1_f),
+ SH_PFC_PIN_GROUP(msiof1_ss2_f),
+ SH_PFC_PIN_GROUP(msiof1_txd_f),
+ SH_PFC_PIN_GROUP(msiof1_rxd_f),
+ SH_PFC_PIN_GROUP(msiof1_clk_g),
+ SH_PFC_PIN_GROUP(msiof1_sync_g),
+ SH_PFC_PIN_GROUP(msiof1_ss1_g),
+ SH_PFC_PIN_GROUP(msiof1_ss2_g),
+ SH_PFC_PIN_GROUP(msiof1_txd_g),
+ SH_PFC_PIN_GROUP(msiof1_rxd_g),
+ SH_PFC_PIN_GROUP(msiof2_clk_a),
+ SH_PFC_PIN_GROUP(msiof2_sync_a),
+ SH_PFC_PIN_GROUP(msiof2_ss1_a),
+ SH_PFC_PIN_GROUP(msiof2_ss2_a),
+ SH_PFC_PIN_GROUP(msiof2_txd_a),
+ SH_PFC_PIN_GROUP(msiof2_rxd_a),
+ SH_PFC_PIN_GROUP(msiof2_clk_b),
+ SH_PFC_PIN_GROUP(msiof2_sync_b),
+ SH_PFC_PIN_GROUP(msiof2_ss1_b),
+ SH_PFC_PIN_GROUP(msiof2_ss2_b),
+ SH_PFC_PIN_GROUP(msiof2_txd_b),
+ SH_PFC_PIN_GROUP(msiof2_rxd_b),
+ SH_PFC_PIN_GROUP(msiof2_clk_c),
+ SH_PFC_PIN_GROUP(msiof2_sync_c),
+ SH_PFC_PIN_GROUP(msiof2_ss1_c),
+ SH_PFC_PIN_GROUP(msiof2_ss2_c),
+ SH_PFC_PIN_GROUP(msiof2_txd_c),
+ SH_PFC_PIN_GROUP(msiof2_rxd_c),
+ SH_PFC_PIN_GROUP(msiof2_clk_d),
+ SH_PFC_PIN_GROUP(msiof2_sync_d),
+ SH_PFC_PIN_GROUP(msiof2_ss1_d),
+ SH_PFC_PIN_GROUP(msiof2_ss2_d),
+ SH_PFC_PIN_GROUP(msiof2_txd_d),
+ SH_PFC_PIN_GROUP(msiof2_rxd_d),
+ SH_PFC_PIN_GROUP(msiof3_clk_a),
+ SH_PFC_PIN_GROUP(msiof3_sync_a),
+ SH_PFC_PIN_GROUP(msiof3_ss1_a),
+ SH_PFC_PIN_GROUP(msiof3_ss2_a),
+ SH_PFC_PIN_GROUP(msiof3_txd_a),
+ SH_PFC_PIN_GROUP(msiof3_rxd_a),
+ SH_PFC_PIN_GROUP(msiof3_clk_b),
+ SH_PFC_PIN_GROUP(msiof3_sync_b),
+ SH_PFC_PIN_GROUP(msiof3_ss1_b),
+ SH_PFC_PIN_GROUP(msiof3_ss2_b),
+ SH_PFC_PIN_GROUP(msiof3_txd_b),
+ SH_PFC_PIN_GROUP(msiof3_rxd_b),
+ SH_PFC_PIN_GROUP(msiof3_clk_c),
+ SH_PFC_PIN_GROUP(msiof3_sync_c),
+ SH_PFC_PIN_GROUP(msiof3_txd_c),
+ SH_PFC_PIN_GROUP(msiof3_rxd_c),
+ SH_PFC_PIN_GROUP(msiof3_clk_d),
+ SH_PFC_PIN_GROUP(msiof3_sync_d),
+ SH_PFC_PIN_GROUP(msiof3_ss1_d),
+ SH_PFC_PIN_GROUP(msiof3_txd_d),
+ SH_PFC_PIN_GROUP(msiof3_rxd_d),
+ SH_PFC_PIN_GROUP(sata0_devslp_a),
+ SH_PFC_PIN_GROUP(sata0_devslp_b),
SH_PFC_PIN_GROUP(scif0_data),
SH_PFC_PIN_GROUP(scif0_clk),
SH_PFC_PIN_GROUP(scif0_ctrl),
@@ -2082,6 +3269,34 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(scif4_ctrl_c),
SH_PFC_PIN_GROUP(scif5_data),
SH_PFC_PIN_GROUP(scif5_clk),
+ SH_PFC_PIN_GROUP(scif_clk_a),
+ SH_PFC_PIN_GROUP(scif_clk_b),
+ SH_PFC_PIN_GROUP(sdhi0_data1),
+ SH_PFC_PIN_GROUP(sdhi0_data4),
+ SH_PFC_PIN_GROUP(sdhi0_ctrl),
+ SH_PFC_PIN_GROUP(sdhi0_cd),
+ SH_PFC_PIN_GROUP(sdhi0_wp),
+ SH_PFC_PIN_GROUP(sdhi1_data1),
+ SH_PFC_PIN_GROUP(sdhi1_data4),
+ SH_PFC_PIN_GROUP(sdhi1_ctrl),
+ SH_PFC_PIN_GROUP(sdhi1_cd),
+ SH_PFC_PIN_GROUP(sdhi1_wp),
+ SH_PFC_PIN_GROUP(sdhi2_data1),
+ SH_PFC_PIN_GROUP(sdhi2_data4),
+ SH_PFC_PIN_GROUP(sdhi2_data8),
+ SH_PFC_PIN_GROUP(sdhi2_ctrl),
+ SH_PFC_PIN_GROUP(sdhi2_cd_a),
+ SH_PFC_PIN_GROUP(sdhi2_wp_a),
+ SH_PFC_PIN_GROUP(sdhi2_cd_b),
+ SH_PFC_PIN_GROUP(sdhi2_wp_b),
+ SH_PFC_PIN_GROUP(sdhi2_ds),
+ SH_PFC_PIN_GROUP(sdhi3_data1),
+ SH_PFC_PIN_GROUP(sdhi3_data4),
+ SH_PFC_PIN_GROUP(sdhi3_data8),
+ SH_PFC_PIN_GROUP(sdhi3_ctrl),
+ SH_PFC_PIN_GROUP(sdhi3_cd),
+ SH_PFC_PIN_GROUP(sdhi3_wp),
+ SH_PFC_PIN_GROUP(sdhi3_ds),
SH_PFC_PIN_GROUP(ssi0_data),
SH_PFC_PIN_GROUP(ssi01239_ctrl),
SH_PFC_PIN_GROUP(ssi1_data_a),
@@ -2141,6 +3356,46 @@ static const char * const avb_groups[] = {
"avb_avtp_capture_b",
};
+static const char * const hscif0_groups[] = {
+ "hscif0_data",
+ "hscif0_clk",
+ "hscif0_ctrl",
+};
+
+static const char * const hscif1_groups[] = {
+ "hscif1_data_a",
+ "hscif1_clk_a",
+ "hscif1_ctrl_a",
+ "hscif1_data_b",
+ "hscif1_clk_b",
+ "hscif1_ctrl_b",
+};
+
+static const char * const hscif2_groups[] = {
+ "hscif2_data_a",
+ "hscif2_clk_a",
+ "hscif2_ctrl_a",
+ "hscif2_data_b",
+ "hscif2_clk_b",
+ "hscif2_ctrl_b",
+};
+
+static const char * const hscif3_groups[] = {
+ "hscif3_data_a",
+ "hscif3_clk",
+ "hscif3_ctrl",
+ "hscif3_data_b",
+ "hscif3_data_c",
+ "hscif3_data_d",
+};
+
+static const char * const hscif4_groups[] = {
+ "hscif4_data_a",
+ "hscif4_clk",
+ "hscif4_ctrl",
+ "hscif4_data_b",
+};
+
static const char * const i2c1_groups[] = {
"i2c1_a",
"i2c1_b",
@@ -2157,6 +3412,116 @@ static const char * const i2c6_groups[] = {
"i2c6_c",
};
+static const char * const msiof0_groups[] = {
+ "msiof0_clk",
+ "msiof0_sync",
+ "msiof0_ss1",
+ "msiof0_ss2",
+ "msiof0_txd",
+ "msiof0_rxd",
+};
+
+static const char * const msiof1_groups[] = {
+ "msiof1_clk_a",
+ "msiof1_sync_a",
+ "msiof1_ss1_a",
+ "msiof1_ss2_a",
+ "msiof1_txd_a",
+ "msiof1_rxd_a",
+ "msiof1_clk_b",
+ "msiof1_sync_b",
+ "msiof1_ss1_b",
+ "msiof1_ss2_b",
+ "msiof1_txd_b",
+ "msiof1_rxd_b",
+ "msiof1_clk_c",
+ "msiof1_sync_c",
+ "msiof1_ss1_c",
+ "msiof1_ss2_c",
+ "msiof1_txd_c",
+ "msiof1_rxd_c",
+ "msiof1_clk_d",
+ "msiof1_sync_d",
+ "msiof1_ss1_d",
+ "msiof1_ss2_d",
+ "msiof1_txd_d",
+ "msiof1_rxd_d",
+ "msiof1_clk_e",
+ "msiof1_sync_e",
+ "msiof1_ss1_e",
+ "msiof1_ss2_e",
+ "msiof1_txd_e",
+ "msiof1_rxd_e",
+ "msiof1_clk_f",
+ "msiof1_sync_f",
+ "msiof1_ss1_f",
+ "msiof1_ss2_f",
+ "msiof1_txd_f",
+ "msiof1_rxd_f",
+ "msiof1_clk_g",
+ "msiof1_sync_g",
+ "msiof1_ss1_g",
+ "msiof1_ss2_g",
+ "msiof1_txd_g",
+ "msiof1_rxd_g",
+};
+
+static const char * const msiof2_groups[] = {
+ "msiof2_clk_a",
+ "msiof2_sync_a",
+ "msiof2_ss1_a",
+ "msiof2_ss2_a",
+ "msiof2_txd_a",
+ "msiof2_rxd_a",
+ "msiof2_clk_b",
+ "msiof2_sync_b",
+ "msiof2_ss1_b",
+ "msiof2_ss2_b",
+ "msiof2_txd_b",
+ "msiof2_rxd_b",
+ "msiof2_clk_c",
+ "msiof2_sync_c",
+ "msiof2_ss1_c",
+ "msiof2_ss2_c",
+ "msiof2_txd_c",
+ "msiof2_rxd_c",
+ "msiof2_clk_d",
+ "msiof2_sync_d",
+ "msiof2_ss1_d",
+ "msiof2_ss2_d",
+ "msiof2_txd_d",
+ "msiof2_rxd_d",
+};
+
+static const char * const msiof3_groups[] = {
+ "msiof3_clk_a",
+ "msiof3_sync_a",
+ "msiof3_ss1_a",
+ "msiof3_ss2_a",
+ "msiof3_txd_a",
+ "msiof3_rxd_a",
+ "msiof3_clk_b",
+ "msiof3_sync_b",
+ "msiof3_ss1_b",
+ "msiof3_ss2_b",
+ "msiof3_txd_b",
+ "msiof3_rxd_b",
+ "msiof3_clk_c",
+ "msiof3_sync_c",
+ "msiof3_txd_c",
+ "msiof3_rxd_c",
+ "msiof3_clk_d",
+ "msiof3_sync_d",
+ "msiof3_ss1_d",
+ "msiof3_txd_d",
+ "msiof3_rxd_d",
+};
+
+static const char * const sata0_groups[] = {
+ "sata0_devslp_a",
+ "sata0_devslp_b",
+};
+
static const char * const scif0_groups[] = {
"scif0_data",
"scif0_clk",
@@ -2200,6 +3565,49 @@ static const char * const scif5_groups[] = {
"scif5_clk",
};
+static const char * const scif_clk_groups[] = {
+ "scif_clk_a",
+ "scif_clk_b",
+};
+
+static const char * const sdhi0_groups[] = {
+ "sdhi0_data1",
+ "sdhi0_data4",
+ "sdhi0_ctrl",
+ "sdhi0_cd",
+ "sdhi0_wp",
+};
+
+static const char * const sdhi1_groups[] = {
+ "sdhi1_data1",
+ "sdhi1_data4",
+ "sdhi1_ctrl",
+ "sdhi1_cd",
+ "sdhi1_wp",
+};
+
+static const char * const sdhi2_groups[] = {
+ "sdhi2_data1",
+ "sdhi2_data4",
+ "sdhi2_data8",
+ "sdhi2_ctrl",
+ "sdhi2_cd_a",
+ "sdhi2_wp_a",
+ "sdhi2_cd_b",
+ "sdhi2_wp_b",
+ "sdhi2_ds",
+};
+
+static const char * const sdhi3_groups[] = {
+ "sdhi3_data1",
+ "sdhi3_data4",
+ "sdhi3_data8",
+ "sdhi3_ctrl",
+ "sdhi3_cd",
+ "sdhi3_wp",
+ "sdhi3_ds",
+};
+
static const char * const ssi_groups[] = {
"ssi0_data",
"ssi01239_ctrl",
@@ -2231,15 +3639,30 @@ static const char * const ssi_groups[] = {
static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(audio_clk),
SH_PFC_FUNCTION(avb),
+ SH_PFC_FUNCTION(hscif0),
+ SH_PFC_FUNCTION(hscif1),
+ SH_PFC_FUNCTION(hscif2),
+ SH_PFC_FUNCTION(hscif3),
+ SH_PFC_FUNCTION(hscif4),
SH_PFC_FUNCTION(i2c1),
SH_PFC_FUNCTION(i2c2),
SH_PFC_FUNCTION(i2c6),
+ SH_PFC_FUNCTION(msiof0),
+ SH_PFC_FUNCTION(msiof1),
+ SH_PFC_FUNCTION(msiof2),
+ SH_PFC_FUNCTION(msiof3),
+ SH_PFC_FUNCTION(sata0),
SH_PFC_FUNCTION(scif0),
SH_PFC_FUNCTION(scif1),
SH_PFC_FUNCTION(scif2),
SH_PFC_FUNCTION(scif3),
SH_PFC_FUNCTION(scif4),
SH_PFC_FUNCTION(scif5),
+ SH_PFC_FUNCTION(scif_clk),
+ SH_PFC_FUNCTION(sdhi0),
+ SH_PFC_FUNCTION(sdhi1),
+ SH_PFC_FUNCTION(sdhi2),
+ SH_PFC_FUNCTION(sdhi3),
SH_PFC_FUNCTION(ssi),
};
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
index 6a69c8c5d943..d25e6f674d0a 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c
@@ -2059,7 +2059,7 @@ static const unsigned int lcd2_data9_mux[] = {
LCD2D8_MARK,
};
static const unsigned int lcd2_data12_pins[] = {
- /* D[0:12] */
+ /* D[0:11] */
128, 129, 142, 143, 144, 145, 138, 139,
140, 141, 130, 131,
};
@@ -2198,6 +2198,420 @@ static const unsigned int mmc0_ctrl_1_pins[] = {
static const unsigned int mmc0_ctrl_1_mux[] = {
MMCCMD1_MARK, MMCCLK1_MARK,
};
+/* - MSIOF0 ----------------------------------------------------------------- */
+static const unsigned int msiof0_rsck_pins[] = {
+ /* RSCK */
+ 66,
+};
+static const unsigned int msiof0_rsck_mux[] = {
+ MSIOF0_RSCK_MARK,
+};
+static const unsigned int msiof0_tsck_pins[] = {
+ /* TSCK */
+ 64,
+};
+static const unsigned int msiof0_tsck_mux[] = {
+ MSIOF0_TSCK_MARK,
+};
+static const unsigned int msiof0_rsync_pins[] = {
+ /* RSYNC */
+ 67,
+};
+static const unsigned int msiof0_rsync_mux[] = {
+ MSIOF0_RSYNC_MARK,
+};
+static const unsigned int msiof0_tsync_pins[] = {
+ /* TSYNC */
+ 63,
+};
+static const unsigned int msiof0_tsync_mux[] = {
+ MSIOF0_TSYNC_MARK,
+};
+static const unsigned int msiof0_ss1_pins[] = {
+ /* SS1 */
+ 62,
+};
+static const unsigned int msiof0_ss1_mux[] = {
+ MSIOF0_SS1_MARK,
+};
+static const unsigned int msiof0_ss2_pins[] = {
+ /* SS2 */
+ 71,
+};
+static const unsigned int msiof0_ss2_mux[] = {
+ MSIOF0_SS2_MARK,
+};
+static const unsigned int msiof0_rxd_pins[] = {
+ /* RXD */
+ 70,
+};
+static const unsigned int msiof0_rxd_mux[] = {
+ MSIOF0_RXD_MARK,
+};
+static const unsigned int msiof0_txd_pins[] = {
+ /* TXD */
+ 65,
+};
+static const unsigned int msiof0_txd_mux[] = {
+ MSIOF0_TXD_MARK,
+};
+static const unsigned int msiof0_mck0_pins[] = {
+ /* MSCK0 */
+ 68,
+};
+static const unsigned int msiof0_mck0_mux[] = {
+ MSIOF0_MCK0_MARK,
+};
+
+static const unsigned int msiof0_mck1_pins[] = {
+ /* MSCK1 */
+ 69,
+};
+static const unsigned int msiof0_mck1_mux[] = {
+ MSIOF0_MCK1_MARK,
+};
+
+static const unsigned int msiof0l_rsck_pins[] = {
+ /* RSCK */
+ 214,
+};
+static const unsigned int msiof0l_rsck_mux[] = {
+ MSIOF0L_RSCK_MARK,
+};
+static const unsigned int msiof0l_tsck_pins[] = {
+ /* TSCK */
+ 219,
+};
+static const unsigned int msiof0l_tsck_mux[] = {
+ MSIOF0L_TSCK_MARK,
+};
+static const unsigned int msiof0l_rsync_pins[] = {
+ /* RSYNC */
+ 215,
+};
+static const unsigned int msiof0l_rsync_mux[] = {
+ MSIOF0L_RSYNC_MARK,
+};
+static const unsigned int msiof0l_tsync_pins[] = {
+ /* TSYNC */
+ 217,
+};
+static const unsigned int msiof0l_tsync_mux[] = {
+ MSIOF0L_TSYNC_MARK,
+};
+static const unsigned int msiof0l_ss1_a_pins[] = {
+ /* SS1 */
+ 207,
+};
+static const unsigned int msiof0l_ss1_a_mux[] = {
+ PORT207_MSIOF0L_SS1_MARK,
+};
+static const unsigned int msiof0l_ss1_b_pins[] = {
+ /* SS1 */
+ 210,
+};
+static const unsigned int msiof0l_ss1_b_mux[] = {
+ PORT210_MSIOF0L_SS1_MARK,
+};
+static const unsigned int msiof0l_ss2_a_pins[] = {
+ /* SS2 */
+ 208,
+};
+static const unsigned int msiof0l_ss2_a_mux[] = {
+ PORT208_MSIOF0L_SS2_MARK,
+};
+static const unsigned int msiof0l_ss2_b_pins[] = {
+ /* SS2 */
+ 211,
+};
+static const unsigned int msiof0l_ss2_b_mux[] = {
+ PORT211_MSIOF0L_SS2_MARK,
+};
+static const unsigned int msiof0l_rxd_pins[] = {
+ /* RXD */
+ 221,
+};
+static const unsigned int msiof0l_rxd_mux[] = {
+ MSIOF0L_RXD_MARK,
+};
+static const unsigned int msiof0l_txd_pins[] = {
+ /* TXD */
+ 222,
+};
+static const unsigned int msiof0l_txd_mux[] = {
+ MSIOF0L_TXD_MARK,
+};
+static const unsigned int msiof0l_mck0_pins[] = {
+ /* MSCK0 */
+ 212,
+};
+static const unsigned int msiof0l_mck0_mux[] = {
+ MSIOF0L_MCK0_MARK,
+};
+static const unsigned int msiof0l_mck1_pins[] = {
+ /* MSCK1 */
+ 213,
+};
+static const unsigned int msiof0l_mck1_mux[] = {
+ MSIOF0L_MCK1_MARK,
+};
+/* - MSIOF1 ----------------------------------------------------------------- */
+static const unsigned int msiof1_rsck_pins[] = {
+ /* RSCK */
+ 234,
+};
+static const unsigned int msiof1_rsck_mux[] = {
+ MSIOF1_RSCK_MARK,
+};
+static const unsigned int msiof1_tsck_pins[] = {
+ /* TSCK */
+ 232,
+};
+static const unsigned int msiof1_tsck_mux[] = {
+ MSIOF1_TSCK_MARK,
+};
+static const unsigned int msiof1_rsync_pins[] = {
+ /* RSYNC */
+ 235,
+};
+static const unsigned int msiof1_rsync_mux[] = {
+ MSIOF1_RSYNC_MARK,
+};
+static const unsigned int msiof1_tsync_pins[] = {
+ /* TSYNC */
+ 231,
+};
+static const unsigned int msiof1_tsync_mux[] = {
+ MSIOF1_TSYNC_MARK,
+};
+static const unsigned int msiof1_ss1_pins[] = {
+ /* SS1 */
+ 238,
+};
+static const unsigned int msiof1_ss1_mux[] = {
+ MSIOF1_SS1_MARK,
+};
+static const unsigned int msiof1_ss2_pins[] = {
+ /* SS2 */
+ 239,
+};
+static const unsigned int msiof1_ss2_mux[] = {
+ MSIOF1_SS2_MARK,
+};
+static const unsigned int msiof1_rxd_pins[] = {
+ /* RXD */
+ 233,
+};
+static const unsigned int msiof1_rxd_mux[] = {
+ MSIOF1_RXD_MARK,
+};
+static const unsigned int msiof1_txd_pins[] = {
+ /* TXD */
+ 230,
+};
+static const unsigned int msiof1_txd_mux[] = {
+ MSIOF1_TXD_MARK,
+};
+static const unsigned int msiof1_mck0_pins[] = {
+ /* MSCK0 */
+ 236,
+};
+static const unsigned int msiof1_mck0_mux[] = {
+ MSIOF1_MCK0_MARK,
+};
+static const unsigned int msiof1_mck1_pins[] = {
+ /* MSCK1 */
+ 237,
+};
+static const unsigned int msiof1_mck1_mux[] = {
+ MSIOF1_MCK1_MARK,
+};
+/* - MSIOF2 ----------------------------------------------------------------- */
+static const unsigned int msiof2_rsck_pins[] = {
+ /* RSCK */
+ 151,
+};
+static const unsigned int msiof2_rsck_mux[] = {
+ MSIOF2_RSCK_MARK,
+};
+static const unsigned int msiof2_tsck_pins[] = {
+ /* TSCK */
+ 135,
+};
+static const unsigned int msiof2_tsck_mux[] = {
+ MSIOF2_TSCK_MARK,
+};
+static const unsigned int msiof2_rsync_pins[] = {
+ /* RSYNC */
+ 152,
+};
+static const unsigned int msiof2_rsync_mux[] = {
+ MSIOF2_RSYNC_MARK,
+};
+static const unsigned int msiof2_tsync_pins[] = {
+ /* TSYNC */
+ 133,
+};
+static const unsigned int msiof2_tsync_mux[] = {
+ MSIOF2_TSYNC_MARK,
+};
+static const unsigned int msiof2_ss1_a_pins[] = {
+ /* SS1 */
+ 131,
+};
+static const unsigned int msiof2_ss1_a_mux[] = {
+ PORT131_MSIOF2_SS1_MARK,
+};
+static const unsigned int msiof2_ss1_b_pins[] = {
+ /* SS1 */
+ 153,
+};
+static const unsigned int msiof2_ss1_b_mux[] = {
+ PORT153_MSIOF2_SS1_MARK,
+};
+static const unsigned int msiof2_ss2_a_pins[] = {
+ /* SS2 */
+ 132,
+};
+static const unsigned int msiof2_ss2_a_mux[] = {
+ PORT132_MSIOF2_SS2_MARK,
+};
+static const unsigned int msiof2_ss2_b_pins[] = {
+ /* SS2 */
+ 156,
+};
+static const unsigned int msiof2_ss2_b_mux[] = {
+ PORT156_MSIOF2_SS2_MARK,
+};
+static const unsigned int msiof2_rxd_a_pins[] = {
+ /* RXD */
+ 130,
+};
+static const unsigned int msiof2_rxd_a_mux[] = {
+ PORT130_MSIOF2_RXD_MARK,
+};
+static const unsigned int msiof2_rxd_b_pins[] = {
+ /* RXD */
+ 157,
+};
+static const unsigned int msiof2_rxd_b_mux[] = {
+ PORT157_MSIOF2_RXD_MARK,
+};
+static const unsigned int msiof2_txd_pins[] = {
+ /* TXD */
+ 134,
+};
+static const unsigned int msiof2_txd_mux[] = {
+ MSIOF2_TXD_MARK,
+};
+static const unsigned int msiof2_mck0_pins[] = {
+ /* MSCK0 */
+ 154,
+};
+static const unsigned int msiof2_mck0_mux[] = {
+ MSIOF2_MCK0_MARK,
+};
+static const unsigned int msiof2_mck1_pins[] = {
+ /* MSCK1 */
+ 155,
+};
+static const unsigned int msiof2_mck1_mux[] = {
+ MSIOF2_MCK1_MARK,
+};
+
+static const unsigned int msiof2r_tsck_pins[] = {
+ /* TSCK */
+ 248,
+};
+static const unsigned int msiof2r_tsck_mux[] = {
+ MSIOF2R_TSCK_MARK,
+};
+static const unsigned int msiof2r_tsync_pins[] = {
+ /* TSYNC */
+ 249,
+};
+static const unsigned int msiof2r_tsync_mux[] = {
+ MSIOF2R_TSYNC_MARK,
+};
+static const unsigned int msiof2r_rxd_pins[] = {
+ /* RXD */
+ 244,
+};
+static const unsigned int msiof2r_rxd_mux[] = {
+ MSIOF2R_RXD_MARK,
+};
+static const unsigned int msiof2r_txd_pins[] = {
+ /* TXD */
+ 245,
+};
+static const unsigned int msiof2r_txd_mux[] = {
+ MSIOF2R_TXD_MARK,
+};
+/* - MSIOF3 (Pin function name of MSIOF3 is named BBIF1) -------------------- */
+static const unsigned int msiof3_rsck_pins[] = {
+ /* RSCK */
+ 115,
+};
+static const unsigned int msiof3_rsck_mux[] = {
+ BBIF1_RSCK_MARK,
+};
+static const unsigned int msiof3_tsck_pins[] = {
+ /* TSCK */
+ 112,
+};
+static const unsigned int msiof3_tsck_mux[] = {
+ BBIF1_TSCK_MARK,
+};
+static const unsigned int msiof3_rsync_pins[] = {
+ /* RSYNC */
+ 116,
+};
+static const unsigned int msiof3_rsync_mux[] = {
+ BBIF1_RSYNC_MARK,
+};
+static const unsigned int msiof3_tsync_pins[] = {
+ /* TSYNC */
+ 113,
+};
+static const unsigned int msiof3_tsync_mux[] = {
+ BBIF1_TSYNC_MARK,
+};
+static const unsigned int msiof3_ss1_pins[] = {
+ /* SS1 */
+ 117,
+};
+static const unsigned int msiof3_ss1_mux[] = {
+ BBIF1_SS1_MARK,
+};
+static const unsigned int msiof3_ss2_pins[] = {
+ /* SS2 */
+ 109,
+};
+static const unsigned int msiof3_ss2_mux[] = {
+ BBIF1_SS2_MARK,
+};
+static const unsigned int msiof3_rxd_pins[] = {
+ /* RXD */
+ 111,
+};
+static const unsigned int msiof3_rxd_mux[] = {
+ BBIF1_RXD_MARK,
+};
+static const unsigned int msiof3_txd_pins[] = {
+ /* TXD */
+ 114,
+};
+static const unsigned int msiof3_txd_mux[] = {
+ BBIF1_TXD_MARK,
+};
+static const unsigned int msiof3_flow_pins[] = {
+ /* FLOW */
+ 117,
+};
+static const unsigned int msiof3_flow_mux[] = {
+ BBIF1_FLOW_MARK,
+};
+
/* - SCIFA0 ----------------------------------------------------------------- */
static const unsigned int scifa0_data_pins[] = {
/* RXD, TXD */
@@ -2782,6 +3196,64 @@ static const struct sh_pfc_pin_group pinmux_groups[] = {
SH_PFC_PIN_GROUP(mmc0_data4_1),
SH_PFC_PIN_GROUP(mmc0_data8_1),
SH_PFC_PIN_GROUP(mmc0_ctrl_1),
+ SH_PFC_PIN_GROUP(msiof0_rsck),
+ SH_PFC_PIN_GROUP(msiof0_tsck),
+ SH_PFC_PIN_GROUP(msiof0_rsync),
+ SH_PFC_PIN_GROUP(msiof0_tsync),
+ SH_PFC_PIN_GROUP(msiof0_ss1),
+ SH_PFC_PIN_GROUP(msiof0_ss2),
+ SH_PFC_PIN_GROUP(msiof0_rxd),
+ SH_PFC_PIN_GROUP(msiof0_txd),
+ SH_PFC_PIN_GROUP(msiof0_mck0),
+ SH_PFC_PIN_GROUP(msiof0_mck1),
+ SH_PFC_PIN_GROUP(msiof0l_rsck),
+ SH_PFC_PIN_GROUP(msiof0l_tsck),
+ SH_PFC_PIN_GROUP(msiof0l_rsync),
+ SH_PFC_PIN_GROUP(msiof0l_tsync),
+ SH_PFC_PIN_GROUP(msiof0l_ss1_a),
+ SH_PFC_PIN_GROUP(msiof0l_ss1_b),
+ SH_PFC_PIN_GROUP(msiof0l_ss2_a),
+ SH_PFC_PIN_GROUP(msiof0l_ss2_b),
+ SH_PFC_PIN_GROUP(msiof0l_rxd),
+ SH_PFC_PIN_GROUP(msiof0l_txd),
+ SH_PFC_PIN_GROUP(msiof0l_mck0),
+ SH_PFC_PIN_GROUP(msiof0l_mck1),
+ SH_PFC_PIN_GROUP(msiof1_rsck),
+ SH_PFC_PIN_GROUP(msiof1_tsck),
+ SH_PFC_PIN_GROUP(msiof1_rsync),
+ SH_PFC_PIN_GROUP(msiof1_tsync),
+ SH_PFC_PIN_GROUP(msiof1_ss1),
+ SH_PFC_PIN_GROUP(msiof1_ss2),
+ SH_PFC_PIN_GROUP(msiof1_rxd),
+ SH_PFC_PIN_GROUP(msiof1_txd),
+ SH_PFC_PIN_GROUP(msiof1_mck0),
+ SH_PFC_PIN_GROUP(msiof1_mck1),
+ SH_PFC_PIN_GROUP(msiof2_rsck),
+ SH_PFC_PIN_GROUP(msiof2_tsck),
+ SH_PFC_PIN_GROUP(msiof2_rsync),
+ SH_PFC_PIN_GROUP(msiof2_tsync),
+ SH_PFC_PIN_GROUP(msiof2_ss1_a),
+ SH_PFC_PIN_GROUP(msiof2_ss1_b),
+ SH_PFC_PIN_GROUP(msiof2_ss2_a),
+ SH_PFC_PIN_GROUP(msiof2_ss2_b),
+ SH_PFC_PIN_GROUP(msiof2_rxd_a),
+ SH_PFC_PIN_GROUP(msiof2_rxd_b),
+ SH_PFC_PIN_GROUP(msiof2_txd),
+ SH_PFC_PIN_GROUP(msiof2_mck0),
+ SH_PFC_PIN_GROUP(msiof2_mck1),
+ SH_PFC_PIN_GROUP(msiof2r_tsck),
+ SH_PFC_PIN_GROUP(msiof2r_tsync),
+ SH_PFC_PIN_GROUP(msiof2r_rxd),
+ SH_PFC_PIN_GROUP(msiof2r_txd),
+ SH_PFC_PIN_GROUP(msiof3_rsck),
+ SH_PFC_PIN_GROUP(msiof3_tsck),
+ SH_PFC_PIN_GROUP(msiof3_rsync),
+ SH_PFC_PIN_GROUP(msiof3_tsync),
+ SH_PFC_PIN_GROUP(msiof3_ss1),
+ SH_PFC_PIN_GROUP(msiof3_ss2),
+ SH_PFC_PIN_GROUP(msiof3_rxd),
+ SH_PFC_PIN_GROUP(msiof3_txd),
+ SH_PFC_PIN_GROUP(msiof3_flow),
SH_PFC_PIN_GROUP(scifa0_data),
SH_PFC_PIN_GROUP(scifa0_clk),
SH_PFC_PIN_GROUP(scifa0_ctrl),
@@ -2982,6 +3454,76 @@ static const char * const mmc0_groups[] = {
"mmc0_ctrl_1",
};
+static const char * const msiof0_groups[] = {
+ "msiof0_rsck",
+ "msiof0_tsck",
+ "msiof0_rsync",
+ "msiof0_tsync",
+ "msiof0_ss1",
+ "msiof0_ss2",
+ "msiof0_rxd",
+ "msiof0_txd",
+ "msiof0_mck0",
+ "msiof0_mck1",
+ "msiof0l_rsck",
+ "msiof0l_tsck",
+ "msiof0l_rsync",
+ "msiof0l_tsync",
+ "msiof0l_ss1_a",
+ "msiof0l_ss1_b",
+ "msiof0l_ss2_a",
+ "msiof0l_ss2_b",
+ "msiof0l_rxd",
+ "msiof0l_txd",
+ "msiof0l_mck0",
+ "msiof0l_mck1",
+};
+
+static const char * const msiof1_groups[] = {
+ "msiof1_rsck",
+ "msiof1_tsck",
+ "msiof1_rsync",
+ "msiof1_tsync",
+ "msiof1_ss1",
+ "msiof1_ss2",
+ "msiof1_rxd",
+ "msiof1_txd",
+ "msiof1_mck0",
+ "msiof1_mck1",
+};
+
+static const char * const msiof2_groups[] = {
+ "msiof2_rsck",
+ "msiof2_tsck",
+ "msiof2_rsync",
+ "msiof2_tsync",
+ "msiof2_ss1_a",
+ "msiof2_ss1_b",
+ "msiof2_ss2_a",
+ "msiof2_ss2_b",
+ "msiof2_rxd_a",
+ "msiof2_rxd_b",
+ "msiof2_txd",
+ "msiof2_mck0",
+ "msiof2_mck1",
+ "msiof2r_tsck",
+ "msiof2r_tsync",
+ "msiof2r_rxd",
+ "msiof2r_txd",
+};
+
+static const char * const msiof3_groups[] = {
+ "msiof3_rsck",
+ "msiof3_tsck",
+ "msiof3_rsync",
+ "msiof3_tsync",
+ "msiof3_ss1",
+ "msiof3_ss2",
+ "msiof3_rxd",
+ "msiof3_txd",
+ "msiof3_flow",
+};
+
static const char * const scifa0_groups[] = {
"scifa0_data",
"scifa0_clk",
@@ -3116,6 +3658,10 @@ static const struct sh_pfc_function pinmux_functions[] = {
SH_PFC_FUNCTION(lcd),
SH_PFC_FUNCTION(lcd2),
SH_PFC_FUNCTION(mmc0),
+ SH_PFC_FUNCTION(msiof0),
+ SH_PFC_FUNCTION(msiof1),
+ SH_PFC_FUNCTION(msiof2),
+ SH_PFC_FUNCTION(msiof3),
SH_PFC_FUNCTION(scifa0),
SH_PFC_FUNCTION(scifa1),
SH_PFC_FUNCTION(scifa2),
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh7734.c b/drivers/pinctrl/sh-pfc/pfc-sh7734.c
index 9842bb106796..b0b328b3130b 100644
--- a/drivers/pinctrl/sh-pfc/pfc-sh7734.c
+++ b/drivers/pinctrl/sh-pfc/pfc-sh7734.c
@@ -14,14 +14,6 @@
#include "sh_pfc.h"
-#define PORT_GP_12(bank, fn, sfx) \
- PORT_GP_1(bank, 0, fn, sfx), PORT_GP_1(bank, 1, fn, sfx), \
- PORT_GP_1(bank, 2, fn, sfx), PORT_GP_1(bank, 3, fn, sfx), \
- PORT_GP_1(bank, 4, fn, sfx), PORT_GP_1(bank, 5, fn, sfx), \
- PORT_GP_1(bank, 6, fn, sfx), PORT_GP_1(bank, 7, fn, sfx), \
- PORT_GP_1(bank, 8, fn, sfx), PORT_GP_1(bank, 9, fn, sfx), \
- PORT_GP_1(bank, 10, fn, sfx), PORT_GP_1(bank, 11, fn, sfx)
-
#define CPU_ALL_PORT(fn, sfx) \
PORT_GP_32(0, fn, sfx), \
PORT_GP_32(1, fn, sfx), \
@@ -585,15 +577,18 @@ enum {
static const u16 pinmux_data[] = {
PINMUX_DATA_GP_ALL(), /* PINMUX_DATA(GP_M_N_DATA, GP_M_N_FN...), */
- PINMUX_DATA(CLKOUT_MARK, FN_CLKOUT),
- PINMUX_DATA(BS_MARK, FN_BS), PINMUX_DATA(CS0_MARK, FN_CS0),
- PINMUX_DATA(EX_CS0_MARK, FN_EX_CS0),
- PINMUX_DATA(RD_MARK, FN_RD), PINMUX_DATA(WE0_MARK, FN_WE0),
- PINMUX_DATA(WE1_MARK, FN_WE1),
- PINMUX_DATA(SCL0_MARK, FN_SCL0), PINMUX_DATA(PENC0_MARK, FN_PENC0),
- PINMUX_DATA(USB_OVC0_MARK, FN_USB_OVC0),
- PINMUX_DATA(IRQ2_B_MARK, FN_IRQ2_B),
- PINMUX_DATA(IRQ3_B_MARK, FN_IRQ3_B),
+ PINMUX_SINGLE(CLKOUT),
+ PINMUX_SINGLE(BS),
+ PINMUX_SINGLE(CS0),
+ PINMUX_SINGLE(EX_CS0),
+ PINMUX_SINGLE(RD),
+ PINMUX_SINGLE(WE0),
+ PINMUX_SINGLE(WE1),
+ PINMUX_SINGLE(SCL0),
+ PINMUX_SINGLE(PENC0),
+ PINMUX_SINGLE(USB_OVC0),
+ PINMUX_SINGLE(IRQ2_B),
+ PINMUX_SINGLE(IRQ3_B),
/* IPSR0 */
PINMUX_IPSR_DATA(IP0_1_0, A0),
diff --git a/drivers/pinctrl/sh-pfc/pinctrl.c b/drivers/pinctrl/sh-pfc/pinctrl.c
index 863c3e30ce05..87b0a599afaf 100644
--- a/drivers/pinctrl/sh-pfc/pinctrl.c
+++ b/drivers/pinctrl/sh-pfc/pinctrl.c
@@ -273,8 +273,10 @@ static int sh_pfc_dt_node_to_map(struct pinctrl_dev *pctldev,
for_each_child_of_node(np, child) {
ret = sh_pfc_dt_subnode_to_map(pctldev, child, map, num_maps,
&index);
- if (ret < 0)
+ if (ret < 0) {
+ of_node_put(child);
goto done;
+ }
}
/* If no mapping has been found in child nodes try the config node. */
diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h
index 7b373d43d981..2123ab49d6a5 100644
--- a/drivers/pinctrl/sh-pfc/sh_pfc.h
+++ b/drivers/pinctrl/sh-pfc/sh_pfc.h
@@ -199,28 +199,82 @@ struct sh_pfc_soc_info {
PINMUX_DATA(fn##_MARK, FN_##ms, FN_##ipsr, FN_##fn)
/*
+ * Describe a pinmux configuration for a single-function pin with GPIO
+ * capability.
+ * - fn: Function name
+ */
+#define PINMUX_SINGLE(fn) \
+ PINMUX_DATA(fn##_MARK, FN_##fn)
+
+/*
* GP port style (32 ports banks)
*/
#define PORT_GP_CFG_1(bank, pin, fn, sfx, cfg) fn(bank, pin, GP_##bank##_##pin, sfx, cfg)
#define PORT_GP_1(bank, pin, fn, sfx) PORT_GP_CFG_1(bank, pin, fn, sfx, 0)
-#define PORT_GP_CFG_32(bank, fn, sfx, cfg) \
+#define PORT_GP_CFG_4(bank, fn, sfx, cfg) \
PORT_GP_CFG_1(bank, 0, fn, sfx, cfg), PORT_GP_CFG_1(bank, 1, fn, sfx, cfg), \
- PORT_GP_CFG_1(bank, 2, fn, sfx, cfg), PORT_GP_CFG_1(bank, 3, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 2, fn, sfx, cfg), PORT_GP_CFG_1(bank, 3, fn, sfx, cfg)
+#define PORT_GP_4(bank, fn, sfx) PORT_GP_CFG_4(bank, fn, sfx, 0)
+
+#define PORT_GP_CFG_8(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_4(bank, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 4, fn, sfx, cfg), PORT_GP_CFG_1(bank, 5, fn, sfx, cfg), \
- PORT_GP_CFG_1(bank, 6, fn, sfx, cfg), PORT_GP_CFG_1(bank, 7, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 6, fn, sfx, cfg), PORT_GP_CFG_1(bank, 7, fn, sfx, cfg)
+#define PORT_GP_8(bank, fn, sfx) PORT_GP_CFG_8(bank, fn, sfx, 0)
+
+#define PORT_GP_CFG_9(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_8(bank, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 8, fn, sfx, cfg)
+#define PORT_GP_9(bank, fn, sfx) PORT_GP_CFG_9(bank, fn, sfx, 0)
+
+#define PORT_GP_CFG_12(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_8(bank, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 8, fn, sfx, cfg), PORT_GP_CFG_1(bank, 9, fn, sfx, cfg), \
- PORT_GP_CFG_1(bank, 10, fn, sfx, cfg), PORT_GP_CFG_1(bank, 11, fn, sfx, cfg), \
- PORT_GP_CFG_1(bank, 12, fn, sfx, cfg), PORT_GP_CFG_1(bank, 13, fn, sfx, cfg), \
- PORT_GP_CFG_1(bank, 14, fn, sfx, cfg), PORT_GP_CFG_1(bank, 15, fn, sfx, cfg), \
- PORT_GP_CFG_1(bank, 16, fn, sfx, cfg), PORT_GP_CFG_1(bank, 17, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 10, fn, sfx, cfg), PORT_GP_CFG_1(bank, 11, fn, sfx, cfg)
+#define PORT_GP_12(bank, fn, sfx) PORT_GP_CFG_12(bank, fn, sfx, 0)
+
+#define PORT_GP_CFG_14(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_12(bank, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 12, fn, sfx, cfg), PORT_GP_CFG_1(bank, 13, fn, sfx, cfg)
+#define PORT_GP_14(bank, fn, sfx) PORT_GP_CFG_14(bank, fn, sfx, 0)
+
+#define PORT_GP_CFG_15(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_14(bank, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 14, fn, sfx, cfg)
+#define PORT_GP_15(bank, fn, sfx) PORT_GP_CFG_15(bank, fn, sfx, 0)
+
+#define PORT_GP_CFG_16(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_14(bank, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 14, fn, sfx, cfg), PORT_GP_CFG_1(bank, 15, fn, sfx, cfg)
+#define PORT_GP_16(bank, fn, sfx) PORT_GP_CFG_16(bank, fn, sfx, 0)
+
+#define PORT_GP_CFG_18(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_16(bank, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 16, fn, sfx, cfg), PORT_GP_CFG_1(bank, 17, fn, sfx, cfg)
+#define PORT_GP_18(bank, fn, sfx) PORT_GP_CFG_18(bank, fn, sfx, 0)
+
+#define PORT_GP_CFG_26(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_18(bank, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 18, fn, sfx, cfg), PORT_GP_CFG_1(bank, 19, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 20, fn, sfx, cfg), PORT_GP_CFG_1(bank, 21, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 22, fn, sfx, cfg), PORT_GP_CFG_1(bank, 23, fn, sfx, cfg), \
- PORT_GP_CFG_1(bank, 24, fn, sfx, cfg), PORT_GP_CFG_1(bank, 25, fn, sfx, cfg), \
- PORT_GP_CFG_1(bank, 26, fn, sfx, cfg), PORT_GP_CFG_1(bank, 27, fn, sfx, cfg), \
- PORT_GP_CFG_1(bank, 28, fn, sfx, cfg), PORT_GP_CFG_1(bank, 29, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 24, fn, sfx, cfg), PORT_GP_CFG_1(bank, 25, fn, sfx, cfg)
+#define PORT_GP_26(bank, fn, sfx) PORT_GP_CFG_26(bank, fn, sfx, 0)
+
+#define PORT_GP_CFG_28(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_26(bank, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 26, fn, sfx, cfg), PORT_GP_CFG_1(bank, 27, fn, sfx, cfg)
+#define PORT_GP_28(bank, fn, sfx) PORT_GP_CFG_28(bank, fn, sfx, 0)
+
+#define PORT_GP_CFG_30(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_28(bank, fn, sfx, cfg), \
+ PORT_GP_CFG_1(bank, 28, fn, sfx, cfg), PORT_GP_CFG_1(bank, 29, fn, sfx, cfg)
+#define PORT_GP_30(bank, fn, sfx) PORT_GP_CFG_30(bank, fn, sfx, 0)
+
+#define PORT_GP_CFG_32(bank, fn, sfx, cfg) \
+ PORT_GP_CFG_30(bank, fn, sfx, cfg), \
PORT_GP_CFG_1(bank, 30, fn, sfx, cfg), PORT_GP_CFG_1(bank, 31, fn, sfx, cfg)
#define PORT_GP_32(bank, fn, sfx) PORT_GP_CFG_32(bank, fn, sfx, 0)
diff --git a/drivers/pinctrl/sirf/pinctrl-atlas7.c b/drivers/pinctrl/sirf/pinctrl-atlas7.c
index 829018c812bd..053d98e33944 100644
--- a/drivers/pinctrl/sirf/pinctrl-atlas7.c
+++ b/drivers/pinctrl/sirf/pinctrl-atlas7.c
@@ -161,6 +161,9 @@ enum altas7_pad_type {
#define IN_DISABLE_VAL_1_REG_SET 0x0A88
#define IN_DISABLE_VAL_1_REG_CLR 0x0A8C
+/* Offset of the SDIO9SEL*/
+#define SYS2PCI_SDIO9SEL 0x14
+
struct dt_params {
const char *property;
int value;
@@ -370,6 +373,7 @@ struct atlas7_pmx {
struct pinctrl_desc pctl_desc;
struct atlas7_pinctrl_data *pctl_data;
void __iomem *regs[ATLAS7_PINCTRL_REG_BANKS];
+ void __iomem *sys2pci_base;
u32 status_ds[NUM_OF_IN_DISABLE_REG];
u32 status_dsv[NUM_OF_IN_DISABLE_REG];
struct atlas7_pad_status sleep_data[ATLAS7_PINCTRL_TOTAL_PINS];
@@ -885,11 +889,12 @@ static const unsigned int lr_lcdrom_pins[] = { 73, 54, 57, 58, 59, 60, 61,
62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 56, 53, 55, };
static const unsigned int lvds_analog_pins[] = { 149, 150, 151, 152, 153, 154,
155, 156, 157, 158, };
-static const unsigned int nd_df_pins[] = { 44, 43, 42, 41, 40, 39, 38, 37,
- 47, 46, 52, 51, 45, 49, 50, 48, 124, };
-static const unsigned int nd_df_nowp_pins[] = { 44, 43, 42, 41, 40, 39, 38,
- 37, 47, 46, 52, 51, 45, 49, 50, 48, };
+static const unsigned int nd_df_basic_pins[] = { 44, 43, 42, 41, 40, 39, 38,
+ 37, 47, 46, 52, 45, 49, 50, 48, };
+static const unsigned int nd_df_wp_pins[] = { 124, };
+static const unsigned int nd_df_cs_pins[] = { 51, };
static const unsigned int ps_pins[] = { 120, 119, 121, };
+static const unsigned int ps_no_dir_pins[] = { 119, };
static const unsigned int pwc_core_on_pins[] = { 8, };
static const unsigned int pwc_ext_on_pins[] = { 6, };
static const unsigned int pwc_gpio3_clk_pins[] = { 3, };
@@ -944,7 +949,7 @@ static const unsigned int sd2_cdb_pins0[] = { 124, };
static const unsigned int sd2_cdb_pins1[] = { 161, };
static const unsigned int sd2_wpb_pins0[] = { 123, };
static const unsigned int sd2_wpb_pins1[] = { 163, };
-static const unsigned int sd3_pins[] = { 85, 86, 87, 88, 89, 90, };
+static const unsigned int sd3_9_pins[] = { 85, 86, 87, 88, 89, 90, };
static const unsigned int sd5_pins[] = { 91, 92, 93, 94, 95, 96, };
static const unsigned int sd6_pins0[] = { 79, 78, 74, 75, 76, 77, };
static const unsigned int sd6_pins1[] = { 101, 99, 100, 110, 109, 111, };
@@ -998,9 +1003,9 @@ static const unsigned int vi_vip1_ext_pins[] = { 74, 75, 76, 77, 78, 79, 80,
81, 82, 83, 84, 108, 103, 104, 105, 106, 107, 102, 97, 98,
99, 100, };
static const unsigned int vi_vip1_low8bit_pins[] = { 74, 75, 76, 77, 78, 79,
- 80, 81, };
-static const unsigned int vi_vip1_high8bit_pins[] = { 82, 83, 84, 108, 103,
- 104, 105, 106, };
+ 80, 81, 82, 83, 84, };
+static const unsigned int vi_vip1_high8bit_pins[] = { 82, 83, 84, 103, 104,
+ 105, 106, 107, 102, 97, 98, };
/* definition of pin group table */
struct atlas7_pin_group altas7_pin_groups[] = {
@@ -1142,9 +1147,11 @@ struct atlas7_pin_group altas7_pin_groups[] = {
GROUP("ld_ldd_lck_grp", ld_ldd_lck_pins),
GROUP("lr_lcdrom_grp", lr_lcdrom_pins),
GROUP("lvds_analog_grp", lvds_analog_pins),
- GROUP("nd_df_grp", nd_df_pins),
- GROUP("nd_df_nowp_grp", nd_df_nowp_pins),
+ GROUP("nd_df_basic_grp", nd_df_basic_pins),
+ GROUP("nd_df_wp_grp", nd_df_wp_pins),
+ GROUP("nd_df_cs_grp", nd_df_cs_pins),
GROUP("ps_grp", ps_pins),
+ GROUP("ps_no_dir_grp", ps_no_dir_pins),
GROUP("pwc_core_on_grp", pwc_core_on_pins),
GROUP("pwc_ext_on_grp", pwc_ext_on_pins),
GROUP("pwc_gpio3_clk_grp", pwc_gpio3_clk_pins),
@@ -1196,7 +1203,7 @@ struct atlas7_pin_group altas7_pin_groups[] = {
GROUP("sd2_cdb_grp1", sd2_cdb_pins1),
GROUP("sd2_wpb_grp0", sd2_wpb_pins0),
GROUP("sd2_wpb_grp1", sd2_wpb_pins1),
- GROUP("sd3_grp", sd3_pins),
+ GROUP("sd3_9_grp", sd3_9_pins),
GROUP("sd5_grp", sd5_pins),
GROUP("sd6_grp0", sd6_pins0),
GROUP("sd6_grp1", sd6_pins1),
@@ -1421,9 +1428,11 @@ static const char * const ld_ldd_fck_grp[] = { "ld_ldd_fck_grp", };
static const char * const ld_ldd_lck_grp[] = { "ld_ldd_lck_grp", };
static const char * const lr_lcdrom_grp[] = { "lr_lcdrom_grp", };
static const char * const lvds_analog_grp[] = { "lvds_analog_grp", };
-static const char * const nd_df_grp[] = { "nd_df_grp", };
-static const char * const nd_df_nowp_grp[] = { "nd_df_nowp_grp", };
+static const char * const nd_df_basic_grp[] = { "nd_df_basic_grp", };
+static const char * const nd_df_wp_grp[] = { "nd_df_wp_grp", };
+static const char * const nd_df_cs_grp[] = { "nd_df_cs_grp", };
static const char * const ps_grp[] = { "ps_grp", };
+static const char * const ps_no_dir_grp[] = { "ps_no_dir_grp", };
static const char * const pwc_core_on_grp[] = { "pwc_core_on_grp", };
static const char * const pwc_ext_on_grp[] = { "pwc_ext_on_grp", };
static const char * const pwc_gpio3_clk_grp[] = { "pwc_gpio3_clk_grp", };
@@ -1478,7 +1487,7 @@ static const char * const sd2_cdb_grp0[] = { "sd2_cdb_grp0", };
static const char * const sd2_cdb_grp1[] = { "sd2_cdb_grp1", };
static const char * const sd2_wpb_grp0[] = { "sd2_wpb_grp0", };
static const char * const sd2_wpb_grp1[] = { "sd2_wpb_grp1", };
-static const char * const sd3_grp[] = { "sd3_grp", };
+static const char * const sd3_9_grp[] = { "sd3_9_grp", };
static const char * const sd5_grp[] = { "sd5_grp", };
static const char * const sd6_grp0[] = { "sd6_grp0", };
static const char * const sd6_grp1[] = { "sd6_grp1", };
@@ -3174,7 +3183,7 @@ static struct atlas7_grp_mux lvds_analog_grp_mux = {
.pad_mux_list = lvds_analog_grp_pad_mux,
};
-static struct atlas7_pad_mux nd_df_grp_pad_mux[] = {
+static struct atlas7_pad_mux nd_df_basic_grp_pad_mux[] = {
MUX(1, 44, 1, N, N, N, N),
MUX(1, 43, 1, N, N, N, N),
MUX(1, 42, 1, N, N, N, N),
@@ -3186,41 +3195,33 @@ static struct atlas7_pad_mux nd_df_grp_pad_mux[] = {
MUX(1, 47, 1, N, N, N, N),
MUX(1, 46, 1, N, N, N, N),
MUX(1, 52, 1, N, N, N, N),
- MUX(1, 51, 1, N, N, N, N),
MUX(1, 45, 1, N, N, N, N),
MUX(1, 49, 1, N, N, N, N),
MUX(1, 50, 1, N, N, N, N),
MUX(1, 48, 1, N, N, N, N),
+};
+
+static struct atlas7_grp_mux nd_df_basic_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(nd_df_basic_grp_pad_mux),
+ .pad_mux_list = nd_df_basic_grp_pad_mux,
+};
+
+static struct atlas7_pad_mux nd_df_wp_grp_pad_mux[] = {
MUX(1, 124, 4, N, N, N, N),
};
-static struct atlas7_grp_mux nd_df_grp_mux = {
- .pad_mux_count = ARRAY_SIZE(nd_df_grp_pad_mux),
- .pad_mux_list = nd_df_grp_pad_mux,
+static struct atlas7_grp_mux nd_df_wp_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(nd_df_wp_grp_pad_mux),
+ .pad_mux_list = nd_df_wp_grp_pad_mux,
};
-static struct atlas7_pad_mux nd_df_nowp_grp_pad_mux[] = {
- MUX(1, 44, 1, N, N, N, N),
- MUX(1, 43, 1, N, N, N, N),
- MUX(1, 42, 1, N, N, N, N),
- MUX(1, 41, 1, N, N, N, N),
- MUX(1, 40, 1, N, N, N, N),
- MUX(1, 39, 1, N, N, N, N),
- MUX(1, 38, 1, N, N, N, N),
- MUX(1, 37, 1, N, N, N, N),
- MUX(1, 47, 1, N, N, N, N),
- MUX(1, 46, 1, N, N, N, N),
- MUX(1, 52, 1, N, N, N, N),
+static struct atlas7_pad_mux nd_df_cs_grp_pad_mux[] = {
MUX(1, 51, 1, N, N, N, N),
- MUX(1, 45, 1, N, N, N, N),
- MUX(1, 49, 1, N, N, N, N),
- MUX(1, 50, 1, N, N, N, N),
- MUX(1, 48, 1, N, N, N, N),
};
-static struct atlas7_grp_mux nd_df_nowp_grp_mux = {
- .pad_mux_count = ARRAY_SIZE(nd_df_nowp_grp_pad_mux),
- .pad_mux_list = nd_df_nowp_grp_pad_mux,
+static struct atlas7_grp_mux nd_df_cs_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(nd_df_cs_grp_pad_mux),
+ .pad_mux_list = nd_df_cs_grp_pad_mux,
};
static struct atlas7_pad_mux ps_grp_pad_mux[] = {
@@ -3234,6 +3235,15 @@ static struct atlas7_grp_mux ps_grp_mux = {
.pad_mux_list = ps_grp_pad_mux,
};
+static struct atlas7_pad_mux ps_no_dir_grp_pad_mux[] = {
+ MUX(1, 119, 2, N, N, N, N),
+};
+
+static struct atlas7_grp_mux ps_no_dir_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(ps_no_dir_grp_pad_mux),
+ .pad_mux_list = ps_no_dir_grp_pad_mux,
+};
+
static struct atlas7_pad_mux pwc_core_on_grp_pad_mux[] = {
MUX(0, 8, 1, N, N, N, N),
};
@@ -3743,7 +3753,7 @@ static struct atlas7_grp_mux sd2_wpb_grp1_mux = {
.pad_mux_list = sd2_wpb_grp1_pad_mux,
};
-static struct atlas7_pad_mux sd3_grp_pad_mux[] = {
+static struct atlas7_pad_mux sd3_9_grp_pad_mux[] = {
MUX(1, 85, 1, N, N, N, N),
MUX(1, 86, 1, N, N, N, N),
MUX(1, 87, 1, N, N, N, N),
@@ -3752,9 +3762,9 @@ static struct atlas7_pad_mux sd3_grp_pad_mux[] = {
MUX(1, 90, 1, N, N, N, N),
};
-static struct atlas7_grp_mux sd3_grp_mux = {
- .pad_mux_count = ARRAY_SIZE(sd3_grp_pad_mux),
- .pad_mux_list = sd3_grp_pad_mux,
+static struct atlas7_grp_mux sd3_9_grp_mux = {
+ .pad_mux_count = ARRAY_SIZE(sd3_9_grp_pad_mux),
+ .pad_mux_list = sd3_9_grp_pad_mux,
};
static struct atlas7_pad_mux sd5_grp_pad_mux[] = {
@@ -4296,6 +4306,9 @@ static struct atlas7_pad_mux vi_vip1_low8bit_grp_pad_mux[] = {
MUX(1, 79, 1, N, N, N, N),
MUX(1, 80, 1, N, N, N, N),
MUX(1, 81, 1, N, N, N, N),
+ MUX(1, 82, 1, N, N, N, N),
+ MUX(1, 83, 1, N, N, N, N),
+ MUX(1, 84, 1, N, N, N, N),
};
static struct atlas7_grp_mux vi_vip1_low8bit_grp_mux = {
@@ -4307,11 +4320,14 @@ static struct atlas7_pad_mux vi_vip1_high8bit_grp_pad_mux[] = {
MUX(1, 82, 1, N, N, N, N),
MUX(1, 83, 1, N, N, N, N),
MUX(1, 84, 1, N, N, N, N),
- MUX(1, 108, 2, N, N, N, N),
MUX(1, 103, 2, N, N, N, N),
MUX(1, 104, 2, N, N, N, N),
MUX(1, 105, 2, N, N, N, N),
MUX(1, 106, 2, N, N, N, N),
+ MUX(1, 107, 2, N, N, N, N),
+ MUX(1, 102, 2, N, N, N, N),
+ MUX(1, 97, 2, N, N, N, N),
+ MUX(1, 98, 2, N, N, N, N),
};
static struct atlas7_grp_mux vi_vip1_high8bit_grp_mux = {
@@ -4598,9 +4614,11 @@ static struct atlas7_pmx_func atlas7_pmx_functions[] = {
FUNCTION("ld_ldd_lck", ld_ldd_lck_grp, &ld_ldd_lck_grp_mux),
FUNCTION("lr_lcdrom", lr_lcdrom_grp, &lr_lcdrom_grp_mux),
FUNCTION("lvds_analog", lvds_analog_grp, &lvds_analog_grp_mux),
- FUNCTION("nd_df", nd_df_grp, &nd_df_grp_mux),
- FUNCTION("nd_df_nowp", nd_df_nowp_grp, &nd_df_nowp_grp_mux),
+ FUNCTION("nd_df_basic", nd_df_basic_grp, &nd_df_basic_grp_mux),
+ FUNCTION("nd_df_wp", nd_df_wp_grp, &nd_df_wp_grp_mux),
+ FUNCTION("nd_df_cs", nd_df_cs_grp, &nd_df_cs_grp_mux),
FUNCTION("ps", ps_grp, &ps_grp_mux),
+ FUNCTION("ps_no_dir", ps_no_dir_grp, &ps_no_dir_grp_mux),
FUNCTION("pwc_core_on", pwc_core_on_grp, &pwc_core_on_grp_mux),
FUNCTION("pwc_ext_on", pwc_ext_on_grp, &pwc_ext_on_grp_mux),
FUNCTION("pwc_gpio3_clk", pwc_gpio3_clk_grp, &pwc_gpio3_clk_grp_mux),
@@ -4686,10 +4704,11 @@ static struct atlas7_pmx_func atlas7_pmx_functions[] = {
FUNCTION("sd2_cdb_m1", sd2_cdb_grp1, &sd2_cdb_grp1_mux),
FUNCTION("sd2_wpb_m0", sd2_wpb_grp0, &sd2_wpb_grp0_mux),
FUNCTION("sd2_wpb_m1", sd2_wpb_grp1, &sd2_wpb_grp1_mux),
- FUNCTION("sd3", sd3_grp, &sd3_grp_mux),
+ FUNCTION("sd3", sd3_9_grp, &sd3_9_grp_mux),
FUNCTION("sd5", sd5_grp, &sd5_grp_mux),
FUNCTION("sd6_m0", sd6_grp0, &sd6_grp0_mux),
FUNCTION("sd6_m1", sd6_grp1, &sd6_grp1_mux),
+ FUNCTION("sd9", sd3_9_grp, &sd3_9_grp_mux),
FUNCTION("sp0_ext_ldo_on",
sp0_ext_ldo_on_grp,
&sp0_ext_ldo_on_grp_mux),
@@ -5097,6 +5116,14 @@ static int atlas7_pmx_set_mux(struct pinctrl_dev *pctldev,
pr_debug("PMX DUMP ### Function:[%s] Group:[%s] #### START >>>\n",
pmx_func->name, pin_grp->name);
+ /* the sd3 and sd9 pin select by SYS2PCI_SDIO9SEL register */
+ if (pin_grp->pins == (unsigned int *)&sd3_9_pins) {
+ if (!strcmp(pmx_func->name, "sd9"))
+ writel(1, pmx->sys2pci_base + SYS2PCI_SDIO9SEL);
+ else
+ writel(0, pmx->sys2pci_base + SYS2PCI_SDIO9SEL);
+ }
+
grp_mux = pmx_func->grpmux;
for (idx = 0; idx < grp_mux->pad_mux_count; idx++) {
@@ -5385,12 +5412,27 @@ static int atlas7_pinmux_probe(struct platform_device *pdev)
struct atlas7_pmx *pmx;
struct device_node *np = pdev->dev.of_node;
u32 banks = ATLAS7_PINCTRL_REG_BANKS;
+ struct device_node *sys2pci_np;
+ struct resource res;
/* Create state holders etc for this driver */
pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
if (!pmx)
return -ENOMEM;
+ /* The sd3 and sd9 shared all pins, and the function select by
+ * SYS2PCI_SDIO9SEL register
+ */
+ sys2pci_np = of_find_node_by_name(NULL, "sys2pci");
+ if (!sys2pci_np)
+ return -EINVAL;
+ ret = of_address_to_resource(sys2pci_np, 0, &res);
+ if (ret)
+ return ret;
+ pmx->sys2pci_base = devm_ioremap_resource(&pdev->dev, &res);
+ if (IS_ERR(pmx->sys2pci_base))
+ return -ENOMEM;
+
pmx->dev = &pdev->dev;
pmx->pctl_data = &atlas7_ioc_data;
diff --git a/drivers/pinctrl/sirf/pinctrl-sirf.c b/drivers/pinctrl/sirf/pinctrl-sirf.c
index 2a8d69725de8..edf40df05ec0 100644
--- a/drivers/pinctrl/sirf/pinctrl-sirf.c
+++ b/drivers/pinctrl/sirf/pinctrl-sirf.c
@@ -85,12 +85,16 @@ static int sirfsoc_dt_node_to_map(struct pinctrl_dev *pctldev,
/* calculate number of maps required */
for_each_child_of_node(np_config, np) {
ret = of_property_read_string(np, "sirf,function", &function);
- if (ret < 0)
+ if (ret < 0) {
+ of_node_put(np);
return ret;
+ }
ret = of_property_count_strings(np, "sirf,pins");
- if (ret < 0)
+ if (ret < 0) {
+ of_node_put(np);
return ret;
+ }
count += ret;
}
diff --git a/drivers/pinctrl/spear/Makefile b/drivers/pinctrl/spear/Makefile
index 0e400ebeb8ff..37b8412ac8a3 100644
--- a/drivers/pinctrl/spear/Makefile
+++ b/drivers/pinctrl/spear/Makefile
@@ -1,7 +1,7 @@
# SPEAr pinmux support
obj-$(CONFIG_PINCTRL_SPEAR_PLGPIO) += pinctrl-plgpio.o
-obj-$(CONFIG_PINCTRL_SPEAR) += pinctrl-spear.o
+obj-y += pinctrl-spear.o
obj-$(CONFIG_PINCTRL_SPEAR3XX) += pinctrl-spear3xx.o
obj-$(CONFIG_PINCTRL_SPEAR300) += pinctrl-spear300.o
obj-$(CONFIG_PINCTRL_SPEAR310) += pinctrl-spear310.o
diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig
index e68fd951129a..f8dbc8bec0e1 100644
--- a/drivers/pinctrl/sunxi/Kconfig
+++ b/drivers/pinctrl/sunxi/Kconfig
@@ -51,8 +51,17 @@ config PINCTRL_SUN8I_A23_R
depends on RESET_CONTROLLER
select PINCTRL_SUNXI_COMMON
+config PINCTRL_SUN8I_H3
+ def_bool MACH_SUN8I
+ select PINCTRL_SUNXI_COMMON
+
config PINCTRL_SUN9I_A80
def_bool MACH_SUN9I
select PINCTRL_SUNXI_COMMON
+config PINCTRL_SUN9I_A80_R
+ def_bool MACH_SUN9I
+ depends on RESET_CONTROLLER
+ select PINCTRL_SUNXI_COMMON
+
endif
diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile
index e08029034510..ef82f22bb9ef 100644
--- a/drivers/pinctrl/sunxi/Makefile
+++ b/drivers/pinctrl/sunxi/Makefile
@@ -13,4 +13,6 @@ obj-$(CONFIG_PINCTRL_SUN8I_A23) += pinctrl-sun8i-a23.o
obj-$(CONFIG_PINCTRL_SUN8I_A23_R) += pinctrl-sun8i-a23-r.o
obj-$(CONFIG_PINCTRL_SUN8I_A33) += pinctrl-sun8i-a33.o
obj-$(CONFIG_PINCTRL_SUN8I_A83T) += pinctrl-sun8i-a83t.o
+obj-$(CONFIG_PINCTRL_SUN8I_H3) += pinctrl-sun8i-h3.o
obj-$(CONFIG_PINCTRL_SUN9I_A80) += pinctrl-sun9i-a80.o
+obj-$(CONFIG_PINCTRL_SUN9I_A80_R) += pinctrl-sun9i-a80-r.o
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
new file mode 100644
index 000000000000..77d4cf047cee
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun8i-h3.c
@@ -0,0 +1,515 @@
+/*
+ * Allwinner H3 SoCs pinctrl driver.
+ *
+ * Copyright (C) 2015 Jens Kuske <jenskuske@gmail.com>
+ *
+ * Based on pinctrl-sun8i-a23.c, which is:
+ * Copyright (C) 2014 Chen-Yu Tsai <wens@csie.org>
+ * Copyright (C) 2014 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin sun8i_h3_pins[] = {
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* TX */
+ SUNXI_FUNCTION(0x3, "jtag"), /* MS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)), /* PA_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* RX */
+ SUNXI_FUNCTION(0x3, "jtag"), /* CK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)), /* PA_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* RTS */
+ SUNXI_FUNCTION(0x3, "jtag"), /* DO */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)), /* PA_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart2"), /* CTS */
+ SUNXI_FUNCTION(0x3, "jtag"), /* DI */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)), /* PA_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart0"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)), /* PA_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart0"), /* RX */
+ SUNXI_FUNCTION(0x3, "pwm0"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)), /* PA_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sim"), /* PWREN */
+ SUNXI_FUNCTION(0x3, "pwm1"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)), /* PA_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sim"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)), /* PA_EINT7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sim"), /* DATA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)), /* PA_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sim"), /* RST */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)), /* PA_EINT9 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "sim"), /* DET */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 10)), /* PA_EINT10 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c0"), /* SCK */
+ SUNXI_FUNCTION(0x3, "di"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 11)), /* PA_EINT11 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2c0"), /* SDA */
+ SUNXI_FUNCTION(0x3, "di"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 12)), /* PA_EINT12 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* CS */
+ SUNXI_FUNCTION(0x3, "uart3"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 13)), /* PA_EINT13 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* CLK */
+ SUNXI_FUNCTION(0x3, "uart3"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 14)), /* PA_EINT14 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* MOSI */
+ SUNXI_FUNCTION(0x3, "uart3"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 15)), /* PA_EINT15 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spi1"), /* MISO */
+ SUNXI_FUNCTION(0x3, "uart3"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 16)), /* PA_EINT16 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 17),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "spdif"), /* OUT */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 17)), /* PA_EINT17 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 18),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* SYNC */
+ SUNXI_FUNCTION(0x3, "i2c1"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 18)), /* PA_EINT18 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 19),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* CLK */
+ SUNXI_FUNCTION(0x3, "i2c1"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 19)), /* PA_EINT19 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 20),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* DOUT */
+ SUNXI_FUNCTION(0x3, "sim"), /* VPPEN */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 20)), /* PA_EINT20 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(A, 21),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s0"), /* DIN */
+ SUNXI_FUNCTION(0x3, "sim"), /* VPPPP */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 21)), /* PA_EINT21 */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* WE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* MOSI */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* ALE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* MISO */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* CLE */
+ SUNXI_FUNCTION(0x3, "spi0")), /* CLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* CE1 */
+ SUNXI_FUNCTION(0x3, "spi0")), /* CS */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* CE0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* RE */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* CLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* RB0 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* CMD */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0")), /* RB1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ0 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ1 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ2 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ3 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ4 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand0"), /* DQ5 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand"), /* DQ6 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand"), /* DQ7 */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* D7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "nand"), /* DQS */
+ SUNXI_FUNCTION(0x3, "mmc2")), /* RST */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXD3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXD2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXD1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXD0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXCTL/RXDV */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* RXERR */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXD3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXD2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXD1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXD0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* CRS */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXCTL/TXEN */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* TXERR */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* CLKIN/COL */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* MDC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "emac")), /* MDIO */
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* PCLK */
+ SUNXI_FUNCTION(0x3, "ts")), /* CLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* MCLK */
+ SUNXI_FUNCTION(0x3, "ts")), /* ERR */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* HSYNC */
+ SUNXI_FUNCTION(0x3, "ts")), /* SYNC */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* VSYNC */
+ SUNXI_FUNCTION(0x3, "ts")), /* DVLD */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D0 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D1 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D2 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D3 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D4 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D5 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D6 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* D7 */
+ SUNXI_FUNCTION(0x3, "ts")), /* D7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* SCK */
+ SUNXI_FUNCTION(0x3, "i2c2")), /* SCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "csi"), /* SDA */
+ SUNXI_FUNCTION(0x3, "i2c2")), /* SDA */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out")),
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out")),
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D1 */
+ SUNXI_FUNCTION(0x3, "jtag")), /* MS */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D0 */
+ SUNXI_FUNCTION(0x3, "jtag")), /* DI */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* CLK */
+ SUNXI_FUNCTION(0x3, "uart0")), /* TX */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* CMD */
+ SUNXI_FUNCTION(0x3, "jtag")), /* DO */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D3 */
+ SUNXI_FUNCTION(0x3, "uart0")), /* RX */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc0"), /* D2 */
+ SUNXI_FUNCTION(0x3, "jtag")), /* CK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out")),
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)), /* PG_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* CMD */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)), /* PG_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D0 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)), /* PG_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)), /* PG_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D2 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)), /* PG_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "mmc1"), /* D3 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 5)), /* PG_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 6)), /* PG_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 7)), /* PG_EINT7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* RTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 8)), /* PG_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "uart1"), /* CTS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 9)), /* PG_EINT9 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* SYNC */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 10)), /* PG_EINT10 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* CLK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 11)), /* PG_EINT11 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* DOUT */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 12)), /* PG_EINT12 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "i2s1"), /* DIN */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 13)), /* PG_EINT13 */
+};
+
+static const struct sunxi_pinctrl_desc sun8i_h3_pinctrl_data = {
+ .pins = sun8i_h3_pins,
+ .npins = ARRAY_SIZE(sun8i_h3_pins),
+ .irq_banks = 2,
+};
+
+static int sun8i_h3_pinctrl_probe(struct platform_device *pdev)
+{
+ return sunxi_pinctrl_init(pdev,
+ &sun8i_h3_pinctrl_data);
+}
+
+static const struct of_device_id sun8i_h3_pinctrl_match[] = {
+ { .compatible = "allwinner,sun8i-h3-pinctrl", },
+ {}
+};
+
+static struct platform_driver sun8i_h3_pinctrl_driver = {
+ .probe = sun8i_h3_pinctrl_probe,
+ .driver = {
+ .name = "sun8i-h3-pinctrl",
+ .of_match_table = sun8i_h3_pinctrl_match,
+ },
+};
+builtin_platform_driver(sun8i_h3_pinctrl_driver);
diff --git a/drivers/pinctrl/sunxi/pinctrl-sun9i-a80-r.c b/drivers/pinctrl/sunxi/pinctrl-sun9i-a80-r.c
new file mode 100644
index 000000000000..42547ffa20a8
--- /dev/null
+++ b/drivers/pinctrl/sunxi/pinctrl-sun9i-a80-r.c
@@ -0,0 +1,181 @@
+/*
+ * Allwinner A80 SoCs special pins pinctrl driver.
+ *
+ * Copyright (C) 2014 Maxime Ripard
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/reset.h>
+
+#include "pinctrl-sunxi.h"
+
+static const struct sunxi_desc_pin sun9i_a80_r_pins[] = {
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "s_uart"), /* TX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 0)), /* PL_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "s_uart"), /* RX */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 1)), /* PL_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "s_jtag"), /* TMS */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 2)), /* PL_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "s_jtag"), /* TCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 3)), /* PL_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "s_jtag"), /* TDO */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 4)), /* PL_EINT4 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 5),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "s_jtag"), /* TDI */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 5)), /* PL_EINT5 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 6),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "s_cir_rx"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 6)), /* PL_EINT6 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 7),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "1wire"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 7)), /* PL_EINT7 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_ps2"), /* SCK1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 8)), /* PL_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(L, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_ps2"), /* SDA1 */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 0, 9)), /* PL_EINT9 */
+
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 0)), /* PM_EINT0 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 1)), /* PM_EINT1 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 2),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 2)), /* PM_EINT2 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 3),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 3)), /* PM_EINT3 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 4),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "s_i2s1"), /* LRCKR */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 4)), /* PM_EINT4 */
+
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 8),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "s_i2c1"), /* SCK */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 8)), /* PM_EINT8 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 9),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x3, "s_i2c1"), /* SDA */
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 9)), /* PM_EINT9 */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 10),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_i2s0"), /* MCLK */
+ SUNXI_FUNCTION(0x3, "s_i2s1")), /* MCLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 11),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_i2s0"), /* BCLK */
+ SUNXI_FUNCTION(0x3, "s_i2s1")), /* BCLK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 12),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_i2s0"), /* LRCK */
+ SUNXI_FUNCTION(0x3, "s_i2s1")), /* LRCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 13),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_i2s0"), /* DIN */
+ SUNXI_FUNCTION(0x3, "s_i2s1")), /* DIN */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 14),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_i2s0"), /* DOUT */
+ SUNXI_FUNCTION(0x3, "s_i2s1")), /* DOUT */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(M, 15),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION_IRQ_BANK(0x6, 1, 15)), /* PM_EINT15 */
+
+ /* Hole */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 0),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_i2c0"), /* SCK */
+ SUNXI_FUNCTION(0x3, "s_rsb")), /* SCK */
+ SUNXI_PIN(SUNXI_PINCTRL_PIN(N, 1),
+ SUNXI_FUNCTION(0x0, "gpio_in"),
+ SUNXI_FUNCTION(0x1, "gpio_out"),
+ SUNXI_FUNCTION(0x2, "s_i2c0"), /* SDA */
+ SUNXI_FUNCTION(0x3, "s_rsb")), /* SDA */
+};
+
+static const struct sunxi_pinctrl_desc sun9i_a80_r_pinctrl_data = {
+ .pins = sun9i_a80_r_pins,
+ .npins = ARRAY_SIZE(sun9i_a80_r_pins),
+ .pin_base = PL_BASE,
+ .irq_banks = 2,
+};
+
+static int sun9i_a80_r_pinctrl_probe(struct platform_device *pdev)
+{
+ return sunxi_pinctrl_init(pdev,
+ &sun9i_a80_r_pinctrl_data);
+}
+
+static const struct of_device_id sun9i_a80_r_pinctrl_match[] = {
+ { .compatible = "allwinner,sun9i-a80-r-pinctrl", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, sun9i_a80_r_pinctrl_match);
+
+static struct platform_driver sun9i_a80_r_pinctrl_driver = {
+ .probe = sun9i_a80_r_pinctrl_probe,
+ .driver = {
+ .name = "sun9i-a80-r-pinctrl",
+ .owner = THIS_MODULE,
+ .of_match_table = sun9i_a80_r_pinctrl_match,
+ },
+};
+module_platform_driver(sun9i_a80_r_pinctrl_driver);
+
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
+MODULE_DESCRIPTION("Allwinner A80 R_PIO pinctrl driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/pinctrl/uniphier/Kconfig b/drivers/pinctrl/uniphier/Kconfig
index ad907072e09f..7abd614dc383 100644
--- a/drivers/pinctrl/uniphier/Kconfig
+++ b/drivers/pinctrl/uniphier/Kconfig
@@ -1,32 +1,35 @@
-if ARCH_UNIPHIER
-
-config PINCTRL_UNIPHIER
- bool
+menuconfig PINCTRL_UNIPHIER
+ bool "UniPhier SoC pinctrl drivers"
+ depends on ARCH_UNIPHIER
+ depends on OF && MFD_SYSCON
+ default y
select PINMUX
select GENERIC_PINCONF
+if PINCTRL_UNIPHIER
+
config PINCTRL_UNIPHIER_PH1_LD4
tristate "UniPhier PH1-LD4 SoC pinctrl driver"
- select PINCTRL_UNIPHIER
+ default y
config PINCTRL_UNIPHIER_PH1_PRO4
tristate "UniPhier PH1-Pro4 SoC pinctrl driver"
- select PINCTRL_UNIPHIER
+ default y
config PINCTRL_UNIPHIER_PH1_SLD8
tristate "UniPhier PH1-sLD8 SoC pinctrl driver"
- select PINCTRL_UNIPHIER
+ default y
config PINCTRL_UNIPHIER_PH1_PRO5
tristate "UniPhier PH1-Pro5 SoC pinctrl driver"
- select PINCTRL_UNIPHIER
+ default y
config PINCTRL_UNIPHIER_PROXSTREAM2
tristate "UniPhier ProXstream2 SoC pinctrl driver"
- select PINCTRL_UNIPHIER
+ default y
config PINCTRL_UNIPHIER_PH1_LD6B
tristate "UniPhier PH1-LD6b SoC pinctrl driver"
- select PINCTRL_UNIPHIER
+ default y
endif
diff --git a/drivers/staging/lustre/lustre/llite/symlink.c b/drivers/staging/lustre/lustre/llite/symlink.c
index 69b203651905..e489a3271f06 100644
--- a/drivers/staging/lustre/lustre/llite/symlink.c
+++ b/drivers/staging/lustre/lustre/llite/symlink.c
@@ -118,12 +118,20 @@ failed:
return rc;
}
-static const char *ll_follow_link(struct dentry *dentry, void **cookie)
+static void ll_put_link(void *p)
+{
+ ptlrpc_req_finished(p);
+}
+
+static const char *ll_get_link(struct dentry *dentry,
+ struct inode *inode,
+ struct delayed_call *done)
{
- struct inode *inode = d_inode(dentry);
struct ptlrpc_request *request = NULL;
int rc;
char *symname = NULL;
+ if (!dentry)
+ return ERR_PTR(-ECHILD);
CDEBUG(D_VFSTRACE, "VFS Op\n");
ll_inode_size_lock(inode);
@@ -135,22 +143,16 @@ static const char *ll_follow_link(struct dentry *dentry, void **cookie)
}
/* symname may contain a pointer to the request message buffer,
- * we delay request releasing until ll_put_link then.
+ * we delay request releasing then.
*/
- *cookie = request;
+ set_delayed_call(done, ll_put_link, request);
return symname;
}
-static void ll_put_link(struct inode *unused, void *cookie)
-{
- ptlrpc_req_finished(cookie);
-}
-
struct inode_operations ll_fast_symlink_inode_operations = {
.readlink = generic_readlink,
.setattr = ll_setattr,
- .follow_link = ll_follow_link,
- .put_link = ll_put_link,
+ .get_link = ll_get_link,
.getattr = ll_getattr,
.permission = ll_inode_permission,
.setxattr = ll_setxattr,
diff --git a/drivers/staging/lustre/lustre/llite/xattr.c b/drivers/staging/lustre/lustre/llite/xattr.c
index 4b7eb33f7d01..660b8ac37ae0 100644
--- a/drivers/staging/lustre/lustre/llite/xattr.c
+++ b/drivers/staging/lustre/lustre/llite/xattr.c
@@ -60,10 +60,10 @@
static
int get_xattr_type(const char *name)
{
- if (!strcmp(name, POSIX_ACL_XATTR_ACCESS))
+ if (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS))
return XATTR_ACL_ACCESS_T;
- if (!strcmp(name, POSIX_ACL_XATTR_DEFAULT))
+ if (!strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT))
return XATTR_ACL_DEFAULT_T;
if (!strncmp(name, XATTR_USER_PREFIX,
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 5381a728d23e..e5139402e7f8 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -133,6 +133,12 @@ static void sysrq_handle_crash(int key)
{
char *killer = NULL;
+ /* we need to release the RCU read lock here,
+ * otherwise we get an annoying
+ * 'BUG: sleeping function called from invalid context'
+ * complaint from the kernel before the panic.
+ */
+ rcu_read_unlock();
panic_on_oops = 1; /* force panic */
wmb();
*killer = 1;