diff options
Diffstat (limited to 'drivers/soc')
-rw-r--r-- | drivers/soc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/soc/Makefile | 1 | ||||
-rw-r--r-- | drivers/soc/fsl/qe/gpio.c | 66 | ||||
-rw-r--r-- | drivers/soc/imx/gpcv2.c | 3 | ||||
-rw-r--r-- | drivers/soc/imx/imx8m-blk-ctrl.c | 11 | ||||
-rw-r--r-- | drivers/soc/loongson/Kconfig | 18 | ||||
-rw-r--r-- | drivers/soc/loongson/Makefile | 6 | ||||
-rw-r--r-- | drivers/soc/loongson/loongson2_guts.c | 192 | ||||
-rw-r--r-- | drivers/soc/renesas/Kconfig | 2 | ||||
-rw-r--r-- | drivers/soc/renesas/renesas-soc.c | 22 | ||||
-rw-r--r-- | drivers/soc/sifive/sifive_ccache.c | 33 | ||||
-rw-r--r-- | drivers/soc/tegra/Kconfig | 1 | ||||
-rw-r--r-- | drivers/soc/tegra/cbb/tegra-cbb.c | 13 | ||||
-rw-r--r-- | drivers/soc/tegra/cbb/tegra194-cbb.c | 18 | ||||
-rw-r--r-- | drivers/soc/tegra/cbb/tegra234-cbb.c | 170 | ||||
-rw-r--r-- | drivers/soc/tegra/fuse/fuse-tegra.c | 134 | ||||
-rw-r--r-- | drivers/soc/tegra/fuse/fuse-tegra30.c | 278 | ||||
-rw-r--r-- | drivers/soc/tegra/fuse/fuse.h | 4 | ||||
-rw-r--r-- | drivers/soc/tegra/fuse/tegra-apbmisc.c | 1 | ||||
-rw-r--r-- | drivers/soc/tegra/pmc.c | 878 |
20 files changed, 1381 insertions, 471 deletions
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig index e461c071189b..5dbb09f843f7 100644 --- a/drivers/soc/Kconfig +++ b/drivers/soc/Kconfig @@ -13,6 +13,7 @@ source "drivers/soc/fujitsu/Kconfig" source "drivers/soc/imx/Kconfig" source "drivers/soc/ixp4xx/Kconfig" source "drivers/soc/litex/Kconfig" +source "drivers/soc/loongson/Kconfig" source "drivers/soc/mediatek/Kconfig" source "drivers/soc/microchip/Kconfig" source "drivers/soc/pxa/Kconfig" diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index 69ba6508cf2c..fff513bd522d 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -18,6 +18,7 @@ obj-y += imx/ obj-y += ixp4xx/ obj-$(CONFIG_SOC_XWAY) += lantiq/ obj-$(CONFIG_LITEX_SOC_CONTROLLER) += litex/ +obj-y += loongson/ obj-y += mediatek/ obj-y += microchip/ obj-y += pxa/ diff --git a/drivers/soc/fsl/qe/gpio.c b/drivers/soc/fsl/qe/gpio.c index 99f7de43c3c6..af9193e7e49b 100644 --- a/drivers/soc/fsl/qe/gpio.c +++ b/drivers/soc/fsl/qe/gpio.c @@ -14,20 +14,23 @@ #include <linux/io.h> #include <linux/of.h> #include <linux/of_gpio.h> +#include <linux/gpio/consumer.h> #include <linux/gpio/driver.h> -/* FIXME: needed for gpio_to_chip() get rid of this */ -#include <linux/gpio.h> #include <linux/slab.h> #include <linux/export.h> #include <soc/fsl/qe/qe.h> +/* + * FIXME: this is legacy code that is accessing gpiolib internals in order + * to implement a custom pin controller. The proper solution is to create + * a real combined pin control and GPIO driver in drivers/pinctrl. However + * this hack is here for legacy code reasons. + */ +#include "../../../gpio/gpiolib.h" struct qe_gpio_chip { struct of_mm_gpio_chip mm_gc; spinlock_t lock; - unsigned long pin_flags[QE_PIO_PINS]; -#define QE_PIN_REQUESTED 0 - /* shadowed data register to clear/set bits safely */ u32 cpdata; @@ -144,6 +147,7 @@ struct qe_pin { * something like qe_pio_controller. Someday. */ struct qe_gpio_chip *controller; + struct gpio_desc *gpiod; int num; }; @@ -160,9 +164,8 @@ struct qe_pin *qe_pin_request(struct device_node *np, int index) { struct qe_pin *qe_pin; struct gpio_chip *gc; - struct qe_gpio_chip *qe_gc; + struct gpio_desc *gpiod; int err; - unsigned long flags; qe_pin = kzalloc(sizeof(*qe_pin), GFP_KERNEL); if (!qe_pin) { @@ -170,38 +173,36 @@ struct qe_pin *qe_pin_request(struct device_node *np, int index) return ERR_PTR(-ENOMEM); } - err = of_get_gpio(np, index); - if (err < 0) + gpiod = fwnode_gpiod_get_index(of_fwnode_handle(np), NULL, index, GPIOD_ASIS, "qe"); + if (IS_ERR(gpiod)) { + err = PTR_ERR(gpiod); + goto err0; + } + if (!gpiod) { + err = -EINVAL; goto err0; - gc = gpio_to_chip(err); + } + gc = gpiod_to_chip(gpiod); if (WARN_ON(!gc)) { err = -ENODEV; goto err0; } + qe_pin->gpiod = gpiod; + qe_pin->controller = gpiochip_get_data(gc); + /* + * FIXME: this gets the local offset on the gpio_chip so that the driver + * can manipulate pin control settings through its custom API. The real + * solution is to create a real pin control driver for this. + */ + qe_pin->num = gpio_chip_hwgpio(gpiod); if (!of_device_is_compatible(gc->of_node, "fsl,mpc8323-qe-pario-bank")) { pr_debug("%s: tried to get a non-qe pin\n", __func__); + gpiod_put(gpiod); err = -EINVAL; goto err0; } - - qe_gc = gpiochip_get_data(gc); - - spin_lock_irqsave(&qe_gc->lock, flags); - - err -= gc->base; - if (test_and_set_bit(QE_PIN_REQUESTED, &qe_gc->pin_flags[err]) == 0) { - qe_pin->controller = qe_gc; - qe_pin->num = err; - err = 0; - } else { - err = -EBUSY; - } - - spin_unlock_irqrestore(&qe_gc->lock, flags); - - if (!err) - return qe_pin; + return qe_pin; err0: kfree(qe_pin); pr_debug("%s failed with status %d\n", __func__, err); @@ -219,14 +220,7 @@ EXPORT_SYMBOL(qe_pin_request); */ void qe_pin_free(struct qe_pin *qe_pin) { - struct qe_gpio_chip *qe_gc = qe_pin->controller; - unsigned long flags; - const int pin = qe_pin->num; - - spin_lock_irqsave(&qe_gc->lock, flags); - test_and_clear_bit(QE_PIN_REQUESTED, &qe_gc->pin_flags[pin]); - spin_unlock_irqrestore(&qe_gc->lock, flags); - + gpiod_put(qe_pin->gpiod); kfree(qe_pin); } EXPORT_SYMBOL(qe_pin_free); diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index 88aee59730e3..7a47d14fde44 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -755,6 +755,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { [IMX8MM_POWER_DOMAIN_OTG1] = { .genpd = { .name = "usb-otg1", + .flags = GENPD_FLAG_ACTIVE_WAKEUP, }, .bits = { .pxx = IMX8MM_OTG1_SW_Pxx_REQ, @@ -766,6 +767,7 @@ static const struct imx_pgc_domain imx8mm_pgc_domains[] = { [IMX8MM_POWER_DOMAIN_OTG2] = { .genpd = { .name = "usb-otg2", + .flags = GENPD_FLAG_ACTIVE_WAKEUP, }, .bits = { .pxx = IMX8MM_OTG2_SW_Pxx_REQ, @@ -1232,6 +1234,7 @@ static const struct imx_pgc_domain imx8mn_pgc_domains[] = { [IMX8MN_POWER_DOMAIN_OTG1] = { .genpd = { .name = "usb-otg1", + .flags = GENPD_FLAG_ACTIVE_WAKEUP, }, .bits = { .pxx = IMX8MN_OTG1_SW_Pxx_REQ, diff --git a/drivers/soc/imx/imx8m-blk-ctrl.c b/drivers/soc/imx/imx8m-blk-ctrl.c index 00879615a701..ddcf6be3d8b4 100644 --- a/drivers/soc/imx/imx8m-blk-ctrl.c +++ b/drivers/soc/imx/imx8m-blk-ctrl.c @@ -210,9 +210,14 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev) return -ENOMEM; bc->bus_power_dev = genpd_dev_pm_attach_by_name(dev, "bus"); - if (IS_ERR(bc->bus_power_dev)) - return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev), - "failed to attach power domain \"bus\"\n"); + if (IS_ERR(bc->bus_power_dev)) { + if (PTR_ERR(bc->bus_power_dev) == -ENODEV) + return dev_err_probe(dev, -EPROBE_DEFER, + "failed to attach power domain \"bus\"\n"); + else + return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev), + "failed to attach power domain \"bus\"\n"); + } for (i = 0; i < bc_data->num_domains; i++) { const struct imx8m_blk_ctrl_domain_data *data = &bc_data->domains[i]; diff --git a/drivers/soc/loongson/Kconfig b/drivers/soc/loongson/Kconfig new file mode 100644 index 000000000000..707f56358dc4 --- /dev/null +++ b/drivers/soc/loongson/Kconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Loongson-2 series SoC drivers +# + +config LOONGSON2_GUTS + tristate "Loongson-2 SoC Global UtiliTieS (GUTS) register block" + depends on LOONGARCH || COMPILE_TEST + select SOC_BUS + help + The global utilities block controls PCIE device enabling, alternate + function selection for multiplexed signals, consistency of HDA, USB + and PCIE, configuration of memory controller, rtc controller, lio + controller, and clock control. This patch adds a driver to manage + and access global utilities block for LoongArch architecture Loongson-2 + SoCs. Initially only reading SVR and registering soc device are + supported. Other guts accesses, such as reading firmware configuration + by default, should eventually be added into this driver as well. diff --git a/drivers/soc/loongson/Makefile b/drivers/soc/loongson/Makefile new file mode 100644 index 000000000000..263c486df638 --- /dev/null +++ b/drivers/soc/loongson/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Makefile for the Linux Kernel SoC Loongson-2 specific device drivers +# + +obj-$(CONFIG_LOONGSON2_GUTS) += loongson2_guts.o diff --git a/drivers/soc/loongson/loongson2_guts.c b/drivers/soc/loongson/loongson2_guts.c new file mode 100644 index 000000000000..bace4bc8e03b --- /dev/null +++ b/drivers/soc/loongson/loongson2_guts.c @@ -0,0 +1,192 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Author: Yinbo Zhu <zhuyinbo@loongson.cn> + * Copyright (C) 2022-2023 Loongson Technology Corporation Limited + */ + +#include <linux/io.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/of_fdt.h> +#include <linux/sys_soc.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> + +static struct soc_device_attribute soc_dev_attr; +static struct soc_device *soc_dev; + +/* + * Global Utility Registers. + * + * Not all registers defined in this structure are available on all chips, so + * you are expected to know whether a given register actually exists on your + * chip before you access it. + * + * Also, some registers are similar on different chips but have slightly + * different names. In these cases, one name is chosen to avoid extraneous + * #ifdefs. + */ +struct scfg_guts { + u32 svr; /* Version Register */ + u8 res0[4]; + u16 feature; /* Feature Register */ + u32 vendor; /* Vendor Register */ + u8 res1[6]; + u32 id; + u8 res2[0x3ff8 - 0x18]; + u32 chip; +}; + +static struct guts { + struct scfg_guts __iomem *regs; + bool little_endian; +} *guts; + +struct loongson2_soc_die_attr { + char *die; + u32 svr; + u32 mask; +}; + +/* SoC die attribute definition for Loongson-2 platform */ +static const struct loongson2_soc_die_attr loongson2_soc_die[] = { + + /* + * LoongArch-based SoCs Loongson-2 Series + */ + + /* Die: 2k1000, SoC: 2k1000 */ + { .die = "2K1000", + .svr = 0x00000013, + .mask = 0x000000ff, + }, + { }, +}; + +static const struct loongson2_soc_die_attr *loongson2_soc_die_match( + u32 svr, const struct loongson2_soc_die_attr *matches) +{ + while (matches->svr) { + if (matches->svr == (svr & matches->mask)) + return matches; + matches++; + }; + + return NULL; +} + +static u32 loongson2_guts_get_svr(void) +{ + u32 svr = 0; + + if (!guts || !guts->regs) + return svr; + + if (guts->little_endian) + svr = ioread32(&guts->regs->svr); + else + svr = ioread32be(&guts->regs->svr); + + return svr; +} + +static int loongson2_guts_probe(struct platform_device *pdev) +{ + struct device_node *root, *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct resource *res; + const struct loongson2_soc_die_attr *soc_die; + const char *machine; + u32 svr; + + /* Initialize guts */ + guts = devm_kzalloc(dev, sizeof(*guts), GFP_KERNEL); + if (!guts) + return -ENOMEM; + + guts->little_endian = of_property_read_bool(np, "little-endian"); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + guts->regs = ioremap(res->start, res->end - res->start + 1); + if (IS_ERR(guts->regs)) + return PTR_ERR(guts->regs); + + /* Register soc device */ + root = of_find_node_by_path("/"); + if (of_property_read_string(root, "model", &machine)) + of_property_read_string_index(root, "compatible", 0, &machine); + of_node_put(root); + if (machine) + soc_dev_attr.machine = devm_kstrdup(dev, machine, GFP_KERNEL); + + svr = loongson2_guts_get_svr(); + soc_die = loongson2_soc_die_match(svr, loongson2_soc_die); + if (soc_die) { + soc_dev_attr.family = devm_kasprintf(dev, GFP_KERNEL, + "Loongson %s", soc_die->die); + } else { + soc_dev_attr.family = devm_kasprintf(dev, GFP_KERNEL, "Loongson"); + } + if (!soc_dev_attr.family) + return -ENOMEM; + soc_dev_attr.soc_id = devm_kasprintf(dev, GFP_KERNEL, + "svr:0x%08x", svr); + if (!soc_dev_attr.soc_id) + return -ENOMEM; + soc_dev_attr.revision = devm_kasprintf(dev, GFP_KERNEL, "%d.%d", + (svr >> 4) & 0xf, svr & 0xf); + if (!soc_dev_attr.revision) + return -ENOMEM; + + soc_dev = soc_device_register(&soc_dev_attr); + if (IS_ERR(soc_dev)) + return PTR_ERR(soc_dev); + + pr_info("Machine: %s\n", soc_dev_attr.machine); + pr_info("SoC family: %s\n", soc_dev_attr.family); + pr_info("SoC ID: %s, Revision: %s\n", + soc_dev_attr.soc_id, soc_dev_attr.revision); + + return 0; +} + +static int loongson2_guts_remove(struct platform_device *dev) +{ + soc_device_unregister(soc_dev); + + return 0; +} + +/* + * Table for matching compatible strings, for device tree + * guts node, for Loongson-2 SoCs. + */ +static const struct of_device_id loongson2_guts_of_match[] = { + { .compatible = "loongson,ls2k-chipid", }, + {} +}; +MODULE_DEVICE_TABLE(of, loongson2_guts_of_match); + +static struct platform_driver loongson2_guts_driver = { + .driver = { + .name = "loongson2-guts", + .of_match_table = loongson2_guts_of_match, + }, + .probe = loongson2_guts_probe, + .remove = loongson2_guts_remove, +}; + +static int __init loongson2_guts_init(void) +{ + return platform_driver_register(&loongson2_guts_driver); +} +core_initcall(loongson2_guts_init); + +static void __exit loongson2_guts_exit(void) +{ + platform_driver_unregister(&loongson2_guts_driver); +} +module_exit(loongson2_guts_exit); + +MODULE_DESCRIPTION("Loongson2 GUTS driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index f95a1337450d..660498252ec5 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -2,6 +2,8 @@ menuconfig SOC_RENESAS bool "Renesas SoC driver support" if COMPILE_TEST && !ARCH_RENESAS default y if ARCH_RENESAS + select GPIOLIB + select PINCTRL select SOC_BUS if SOC_RENESAS diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c index 621ceaa047d4..468ebce1ea88 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c @@ -76,6 +76,10 @@ static const struct renesas_family fam_rzv2l __initconst __maybe_unused = { .name = "RZ/V2L", }; +static const struct renesas_family fam_rzv2m __initconst __maybe_unused = { + .name = "RZ/V2M", +}; + static const struct renesas_family fam_shmobile __initconst __maybe_unused = { .name = "SH-Mobile", .reg = 0xe600101c, /* CCCR (Common Chip Code Register) */ @@ -171,6 +175,10 @@ static const struct renesas_soc soc_rz_v2l __initconst __maybe_unused = { .id = 0x8447447, }; +static const struct renesas_soc soc_rz_v2m __initconst __maybe_unused = { + .family = &fam_rzv2m, +}; + static const struct renesas_soc soc_rcar_m1a __initconst __maybe_unused = { .family = &fam_rcar_gen1, }; @@ -380,6 +388,9 @@ static const struct of_device_id renesas_socs[] __initconst = { #if defined(CONFIG_ARCH_R9A07G054) { .compatible = "renesas,r9a07g054", .data = &soc_rz_v2l }, #endif +#if defined(CONFIG_ARCH_R9A09G011) + { .compatible = "renesas,r9a09g011", .data = &soc_rz_v2m }, +#endif #ifdef CONFIG_ARCH_SH73A0 { .compatible = "renesas,sh73a0", .data = &soc_shmobile_ag5 }, #endif @@ -405,6 +416,11 @@ static const struct renesas_id id_rzg2l __initconst = { .mask = 0xfffffff, }; +static const struct renesas_id id_rzv2m __initconst = { + .offset = 0x104, + .mask = 0xff, +}; + static const struct renesas_id id_prr __initconst = { .offset = 0, .mask = 0xff00, @@ -415,6 +431,7 @@ static const struct of_device_id renesas_ids[] __initconst = { { .compatible = "renesas,r9a07g043-sysc", .data = &id_rzg2l }, { .compatible = "renesas,r9a07g044-sysc", .data = &id_rzg2l }, { .compatible = "renesas,r9a07g054-sysc", .data = &id_rzg2l }, + { .compatible = "renesas,r9a09g011-sys", .data = &id_rzv2m }, { .compatible = "renesas,prr", .data = &id_prr }, { /* sentinel */ } }; @@ -485,6 +502,11 @@ static int __init renesas_soc_init(void) soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%u", eshi); rev_prefix = "Rev "; + } else if (id == &id_rzv2m) { + eshi = ((product >> 4) & 0x0f); + eslo = product & 0xf; + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%u.%u", + eshi, eslo); } if (soc->id && diff --git a/drivers/soc/sifive/sifive_ccache.c b/drivers/soc/sifive/sifive_ccache.c index 1c171150e878..3684f5b40a80 100644 --- a/drivers/soc/sifive/sifive_ccache.c +++ b/drivers/soc/sifive/sifive_ccache.c @@ -215,20 +215,27 @@ static int __init sifive_ccache_init(void) if (!np) return -ENODEV; - if (of_address_to_resource(np, 0, &res)) - return -ENODEV; + if (of_address_to_resource(np, 0, &res)) { + rc = -ENODEV; + goto err_node_put; + } ccache_base = ioremap(res.start, resource_size(&res)); - if (!ccache_base) - return -ENOMEM; + if (!ccache_base) { + rc = -ENOMEM; + goto err_node_put; + } - if (of_property_read_u32(np, "cache-level", &level)) - return -ENOENT; + if (of_property_read_u32(np, "cache-level", &level)) { + rc = -ENOENT; + goto err_unmap; + } intr_num = of_property_count_u32_elems(np, "interrupts"); if (!intr_num) { pr_err("No interrupts property\n"); - return -ENODEV; + rc = -ENODEV; + goto err_unmap; } for (i = 0; i < intr_num; i++) { @@ -237,9 +244,10 @@ static int __init sifive_ccache_init(void) NULL); if (rc) { pr_err("Could not request IRQ %d\n", g_irq[i]); - return rc; + goto err_free_irq; } } + of_node_put(np); ccache_config_read(); @@ -250,6 +258,15 @@ static int __init sifive_ccache_init(void) setup_sifive_debug(); #endif return 0; + +err_free_irq: + while (--i >= 0) + free_irq(g_irq[i], NULL); +err_unmap: + iounmap(ccache_base); +err_node_put: + of_node_put(np); + return rc; } device_initcall(sifive_ccache_init); diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig index d1ecadffa1bb..5f5324294636 100644 --- a/drivers/soc/tegra/Kconfig +++ b/drivers/soc/tegra/Kconfig @@ -143,6 +143,7 @@ config SOC_TEGRA_FLOWCTRL config SOC_TEGRA_PMC bool select GENERIC_PINCONF + select IRQ_DOMAIN_HIERARCHY select PM_OPP select PM_GENERIC_DOMAINS select REGMAP diff --git a/drivers/soc/tegra/cbb/tegra-cbb.c b/drivers/soc/tegra/cbb/tegra-cbb.c index d200937353c7..a8566b9dd8de 100644 --- a/drivers/soc/tegra/cbb/tegra-cbb.c +++ b/drivers/soc/tegra/cbb/tegra-cbb.c @@ -72,18 +72,7 @@ static int tegra_cbb_err_show(struct seq_file *file, void *data) return cbb->ops->debugfs_show(cbb, file, data); } - -static int tegra_cbb_err_open(struct inode *inode, struct file *file) -{ - return single_open(file, tegra_cbb_err_show, inode->i_private); -} - -static const struct file_operations tegra_cbb_err_fops = { - .open = tegra_cbb_err_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release -}; +DEFINE_SHOW_ATTRIBUTE(tegra_cbb_err); static int tegra_cbb_err_debugfs_init(struct tegra_cbb *cbb) { diff --git a/drivers/soc/tegra/cbb/tegra194-cbb.c b/drivers/soc/tegra/cbb/tegra194-cbb.c index 1ae0bd9a1ac1..d4112b683f00 100644 --- a/drivers/soc/tegra/cbb/tegra194-cbb.c +++ b/drivers/soc/tegra/cbb/tegra194-cbb.c @@ -102,8 +102,6 @@ #define CLUSTER_NOC_VQC GENMASK(17, 16) #define CLUSTER_NOC_MSTR_ID GENMASK(21, 18) -#define USRBITS_MSTR_ID GENMASK(21, 18) - #define CBB_ERR_OPC GENMASK(4, 1) #define CBB_ERR_ERRCODE GENMASK(10, 8) #define CBB_ERR_LEN1 GENMASK(27, 16) @@ -2038,15 +2036,17 @@ static irqreturn_t tegra194_cbb_err_isr(int irq, void *data) smp_processor_id(), priv->noc->name, priv->res->start, irq); - mstr_id = FIELD_GET(USRBITS_MSTR_ID, priv->errlog5) - 1; is_fatal = print_errlog(NULL, priv, status); /* - * If illegal request is from CCPLEX(0x1) - * initiator then call BUG() to crash system. + * If illegal request is from CCPLEX(0x1) initiator + * and error is fatal then call BUG() to crash system. */ - if ((mstr_id == 0x1) && priv->noc->erd_mask_inband_err) - is_inband_err = 1; + if (priv->noc->erd_mask_inband_err) { + mstr_id = FIELD_GET(CBB_NOC_MSTR_ID, priv->errlog5); + if (mstr_id == 0x1) + is_inband_err = 1; + } } } @@ -2226,10 +2226,8 @@ static int tegra194_cbb_get_bridges(struct tegra194_cbb *cbb, struct device_node cbb->bridges[i].base = devm_ioremap_resource(cbb->base.dev, &cbb->bridges[i].res); - if (IS_ERR(cbb->bridges[i].base)) { - dev_err(cbb->base.dev, "failed to map AXI2APB range\n"); + if (IS_ERR(cbb->bridges[i].base)) return PTR_ERR(cbb->bridges[i].base); - } } } diff --git a/drivers/soc/tegra/cbb/tegra234-cbb.c b/drivers/soc/tegra/cbb/tegra234-cbb.c index 3528f9e15d5c..f33d094e5ea6 100644 --- a/drivers/soc/tegra/cbb/tegra234-cbb.c +++ b/drivers/soc/tegra/cbb/tegra234-cbb.c @@ -72,6 +72,11 @@ #define REQ_SOCKET_ID GENMASK(27, 24) +#define CCPLEX_MSTRID 0x1 +#define FIREWALL_APERTURE_SZ 0x10000 +/* Write firewall check enable */ +#define WEN 0x20000 + enum tegra234_cbb_fabric_ids { CBB_FAB_ID, SCE_FAB_ID, @@ -92,11 +97,15 @@ struct tegra234_slave_lookup { struct tegra234_cbb_fabric { const char *name; phys_addr_t off_mask_erd; - bool erd_mask_inband_err; + phys_addr_t firewall_base; + unsigned int firewall_ctl; + unsigned int firewall_wr_ctl; const char * const *master_id; unsigned int notifier_offset; const struct tegra_cbb_error *errors; + const int max_errors; const struct tegra234_slave_lookup *slave_map; + const int max_slaves; }; struct tegra234_cbb { @@ -128,6 +137,44 @@ static inline struct tegra234_cbb *to_tegra234_cbb(struct tegra_cbb *cbb) static LIST_HEAD(cbb_list); static DEFINE_SPINLOCK(cbb_lock); +static bool +tegra234_cbb_write_access_allowed(struct platform_device *pdev, struct tegra234_cbb *cbb) +{ + u32 val; + + if (!cbb->fabric->firewall_base || + !cbb->fabric->firewall_ctl || + !cbb->fabric->firewall_wr_ctl) { + dev_info(&pdev->dev, "SoC data missing for firewall\n"); + return false; + } + + if ((cbb->fabric->firewall_ctl > FIREWALL_APERTURE_SZ) || + (cbb->fabric->firewall_wr_ctl > FIREWALL_APERTURE_SZ)) { + dev_err(&pdev->dev, "wrong firewall offset value\n"); + return false; + } + + val = readl(cbb->regs + cbb->fabric->firewall_base + cbb->fabric->firewall_ctl); + /* + * If the firewall check feature for allowing or blocking the + * write accesses through the firewall of a fabric is disabled + * then CCPLEX can write to the registers of that fabric. + */ + if (!(val & WEN)) + return true; + + /* + * If the firewall check is enabled then check whether CCPLEX + * has write access to the fabric's error notifier registers + */ + val = readl(cbb->regs + cbb->fabric->firewall_base + cbb->fabric->firewall_wr_ctl); + if (val & (BIT(CCPLEX_MSTRID))) + return true; + + return false; +} + static void tegra234_cbb_fault_enable(struct tegra_cbb *cbb) { struct tegra234_cbb *priv = to_tegra234_cbb(cbb); @@ -271,6 +318,12 @@ static void tegra234_cbb_print_error(struct seq_file *file, struct tegra234_cbb tegra_cbb_print_err(file, "\t Multiple type of errors reported\n"); while (status) { + if (type >= cbb->fabric->max_errors) { + tegra_cbb_print_err(file, "\t Wrong type index:%u, status:%u\n", + type, status); + return; + } + if (status & 0x1) tegra_cbb_print_err(file, "\t Error Code\t\t: %s\n", cbb->fabric->errors[type].code); @@ -282,6 +335,12 @@ static void tegra234_cbb_print_error(struct seq_file *file, struct tegra234_cbb type = 0; while (overflow) { + if (type >= cbb->fabric->max_errors) { + tegra_cbb_print_err(file, "\t Wrong type index:%u, overflow:%u\n", + type, overflow); + return; + } + if (overflow & 0x1) tegra_cbb_print_err(file, "\t Overflow\t\t: Multiple %s\n", cbb->fabric->errors[type].code); @@ -334,8 +393,11 @@ static void print_errlog_err(struct seq_file *file, struct tegra234_cbb *cbb) access_type = FIELD_GET(FAB_EM_EL_ACCESSTYPE, cbb->mn_attr0); tegra_cbb_print_err(file, "\n"); - tegra_cbb_print_err(file, "\t Error Code\t\t: %s\n", - cbb->fabric->errors[cbb->type].code); + if (cbb->type < cbb->fabric->max_errors) + tegra_cbb_print_err(file, "\t Error Code\t\t: %s\n", + cbb->fabric->errors[cbb->type].code); + else + tegra_cbb_print_err(file, "\t Wrong type index:%u\n", cbb->type); tegra_cbb_print_err(file, "\t MASTER_ID\t\t: %s\n", cbb->fabric->master_id[mstr_id]); tegra_cbb_print_err(file, "\t Address\t\t: %#llx\n", cbb->access); @@ -374,6 +436,11 @@ static void print_errlog_err(struct seq_file *file, struct tegra234_cbb *cbb) if ((fab_id == PSC_FAB_ID) || (fab_id == FSI_FAB_ID)) return; + if (slave_id >= cbb->fabric->max_slaves) { + tegra_cbb_print_err(file, "\t Invalid slave_id:%d\n", slave_id); + return; + } + if (!strcmp(cbb->fabric->errors[cbb->type].code, "TIMEOUT_ERR")) { tegra234_lookup_slave_timeout(file, cbb, slave_id, fab_id); return; @@ -517,7 +584,7 @@ static irqreturn_t tegra234_cbb_isr(int irq, void *data) u32 status = tegra_cbb_get_status(cbb); if (status && (irq == priv->sec_irq)) { - tegra_cbb_print_err(NULL, "CPU:%d, Error: %s@%llx, irq=%d\n", + tegra_cbb_print_err(NULL, "CPU:%d, Error: %s@0x%llx, irq=%d\n", smp_processor_id(), priv->fabric->name, priv->res->start, irq); @@ -525,14 +592,14 @@ static irqreturn_t tegra234_cbb_isr(int irq, void *data) if (err) goto unlock; - mstr_id = FIELD_GET(USRBITS_MSTR_ID, priv->mn_user_bits); - /* - * If illegal request is from CCPLEX(id:0x1) master then call BUG() to - * crash system. + * If illegal request is from CCPLEX(id:0x1) master then call WARN() */ - if ((mstr_id == 0x1) && priv->fabric->off_mask_erd) - is_inband_err = 1; + if (priv->fabric->off_mask_erd) { + mstr_id = FIELD_GET(USRBITS_MSTR_ID, priv->mn_user_bits); + if (mstr_id == CCPLEX_MSTRID) + is_inband_err = 1; + } } } @@ -640,8 +707,13 @@ static const struct tegra234_cbb_fabric tegra234_aon_fabric = { .name = "aon-fabric", .master_id = tegra234_master_id, .slave_map = tegra234_aon_slave_map, + .max_slaves = ARRAY_SIZE(tegra234_aon_slave_map), .errors = tegra234_cbb_errors, + .max_errors = ARRAY_SIZE(tegra234_cbb_errors), .notifier_offset = 0x17000, + .firewall_base = 0x30000, + .firewall_ctl = 0x8d0, + .firewall_wr_ctl = 0x8c8, }; static const struct tegra234_slave_lookup tegra234_bpmp_slave_map[] = { @@ -656,8 +728,13 @@ static const struct tegra234_cbb_fabric tegra234_bpmp_fabric = { .name = "bpmp-fabric", .master_id = tegra234_master_id, .slave_map = tegra234_bpmp_slave_map, + .max_slaves = ARRAY_SIZE(tegra234_bpmp_slave_map), .errors = tegra234_cbb_errors, + .max_errors = ARRAY_SIZE(tegra234_cbb_errors), .notifier_offset = 0x19000, + .firewall_base = 0x30000, + .firewall_ctl = 0x8f0, + .firewall_wr_ctl = 0x8e8, }; static const struct tegra234_slave_lookup tegra234_cbb_slave_map[] = { @@ -728,55 +805,62 @@ static const struct tegra234_cbb_fabric tegra234_cbb_fabric = { .name = "cbb-fabric", .master_id = tegra234_master_id, .slave_map = tegra234_cbb_slave_map, + .max_slaves = ARRAY_SIZE(tegra234_cbb_slave_map), .errors = tegra234_cbb_errors, + .max_errors = ARRAY_SIZE(tegra234_cbb_errors), .notifier_offset = 0x60000, - .off_mask_erd = 0x3a004 + .off_mask_erd = 0x3a004, + .firewall_base = 0x10000, + .firewall_ctl = 0x23f0, + .firewall_wr_ctl = 0x23e8, }; -static const struct tegra234_slave_lookup tegra234_dce_slave_map[] = { +static const struct tegra234_slave_lookup tegra234_common_slave_map[] = { { "AXI2APB", 0x00000 }, { "AST0", 0x15000 }, { "AST1", 0x16000 }, + { "CBB", 0x17000 }, + { "RSVD", 0x00000 }, { "CPU", 0x18000 }, }; static const struct tegra234_cbb_fabric tegra234_dce_fabric = { .name = "dce-fabric", .master_id = tegra234_master_id, - .slave_map = tegra234_dce_slave_map, + .slave_map = tegra234_common_slave_map, + .max_slaves = ARRAY_SIZE(tegra234_common_slave_map), .errors = tegra234_cbb_errors, + .max_errors = ARRAY_SIZE(tegra234_cbb_errors), .notifier_offset = 0x19000, -}; - -static const struct tegra234_slave_lookup tegra234_rce_slave_map[] = { - { "AXI2APB", 0x00000 }, - { "AST0", 0x15000 }, - { "AST1", 0x16000 }, - { "CPU", 0x18000 }, + .firewall_base = 0x30000, + .firewall_ctl = 0x290, + .firewall_wr_ctl = 0x288, }; static const struct tegra234_cbb_fabric tegra234_rce_fabric = { .name = "rce-fabric", .master_id = tegra234_master_id, - .slave_map = tegra234_rce_slave_map, + .slave_map = tegra234_common_slave_map, + .max_slaves = ARRAY_SIZE(tegra234_common_slave_map), .errors = tegra234_cbb_errors, + .max_errors = ARRAY_SIZE(tegra234_cbb_errors), .notifier_offset = 0x19000, -}; - -static const struct tegra234_slave_lookup tegra234_sce_slave_map[] = { - { "AXI2APB", 0x00000 }, - { "AST0", 0x15000 }, - { "AST1", 0x16000 }, - { "CBB", 0x17000 }, - { "CPU", 0x18000 }, + .firewall_base = 0x30000, + .firewall_ctl = 0x290, + .firewall_wr_ctl = 0x288, }; static const struct tegra234_cbb_fabric tegra234_sce_fabric = { .name = "sce-fabric", .master_id = tegra234_master_id, - .slave_map = tegra234_sce_slave_map, + .slave_map = tegra234_common_slave_map, + .max_slaves = ARRAY_SIZE(tegra234_common_slave_map), .errors = tegra234_cbb_errors, + .max_errors = ARRAY_SIZE(tegra234_cbb_errors), .notifier_offset = 0x19000, + .firewall_base = 0x30000, + .firewall_ctl = 0x290, + .firewall_wr_ctl = 0x288, }; static const char * const tegra241_master_id[] = { @@ -889,7 +973,7 @@ static const struct tegra_cbb_error tegra241_cbb_errors[] = { }; static const struct tegra234_slave_lookup tegra241_cbb_slave_map[] = { - { "CCPLEX", 0x50000 }, + { "RSVD", 0x00000 }, { "PCIE_C8", 0x51000 }, { "PCIE_C9", 0x52000 }, { "RSVD", 0x00000 }, @@ -942,22 +1026,32 @@ static const struct tegra234_slave_lookup tegra241_cbb_slave_map[] = { { "PCIE_C3", 0x58000 }, { "PCIE_C0", 0x59000 }, { "PCIE_C1", 0x5a000 }, + { "CCPLEX", 0x50000 }, { "AXI2APB_29", 0x85000 }, { "AXI2APB_30", 0x86000 }, + { "CBB_CENTRAL", 0x00000 }, + { "AXI2APB_31", 0x8E000 }, + { "AXI2APB_32", 0x8F000 }, }; static const struct tegra234_cbb_fabric tegra241_cbb_fabric = { .name = "cbb-fabric", .master_id = tegra241_master_id, .slave_map = tegra241_cbb_slave_map, + .max_slaves = ARRAY_SIZE(tegra241_cbb_slave_map), .errors = tegra241_cbb_errors, + .max_errors = ARRAY_SIZE(tegra241_cbb_errors), .notifier_offset = 0x60000, .off_mask_erd = 0x40004, + .firewall_base = 0x20000, + .firewall_ctl = 0x2370, + .firewall_wr_ctl = 0x2368, }; static const struct tegra234_slave_lookup tegra241_bpmp_slave_map[] = { { "RSVD", 0x00000 }, { "RSVD", 0x00000 }, + { "RSVD", 0x00000 }, { "CBB", 0x15000 }, { "CPU", 0x16000 }, { "AXI2APB", 0x00000 }, @@ -969,8 +1063,13 @@ static const struct tegra234_cbb_fabric tegra241_bpmp_fabric = { .name = "bpmp-fabric", .master_id = tegra241_master_id, .slave_map = tegra241_bpmp_slave_map, + .max_slaves = ARRAY_SIZE(tegra241_bpmp_slave_map), .errors = tegra241_cbb_errors, + .max_errors = ARRAY_SIZE(tegra241_cbb_errors), .notifier_offset = 0x19000, + .firewall_base = 0x30000, + .firewall_ctl = 0x8f0, + .firewall_wr_ctl = 0x8e8, }; static const struct of_device_id tegra234_cbb_dt_ids[] = { @@ -1055,6 +1154,15 @@ static int tegra234_cbb_probe(struct platform_device *pdev) platform_set_drvdata(pdev, cbb); + /* + * Don't enable error reporting for a Fabric if write to it's registers + * is blocked by CBB firewall. + */ + if (!tegra234_cbb_write_access_allowed(pdev, cbb)) { + dev_info(&pdev->dev, "error reporting not enabled due to firewall\n"); + return 0; + } + spin_lock_irqsave(&cbb_lock, flags); list_add(&cbb->base.node, &cbb_list); spin_unlock_irqrestore(&cbb_lock, flags); diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c index 6542267a224d..f02953f793e9 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra.c +++ b/drivers/soc/tegra/fuse/fuse-tegra.c @@ -35,6 +35,19 @@ static const char *tegra_revision_name[TEGRA_REVISION_MAX] = { [TEGRA_REVISION_A04] = "A04", }; +static const char *tegra_platform_name[TEGRA_PLATFORM_MAX] = { + [TEGRA_PLATFORM_SILICON] = "Silicon", + [TEGRA_PLATFORM_QT] = "QT", + [TEGRA_PLATFORM_SYSTEM_FPGA] = "System FPGA", + [TEGRA_PLATFORM_UNIT_FPGA] = "Unit FPGA", + [TEGRA_PLATFORM_ASIM_QT] = "Asim QT", + [TEGRA_PLATFORM_ASIM_LINSIM] = "Asim Linsim", + [TEGRA_PLATFORM_DSIM_ASIM_LINSIM] = "Dsim Asim Linsim", + [TEGRA_PLATFORM_VERIFICATION_SIMULATION] = "Verification Simulation", + [TEGRA_PLATFORM_VDK] = "VDK", + [TEGRA_PLATFORM_VSP] = "VSP", +}; + static const struct of_device_id car_match[] __initconst = { { .compatible = "nvidia,tegra20-car", }, { .compatible = "nvidia,tegra30-car", }, @@ -94,112 +107,6 @@ static int tegra_fuse_read(void *priv, unsigned int offset, void *value, return 0; } -static const struct nvmem_cell_info tegra_fuse_cells[] = { - { - .name = "tsensor-cpu1", - .offset = 0x084, - .bytes = 4, - .bit_offset = 0, - .nbits = 32, - }, { - .name = "tsensor-cpu2", - .offset = 0x088, - .bytes = 4, - .bit_offset = 0, - .nbits = 32, - }, { - .name = "tsensor-cpu0", - .offset = 0x098, - .bytes = 4, - .bit_offset = 0, - .nbits = 32, - }, { - .name = "xusb-pad-calibration", - .offset = 0x0f0, - .bytes = 4, - .bit_offset = 0, - .nbits = 32, - }, { - .name = "tsensor-cpu3", - .offset = 0x12c, - .bytes = 4, - .bit_offset = 0, - .nbits = 32, - }, { - .name = "sata-calibration", - .offset = 0x124, - .bytes = 1, - .bit_offset = 0, - .nbits = 2, - }, { - .name = "tsensor-gpu", - .offset = 0x154, - .bytes = 4, - .bit_offset = 0, - .nbits = 32, - }, { - .name = "tsensor-mem0", - .offset = 0x158, - .bytes = 4, - .bit_offset = 0, - .nbits = 32, - }, { - .name = "tsensor-mem1", - .offset = 0x15c, - .bytes = 4, - .bit_offset = 0, - .nbits = 32, - }, { - .name = "tsensor-pllx", - .offset = 0x160, - .bytes = 4, - .bit_offset = 0, - .nbits = 32, - }, { - .name = "tsensor-common", - .offset = 0x180, - .bytes = 4, - .bit_offset = 0, - .nbits = 32, - }, { - .name = "gpu-gcplex-config-fuse", - .offset = 0x1c8, - .bytes = 4, - .bit_offset = 0, - .nbits = 32, - }, { - .name = "tsensor-realignment", - .offset = 0x1fc, - .bytes = 4, - .bit_offset = 0, - .nbits = 32, - }, { - .name = "gpu-calibration", - .offset = 0x204, - .bytes = 4, - .bit_offset = 0, - .nbits = 32, - }, { - .name = "xusb-pad-calibration-ext", - .offset = 0x250, - .bytes = 4, - .bit_offset = 0, - .nbits = 32, - }, { - .name = "gpu-pdi0", - .offset = 0x300, - .bytes = 4, - .bit_offset = 0, - .nbits = 32, - }, { - .name = "gpu-pdi1", - .offset = 0x304, - .bytes = 4, - .bit_offset = 0, - .nbits = 32, - }, -}; - static void tegra_fuse_restore(void *base) { fuse->base = (void __iomem *)base; @@ -253,8 +160,10 @@ static int tegra_fuse_probe(struct platform_device *pdev) nvmem.name = "fuse"; nvmem.id = -1; nvmem.owner = THIS_MODULE; - nvmem.cells = tegra_fuse_cells; - nvmem.ncells = ARRAY_SIZE(tegra_fuse_cells); + nvmem.cells = fuse->soc->cells; + nvmem.ncells = fuse->soc->num_cells; + nvmem.keepout = fuse->soc->keepouts; + nvmem.nkeepout = fuse->soc->num_keepouts; nvmem.type = NVMEM_TYPE_OTP; nvmem.read_only = true; nvmem.root_only = true; @@ -474,8 +383,13 @@ struct device * __init tegra_soc_device_register(void) return NULL; attr->family = kasprintf(GFP_KERNEL, "Tegra"); - attr->revision = kasprintf(GFP_KERNEL, "%s", - tegra_revision_name[tegra_sku_info.revision]); + if (tegra_is_silicon()) + attr->revision = kasprintf(GFP_KERNEL, "%s %s", + tegra_platform_name[tegra_sku_info.platform], + tegra_revision_name[tegra_sku_info.revision]); + else + attr->revision = kasprintf(GFP_KERNEL, "%s", + tegra_platform_name[tegra_sku_info.platform]); attr->soc_id = kasprintf(GFP_KERNEL, "%u", tegra_get_chip_id()); attr->custom_attr_group = fuse->soc->soc_attr_group; diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c index f01d8a2547b6..932a03c64534 100644 --- a/drivers/soc/tegra/fuse/fuse-tegra30.c +++ b/drivers/soc/tegra/fuse/fuse-tegra30.c @@ -9,6 +9,7 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/nvmem-consumer.h> +#include <linux/nvmem-provider.h> #include <linux/of_device.h> #include <linux/of_address.h> #include <linux/platform_device.h> @@ -133,6 +134,82 @@ const struct tegra_fuse_soc tegra114_fuse_soc = { #endif #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC) +static const struct nvmem_cell_info tegra124_fuse_cells[] = { + { + .name = "tsensor-cpu1", + .offset = 0x084, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-cpu2", + .offset = 0x088, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-cpu0", + .offset = 0x098, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "xusb-pad-calibration", + .offset = 0x0f0, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-cpu3", + .offset = 0x12c, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "sata-calibration", + .offset = 0x124, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-gpu", + .offset = 0x154, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-mem0", + .offset = 0x158, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-mem1", + .offset = 0x15c, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-pllx", + .offset = 0x160, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-common", + .offset = 0x180, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-realignment", + .offset = 0x1fc, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, +}; + static const struct nvmem_cell_lookup tegra124_fuse_lookups[] = { { .nvmem_name = "fuse", @@ -209,12 +286,96 @@ const struct tegra_fuse_soc tegra124_fuse_soc = { .info = &tegra124_fuse_info, .lookups = tegra124_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra124_fuse_lookups), + .cells = tegra124_fuse_cells, + .num_cells = ARRAY_SIZE(tegra124_fuse_cells), .soc_attr_group = &tegra_soc_attr_group, .clk_suspend_on = true, }; #endif #if defined(CONFIG_ARCH_TEGRA_210_SOC) +static const struct nvmem_cell_info tegra210_fuse_cells[] = { + { + .name = "tsensor-cpu1", + .offset = 0x084, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-cpu2", + .offset = 0x088, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-cpu0", + .offset = 0x098, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "xusb-pad-calibration", + .offset = 0x0f0, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-cpu3", + .offset = 0x12c, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "sata-calibration", + .offset = 0x124, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-gpu", + .offset = 0x154, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-mem0", + .offset = 0x158, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-mem1", + .offset = 0x15c, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-pllx", + .offset = 0x160, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "tsensor-common", + .offset = 0x180, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "gpu-calibration", + .offset = 0x204, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "xusb-pad-calibration-ext", + .offset = 0x250, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, +}; + static const struct nvmem_cell_lookup tegra210_fuse_lookups[] = { { .nvmem_name = "fuse", @@ -295,6 +456,8 @@ const struct tegra_fuse_soc tegra210_fuse_soc = { .speedo_init = tegra210_init_speedo_data, .info = &tegra210_fuse_info, .lookups = tegra210_fuse_lookups, + .cells = tegra210_fuse_cells, + .num_cells = ARRAY_SIZE(tegra210_fuse_cells), .num_lookups = ARRAY_SIZE(tegra210_fuse_lookups), .soc_attr_group = &tegra_soc_attr_group, .clk_suspend_on = false, @@ -302,6 +465,22 @@ const struct tegra_fuse_soc tegra210_fuse_soc = { #endif #if defined(CONFIG_ARCH_TEGRA_186_SOC) +static const struct nvmem_cell_info tegra186_fuse_cells[] = { + { + .name = "xusb-pad-calibration", + .offset = 0x0f0, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "xusb-pad-calibration-ext", + .offset = 0x250, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, +}; + static const struct nvmem_cell_lookup tegra186_fuse_lookups[] = { { .nvmem_name = "fuse", @@ -316,9 +495,17 @@ static const struct nvmem_cell_lookup tegra186_fuse_lookups[] = { }, }; +static const struct nvmem_keepout tegra186_fuse_keepouts[] = { + { .start = 0x01c, .end = 0x0f0 }, + { .start = 0x138, .end = 0x198 }, + { .start = 0x1d8, .end = 0x250 }, + { .start = 0x280, .end = 0x290 }, + { .start = 0x340, .end = 0x344 } +}; + static const struct tegra_fuse_info tegra186_fuse_info = { .read = tegra30_fuse_read, - .size = 0x300, + .size = 0x478, .spare = 0x280, }; @@ -327,12 +514,50 @@ const struct tegra_fuse_soc tegra186_fuse_soc = { .info = &tegra186_fuse_info, .lookups = tegra186_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra186_fuse_lookups), + .cells = tegra186_fuse_cells, + .num_cells = ARRAY_SIZE(tegra186_fuse_cells), + .keepouts = tegra186_fuse_keepouts, + .num_keepouts = ARRAY_SIZE(tegra186_fuse_keepouts), .soc_attr_group = &tegra_soc_attr_group, .clk_suspend_on = false, }; #endif #if defined(CONFIG_ARCH_TEGRA_194_SOC) +static const struct nvmem_cell_info tegra194_fuse_cells[] = { + { + .name = "xusb-pad-calibration", + .offset = 0x0f0, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "gpu-gcplex-config-fuse", + .offset = 0x1c8, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "xusb-pad-calibration-ext", + .offset = 0x250, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "gpu-pdi0", + .offset = 0x300, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "gpu-pdi1", + .offset = 0x304, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, +}; + static const struct nvmem_cell_lookup tegra194_fuse_lookups[] = { { .nvmem_name = "fuse", @@ -362,9 +587,18 @@ static const struct nvmem_cell_lookup tegra194_fuse_lookups[] = { }, }; +static const struct nvmem_keepout tegra194_fuse_keepouts[] = { + { .start = 0x01c, .end = 0x0b8 }, + { .start = 0x12c, .end = 0x198 }, + { .start = 0x1a0, .end = 0x1bc }, + { .start = 0x1d8, .end = 0x250 }, + { .start = 0x270, .end = 0x290 }, + { .start = 0x310, .end = 0x45c } +}; + static const struct tegra_fuse_info tegra194_fuse_info = { .read = tegra30_fuse_read, - .size = 0x300, + .size = 0x650, .spare = 0x280, }; @@ -373,12 +607,32 @@ const struct tegra_fuse_soc tegra194_fuse_soc = { .info = &tegra194_fuse_info, .lookups = tegra194_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra194_fuse_lookups), + .cells = tegra194_fuse_cells, + .num_cells = ARRAY_SIZE(tegra194_fuse_cells), + .keepouts = tegra194_fuse_keepouts, + .num_keepouts = ARRAY_SIZE(tegra194_fuse_keepouts), .soc_attr_group = &tegra194_soc_attr_group, .clk_suspend_on = false, }; #endif #if defined(CONFIG_ARCH_TEGRA_234_SOC) +static const struct nvmem_cell_info tegra234_fuse_cells[] = { + { + .name = "xusb-pad-calibration", + .offset = 0x0f0, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, { + .name = "xusb-pad-calibration-ext", + .offset = 0x250, + .bytes = 4, + .bit_offset = 0, + .nbits = 32, + }, +}; + static const struct nvmem_cell_lookup tegra234_fuse_lookups[] = { { .nvmem_name = "fuse", @@ -393,9 +647,23 @@ static const struct nvmem_cell_lookup tegra234_fuse_lookups[] = { }, }; +static const struct nvmem_keepout tegra234_fuse_keepouts[] = { + { .start = 0x01c, .end = 0x0c8 }, + { .start = 0x12c, .end = 0x184 }, + { .start = 0x190, .end = 0x198 }, + { .start = 0x1a0, .end = 0x204 }, + { .start = 0x21c, .end = 0x250 }, + { .start = 0x25c, .end = 0x2f0 }, + { .start = 0x310, .end = 0x3d8 }, + { .start = 0x400, .end = 0x4f0 }, + { .start = 0x4f8, .end = 0x7e8 }, + { .start = 0x8d0, .end = 0x8d8 }, + { .start = 0xacc, .end = 0xf00 } +}; + static const struct tegra_fuse_info tegra234_fuse_info = { .read = tegra30_fuse_read, - .size = 0x300, + .size = 0x98c, .spare = 0x280, }; @@ -404,6 +672,10 @@ const struct tegra_fuse_soc tegra234_fuse_soc = { .info = &tegra234_fuse_info, .lookups = tegra234_fuse_lookups, .num_lookups = ARRAY_SIZE(tegra234_fuse_lookups), + .cells = tegra234_fuse_cells, + .num_cells = ARRAY_SIZE(tegra234_fuse_cells), + .keepouts = tegra234_fuse_keepouts, + .num_keepouts = ARRAY_SIZE(tegra234_fuse_keepouts), .soc_attr_group = &tegra194_soc_attr_group, .clk_suspend_on = false, }; diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h index 2bb1f9d6a6e6..90f23be73894 100644 --- a/drivers/soc/tegra/fuse/fuse.h +++ b/drivers/soc/tegra/fuse/fuse.h @@ -32,6 +32,10 @@ struct tegra_fuse_soc { const struct nvmem_cell_lookup *lookups; unsigned int num_lookups; + const struct nvmem_cell_info *cells; + unsigned int num_cells; + const struct nvmem_keepout *keepouts; + unsigned int num_keepouts; const struct attribute_group *soc_attr_group; diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c index 3351bd872ab2..4591c5bcb690 100644 --- a/drivers/soc/tegra/fuse/tegra-apbmisc.c +++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c @@ -156,6 +156,7 @@ void __init tegra_init_revision(void) } tegra_sku_info.sku_id = tegra_fuse_read_early(FUSE_SKU_INFO); + tegra_sku_info.platform = tegra_get_platform(); } void __init tegra_init_apbmisc(void) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 678e8bc8a45d..cf4cfbf9f7c5 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -23,6 +23,7 @@ #include <linux/err.h> #include <linux/export.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/io.h> #include <linux/iopoll.h> #include <linux/irqdomain.h> @@ -46,6 +47,7 @@ #include <linux/seq_file.h> #include <linux/slab.h> #include <linux/spinlock.h> +#include <linux/syscore_ops.h> #include <soc/tegra/common.h> #include <soc/tegra/fuse.h> @@ -182,6 +184,9 @@ #define WAKE_AOWAKE_TIER0_ROUTING(x) (0x4b4 + ((x) << 2)) #define WAKE_AOWAKE_TIER1_ROUTING(x) (0x4c0 + ((x) << 2)) #define WAKE_AOWAKE_TIER2_ROUTING(x) (0x4cc + ((x) << 2)) +#define WAKE_AOWAKE_SW_STATUS_W_0 0x49c +#define WAKE_AOWAKE_SW_STATUS(x) (0x4a0 + ((x) << 2)) +#define WAKE_LATCH_SW 0x498 #define WAKE_AOWAKE_CTRL 0x4f4 #define WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0) @@ -269,16 +274,14 @@ struct tegra_powergate { struct tegra_io_pad_soc { enum tegra_io_pad id; unsigned int dpd; + unsigned int request; + unsigned int status; unsigned int voltage; const char *name; }; struct tegra_pmc_regs { unsigned int scratch0; - unsigned int dpd_req; - unsigned int dpd_status; - unsigned int dpd2_req; - unsigned int dpd2_status; unsigned int rst_status; unsigned int rst_source_shift; unsigned int rst_source_mask; @@ -369,6 +372,8 @@ struct tegra_pmc_soc { */ const struct tegra_wake_event *wake_events; unsigned int num_wake_events; + unsigned int max_wake_events; + unsigned int max_wake_vectors; const struct pmc_clk_init_data *pmc_clks_data; unsigned int num_pmc_clks; @@ -409,6 +414,11 @@ struct tegra_pmc_soc { * @clk_nb: pclk clock changes handler * @core_domain_state_synced: flag marking the core domain's state as synced * @core_domain_registered: flag marking the core domain as registered + * @wake_type_level_map: Bitmap indicating level type for non-dual edge wakes + * @wake_type_dual_edge_map: Bitmap indicating if a wake is dual-edge or not + * @wake_sw_status_map: Bitmap to hold raw status of wakes without mask + * @wake_cntrl_level_map: Bitmap to hold wake levels to be programmed in + * cntrl register associated with each wake during system suspend. */ struct tegra_pmc { struct device *dev; @@ -449,6 +459,12 @@ struct tegra_pmc { bool core_domain_state_synced; bool core_domain_registered; + + unsigned long *wake_type_level_map; + unsigned long *wake_type_dual_edge_map; + unsigned long *wake_sw_status_map; + unsigned long *wake_cntrl_level_map; + struct syscore_ops syscore; }; static struct tegra_pmc *pmc = &(struct tegra_pmc) { @@ -1540,46 +1556,20 @@ tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id) return NULL; } -static int tegra_io_pad_get_dpd_register_bit(struct tegra_pmc *pmc, - enum tegra_io_pad id, - unsigned long *request, - unsigned long *status, - u32 *mask) -{ - const struct tegra_io_pad_soc *pad; - - pad = tegra_io_pad_find(pmc, id); - if (!pad) { - dev_err(pmc->dev, "invalid I/O pad ID %u\n", id); - return -ENOENT; - } - - if (pad->dpd == UINT_MAX) - return -ENOTSUPP; - - *mask = BIT(pad->dpd % 32); - - if (pad->dpd < 32) { - *status = pmc->soc->regs->dpd_status; - *request = pmc->soc->regs->dpd_req; - } else { - *status = pmc->soc->regs->dpd2_status; - *request = pmc->soc->regs->dpd2_req; - } - - return 0; -} - -static int tegra_io_pad_prepare(struct tegra_pmc *pmc, enum tegra_io_pad id, - unsigned long *request, unsigned long *status, +static int tegra_io_pad_prepare(struct tegra_pmc *pmc, + const struct tegra_io_pad_soc *pad, + unsigned long *request, + unsigned long *status, u32 *mask) { unsigned long rate, value; - int err; - err = tegra_io_pad_get_dpd_register_bit(pmc, id, request, status, mask); - if (err) - return err; + if (pad->dpd == UINT_MAX) + return -EINVAL; + + *request = pad->request; + *status = pad->status; + *mask = BIT(pad->dpd); if (pmc->clk) { rate = pmc->rate; @@ -1631,13 +1621,20 @@ static void tegra_io_pad_unprepare(struct tegra_pmc *pmc) */ int tegra_io_pad_power_enable(enum tegra_io_pad id) { + const struct tegra_io_pad_soc *pad; unsigned long request, status; u32 mask; int err; + pad = tegra_io_pad_find(pmc, id); + if (!pad) { + dev_err(pmc->dev, "invalid I/O pad ID %u\n", id); + return -ENOENT; + } + mutex_lock(&pmc->powergates_lock); - err = tegra_io_pad_prepare(pmc, id, &request, &status, &mask); + err = tegra_io_pad_prepare(pmc, pad, &request, &status, &mask); if (err < 0) { dev_err(pmc->dev, "failed to prepare I/O pad: %d\n", err); goto unlock; @@ -1667,13 +1664,20 @@ EXPORT_SYMBOL(tegra_io_pad_power_enable); */ int tegra_io_pad_power_disable(enum tegra_io_pad id) { + const struct tegra_io_pad_soc *pad; unsigned long request, status; u32 mask; int err; + pad = tegra_io_pad_find(pmc, id); + if (!pad) { + dev_err(pmc->dev, "invalid I/O pad ID %u\n", id); + return -ENOENT; + } + mutex_lock(&pmc->powergates_lock); - err = tegra_io_pad_prepare(pmc, id, &request, &status, &mask); + err = tegra_io_pad_prepare(pmc, pad, &request, &status, &mask); if (err < 0) { dev_err(pmc->dev, "failed to prepare I/O pad: %d\n", err); goto unlock; @@ -1697,14 +1701,21 @@ EXPORT_SYMBOL(tegra_io_pad_power_disable); static int tegra_io_pad_is_powered(struct tegra_pmc *pmc, enum tegra_io_pad id) { - unsigned long request, status; + const struct tegra_io_pad_soc *pad; + unsigned long status; u32 mask, value; - int err; - err = tegra_io_pad_get_dpd_register_bit(pmc, id, &request, &status, - &mask); - if (err) - return err; + pad = tegra_io_pad_find(pmc, id); + if (!pad) { + dev_err(pmc->dev, "invalid I/O pad ID %u\n", id); + return -ENOENT; + } + + if (pad->dpd == UINT_MAX) + return -EINVAL; + + status = pad->status; + mask = BIT(pad->dpd); value = tegra_pmc_readl(pmc, status); @@ -1930,10 +1941,30 @@ static int tegra_pmc_parse_dt(struct tegra_pmc *pmc, struct device_node *np) return 0; } -static void tegra_pmc_init(struct tegra_pmc *pmc) +static int tegra_pmc_init(struct tegra_pmc *pmc) { + if (pmc->soc->max_wake_events > 0) { + pmc->wake_type_level_map = bitmap_zalloc(pmc->soc->max_wake_events, GFP_KERNEL); + if (!pmc->wake_type_level_map) + return -ENOMEM; + + pmc->wake_type_dual_edge_map = bitmap_zalloc(pmc->soc->max_wake_events, GFP_KERNEL); + if (!pmc->wake_type_dual_edge_map) + return -ENOMEM; + + pmc->wake_sw_status_map = bitmap_zalloc(pmc->soc->max_wake_events, GFP_KERNEL); + if (!pmc->wake_sw_status_map) + return -ENOMEM; + + pmc->wake_cntrl_level_map = bitmap_zalloc(pmc->soc->max_wake_events, GFP_KERNEL); + if (!pmc->wake_cntrl_level_map) + return -ENOMEM; + } + if (pmc->soc->init) pmc->soc->init(pmc); + + return 0; } static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc) @@ -2424,15 +2455,21 @@ static int tegra186_pmc_irq_set_type(struct irq_data *data, unsigned int type) case IRQ_TYPE_EDGE_RISING: case IRQ_TYPE_LEVEL_HIGH: value |= WAKE_AOWAKE_CNTRL_LEVEL; + set_bit(data->hwirq, pmc->wake_type_level_map); + clear_bit(data->hwirq, pmc->wake_type_dual_edge_map); break; case IRQ_TYPE_EDGE_FALLING: case IRQ_TYPE_LEVEL_LOW: value &= ~WAKE_AOWAKE_CNTRL_LEVEL; + clear_bit(data->hwirq, pmc->wake_type_level_map); + clear_bit(data->hwirq, pmc->wake_type_dual_edge_map); break; case IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING: value ^= WAKE_AOWAKE_CNTRL_LEVEL; + clear_bit(data->hwirq, pmc->wake_type_level_map); + set_bit(data->hwirq, pmc->wake_type_dual_edge_map); break; default: @@ -2964,7 +3001,11 @@ static int tegra_pmc_probe(struct platform_device *pdev) pmc->dev = &pdev->dev; - tegra_pmc_init(pmc); + err = tegra_pmc_init(pmc); + if (err < 0) { + dev_err(&pdev->dev, "failed to initialize PMC: %d\n", err); + return err; + } tegra_pmc_init_tsense_reset(pmc); @@ -3015,6 +3056,156 @@ cleanup_sysfs: return err; } +/* + * Ensures that sufficient time is passed for a register write to + * serialize into the 32KHz domain. + */ +static void wke_32kwritel(struct tegra_pmc *pmc, u32 value, unsigned int offset) +{ + writel(value, pmc->wake + offset); + udelay(130); +} + +static void wke_write_wake_level(struct tegra_pmc *pmc, int wake, int level) +{ + unsigned int offset = WAKE_AOWAKE_CNTRL(wake); + u32 value; + + value = readl(pmc->wake + offset); + if (level) + value |= WAKE_AOWAKE_CNTRL_LEVEL; + else + value &= ~WAKE_AOWAKE_CNTRL_LEVEL; + + writel(value, pmc->wake + offset); +} + +static void wke_write_wake_levels(struct tegra_pmc *pmc) +{ + unsigned int i; + + for (i = 0; i < pmc->soc->max_wake_events; i++) + wke_write_wake_level(pmc, i, test_bit(i, pmc->wake_cntrl_level_map)); +} + +static void wke_clear_sw_wake_status(struct tegra_pmc *pmc) +{ + wke_32kwritel(pmc, 1, WAKE_AOWAKE_SW_STATUS_W_0); +} + +static void wke_read_sw_wake_status(struct tegra_pmc *pmc) +{ + unsigned long status; + unsigned int wake, i; + + for (i = 0; i < pmc->soc->max_wake_events; i++) + wke_write_wake_level(pmc, i, 0); + + wke_clear_sw_wake_status(pmc); + + wke_32kwritel(pmc, 1, WAKE_LATCH_SW); + + /* + * WAKE_AOWAKE_SW_STATUS is edge triggered, so in order to + * obtain the current status of the input wake signals, change + * the polarity of the wake level from 0->1 while latching to force + * a positive edge if the sampled signal is '1'. + */ + for (i = 0; i < pmc->soc->max_wake_events; i++) + wke_write_wake_level(pmc, i, 1); + + /* + * Wait for the update to be synced into the 32kHz domain, + * and let enough time lapse, so that the wake signals have time to + * be sampled. + */ + udelay(300); + + wke_32kwritel(pmc, 0, WAKE_LATCH_SW); + + bitmap_zero(pmc->wake_sw_status_map, pmc->soc->max_wake_events); + + for (i = 0; i < pmc->soc->max_wake_vectors; i++) { + status = readl(pmc->wake + WAKE_AOWAKE_SW_STATUS(i)); + + for_each_set_bit(wake, &status, 32) + set_bit(wake + (i * 32), pmc->wake_sw_status_map); + } +} + +static void wke_clear_wake_status(struct tegra_pmc *pmc) +{ + unsigned long status; + unsigned int i, wake; + u32 mask; + + for (i = 0; i < pmc->soc->max_wake_vectors; i++) { + mask = readl(pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(i)); + status = readl(pmc->wake + WAKE_AOWAKE_STATUS_R(i)) & mask; + + for_each_set_bit(wake, &status, 32) + wke_32kwritel(pmc, 0x1, WAKE_AOWAKE_STATUS_W((i * 32) + wake)); + } +} + +/* translate sc7 wake sources back into IRQs to catch edge triggered wakeups */ +static void tegra186_pmc_process_wake_events(struct tegra_pmc *pmc, unsigned int index, + unsigned long status) +{ + unsigned int wake; + + dev_dbg(pmc->dev, "Wake[%d:%d] status=%#lx\n", (index * 32) + 31, index * 32, status); + + for_each_set_bit(wake, &status, 32) { + irq_hw_number_t hwirq = wake + 32 * index; + struct irq_desc *desc; + unsigned int irq; + + irq = irq_find_mapping(pmc->domain, hwirq); + + desc = irq_to_desc(irq); + if (!desc || !desc->action || !desc->action->name) { + dev_dbg(pmc->dev, "Resume caused by WAKE%ld, IRQ %d\n", hwirq, irq); + continue; + } + + dev_dbg(pmc->dev, "Resume caused by WAKE%ld, %s\n", hwirq, desc->action->name); + generic_handle_irq(irq); + } +} + +static void tegra186_pmc_wake_syscore_resume(void) +{ + u32 status, mask; + unsigned int i; + + for (i = 0; i < pmc->soc->max_wake_vectors; i++) { + mask = readl(pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(i)); + status = readl(pmc->wake + WAKE_AOWAKE_STATUS_R(i)) & mask; + + tegra186_pmc_process_wake_events(pmc, i, status); + } +} + +static int tegra186_pmc_wake_syscore_suspend(void) +{ + wke_read_sw_wake_status(pmc); + + /* flip the wakeup trigger for dual-edge triggered pads + * which are currently asserting as wakeups + */ + bitmap_andnot(pmc->wake_cntrl_level_map, pmc->wake_type_dual_edge_map, + pmc->wake_sw_status_map, pmc->soc->max_wake_events); + bitmap_or(pmc->wake_cntrl_level_map, pmc->wake_cntrl_level_map, + pmc->wake_type_level_map, pmc->soc->max_wake_events); + + /* Clear PMC Wake Status registers while going to suspend */ + wke_clear_wake_status(pmc); + wke_write_wake_levels(pmc); + + return 0; +} + #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM) static int tegra_pmc_suspend(struct device *dev) { @@ -3050,10 +3241,6 @@ static const char * const tegra20_powergates[] = { static const struct tegra_pmc_regs tegra20_pmc_regs = { .scratch0 = 0x50, - .dpd_req = 0x1b8, - .dpd_status = 0x1bc, - .dpd2_req = 0x1c0, - .dpd2_status = 0x1c4, .rst_status = 0x1b4, .rst_source_shift = 0x0, .rst_source_mask = 0x7, @@ -3297,59 +3484,86 @@ static const u8 tegra124_cpu_powergates[] = { TEGRA_POWERGATE_CPU3, }; -#define TEGRA_IO_PAD(_id, _dpd, _voltage, _name) \ - ((struct tegra_io_pad_soc) { \ - .id = (_id), \ - .dpd = (_dpd), \ - .voltage = (_voltage), \ - .name = (_name), \ +#define TEGRA_IO_PAD(_id, _dpd, _request, _status, _voltage, _name) \ + ((struct tegra_io_pad_soc) { \ + .id = (_id), \ + .dpd = (_dpd), \ + .request = (_request), \ + .status = (_status), \ + .voltage = (_voltage), \ + .name = (_name), \ }) -#define TEGRA_IO_PIN_DESC(_id, _dpd, _voltage, _name) \ - ((struct pinctrl_pin_desc) { \ - .number = (_id), \ - .name = (_name) \ +#define TEGRA_IO_PIN_DESC(_id, _name) \ + ((struct pinctrl_pin_desc) { \ + .number = (_id), \ + .name = (_name), \ }) -#define TEGRA124_IO_PAD_TABLE(_pad) \ - /* .id .dpd .voltage .name */ \ - _pad(TEGRA_IO_PAD_AUDIO, 17, UINT_MAX, "audio"), \ - _pad(TEGRA_IO_PAD_BB, 15, UINT_MAX, "bb"), \ - _pad(TEGRA_IO_PAD_CAM, 36, UINT_MAX, "cam"), \ - _pad(TEGRA_IO_PAD_COMP, 22, UINT_MAX, "comp"), \ - _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \ - _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csb"), \ - _pad(TEGRA_IO_PAD_CSIE, 44, UINT_MAX, "cse"), \ - _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \ - _pad(TEGRA_IO_PAD_DSIB, 39, UINT_MAX, "dsib"), \ - _pad(TEGRA_IO_PAD_DSIC, 40, UINT_MAX, "dsic"), \ - _pad(TEGRA_IO_PAD_DSID, 41, UINT_MAX, "dsid"), \ - _pad(TEGRA_IO_PAD_HDMI, 28, UINT_MAX, "hdmi"), \ - _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \ - _pad(TEGRA_IO_PAD_HV, 38, UINT_MAX, "hv"), \ - _pad(TEGRA_IO_PAD_LVDS, 57, UINT_MAX, "lvds"), \ - _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \ - _pad(TEGRA_IO_PAD_NAND, 13, UINT_MAX, "nand"), \ - _pad(TEGRA_IO_PAD_PEX_BIAS, 4, UINT_MAX, "pex-bias"), \ - _pad(TEGRA_IO_PAD_PEX_CLK1, 5, UINT_MAX, "pex-clk1"), \ - _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \ - _pad(TEGRA_IO_PAD_PEX_CNTRL, 32, UINT_MAX, "pex-cntrl"), \ - _pad(TEGRA_IO_PAD_SDMMC1, 33, UINT_MAX, "sdmmc1"), \ - _pad(TEGRA_IO_PAD_SDMMC3, 34, UINT_MAX, "sdmmc3"), \ - _pad(TEGRA_IO_PAD_SDMMC4, 35, UINT_MAX, "sdmmc4"), \ - _pad(TEGRA_IO_PAD_SYS_DDC, 58, UINT_MAX, "sys_ddc"), \ - _pad(TEGRA_IO_PAD_UART, 14, UINT_MAX, "uart"), \ - _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \ - _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \ - _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \ - _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb_bias") - static const struct tegra_io_pad_soc tegra124_io_pads[] = { - TEGRA124_IO_PAD_TABLE(TEGRA_IO_PAD) + TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO, 17, 0x1b8, 0x1bc, UINT_MAX, "audio"), + TEGRA_IO_PAD(TEGRA_IO_PAD_BB, 15, 0x1b8, 0x1bc, UINT_MAX, "bb"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CAM, 4, 0x1c0, 0x1c4, UINT_MAX, "cam"), + TEGRA_IO_PAD(TEGRA_IO_PAD_COMP, 22, 0x1b8, 0x1bc, UINT_MAX, "comp"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0x1b8, 0x1bc, UINT_MAX, "csia"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0x1b8, 0x1bc, UINT_MAX, "csib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIE, 12, 0x1c0, 0x1c4, UINT_MAX, "csie"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSI, 2, 0x1b8, 0x1bc, UINT_MAX, "dsi"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSIB, 7, 0x1c0, 0x1c4, UINT_MAX, "dsib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSIC, 8, 0x1c0, 0x1c4, UINT_MAX, "dsic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSID, 9, 0x1c0, 0x1c4, UINT_MAX, "dsid"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI, 28, 0x1b8, 0x1bc, UINT_MAX, "hdmi"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HSIC, 19, 0x1b8, 0x1bc, UINT_MAX, "hsic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HV, 6, 0x1c0, 0x1c4, UINT_MAX, "hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_LVDS, 25, 0x1c0, 0x1c4, UINT_MAX, "lvds"), + TEGRA_IO_PAD(TEGRA_IO_PAD_MIPI_BIAS, 3, 0x1b8, 0x1bc, UINT_MAX, "mipi-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_NAND, 13, 0x1b8, 0x1bc, UINT_MAX, "nand"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_BIAS, 4, 0x1b8, 0x1bc, UINT_MAX, "pex-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK1, 5, 0x1b8, 0x1bc, UINT_MAX, "pex-clk1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK2, 6, 0x1b8, 0x1bc, UINT_MAX, "pex-clk2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CNTRL, 0, 0x1c0, 0x1c4, UINT_MAX, "pex-cntrl"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1, 1, 0x1c0, 0x1c4, UINT_MAX, "sdmmc1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC3, 2, 0x1c0, 0x1c4, UINT_MAX, "sdmmc3"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC4, 3, 0x1c0, 0x1c4, UINT_MAX, "sdmmc4"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SYS_DDC, 26, 0x1c0, 0x1c4, UINT_MAX, "sys_ddc"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UART, 14, 0x1b8, 0x1bc, UINT_MAX, "uart"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB0, 9, 0x1b8, 0x1bc, UINT_MAX, "usb0"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB1, 10, 0x1b8, 0x1bc, UINT_MAX, "usb1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB2, 11, 0x1b8, 0x1bc, UINT_MAX, "usb2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB_BIAS, 12, 0x1b8, 0x1bc, UINT_MAX, "usb_bias"), }; static const struct pinctrl_pin_desc tegra124_pin_descs[] = { - TEGRA124_IO_PAD_TABLE(TEGRA_IO_PIN_DESC) + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_AUDIO, "audio"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_BB, "bb"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CAM, "cam"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_COMP, "comp"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIA, "csia"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIB, "csib"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIE, "csie"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DSI, "dsi"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DSIB, "dsib"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DSIC, "dsic"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DSID, "dsid"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_HDMI, "hdmi"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_HSIC, "hsic"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_HV, "hv"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_LVDS, "lvds"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_MIPI_BIAS, "mipi-bias"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_NAND, "nand"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_BIAS, "pex-bias"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CLK1, "pex-clk1"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CLK2, "pex-clk2"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CNTRL, "pex-cntrl"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SDMMC1, "sdmmc1"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SDMMC3, "sdmmc3"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SDMMC4, "sdmmc4"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SYS_DDC, "sys_ddc"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_UART, "uart"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_USB0, "usb0"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_USB1, "usb1"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_USB2, "usb2"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_USB_BIAS, "usb_bias"), }; static const struct tegra_pmc_soc tegra124_pmc_soc = { @@ -3415,53 +3629,86 @@ static const u8 tegra210_cpu_powergates[] = { TEGRA_POWERGATE_CPU3, }; -#define TEGRA210_IO_PAD_TABLE(_pad) \ - /* .id .dpd .voltage .name */ \ - _pad(TEGRA_IO_PAD_AUDIO, 17, 5, "audio"), \ - _pad(TEGRA_IO_PAD_AUDIO_HV, 61, 18, "audio-hv"), \ - _pad(TEGRA_IO_PAD_CAM, 36, 10, "cam"), \ - _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \ - _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csib"), \ - _pad(TEGRA_IO_PAD_CSIC, 42, UINT_MAX, "csic"), \ - _pad(TEGRA_IO_PAD_CSID, 43, UINT_MAX, "csid"), \ - _pad(TEGRA_IO_PAD_CSIE, 44, UINT_MAX, "csie"), \ - _pad(TEGRA_IO_PAD_CSIF, 45, UINT_MAX, "csif"), \ - _pad(TEGRA_IO_PAD_DBG, 25, 19, "dbg"), \ - _pad(TEGRA_IO_PAD_DEBUG_NONAO, 26, UINT_MAX, "debug-nonao"), \ - _pad(TEGRA_IO_PAD_DMIC, 50, 20, "dmic"), \ - _pad(TEGRA_IO_PAD_DP, 51, UINT_MAX, "dp"), \ - _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \ - _pad(TEGRA_IO_PAD_DSIB, 39, UINT_MAX, "dsib"), \ - _pad(TEGRA_IO_PAD_DSIC, 40, UINT_MAX, "dsic"), \ - _pad(TEGRA_IO_PAD_DSID, 41, UINT_MAX, "dsid"), \ - _pad(TEGRA_IO_PAD_EMMC, 35, UINT_MAX, "emmc"), \ - _pad(TEGRA_IO_PAD_EMMC2, 37, UINT_MAX, "emmc2"), \ - _pad(TEGRA_IO_PAD_GPIO, 27, 21, "gpio"), \ - _pad(TEGRA_IO_PAD_HDMI, 28, UINT_MAX, "hdmi"), \ - _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \ - _pad(TEGRA_IO_PAD_LVDS, 57, UINT_MAX, "lvds"), \ - _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \ - _pad(TEGRA_IO_PAD_PEX_BIAS, 4, UINT_MAX, "pex-bias"), \ - _pad(TEGRA_IO_PAD_PEX_CLK1, 5, UINT_MAX, "pex-clk1"), \ - _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \ - _pad(TEGRA_IO_PAD_PEX_CNTRL, UINT_MAX, 11, "pex-cntrl"), \ - _pad(TEGRA_IO_PAD_SDMMC1, 33, 12, "sdmmc1"), \ - _pad(TEGRA_IO_PAD_SDMMC3, 34, 13, "sdmmc3"), \ - _pad(TEGRA_IO_PAD_SPI, 46, 22, "spi"), \ - _pad(TEGRA_IO_PAD_SPI_HV, 47, 23, "spi-hv"), \ - _pad(TEGRA_IO_PAD_UART, 14, 2, "uart"), \ - _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \ - _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \ - _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \ - _pad(TEGRA_IO_PAD_USB3, 18, UINT_MAX, "usb3"), \ - _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb-bias") - static const struct tegra_io_pad_soc tegra210_io_pads[] = { - TEGRA210_IO_PAD_TABLE(TEGRA_IO_PAD) + TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO, 17, 0x1b8, 0x1bc, 5, "audio"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO_HV, 29, 0x1c0, 0x1c4, 18, "audio-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CAM, 4, 0x1c0, 0x1c4, 10, "cam"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0x1b8, 0x1bc, UINT_MAX, "csia"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0x1b8, 0x1bc, UINT_MAX, "csib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIC, 10, 0x1c0, 0x1c4, UINT_MAX, "csic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSID, 11, 0x1c0, 0x1c4, UINT_MAX, "csid"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIE, 12, 0x1c0, 0x1c4, UINT_MAX, "csie"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIF, 13, 0x1c0, 0x1c4, UINT_MAX, "csif"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DBG, 25, 0x1b8, 0x1bc, 19, "dbg"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DEBUG_NONAO, 26, 0x1b8, 0x1bc, UINT_MAX, "debug-nonao"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DMIC, 18, 0x1c0, 0x1c4, 20, "dmic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DP, 19, 0x1c0, 0x1c4, UINT_MAX, "dp"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSI, 2, 0x1b8, 0x1bc, UINT_MAX, "dsi"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSIB, 7, 0x1c0, 0x1c4, UINT_MAX, "dsib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSIC, 8, 0x1c0, 0x1c4, UINT_MAX, "dsic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSID, 9, 0x1c0, 0x1c4, UINT_MAX, "dsid"), + TEGRA_IO_PAD(TEGRA_IO_PAD_EMMC, 3, 0x1c0, 0x1c4, UINT_MAX, "emmc"), + TEGRA_IO_PAD(TEGRA_IO_PAD_EMMC2, 5, 0x1c0, 0x1c4, UINT_MAX, "emmc2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_GPIO, 27, 0x1b8, 0x1bc, 21, "gpio"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI, 28, 0x1b8, 0x1bc, UINT_MAX, "hdmi"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HSIC, 19, 0x1b8, 0x1bc, UINT_MAX, "hsic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_LVDS, 25, 0x1c0, 0x1c4, UINT_MAX, "lvds"), + TEGRA_IO_PAD(TEGRA_IO_PAD_MIPI_BIAS, 3, 0x1b8, 0x1bc, UINT_MAX, "mipi-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_BIAS, 4, 0x1b8, 0x1bc, UINT_MAX, "pex-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK1, 5, 0x1b8, 0x1bc, UINT_MAX, "pex-clk1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK2, 6, 0x1b8, 0x1bc, UINT_MAX, "pex-clk2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CNTRL, UINT_MAX, UINT_MAX, UINT_MAX, 11, "pex-cntrl"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1, 1, 0x1c0, 0x1c4, 12, "sdmmc1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC3, 2, 0x1c0, 0x1c4, 13, "sdmmc3"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SPI, 14, 0x1c0, 0x1c4, 22, "spi"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SPI_HV, 15, 0x1c0, 0x1c4, 23, "spi-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UART, 14, 0x1b8, 0x1bc, 2, "uart"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB0, 9, 0x1b8, 0x1bc, UINT_MAX, "usb0"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB1, 10, 0x1b8, 0x1bc, UINT_MAX, "usb1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB2, 11, 0x1b8, 0x1bc, UINT_MAX, "usb2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB3, 18, 0x1b8, 0x1bc, UINT_MAX, "usb3"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB_BIAS, 12, 0x1b8, 0x1bc, UINT_MAX, "usb-bias"), }; static const struct pinctrl_pin_desc tegra210_pin_descs[] = { - TEGRA210_IO_PAD_TABLE(TEGRA_IO_PIN_DESC) + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_AUDIO, "audio"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_AUDIO_HV, "audio-hv"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CAM, "cam"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIA, "csia"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIB, "csib"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIC, "csic"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSID, "csid"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIE, "csie"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIF, "csif"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DBG, "dbg"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DEBUG_NONAO, "debug-nonao"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DMIC, "dmic"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DP, "dp"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DSI, "dsi"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DSIB, "dsib"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DSIC, "dsic"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DSID, "dsid"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_EMMC, "emmc"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_EMMC2, "emmc2"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_GPIO, "gpio"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_HDMI, "hdmi"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_HSIC, "hsic"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_LVDS, "lvds"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_MIPI_BIAS, "mipi-bias"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_BIAS, "pex-bias"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CLK1, "pex-clk1"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CLK2, "pex-clk2"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CNTRL, "pex-cntrl"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SDMMC1, "sdmmc1"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SDMMC3, "sdmmc3"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SPI, "spi"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SPI_HV, "spi-hv"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_UART, "uart"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_USB0, "usb0"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_USB1, "usb1"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_USB2, "usb2"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_USB3, "usb3"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_USB_BIAS, "usb-bias"), }; static const char * const tegra210_reset_sources[] = { @@ -3511,61 +3758,90 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = { .has_usb_sleepwalk = true, }; -#define TEGRA186_IO_PAD_TABLE(_pad) \ - /* .id .dpd .voltage .name */ \ - _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \ - _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csib"), \ - _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \ - _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \ - _pad(TEGRA_IO_PAD_PEX_CLK_BIAS, 4, UINT_MAX, "pex-clk-bias"), \ - _pad(TEGRA_IO_PAD_PEX_CLK3, 5, UINT_MAX, "pex-clk3"), \ - _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \ - _pad(TEGRA_IO_PAD_PEX_CLK1, 7, UINT_MAX, "pex-clk1"), \ - _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \ - _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \ - _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \ - _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb-bias"), \ - _pad(TEGRA_IO_PAD_UART, 14, UINT_MAX, "uart"), \ - _pad(TEGRA_IO_PAD_AUDIO, 17, UINT_MAX, "audio"), \ - _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \ - _pad(TEGRA_IO_PAD_DBG, 25, UINT_MAX, "dbg"), \ - _pad(TEGRA_IO_PAD_HDMI_DP0, 28, UINT_MAX, "hdmi-dp0"), \ - _pad(TEGRA_IO_PAD_HDMI_DP1, 29, UINT_MAX, "hdmi-dp1"), \ - _pad(TEGRA_IO_PAD_PEX_CNTRL, 32, UINT_MAX, "pex-cntrl"), \ - _pad(TEGRA_IO_PAD_SDMMC2_HV, 34, 5, "sdmmc2-hv"), \ - _pad(TEGRA_IO_PAD_SDMMC4, 36, UINT_MAX, "sdmmc4"), \ - _pad(TEGRA_IO_PAD_CAM, 38, UINT_MAX, "cam"), \ - _pad(TEGRA_IO_PAD_DSIB, 40, UINT_MAX, "dsib"), \ - _pad(TEGRA_IO_PAD_DSIC, 41, UINT_MAX, "dsic"), \ - _pad(TEGRA_IO_PAD_DSID, 42, UINT_MAX, "dsid"), \ - _pad(TEGRA_IO_PAD_CSIC, 43, UINT_MAX, "csic"), \ - _pad(TEGRA_IO_PAD_CSID, 44, UINT_MAX, "csid"), \ - _pad(TEGRA_IO_PAD_CSIE, 45, UINT_MAX, "csie"), \ - _pad(TEGRA_IO_PAD_CSIF, 46, UINT_MAX, "csif"), \ - _pad(TEGRA_IO_PAD_SPI, 47, UINT_MAX, "spi"), \ - _pad(TEGRA_IO_PAD_UFS, 49, UINT_MAX, "ufs"), \ - _pad(TEGRA_IO_PAD_DMIC_HV, 52, 2, "dmic-hv"), \ - _pad(TEGRA_IO_PAD_EDP, 53, UINT_MAX, "edp"), \ - _pad(TEGRA_IO_PAD_SDMMC1_HV, 55, 4, "sdmmc1-hv"), \ - _pad(TEGRA_IO_PAD_SDMMC3_HV, 56, 6, "sdmmc3-hv"), \ - _pad(TEGRA_IO_PAD_CONN, 60, UINT_MAX, "conn"), \ - _pad(TEGRA_IO_PAD_AUDIO_HV, 61, 1, "audio-hv"), \ - _pad(TEGRA_IO_PAD_AO_HV, UINT_MAX, 0, "ao-hv") - static const struct tegra_io_pad_soc tegra186_io_pads[] = { - TEGRA186_IO_PAD_TABLE(TEGRA_IO_PAD) + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0x74, 0x78, UINT_MAX, "csia"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0x74, 0x78, UINT_MAX, "csib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSI, 2, 0x74, 0x78, UINT_MAX, "dsi"), + TEGRA_IO_PAD(TEGRA_IO_PAD_MIPI_BIAS, 3, 0x74, 0x78, UINT_MAX, "mipi-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK_BIAS, 4, 0x74, 0x78, UINT_MAX, "pex-clk-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK3, 5, 0x74, 0x78, UINT_MAX, "pex-clk3"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK2, 6, 0x74, 0x78, UINT_MAX, "pex-clk2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK1, 7, 0x74, 0x78, UINT_MAX, "pex-clk1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB0, 9, 0x74, 0x78, UINT_MAX, "usb0"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB1, 10, 0x74, 0x78, UINT_MAX, "usb1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB2, 11, 0x74, 0x78, UINT_MAX, "usb2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_USB_BIAS, 12, 0x74, 0x78, UINT_MAX, "usb-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UART, 14, 0x74, 0x78, UINT_MAX, "uart"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO, 17, 0x74, 0x78, UINT_MAX, "audio"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HSIC, 19, 0x74, 0x78, UINT_MAX, "hsic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DBG, 25, 0x74, 0x78, UINT_MAX, "dbg"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP0, 28, 0x74, 0x78, UINT_MAX, "hdmi-dp0"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP1, 29, 0x74, 0x78, UINT_MAX, "hdmi-dp1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CNTRL, 0, 0x7c, 0x80, UINT_MAX, "pex-cntrl"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC2_HV, 2, 0x7c, 0x80, 5, "sdmmc2-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC4, 4, 0x7c, 0x80, UINT_MAX, "sdmmc4"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CAM, 6, 0x7c, 0x80, UINT_MAX, "cam"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSIB, 8, 0x7c, 0x80, UINT_MAX, "dsib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSIC, 9, 0x7c, 0x80, UINT_MAX, "dsic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DSID, 10, 0x7c, 0x80, UINT_MAX, "dsid"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIC, 11, 0x7c, 0x80, UINT_MAX, "csic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSID, 12, 0x7c, 0x80, UINT_MAX, "csid"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIE, 13, 0x7c, 0x80, UINT_MAX, "csie"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIF, 14, 0x7c, 0x80, UINT_MAX, "csif"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SPI, 15, 0x7c, 0x80, UINT_MAX, "spi"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UFS, 17, 0x7c, 0x80, UINT_MAX, "ufs"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DMIC_HV, 20, 0x7c, 0x80, 2, "dmic-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_EDP, 21, 0x7c, 0x80, UINT_MAX, "edp"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1_HV, 23, 0x7c, 0x80, 4, "sdmmc1-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC3_HV, 24, 0x7c, 0x80, 6, "sdmmc3-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CONN, 28, 0x7c, 0x80, UINT_MAX, "conn"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO_HV, 29, 0x7c, 0x80, 1, "audio-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AO_HV, UINT_MAX, UINT_MAX, UINT_MAX, 0, "ao-hv"), }; static const struct pinctrl_pin_desc tegra186_pin_descs[] = { - TEGRA186_IO_PAD_TABLE(TEGRA_IO_PIN_DESC) + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIA, "csia"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIB, "csib"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DSI, "dsi"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_MIPI_BIAS, "mipi-bias"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CLK_BIAS, "pex-clk-bias"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CLK3, "pex-clk3"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CLK2, "pex-clk2"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CLK1, "pex-clk1"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_USB0, "usb0"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_USB1, "usb1"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_USB2, "usb2"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_USB_BIAS, "usb-bias"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_UART, "uart"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_AUDIO, "audio"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_HSIC, "hsic"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DBG, "dbg"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_HDMI_DP0, "hdmi-dp0"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_HDMI_DP1, "hdmi-dp1"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CNTRL, "pex-cntrl"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SDMMC2_HV, "sdmmc2-hv"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SDMMC4, "sdmmc4"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CAM, "cam"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DSIB, "dsib"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DSIC, "dsic"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DSID, "dsid"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIC, "csic"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSID, "csid"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIE, "csie"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIF, "csif"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SPI, "spi"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_UFS, "ufs"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DMIC_HV, "dmic-hv"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_EDP, "edp"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SDMMC1_HV, "sdmmc1-hv"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SDMMC3_HV, "sdmmc3-hv"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CONN, "conn"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_AUDIO_HV, "audio-hv"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_AO_HV, "ao-hv"), }; static const struct tegra_pmc_regs tegra186_pmc_regs = { .scratch0 = 0x2000, - .dpd_req = 0x74, - .dpd_status = 0x78, - .dpd2_req = 0x7c, - .dpd2_status = 0x80, .rst_status = 0x70, .rst_source_shift = 0x2, .rst_source_mask = 0x3c, @@ -3573,6 +3849,14 @@ static const struct tegra_pmc_regs tegra186_pmc_regs = { .rst_level_mask = 0x3, }; +static void tegra186_pmc_init(struct tegra_pmc *pmc) +{ + pmc->syscore.suspend = tegra186_pmc_wake_syscore_suspend; + pmc->syscore.resume = tegra186_pmc_wake_syscore_resume; + + register_syscore_ops(&pmc->syscore); +} + static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc, struct device_node *np, bool invert) @@ -3652,7 +3936,7 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = { .num_pin_descs = ARRAY_SIZE(tegra186_pin_descs), .pin_descs = tegra186_pin_descs, .regs = &tegra186_pmc_regs, - .init = NULL, + .init = tegra186_pmc_init, .setup_irq_polarity = tegra186_pmc_setup_irq_polarity, .irq_set_wake = tegra186_pmc_irq_set_wake, .irq_set_type = tegra186_pmc_irq_set_type, @@ -3662,78 +3946,120 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = { .num_reset_levels = ARRAY_SIZE(tegra186_reset_levels), .num_wake_events = ARRAY_SIZE(tegra186_wake_events), .wake_events = tegra186_wake_events, + .max_wake_events = 96, + .max_wake_vectors = 3, .pmc_clks_data = NULL, .num_pmc_clks = 0, .has_blink_output = false, .has_usb_sleepwalk = false, }; -#define TEGRA194_IO_PAD_TABLE(_pad) \ - /* .id .dpd .voltage .name */ \ - _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \ - _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csib"), \ - _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \ - _pad(TEGRA_IO_PAD_PEX_CLK_BIAS, 4, UINT_MAX, "pex-clk-bias"), \ - _pad(TEGRA_IO_PAD_PEX_CLK3, 5, UINT_MAX, "pex-clk3"), \ - _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \ - _pad(TEGRA_IO_PAD_PEX_CLK1, 7, UINT_MAX, "pex-clk1"), \ - _pad(TEGRA_IO_PAD_EQOS, 8, UINT_MAX, "eqos"), \ - _pad(TEGRA_IO_PAD_PEX_CLK_2_BIAS, 9, UINT_MAX, "pex-clk-2-bias"), \ - _pad(TEGRA_IO_PAD_PEX_CLK_2, 10, UINT_MAX, "pex-clk-2"), \ - _pad(TEGRA_IO_PAD_DAP3, 11, UINT_MAX, "dap3"), \ - _pad(TEGRA_IO_PAD_DAP5, 12, UINT_MAX, "dap5"), \ - _pad(TEGRA_IO_PAD_UART, 14, UINT_MAX, "uart"), \ - _pad(TEGRA_IO_PAD_PWR_CTL, 15, UINT_MAX, "pwr-ctl"), \ - _pad(TEGRA_IO_PAD_SOC_GPIO53, 16, UINT_MAX, "soc-gpio53"), \ - _pad(TEGRA_IO_PAD_AUDIO, 17, UINT_MAX, "audio"), \ - _pad(TEGRA_IO_PAD_GP_PWM2, 18, UINT_MAX, "gp-pwm2"), \ - _pad(TEGRA_IO_PAD_GP_PWM3, 19, UINT_MAX, "gp-pwm3"), \ - _pad(TEGRA_IO_PAD_SOC_GPIO12, 20, UINT_MAX, "soc-gpio12"), \ - _pad(TEGRA_IO_PAD_SOC_GPIO13, 21, UINT_MAX, "soc-gpio13"), \ - _pad(TEGRA_IO_PAD_SOC_GPIO10, 22, UINT_MAX, "soc-gpio10"), \ - _pad(TEGRA_IO_PAD_UART4, 23, UINT_MAX, "uart4"), \ - _pad(TEGRA_IO_PAD_UART5, 24, UINT_MAX, "uart5"), \ - _pad(TEGRA_IO_PAD_DBG, 25, UINT_MAX, "dbg"), \ - _pad(TEGRA_IO_PAD_HDMI_DP3, 26, UINT_MAX, "hdmi-dp3"), \ - _pad(TEGRA_IO_PAD_HDMI_DP2, 27, UINT_MAX, "hdmi-dp2"), \ - _pad(TEGRA_IO_PAD_HDMI_DP0, 28, UINT_MAX, "hdmi-dp0"), \ - _pad(TEGRA_IO_PAD_HDMI_DP1, 29, UINT_MAX, "hdmi-dp1"), \ - _pad(TEGRA_IO_PAD_PEX_CNTRL, 32, UINT_MAX, "pex-cntrl"), \ - _pad(TEGRA_IO_PAD_PEX_CTL2, 33, UINT_MAX, "pex-ctl2"), \ - _pad(TEGRA_IO_PAD_PEX_L0_RST_N, 34, UINT_MAX, "pex-l0-rst"), \ - _pad(TEGRA_IO_PAD_PEX_L1_RST_N, 35, UINT_MAX, "pex-l1-rst"), \ - _pad(TEGRA_IO_PAD_SDMMC4, 36, UINT_MAX, "sdmmc4"), \ - _pad(TEGRA_IO_PAD_PEX_L5_RST_N, 37, UINT_MAX, "pex-l5-rst"), \ - _pad(TEGRA_IO_PAD_CAM, 38, UINT_MAX, "cam"), \ - _pad(TEGRA_IO_PAD_CSIC, 43, UINT_MAX, "csic"), \ - _pad(TEGRA_IO_PAD_CSID, 44, UINT_MAX, "csid"), \ - _pad(TEGRA_IO_PAD_CSIE, 45, UINT_MAX, "csie"), \ - _pad(TEGRA_IO_PAD_CSIF, 46, UINT_MAX, "csif"), \ - _pad(TEGRA_IO_PAD_SPI, 47, UINT_MAX, "spi"), \ - _pad(TEGRA_IO_PAD_UFS, 49, UINT_MAX, "ufs"), \ - _pad(TEGRA_IO_PAD_CSIG, 50, UINT_MAX, "csig"), \ - _pad(TEGRA_IO_PAD_CSIH, 51, UINT_MAX, "csih"), \ - _pad(TEGRA_IO_PAD_EDP, 53, UINT_MAX, "edp"), \ - _pad(TEGRA_IO_PAD_SDMMC1_HV, 55, 4, "sdmmc1-hv"), \ - _pad(TEGRA_IO_PAD_SDMMC3_HV, 56, 6, "sdmmc3-hv"), \ - _pad(TEGRA_IO_PAD_CONN, 60, UINT_MAX, "conn"), \ - _pad(TEGRA_IO_PAD_AUDIO_HV, 61, 1, "audio-hv"), \ - _pad(TEGRA_IO_PAD_AO_HV, UINT_MAX, 0, "ao-hv") - static const struct tegra_io_pad_soc tegra194_io_pads[] = { - TEGRA194_IO_PAD_TABLE(TEGRA_IO_PAD) + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0x74, 0x78, UINT_MAX, "csia"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0x74, 0x78, UINT_MAX, "csib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_MIPI_BIAS, 3, 0x74, 0x78, UINT_MAX, "mipi-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK_BIAS, 4, 0x74, 0x78, UINT_MAX, "pex-clk-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK3, 5, 0x74, 0x78, UINT_MAX, "pex-clk3"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK2, 6, 0x74, 0x78, UINT_MAX, "pex-clk2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK1, 7, 0x74, 0x78, UINT_MAX, "pex-clk1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_EQOS, 8, 0x74, 0x78, UINT_MAX, "eqos"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK_2_BIAS, 9, 0x74, 0x78, UINT_MAX, "pex-clk-2-bias"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CLK_2, 10, 0x74, 0x78, UINT_MAX, "pex-clk-2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DAP3, 11, 0x74, 0x78, UINT_MAX, "dap3"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DAP5, 12, 0x74, 0x78, UINT_MAX, "dap5"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UART, 14, 0x74, 0x78, UINT_MAX, "uart"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PWR_CTL, 15, 0x74, 0x78, UINT_MAX, "pwr-ctl"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SOC_GPIO53, 16, 0x74, 0x78, UINT_MAX, "soc-gpio53"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO, 17, 0x74, 0x78, UINT_MAX, "audio"), + TEGRA_IO_PAD(TEGRA_IO_PAD_GP_PWM2, 18, 0x74, 0x78, UINT_MAX, "gp-pwm2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_GP_PWM3, 19, 0x74, 0x78, UINT_MAX, "gp-pwm3"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SOC_GPIO12, 20, 0x74, 0x78, UINT_MAX, "soc-gpio12"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SOC_GPIO13, 21, 0x74, 0x78, UINT_MAX, "soc-gpio13"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SOC_GPIO10, 22, 0x74, 0x78, UINT_MAX, "soc-gpio10"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UART4, 23, 0x74, 0x78, UINT_MAX, "uart4"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UART5, 24, 0x74, 0x78, UINT_MAX, "uart5"), + TEGRA_IO_PAD(TEGRA_IO_PAD_DBG, 25, 0x74, 0x78, UINT_MAX, "dbg"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP3, 26, 0x74, 0x78, UINT_MAX, "hdmi-dp3"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP2, 27, 0x74, 0x78, UINT_MAX, "hdmi-dp2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP0, 28, 0x74, 0x78, UINT_MAX, "hdmi-dp0"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP1, 29, 0x74, 0x78, UINT_MAX, "hdmi-dp1"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CNTRL, 0, 0x7c, 0x80, UINT_MAX, "pex-cntrl"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_CTL2, 1, 0x7c, 0x80, UINT_MAX, "pex-ctl2"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_L0_RST, 2, 0x7c, 0x80, UINT_MAX, "pex-l0-rst"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_L1_RST, 3, 0x7c, 0x80, UINT_MAX, "pex-l1-rst"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC4, 4, 0x7c, 0x80, UINT_MAX, "sdmmc4"), + TEGRA_IO_PAD(TEGRA_IO_PAD_PEX_L5_RST, 5, 0x7c, 0x80, UINT_MAX, "pex-l5-rst"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CAM, 6, 0x7c, 0x80, UINT_MAX, "cam"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIC, 11, 0x7c, 0x80, UINT_MAX, "csic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSID, 12, 0x7c, 0x80, UINT_MAX, "csid"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIE, 13, 0x7c, 0x80, UINT_MAX, "csie"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIF, 14, 0x7c, 0x80, UINT_MAX, "csif"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SPI, 15, 0x7c, 0x80, UINT_MAX, "spi"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UFS, 17, 0x7c, 0x80, UINT_MAX, "ufs"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIG, 18, 0x7c, 0x80, UINT_MAX, "csig"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIH, 19, 0x7c, 0x80, UINT_MAX, "csih"), + TEGRA_IO_PAD(TEGRA_IO_PAD_EDP, 21, 0x7c, 0x80, UINT_MAX, "edp"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1_HV, 23, 0x7c, 0x80, 4, "sdmmc1-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC3_HV, 24, 0x7c, 0x80, 6, "sdmmc3-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CONN, 28, 0x7c, 0x80, UINT_MAX, "conn"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO_HV, 29, 0x7c, 0x80, 1, "audio-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AO_HV, UINT_MAX, UINT_MAX, UINT_MAX, 0, "ao-hv"), }; static const struct pinctrl_pin_desc tegra194_pin_descs[] = { - TEGRA194_IO_PAD_TABLE(TEGRA_IO_PIN_DESC) + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIA, "csia"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIB, "csib"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_MIPI_BIAS, "mipi-bias"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CLK_BIAS, "pex-clk-bias"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CLK3, "pex-clk3"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CLK2, "pex-clk2"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CLK1, "pex-clk1"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_EQOS, "eqos"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CLK_2_BIAS, "pex-clk-2-bias"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CLK_2, "pex-clk-2"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DAP3, "dap3"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DAP5, "dap5"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_UART, "uart"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PWR_CTL, "pwr-ctl"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SOC_GPIO53, "soc-gpio53"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_AUDIO, "audio"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_GP_PWM2, "gp-pwm2"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_GP_PWM3, "gp-pwm3"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SOC_GPIO12, "soc-gpio12"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SOC_GPIO13, "soc-gpio13"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SOC_GPIO10, "soc-gpio10"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_UART4, "uart4"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_UART5, "uart5"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_DBG, "dbg"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_HDMI_DP3, "hdmi-dp3"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_HDMI_DP2, "hdmi-dp2"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_HDMI_DP0, "hdmi-dp0"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_HDMI_DP1, "hdmi-dp1"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CNTRL, "pex-cntrl"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_CTL2, "pex-ctl2"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_L0_RST, "pex-l0-rst"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_L1_RST, "pex-l1-rst"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SDMMC4, "sdmmc4"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_PEX_L5_RST, "pex-l5-rst"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CAM, "cam"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIC, "csic"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSID, "csid"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIE, "csie"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIF, "csif"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SPI, "spi"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_UFS, "ufs"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIG, "csig"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIH, "csih"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_EDP, "edp"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SDMMC1_HV, "sdmmc1-hv"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SDMMC3_HV, "sdmmc3-hv"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CONN, "conn"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_AUDIO_HV, "audio-hv"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_AO_HV, "ao-hv"), }; static const struct tegra_pmc_regs tegra194_pmc_regs = { .scratch0 = 0x2000, - .dpd_req = 0x74, - .dpd_status = 0x78, - .dpd2_req = 0x7c, - .dpd2_status = 0x80, .rst_status = 0x70, .rst_source_shift = 0x2, .rst_source_mask = 0x7c, @@ -3794,7 +4120,7 @@ static const struct tegra_pmc_soc tegra194_pmc_soc = { .num_pin_descs = ARRAY_SIZE(tegra194_pin_descs), .pin_descs = tegra194_pin_descs, .regs = &tegra194_pmc_regs, - .init = NULL, + .init = tegra186_pmc_init, .setup_irq_polarity = tegra186_pmc_setup_irq_polarity, .irq_set_wake = tegra186_pmc_irq_set_wake, .irq_set_type = tegra186_pmc_irq_set_type, @@ -3804,18 +4130,52 @@ static const struct tegra_pmc_soc tegra194_pmc_soc = { .num_reset_levels = ARRAY_SIZE(tegra186_reset_levels), .num_wake_events = ARRAY_SIZE(tegra194_wake_events), .wake_events = tegra194_wake_events, + .max_wake_events = 96, + .max_wake_vectors = 3, .pmc_clks_data = NULL, .num_pmc_clks = 0, .has_blink_output = false, .has_usb_sleepwalk = false, }; +static const struct tegra_io_pad_soc tegra234_io_pads[] = { + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIA, 0, 0xe0c0, 0xe0c4, UINT_MAX, "csia"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIB, 1, 0xe0c0, 0xe0c4, UINT_MAX, "csib"), + TEGRA_IO_PAD(TEGRA_IO_PAD_HDMI_DP0, 0, 0xe0d0, 0xe0d4, UINT_MAX, "hdmi-dp0"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIC, 2, 0xe0c0, 0xe0c4, UINT_MAX, "csic"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSID, 3, 0xe0c0, 0xe0c4, UINT_MAX, "csid"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIE, 4, 0xe0c0, 0xe0c4, UINT_MAX, "csie"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIF, 5, 0xe0c0, 0xe0c4, UINT_MAX, "csif"), + TEGRA_IO_PAD(TEGRA_IO_PAD_UFS, 0, 0xe064, 0xe068, UINT_MAX, "ufs"), + TEGRA_IO_PAD(TEGRA_IO_PAD_EDP, 1, 0xe05c, 0xe060, UINT_MAX, "edp"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC1_HV, 0, 0xe054, 0xe058, 4, "sdmmc1-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_SDMMC3_HV, UINT_MAX, UINT_MAX, UINT_MAX, 6, "sdmmc3-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AUDIO_HV, UINT_MAX, UINT_MAX, UINT_MAX, 1, "audio-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_AO_HV, UINT_MAX, UINT_MAX, UINT_MAX, 0, "ao-hv"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIG, 6, 0xe0c0, 0xe0c4, UINT_MAX, "csig"), + TEGRA_IO_PAD(TEGRA_IO_PAD_CSIH, 7, 0xe0c0, 0xe0c4, UINT_MAX, "csih"), +}; + +static const struct pinctrl_pin_desc tegra234_pin_descs[] = { + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIA, "csia"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIB, "csib"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_HDMI_DP0, "hdmi-dp0"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIC, "csic"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSID, "csid"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIE, "csie"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIF, "csif"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_UFS, "ufs"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_EDP, "edp"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SDMMC1_HV, "sdmmc1-hv"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_SDMMC3_HV, "sdmmc3-hv"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_AUDIO_HV, "audio-hv"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_AO_HV, "ao-hv"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIG, "csig"), + TEGRA_IO_PIN_DESC(TEGRA_IO_PAD_CSIH, "csih"), +}; + static const struct tegra_pmc_regs tegra234_pmc_regs = { .scratch0 = 0x2000, - .dpd_req = 0, - .dpd_status = 0, - .dpd2_req = 0, - .dpd2_status = 0, .rst_status = 0x70, .rst_source_shift = 0x2, .rst_source_mask = 0xfc, @@ -3880,12 +4240,12 @@ static const struct tegra_pmc_soc tegra234_pmc_soc = { .needs_mbist_war = false, .has_impl_33v_pwr = true, .maybe_tz_only = false, - .num_io_pads = 0, - .io_pads = NULL, - .num_pin_descs = 0, - .pin_descs = NULL, + .num_io_pads = ARRAY_SIZE(tegra234_io_pads), + .io_pads = tegra234_io_pads, + .num_pin_descs = ARRAY_SIZE(tegra234_pin_descs), + .pin_descs = tegra234_pin_descs, .regs = &tegra234_pmc_regs, - .init = NULL, + .init = tegra186_pmc_init, .setup_irq_polarity = tegra186_pmc_setup_irq_polarity, .irq_set_wake = tegra186_pmc_irq_set_wake, .irq_set_type = tegra186_pmc_irq_set_type, @@ -3895,6 +4255,8 @@ static const struct tegra_pmc_soc tegra234_pmc_soc = { .num_reset_levels = ARRAY_SIZE(tegra186_reset_levels), .num_wake_events = ARRAY_SIZE(tegra234_wake_events), .wake_events = tegra234_wake_events, + .max_wake_events = 96, + .max_wake_vectors = 3, .pmc_clks_data = NULL, .num_pmc_clks = 0, .has_blink_output = false, |