diff options
Diffstat (limited to 'drivers')
199 files changed, 12913 insertions, 2810 deletions
diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c index 707cf6213bc2..b9afb47db7ed 100644 --- a/drivers/acpi/device_sysfs.c +++ b/drivers/acpi/device_sysfs.c @@ -104,7 +104,7 @@ static void acpi_expose_nondev_subnodes(struct kobject *kobj, init_completion(&dn->kobj_done); ret = kobject_init_and_add(&dn->kobj, &acpi_data_node_ktype, - kobj, dn->name); + kobj, "%s", dn->name); if (ret) acpi_handle_err(dn->handle, "Failed to expose (%d)\n", ret); else 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/connector/connector.c b/drivers/connector/connector.c index d7373ca69c99..25693b045371 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -179,26 +179,21 @@ static int cn_call_callback(struct sk_buff *skb) * * It checks skb, netlink header and msg sizes, and calls callback helper. */ -static void cn_rx_skb(struct sk_buff *__skb) +static void cn_rx_skb(struct sk_buff *skb) { struct nlmsghdr *nlh; - struct sk_buff *skb; int len, err; - skb = skb_get(__skb); - if (skb->len >= NLMSG_HDRLEN) { nlh = nlmsg_hdr(skb); len = nlmsg_len(nlh); if (len < (int)sizeof(struct cn_msg) || skb->len < nlh->nlmsg_len || - len > CONNECTOR_MAX_MSG_SIZE) { - kfree_skb(skb); + len > CONNECTOR_MAX_MSG_SIZE) return; - } - err = cn_call_callback(skb); + err = cn_call_callback(skb_get(skb)); if (err < 0) kfree_skb(skb); } 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/dma/mic_x100_dma.c b/drivers/dma/mic_x100_dma.c index cddfa8dbf4bd..068e920ecb68 100644 --- a/drivers/dma/mic_x100_dma.c +++ b/drivers/dma/mic_x100_dma.c @@ -317,7 +317,6 @@ mic_dma_prep_memcpy_lock(struct dma_chan *ch, dma_addr_t dma_dest, struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch); struct device *dev = mic_dma_ch_to_device(mic_ch); int result; - struct dma_async_tx_descriptor *tx = NULL; if (!len && !flags) return NULL; @@ -325,13 +324,10 @@ mic_dma_prep_memcpy_lock(struct dma_chan *ch, dma_addr_t dma_dest, spin_lock(&mic_ch->prep_lock); result = mic_dma_do_dma(mic_ch, flags, dma_src, dma_dest, len); if (result >= 0) - tx = allocate_tx(mic_ch); - - if (!tx) - dev_err(dev, "Error enqueueing dma, error=%d\n", result); - + return allocate_tx(mic_ch); + dev_err(dev, "Error enqueueing dma, error=%d\n", result); spin_unlock(&mic_ch->prep_lock); - return tx; + return NULL; } static struct dma_async_tx_descriptor * @@ -339,14 +335,13 @@ mic_dma_prep_interrupt_lock(struct dma_chan *ch, unsigned long flags) { struct mic_dma_chan *mic_ch = to_mic_dma_chan(ch); int ret; - struct dma_async_tx_descriptor *tx = NULL; spin_lock(&mic_ch->prep_lock); ret = mic_dma_do_dma(mic_ch, flags, 0, 0, 0); if (!ret) - tx = allocate_tx(mic_ch); + return allocate_tx(mic_ch); spin_unlock(&mic_ch->prep_lock); - return tx; + return NULL; } /* Return the status of the transaction */ diff --git a/drivers/dma/xgene-dma.c b/drivers/dma/xgene-dma.c index 9dfa2b0fa5da..9cb93c5b655d 100644 --- a/drivers/dma/xgene-dma.c +++ b/drivers/dma/xgene-dma.c @@ -29,6 +29,7 @@ #include <linux/dmapool.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/irq.h> #include <linux/module.h> #include <linux/of_device.h> @@ -1610,6 +1611,7 @@ static int xgene_dma_request_irqs(struct xgene_dma *pdma) /* Register DMA channel rx irq */ for (i = 0; i < XGENE_DMA_MAX_CHANNEL; i++) { chan = &pdma->chan[i]; + irq_set_status_flags(chan->rx_irq, IRQ_DISABLE_UNLAZY); ret = devm_request_irq(chan->dev, chan->rx_irq, xgene_dma_chan_ring_isr, 0, chan->name, chan); @@ -1620,6 +1622,7 @@ static int xgene_dma_request_irqs(struct xgene_dma *pdma) for (j = 0; j < i; j++) { chan = &pdma->chan[i]; + irq_clear_status_flags(chan->rx_irq, IRQ_DISABLE_UNLAZY); devm_free_irq(chan->dev, chan->rx_irq, chan); } @@ -1640,6 +1643,7 @@ static void xgene_dma_free_irqs(struct xgene_dma *pdma) for (i = 0; i < XGENE_DMA_MAX_CHANNEL; i++) { chan = &pdma->chan[i]; + irq_clear_status_flags(chan->rx_irq, IRQ_DISABLE_UNLAZY); devm_free_irq(chan->dev, chan->rx_irq, chan); } } 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, ®); + 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, ®); + 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, ®_lo); + pci_read_config_dword(pvt->knl.pci_mc_info, KNL_TOHM_1, ®_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], ®_limit_lo); + pci_read_config_dword(pci_mc, + knl_tad_dram_offset_lo[entry], ®_offset_lo); + pci_read_config_dword(pci_mc, + knl_tad_dram_hi[entry], ®_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, ®); else pci_read_config_dword(pvt->pci_br0, SAD_TARGET, ®); - 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, ®); - 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, ®); + 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], ®); - 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], ®); @@ -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/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index ac1ce4a73edf..0e08e665f715 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -521,6 +521,7 @@ static int __init dmi_present(const u8 *buf) dmi_ver = smbios_ver; else dmi_ver = (buf[14] & 0xF0) << 4 | (buf[14] & 0x0F); + dmi_ver <<= 8; dmi_num = get_unaligned_le16(buf + 12); dmi_len = get_unaligned_le16(buf + 6); dmi_base = get_unaligned_le32(buf + 8); @@ -528,15 +529,14 @@ static int __init dmi_present(const u8 *buf) if (dmi_walk_early(dmi_decode) == 0) { if (smbios_ver) { pr_info("SMBIOS %d.%d present.\n", - dmi_ver >> 8, dmi_ver & 0xFF); + dmi_ver >> 16, (dmi_ver >> 8) & 0xFF); } else { smbios_entry_point_size = 15; memcpy(smbios_entry_point, buf, smbios_entry_point_size); pr_info("Legacy DMI %d.%d present.\n", - dmi_ver >> 8, dmi_ver & 0xFF); + dmi_ver >> 16, (dmi_ver >> 8) & 0xFF); } - dmi_ver <<= 8; dmi_format_ids(dmi_ids_string, sizeof(dmi_ids_string)); printk(KERN_DEBUG "DMI: %s\n", dmi_ids_string); return 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c index ffa902ece872..05a895496fc6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c @@ -156,6 +156,7 @@ nv40_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, return -ENOMEM; nvkm_object_ctor(&nv40_gr_chan, oclass, &chan->object); chan->gr = gr; + chan->fifo = fifoch; *pobject = &chan->object; spin_lock_irqsave(&chan->gr->base.engine.lock, flags); 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, <c3815_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/dma-iommu.c b/drivers/iommu/dma-iommu.c index 3a20db4f8604..72d6182666cb 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -21,10 +21,13 @@ #include <linux/device.h> #include <linux/dma-iommu.h> +#include <linux/gfp.h> #include <linux/huge_mm.h> #include <linux/iommu.h> #include <linux/iova.h> #include <linux/mm.h> +#include <linux/scatterlist.h> +#include <linux/vmalloc.h> int iommu_dma_init(void) { @@ -191,6 +194,7 @@ static struct page **__iommu_dma_alloc_pages(unsigned int count, gfp_t gfp) { struct page **pages; unsigned int i = 0, array_size = count * sizeof(*pages); + unsigned int order = MAX_ORDER; if (array_size <= PAGE_SIZE) pages = kzalloc(array_size, GFP_KERNEL); @@ -204,14 +208,15 @@ static struct page **__iommu_dma_alloc_pages(unsigned int count, gfp_t gfp) while (count) { struct page *page = NULL; - int j, order = __fls(count); + int j; /* * Higher-order allocations are a convenience rather * than a necessity, hence using __GFP_NORETRY until * falling back to single-page allocations. */ - for (order = min(order, MAX_ORDER); order > 0; order--) { + for (order = min_t(unsigned int, order, __fls(count)); + order > 0; order--) { page = alloc_pages(gfp | __GFP_NORETRY, order); if (!page) continue; @@ -453,7 +458,7 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg, size_t s_offset = iova_offset(iovad, s->offset); size_t s_length = s->length; - sg_dma_address(s) = s->offset; + sg_dma_address(s) = s_offset; sg_dma_len(s) = s_length; s->offset -= s_offset; s_length = iova_align(iovad, s_length + s_offset); 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/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 8cf605fa9946..dfb868e2d129 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -295,7 +295,7 @@ static struct iommu_gather_ops ipmmu_gather_ops = { static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain) { - phys_addr_t ttbr; + u64 ttbr; /* * Allocate the page table operations. 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/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/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 95c13b2ffa79..ffa288474820 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -426,15 +426,6 @@ int add_mtd_device(struct mtd_info *mtd) mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; - if (mtd->dev.parent) { - if (!mtd->owner && mtd->dev.parent->driver) - mtd->owner = mtd->dev.parent->driver->owner; - if (!mtd->name) - mtd->name = dev_name(mtd->dev.parent); - } else { - pr_debug("mtd device won't show a device symlink in sysfs\n"); - } - /* Some chips always power up locked. Unlock them now */ if ((mtd->flags & MTD_WRITEABLE) && (mtd->flags & MTD_POWERUP_LOCK)) { error = mtd_unlock(mtd, 0, mtd->size); @@ -549,6 +540,21 @@ static int mtd_add_device_partitions(struct mtd_info *mtd, return 0; } +/* + * Set a few defaults based on the parent devices, if not provided by the + * driver + */ +static void mtd_set_dev_defaults(struct mtd_info *mtd) +{ + if (mtd->dev.parent) { + if (!mtd->owner && mtd->dev.parent->driver) + mtd->owner = mtd->dev.parent->driver->owner; + if (!mtd->name) + mtd->name = dev_name(mtd->dev.parent); + } else { + pr_debug("mtd device won't show a device symlink in sysfs\n"); + } +} /** * mtd_device_parse_register - parse partitions and register an MTD device. @@ -587,6 +593,8 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types, int ret; struct mtd_partition *real_parts = NULL; + mtd_set_dev_defaults(mtd); + ret = parse_mtd_partitions(mtd, types, &real_parts, parser_data); if (ret <= 0 && nr_parts && parts) { real_parts = kmemdup(parts, sizeof(*parts) * nr_parts, diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 49883905a434..32477c4eb421 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -516,8 +516,8 @@ static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len) status_old = read_sr(nor); /* Cannot unlock; would unlock larger region than requested */ - if (stm_is_locked_sr(nor, status_old, ofs - mtd->erasesize, - mtd->erasesize)) + if (stm_is_locked_sr(nor, ofs - mtd->erasesize, mtd->erasesize, + status_old)) return -EINVAL; /* @@ -1200,8 +1200,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) if (JEDEC_MFR(info) == SNOR_MFR_ATMEL || JEDEC_MFR(info) == SNOR_MFR_INTEL || - JEDEC_MFR(info) == SNOR_MFR_SST || - JEDEC_MFR(info) == SNOR_MFR_WINBOND) { + JEDEC_MFR(info) == SNOR_MFR_SST) { write_enable(nor); write_sr(nor, 0); } @@ -1217,8 +1216,7 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) mtd->_read = spi_nor_read; /* NOR protection support for STmicro/Micron chips and similar */ - if (JEDEC_MFR(info) == SNOR_MFR_MICRON || - JEDEC_MFR(info) == SNOR_MFR_WINBOND) { + if (JEDEC_MFR(info) == SNOR_MFR_MICRON) { nor->flash_lock = stm_lock; nor->flash_unlock = stm_unlock; nor->flash_is_locked = stm_is_locked; diff --git a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c index c308429dd9c7..11dd91e4db56 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c +++ b/drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c @@ -295,6 +295,10 @@ struct clip_tbl *t4_init_clip_tbl(unsigned int clipt_start, INIT_LIST_HEAD(&ctbl->hash_list[i]); cl_list = t4_alloc_mem(clipt_size*sizeof(struct clip_entry)); + if (!cl_list) { + t4_free_mem(ctbl); + return NULL; + } ctbl->cl_list = (void *)cl_list; for (i = 0; i < clipt_size; i++) { diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c index a5f422f26cb4..daf05155b732 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c @@ -772,8 +772,10 @@ int qlcnic_82xx_config_intrpt(struct qlcnic_adapter *adapter, u8 op_type) int i, err = 0; for (i = 0; i < ahw->num_msix; i++) { - qlcnic_alloc_mbx_args(&cmd, adapter, - QLCNIC_CMD_MQ_TX_CONFIG_INTR); + err = qlcnic_alloc_mbx_args(&cmd, adapter, + QLCNIC_CMD_MQ_TX_CONFIG_INTR); + if (err) + return err; type = op_type ? QLCNIC_INTRPT_ADD : QLCNIC_INTRPT_DEL; val = type | (ahw->intr_tbl[i].type << 4); if (ahw->intr_tbl[i].type == QLCNIC_INTRPT_MSIX) diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 9f0b1c342b77..5a1e98547031 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -683,6 +683,12 @@ static void sixpack_close(struct tty_struct *tty) if (!atomic_dec_and_test(&sp->refcnt)) down(&sp->dead_sem); + /* We must stop the queue to avoid potentially scribbling + * on the free buffers. The sp->dead_sem is not sufficient + * to protect us from sp->xbuff access. + */ + netif_stop_queue(sp->dev); + del_timer_sync(&sp->tx_t); del_timer_sync(&sp->resync_t); diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c index 0b72b9de5207..85828f153445 100644 --- a/drivers/net/hamradio/mkiss.c +++ b/drivers/net/hamradio/mkiss.c @@ -797,6 +797,11 @@ static void mkiss_close(struct tty_struct *tty) */ if (!atomic_dec_and_test(&ax->refcnt)) down(&ax->dead_sem); + /* + * Halt the transmit queue so that a new transmit cannot scribble + * on our buffers + */ + netif_stop_queue(ax->dev); /* Free all AX25 frame buffers. */ kfree(ax->rbuff); diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 9a5be8b85186..5fccc5a8153f 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -742,6 +742,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */ {QMI_FIXED_INTF(0x413c, 0x81b1, 8)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */ {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */ + {QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */ /* 4. Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 2e32c41536ae..2fb637ad594a 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -3525,6 +3525,14 @@ static int rtl8152_resume(struct usb_interface *intf) return 0; } +static int rtl8152_reset_resume(struct usb_interface *intf) +{ + struct r8152 *tp = usb_get_intfdata(intf); + + clear_bit(SELECTIVE_SUSPEND, &tp->flags); + return rtl8152_resume(intf); +} + static void rtl8152_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) { struct r8152 *tp = netdev_priv(dev); @@ -4276,7 +4284,7 @@ static struct usb_driver rtl8152_driver = { .disconnect = rtl8152_disconnect, .suspend = rtl8152_suspend, .resume = rtl8152_resume, - .reset_resume = rtl8152_resume, + .reset_resume = rtl8152_reset_resume, .pre_reset = rtl8152_pre_reset, .post_reset = rtl8152_post_reset, .supports_autosuspend = 1, diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 417903715437..0cbf520cea77 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -1380,10 +1380,10 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq, skip_page_frags = true; goto rcd_done; } - new_dma_addr = dma_map_page(&adapter->pdev->dev - , rbi->page, - 0, PAGE_SIZE, - PCI_DMA_FROMDEVICE); + new_dma_addr = dma_map_page(&adapter->pdev->dev, + new_page, + 0, PAGE_SIZE, + PCI_DMA_FROMDEVICE); if (dma_mapping_error(&adapter->pdev->dev, new_dma_addr)) { put_page(new_page); diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h index 4c58c83dc225..bdb8a6c0f8aa 100644 --- a/drivers/net/vmxnet3/vmxnet3_int.h +++ b/drivers/net/vmxnet3/vmxnet3_int.h @@ -69,10 +69,10 @@ /* * Version numbers */ -#define VMXNET3_DRIVER_VERSION_STRING "1.4.4.0-k" +#define VMXNET3_DRIVER_VERSION_STRING "1.4.5.0-k" /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */ -#define VMXNET3_DRIVER_VERSION_NUM 0x01040400 +#define VMXNET3_DRIVER_VERSION_NUM 0x01040500 #if defined(CONFIG_PCI_MSI) /* RSS only makes sense if MSI-X is supported. */ diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 4f9748457f5a..0a242b200df4 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -800,7 +800,7 @@ static struct rtable *vrf_get_rtable(const struct net_device *dev, } /* called under rcu_read_lock */ -static void vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4) +static int vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4) { struct fib_result res = { .tclassid = 0 }; struct net *net = dev_net(dev); @@ -808,9 +808,10 @@ static void vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4) u8 flags = fl4->flowi4_flags; u8 scope = fl4->flowi4_scope; u8 tos = RT_FL_TOS(fl4); + int rc; if (unlikely(!fl4->daddr)) - return; + return 0; fl4->flowi4_flags |= FLOWI_FLAG_SKIP_NH_OIF; fl4->flowi4_iif = LOOPBACK_IFINDEX; @@ -818,7 +819,8 @@ static void vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4) fl4->flowi4_scope = ((tos & RTO_ONLINK) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); - if (!fib_lookup(net, fl4, &res, 0)) { + rc = fib_lookup(net, fl4, &res, 0); + if (!rc) { if (res.type == RTN_LOCAL) fl4->saddr = res.fi->fib_prefsrc ? : fl4->daddr; else @@ -828,6 +830,8 @@ static void vrf_get_saddr(struct net_device *dev, struct flowi4 *fl4) fl4->flowi4_flags = flags; fl4->flowi4_tos = orig_tos; fl4->flowi4_scope = scope; + + return rc; } #if IS_ENABLED(CONFIG_IPV6) diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index f131ba947dc6..c0ad9aaa16a7 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig @@ -5,6 +5,7 @@ config PCI_DRA7XX bool "TI DRA7xx PCIe controller" select PCIE_DW depends on OF && HAS_IOMEM && TI_PIPE3 + depends on BROKEN help Enables support for the PCIe controller in the DRA7xx SoC. There are two instances of PCIe controller in DRA7xx. This controller can 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", ®); 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", ®); 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/scsi/sd.c b/drivers/scsi/sd.c index 3d22fc3e3c1a..4e08d1cd704d 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2885,10 +2885,13 @@ static int sd_revalidate_disk(struct gendisk *disk) /* * Use the device's preferred I/O size for reads and writes - * unless the reported value is unreasonably large (or garbage). + * unless the reported value is unreasonably small, large, or + * garbage. */ - if (sdkp->opt_xfer_blocks && sdkp->opt_xfer_blocks <= dev_max && - sdkp->opt_xfer_blocks <= SD_DEF_XFER_BLOCKS) + if (sdkp->opt_xfer_blocks && + sdkp->opt_xfer_blocks <= dev_max && + sdkp->opt_xfer_blocks <= SD_DEF_XFER_BLOCKS && + sdkp->opt_xfer_blocks * sdp->sector_size >= PAGE_CACHE_SIZE) rw_max = q->limits.io_opt = logical_to_sectors(sdp, sdkp->opt_xfer_blocks); else 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; |