diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-12 21:17:08 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-12-12 21:17:08 +0300 |
commit | 8e17b16a2c13406c56a4d292df3ca083f8729666 (patch) | |
tree | 30bb0fe90b00e857bb708aaa3605f671a66e8101 /drivers/soc | |
parent | 69700db4212ac784130f63a350b1ede3b7184494 (diff) | |
parent | 9379885d07c466a9207e88c0fd0c8b3541536fe3 (diff) | |
download | linux-8e17b16a2c13406c56a4d292df3ca083f8729666.tar.xz |
Merge tag 'soc-drivers-6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull ARM SoC driver updates from Arnd Bergmann:
"There are few major updates in the SoC specific drivers, mainly the
usual reworks and support for variants of the existing SoC. While this
remains Arm centric for the most part, the branch now also contains
updates to risc-v and loongarch specific code in drivers/soc/.
Notable changes include:
- Support for the newly added Qualcomm Snapdragon variants (MSM8956,
MSM8976, SM6115, SM4250, SM8150, SA8155 and SM8550) in the soc ID,
rpmh, rpm, spm and powerdomain drivers.
- Documentation for the somewhat controversial qcom,board-id
properties that are required for booting a number of machines
- A new SoC identification driver for the loongson-2 (loongarch)
platform
- memory controller updates for stm32, tegra, and renesas.
- a new DT binding to better describe LPDDR2/3/4/5 chips in the
memory controller subsystem
- Updates for Tegra specific drivers across multiple subsystems,
improving support for newer SoCs and better identification
- Minor fixes for Broadcom, Freescale, Apple, Renesas, Sifive, TI,
Mediatek and Marvell SoC drivers"
* tag 'soc-drivers-6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (137 commits)
soc: qcom: socinfo: Add SM6115 / SM4250 SoC IDs to the soc_id table
dt-bindings: arm: qcom,ids: Add SoC IDs for SM6115 / SM4250 and variants
soc: qcom: socinfo: Add SM8150 and SA8155 SoC IDs to the soc_id table
dt-bindings: arm: qcom,ids: Add SoC IDs for SM8150 and SA8155
dt-bindings: soc: qcom: apr: document generic qcom,apr compatible
soc: qcom: Select REMAP_MMIO for ICC_BWMON driver
soc: qcom: Select REMAP_MMIO for LLCC driver
soc: qcom: rpmpd: Add SM4250 support
dt-bindings: power: rpmpd: Add SM4250 support
dt-bindings: soc: qcom: aoss: Add compatible for SM8550
soc: qcom: llcc: Add configuration data for SM8550
dt-bindings: arm: msm: Add LLCC compatible for SM8550
soc: qcom: llcc: Add v4.1 HW version support
soc: qcom: socinfo: Add SM8550 ID
soc: qcom: rpmh-rsc: Avoid unnecessary checks on irq-done response
soc: qcom: rpmh-rsc: Add support for RSC v3 register offsets
soc: qcom: rpmhpd: Add SM8550 power domains
dt-bindings: power: rpmpd: Add SM8550 to rpmpd binding
soc: qcom: socinfo: Add MSM8956/76 SoC IDs to the soc_id table
dt-bindings: arm: qcom,ids: Add SoC IDs for MSM8956 and MSM8976
...
Diffstat (limited to 'drivers/soc')
47 files changed, 2337 insertions, 900 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/apple/rtkit.c b/drivers/soc/apple/rtkit.c index 031ec4aa06d5..8ec74d7539eb 100644 --- a/drivers/soc/apple/rtkit.c +++ b/drivers/soc/apple/rtkit.c @@ -926,8 +926,10 @@ int apple_rtkit_wake(struct apple_rtkit *rtk) } EXPORT_SYMBOL_GPL(apple_rtkit_wake); -static void apple_rtkit_free(struct apple_rtkit *rtk) +static void apple_rtkit_free(void *data) { + struct apple_rtkit *rtk = data; + mbox_free_channel(rtk->mbox_chan); destroy_workqueue(rtk->wq); @@ -950,8 +952,7 @@ struct apple_rtkit *devm_apple_rtkit_init(struct device *dev, void *cookie, if (IS_ERR(rtk)) return rtk; - ret = devm_add_action_or_reset(dev, (void (*)(void *))apple_rtkit_free, - rtk); + ret = devm_add_action_or_reset(dev, apple_rtkit_free, rtk); if (ret) return ERR_PTR(ret); diff --git a/drivers/soc/apple/sart.c b/drivers/soc/apple/sart.c index 83804b16ad03..afa111736899 100644 --- a/drivers/soc/apple/sart.c +++ b/drivers/soc/apple/sart.c @@ -164,6 +164,11 @@ static int apple_sart_probe(struct platform_device *pdev) return 0; } +static void apple_sart_put_device(void *dev) +{ + put_device(dev); +} + struct apple_sart *devm_apple_sart_get(struct device *dev) { struct device_node *sart_node; @@ -187,7 +192,7 @@ struct apple_sart *devm_apple_sart_get(struct device *dev) return ERR_PTR(-EPROBE_DEFER); } - ret = devm_add_action_or_reset(dev, (void (*)(void *))put_device, + ret = devm_add_action_or_reset(dev, apple_sart_put_device, &sart_pdev->dev); if (ret) return ERR_PTR(ret); diff --git a/drivers/soc/fsl/qe/gpio.c b/drivers/soc/fsl/qe/gpio.c index 99f7de43c3c6..1440922341d8 100644 --- a/drivers/soc/fsl/qe/gpio.c +++ b/drivers/soc/fsl/qe/gpio.c @@ -13,10 +13,9 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/of.h> -#include <linux/of_gpio.h> +#include <linux/of_gpio.h> /* for of_mm_gpio_chip */ +#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> @@ -25,9 +24,6 @@ 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; @@ -149,62 +145,65 @@ struct qe_pin { /** * qe_pin_request - Request a QE pin - * @np: device node to get a pin from - * @index: index of a pin in the device tree + * @dev: device to get the pin from + * @index: index of the pin in the device tree * Context: non-atomic * * This function return qe_pin so that you could use it with the rest of * the QE Pin Multiplexing API. */ -struct qe_pin *qe_pin_request(struct device_node *np, int index) +struct qe_pin *qe_pin_request(struct device *dev, int index) { struct qe_pin *qe_pin; struct gpio_chip *gc; - struct qe_gpio_chip *qe_gc; + struct gpio_desc *gpiod; + int gpio_num; int err; - unsigned long flags; qe_pin = kzalloc(sizeof(*qe_pin), GFP_KERNEL); if (!qe_pin) { - pr_debug("%s: can't allocate memory\n", __func__); + dev_dbg(dev, "%s: can't allocate memory\n", __func__); return ERR_PTR(-ENOMEM); } - err = of_get_gpio(np, index); - if (err < 0) + /* + * Request gpio as nonexclusive as it was likely reserved by the + * caller, and we are not planning on controlling it, we only need + * the descriptor to the to the gpio chip structure. + */ + gpiod = gpiod_get_index(dev, NULL, index, + GPIOD_ASIS | GPIOD_FLAGS_BIT_NONEXCLUSIVE); + err = PTR_ERR_OR_ZERO(gpiod); + if (err) goto err0; - gc = gpio_to_chip(err); + + gc = gpiod_to_chip(gpiod); + gpio_num = desc_to_gpio(gpiod); + /* We no longer need this descriptor */ + gpiod_put(gpiod); + if (WARN_ON(!gc)) { err = -ENODEV; goto err0; } + 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_num - gc->base; + 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__); + dev_dbg(dev, "%s: tried to get a non-qe pin\n", __func__); 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); + dev_dbg(dev, "%s failed with status %d\n", __func__, err); return ERR_PTR(err); } EXPORT_SYMBOL(qe_pin_request); @@ -219,14 +218,6 @@ 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); - 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/mediatek/mt8186-mmsys.h b/drivers/soc/mediatek/mt8186-mmsys.h index 09b1ccbc0093..279d4138525b 100644 --- a/drivers/soc/mediatek/mt8186-mmsys.h +++ b/drivers/soc/mediatek/mt8186-mmsys.h @@ -5,9 +5,11 @@ /* Values for DPI configuration in MMSYS address space */ #define MT8186_MMSYS_DPI_OUTPUT_FORMAT 0x400 -#define DPI_FORMAT_MASK 0x1 -#define DPI_RGB888_DDR_CON BIT(0) -#define DPI_RGB565_SDR_CON BIT(1) +#define MT8186_DPI_FORMAT_MASK GENMASK(1, 0) +#define MT8186_DPI_RGB888_SDR_CON 0 +#define MT8186_DPI_RGB888_DDR_CON 1 +#define MT8186_DPI_RGB565_SDR_CON 2 +#define MT8186_DPI_RGB565_DDR_CON 3 #define MT8186_MMSYS_OVL_CON 0xF04 #define MT8186_MMSYS_OVL0_CON_MASK 0x3 diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c index d2c7a87aab87..f3431448e843 100644 --- a/drivers/soc/mediatek/mtk-mmsys.c +++ b/drivers/soc/mediatek/mtk-mmsys.c @@ -26,61 +26,26 @@ static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = { .num_routes = ARRAY_SIZE(mmsys_default_routing_table), }; -static const struct mtk_mmsys_match_data mt2701_mmsys_match_data = { - .num_drv_data = 1, - .drv_data = { - &mt2701_mmsys_driver_data, - }, -}; - static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = { .clk_driver = "clk-mt2712-mm", .routes = mmsys_default_routing_table, .num_routes = ARRAY_SIZE(mmsys_default_routing_table), }; -static const struct mtk_mmsys_match_data mt2712_mmsys_match_data = { - .num_drv_data = 1, - .drv_data = { - &mt2712_mmsys_driver_data, - }, -}; - static const struct mtk_mmsys_driver_data mt6779_mmsys_driver_data = { .clk_driver = "clk-mt6779-mm", }; -static const struct mtk_mmsys_match_data mt6779_mmsys_match_data = { - .num_drv_data = 1, - .drv_data = { - &mt6779_mmsys_driver_data, - }, -}; - static const struct mtk_mmsys_driver_data mt6797_mmsys_driver_data = { .clk_driver = "clk-mt6797-mm", }; -static const struct mtk_mmsys_match_data mt6797_mmsys_match_data = { - .num_drv_data = 1, - .drv_data = { - &mt6797_mmsys_driver_data, - }, -}; - static const struct mtk_mmsys_driver_data mt8167_mmsys_driver_data = { .clk_driver = "clk-mt8167-mm", .routes = mt8167_mmsys_routing_table, .num_routes = ARRAY_SIZE(mt8167_mmsys_routing_table), }; -static const struct mtk_mmsys_match_data mt8167_mmsys_match_data = { - .num_drv_data = 1, - .drv_data = { - &mt8167_mmsys_driver_data, - }, -}; - static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = { .clk_driver = "clk-mt8173-mm", .routes = mmsys_default_routing_table, @@ -88,13 +53,6 @@ static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = { .sw0_rst_offset = MT8183_MMSYS_SW0_RST_B, }; -static const struct mtk_mmsys_match_data mt8173_mmsys_match_data = { - .num_drv_data = 1, - .drv_data = { - &mt8173_mmsys_driver_data, - }, -}; - static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = { .clk_driver = "clk-mt8183-mm", .routes = mmsys_mt8183_routing_table, @@ -102,13 +60,6 @@ static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = { .sw0_rst_offset = MT8183_MMSYS_SW0_RST_B, }; -static const struct mtk_mmsys_match_data mt8183_mmsys_match_data = { - .num_drv_data = 1, - .drv_data = { - &mt8183_mmsys_driver_data, - }, -}; - static const struct mtk_mmsys_driver_data mt8186_mmsys_driver_data = { .clk_driver = "clk-mt8186-mm", .routes = mmsys_mt8186_routing_table, @@ -116,13 +67,6 @@ static const struct mtk_mmsys_driver_data mt8186_mmsys_driver_data = { .sw0_rst_offset = MT8186_MMSYS_SW0_RST_B, }; -static const struct mtk_mmsys_match_data mt8186_mmsys_match_data = { - .num_drv_data = 1, - .drv_data = { - &mt8186_mmsys_driver_data, - }, -}; - static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = { .clk_driver = "clk-mt8192-mm", .routes = mmsys_mt8192_routing_table, @@ -130,66 +74,25 @@ static const struct mtk_mmsys_driver_data mt8192_mmsys_driver_data = { .sw0_rst_offset = MT8186_MMSYS_SW0_RST_B, }; -static const struct mtk_mmsys_match_data mt8192_mmsys_match_data = { - .num_drv_data = 1, - .drv_data = { - &mt8192_mmsys_driver_data, - }, -}; - static const struct mtk_mmsys_driver_data mt8195_vdosys0_driver_data = { - .io_start = 0x1c01a000, .clk_driver = "clk-mt8195-vdo0", .routes = mmsys_mt8195_routing_table, .num_routes = ARRAY_SIZE(mmsys_mt8195_routing_table), }; -static const struct mtk_mmsys_driver_data mt8195_vdosys1_driver_data = { - .io_start = 0x1c100000, - .clk_driver = "clk-mt8195-vdo1", -}; - -static const struct mtk_mmsys_match_data mt8195_mmsys_match_data = { - .num_drv_data = 2, - .drv_data = { - &mt8195_vdosys0_driver_data, - &mt8195_vdosys1_driver_data, - }, -}; - static const struct mtk_mmsys_driver_data mt8365_mmsys_driver_data = { .clk_driver = "clk-mt8365-mm", .routes = mt8365_mmsys_routing_table, .num_routes = ARRAY_SIZE(mt8365_mmsys_routing_table), }; -static const struct mtk_mmsys_match_data mt8365_mmsys_match_data = { - .num_drv_data = 1, - .drv_data = { - &mt8365_mmsys_driver_data, - }, -}; - struct mtk_mmsys { void __iomem *regs; const struct mtk_mmsys_driver_data *data; spinlock_t lock; /* protects mmsys_sw_rst_b reg */ struct reset_controller_dev rcdev; - phys_addr_t io_start; }; -static int mtk_mmsys_find_match_drvdata(struct mtk_mmsys *mmsys, - const struct mtk_mmsys_match_data *match) -{ - int i; - - for (i = 0; i < match->num_drv_data; i++) - if (mmsys->io_start == match->drv_data[i]->io_start) - return i; - - return -EINVAL; -} - void mtk_mmsys_ddp_connect(struct device *dev, enum mtk_ddp_comp_id cur, enum mtk_ddp_comp_id next) @@ -238,12 +141,27 @@ static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 mask, void mtk_mmsys_ddp_dpi_fmt_config(struct device *dev, u32 val) { - if (val) - mtk_mmsys_update_bits(dev_get_drvdata(dev), MT8186_MMSYS_DPI_OUTPUT_FORMAT, - DPI_RGB888_DDR_CON, DPI_FORMAT_MASK); - else - mtk_mmsys_update_bits(dev_get_drvdata(dev), MT8186_MMSYS_DPI_OUTPUT_FORMAT, - DPI_RGB565_SDR_CON, DPI_FORMAT_MASK); + struct mtk_mmsys *mmsys = dev_get_drvdata(dev); + + switch (val) { + case MTK_DPI_RGB888_SDR_CON: + mtk_mmsys_update_bits(mmsys, MT8186_MMSYS_DPI_OUTPUT_FORMAT, + MT8186_DPI_FORMAT_MASK, MT8186_DPI_RGB888_SDR_CON); + break; + case MTK_DPI_RGB565_SDR_CON: + mtk_mmsys_update_bits(mmsys, MT8186_MMSYS_DPI_OUTPUT_FORMAT, + MT8186_DPI_FORMAT_MASK, MT8186_DPI_RGB565_SDR_CON); + break; + case MTK_DPI_RGB565_DDR_CON: + mtk_mmsys_update_bits(mmsys, MT8186_MMSYS_DPI_OUTPUT_FORMAT, + MT8186_DPI_FORMAT_MASK, MT8186_DPI_RGB565_DDR_CON); + break; + case MTK_DPI_RGB888_DDR_CON: + default: + mtk_mmsys_update_bits(mmsys, MT8186_MMSYS_DPI_OUTPUT_FORMAT, + MT8186_DPI_FORMAT_MASK, MT8186_DPI_RGB888_DDR_CON); + break; + } } EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_dpi_fmt_config); @@ -304,9 +222,7 @@ static int mtk_mmsys_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct platform_device *clks; struct platform_device *drm; - const struct mtk_mmsys_match_data *match_data; struct mtk_mmsys *mmsys; - struct resource *res; int ret; mmsys = devm_kzalloc(dev, sizeof(*mmsys), GFP_KERNEL); @@ -332,27 +248,7 @@ static int mtk_mmsys_probe(struct platform_device *pdev) return ret; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "Couldn't get mmsys resource\n"); - return -EINVAL; - } - mmsys->io_start = res->start; - - match_data = of_device_get_match_data(dev); - if (match_data->num_drv_data > 1) { - /* This SoC has multiple mmsys channels */ - ret = mtk_mmsys_find_match_drvdata(mmsys, match_data); - if (ret < 0) { - dev_err(dev, "Couldn't get match driver data\n"); - return ret; - } - mmsys->data = match_data->drv_data[ret]; - } else { - dev_dbg(dev, "Using single mmsys channel\n"); - mmsys->data = match_data->drv_data[0]; - } - + mmsys->data = of_device_get_match_data(&pdev->dev); platform_set_drvdata(pdev, mmsys); clks = platform_device_register_data(&pdev->dev, mmsys->data->clk_driver, @@ -373,47 +269,51 @@ static int mtk_mmsys_probe(struct platform_device *pdev) static const struct of_device_id of_match_mtk_mmsys[] = { { .compatible = "mediatek,mt2701-mmsys", - .data = &mt2701_mmsys_match_data, + .data = &mt2701_mmsys_driver_data, }, { .compatible = "mediatek,mt2712-mmsys", - .data = &mt2712_mmsys_match_data, + .data = &mt2712_mmsys_driver_data, }, { .compatible = "mediatek,mt6779-mmsys", - .data = &mt6779_mmsys_match_data, + .data = &mt6779_mmsys_driver_data, }, { .compatible = "mediatek,mt6797-mmsys", - .data = &mt6797_mmsys_match_data, + .data = &mt6797_mmsys_driver_data, }, { .compatible = "mediatek,mt8167-mmsys", - .data = &mt8167_mmsys_match_data, + .data = &mt8167_mmsys_driver_data, }, { .compatible = "mediatek,mt8173-mmsys", - .data = &mt8173_mmsys_match_data, + .data = &mt8173_mmsys_driver_data, }, { .compatible = "mediatek,mt8183-mmsys", - .data = &mt8183_mmsys_match_data, + .data = &mt8183_mmsys_driver_data, }, { .compatible = "mediatek,mt8186-mmsys", - .data = &mt8186_mmsys_match_data, + .data = &mt8186_mmsys_driver_data, }, { .compatible = "mediatek,mt8192-mmsys", - .data = &mt8192_mmsys_match_data, + .data = &mt8192_mmsys_driver_data, }, - { + { /* deprecated compatible */ .compatible = "mediatek,mt8195-mmsys", - .data = &mt8195_mmsys_match_data, + .data = &mt8195_vdosys0_driver_data, + }, + { + .compatible = "mediatek,mt8195-vdosys0", + .data = &mt8195_vdosys0_driver_data, }, { .compatible = "mediatek,mt8365-mmsys", - .data = &mt8365_mmsys_match_data, + .data = &mt8365_mmsys_driver_data, }, { } }; diff --git a/drivers/soc/mediatek/mtk-mmsys.h b/drivers/soc/mediatek/mtk-mmsys.h index f01ba206481d..77f37f8c715b 100644 --- a/drivers/soc/mediatek/mtk-mmsys.h +++ b/drivers/soc/mediatek/mtk-mmsys.h @@ -87,18 +87,12 @@ struct mtk_mmsys_routes { }; struct mtk_mmsys_driver_data { - const resource_size_t io_start; const char *clk_driver; const struct mtk_mmsys_routes *routes; const unsigned int num_routes; const u16 sw0_rst_offset; }; -struct mtk_mmsys_match_data { - unsigned short num_drv_data; - const struct mtk_mmsys_driver_data *drv_data[]; -}; - /* * Routes in mt8173, mt2701, mt2712 are different. That means * in the same register address, it controls different input/output diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index eb82ae06697f..15789a03e6c6 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -983,6 +983,68 @@ static int mt8195_regs[] = { [PWRAP_WACS2_RDATA] = 0x8A8, }; +static int mt8365_regs[] = { + [PWRAP_MUX_SEL] = 0x0, + [PWRAP_WRAP_EN] = 0x4, + [PWRAP_DIO_EN] = 0x8, + [PWRAP_CSHEXT_WRITE] = 0x24, + [PWRAP_CSHEXT_READ] = 0x28, + [PWRAP_STAUPD_PRD] = 0x3c, + [PWRAP_STAUPD_GRPEN] = 0x40, + [PWRAP_STAUPD_MAN_TRIG] = 0x58, + [PWRAP_STAUPD_STA] = 0x5c, + [PWRAP_WRAP_STA] = 0x60, + [PWRAP_HARB_INIT] = 0x64, + [PWRAP_HARB_HPRIO] = 0x68, + [PWRAP_HIPRIO_ARB_EN] = 0x6c, + [PWRAP_HARB_STA0] = 0x70, + [PWRAP_HARB_STA1] = 0x74, + [PWRAP_MAN_EN] = 0x7c, + [PWRAP_MAN_CMD] = 0x80, + [PWRAP_MAN_RDATA] = 0x84, + [PWRAP_MAN_VLDCLR] = 0x88, + [PWRAP_WACS0_EN] = 0x8c, + [PWRAP_INIT_DONE0] = 0x90, + [PWRAP_WACS0_CMD] = 0xc00, + [PWRAP_WACS0_RDATA] = 0xc04, + [PWRAP_WACS0_VLDCLR] = 0xc08, + [PWRAP_WACS1_EN] = 0x94, + [PWRAP_INIT_DONE1] = 0x98, + [PWRAP_WACS2_EN] = 0x9c, + [PWRAP_INIT_DONE2] = 0xa0, + [PWRAP_WACS2_CMD] = 0xc20, + [PWRAP_WACS2_RDATA] = 0xc24, + [PWRAP_WACS2_VLDCLR] = 0xc28, + [PWRAP_INT_EN] = 0xb4, + [PWRAP_INT_FLG_RAW] = 0xb8, + [PWRAP_INT_FLG] = 0xbc, + [PWRAP_INT_CLR] = 0xc0, + [PWRAP_SIG_ADR] = 0xd4, + [PWRAP_SIG_MODE] = 0xd8, + [PWRAP_SIG_VALUE] = 0xdc, + [PWRAP_SIG_ERRVAL] = 0xe0, + [PWRAP_CRC_EN] = 0xe4, + [PWRAP_TIMER_EN] = 0xe8, + [PWRAP_TIMER_STA] = 0xec, + [PWRAP_WDT_UNIT] = 0xf0, + [PWRAP_WDT_SRC_EN] = 0xf4, + [PWRAP_WDT_FLG] = 0xfc, + [PWRAP_DEBUG_INT_SEL] = 0x104, + [PWRAP_CIPHER_KEY_SEL] = 0x1c4, + [PWRAP_CIPHER_IV_SEL] = 0x1c8, + [PWRAP_CIPHER_RDY] = 0x1d0, + [PWRAP_CIPHER_MODE] = 0x1d4, + [PWRAP_CIPHER_SWRST] = 0x1d8, + [PWRAP_DCM_EN] = 0x1dc, + [PWRAP_DCM_DBC_PRD] = 0x1e0, + [PWRAP_EINT_STA0_ADR] = 0x44, + [PWRAP_EINT_STA1_ADR] = 0x48, + [PWRAP_INT1_EN] = 0xc4, + [PWRAP_INT1_FLG] = 0xcc, + [PWRAP_INT1_CLR] = 0xd0, + [PWRAP_WDT_SRC_EN_1] = 0xf8, +}; + static int mt8516_regs[] = { [PWRAP_MUX_SEL] = 0x0, [PWRAP_WRAP_EN] = 0x4, @@ -1139,6 +1201,7 @@ enum pwrap_type { PWRAP_MT8183, PWRAP_MT8186, PWRAP_MT8195, + PWRAP_MT8365, PWRAP_MT8516, }; @@ -1171,6 +1234,8 @@ struct pmic_wrapper { const struct pwrap_slv_type *slave; struct clk *clk_spi; struct clk *clk_wrap; + struct clk *clk_sys; + struct clk *clk_tmr; struct reset_control *rstc; struct reset_control *rstc_bridge; @@ -1596,6 +1661,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) case PWRAP_MT6797: case PWRAP_MT8173: case PWRAP_MT8186: + case PWRAP_MT8365: case PWRAP_MT8516: pwrap_writel(wrp, 1, PWRAP_CIPHER_EN); break; @@ -2104,6 +2170,19 @@ static struct pmic_wrapper_type pwrap_mt8195 = { .init_soc_specific = NULL, }; +static const struct pmic_wrapper_type pwrap_mt8365 = { + .regs = mt8365_regs, + .type = PWRAP_MT8365, + .arb_en_all = 0x3ffff, + .int_en_all = 0x7f1fffff, + .int1_en_all = 0x0, + .spi_w = PWRAP_MAN_CMD_SPI_WRITE, + .wdt_src = PWRAP_WDT_SRC_MASK_ALL, + .caps = PWRAP_CAP_INT1_EN | PWRAP_CAP_WDT_SRC1, + .init_reg_clock = pwrap_common_init_reg_clock, + .init_soc_specific = NULL, +}; + static struct pmic_wrapper_type pwrap_mt8516 = { .regs = mt8516_regs, .type = PWRAP_MT8516, @@ -2141,6 +2220,7 @@ static const struct of_device_id of_pwrap_match_tbl[] = { { .compatible = "mediatek,mt8183-pwrap", .data = &pwrap_mt8183 }, { .compatible = "mediatek,mt8186-pwrap", .data = &pwrap_mt8186 }, { .compatible = "mediatek,mt8195-pwrap", .data = &pwrap_mt8195 }, + { .compatible = "mediatek,mt8365-pwrap", .data = &pwrap_mt8365 }, { .compatible = "mediatek,mt8516-pwrap", .data = &pwrap_mt8516 }, { /* sentinel */ } }; @@ -2214,6 +2294,20 @@ static int pwrap_probe(struct platform_device *pdev) return PTR_ERR(wrp->clk_wrap); } + wrp->clk_sys = devm_clk_get_optional(wrp->dev, "sys"); + if (IS_ERR(wrp->clk_sys)) { + return dev_err_probe(wrp->dev, PTR_ERR(wrp->clk_sys), + "failed to get clock: %pe\n", + wrp->clk_sys); + } + + wrp->clk_tmr = devm_clk_get_optional(wrp->dev, "tmr"); + if (IS_ERR(wrp->clk_tmr)) { + return dev_err_probe(wrp->dev, PTR_ERR(wrp->clk_tmr), + "failed to get clock: %pe\n", + wrp->clk_tmr); + } + ret = clk_prepare_enable(wrp->clk_spi); if (ret) return ret; @@ -2222,6 +2316,14 @@ static int pwrap_probe(struct platform_device *pdev) if (ret) goto err_out1; + ret = clk_prepare_enable(wrp->clk_sys); + if (ret) + goto err_out2; + + ret = clk_prepare_enable(wrp->clk_tmr); + if (ret) + goto err_out3; + /* Enable internal dynamic clock */ if (HAS_CAP(wrp->master->caps, PWRAP_CAP_DCM)) { pwrap_writel(wrp, 1, PWRAP_DCM_EN); @@ -2236,7 +2338,7 @@ static int pwrap_probe(struct platform_device *pdev) ret = pwrap_init(wrp); if (ret) { dev_dbg(wrp->dev, "init failed with %d\n", ret); - goto err_out2; + goto err_out4; } } @@ -2250,7 +2352,7 @@ static int pwrap_probe(struct platform_device *pdev) if (!(pwrap_readl(wrp, PWRAP_WACS2_RDATA) & mask_done)) { dev_dbg(wrp->dev, "initialization isn't finished\n"); ret = -ENODEV; - goto err_out2; + goto err_out4; } /* Initialize watchdog, may not be done by the bootloader */ @@ -2288,7 +2390,7 @@ static int pwrap_probe(struct platform_device *pdev) IRQF_TRIGGER_HIGH, "mt-pmic-pwrap", wrp); if (ret) - goto err_out2; + goto err_out4; wrp->regmap = devm_regmap_init(wrp->dev, NULL, wrp, wrp->slave->regops->regmap); if (IS_ERR(wrp->regmap)) { @@ -2300,11 +2402,15 @@ static int pwrap_probe(struct platform_device *pdev) if (ret) { dev_dbg(wrp->dev, "failed to create child devices at %pOF\n", np); - goto err_out2; + goto err_out4; } return 0; +err_out4: + clk_disable_unprepare(wrp->clk_tmr); +err_out3: + clk_disable_unprepare(wrp->clk_sys); err_out2: clk_disable_unprepare(wrp->clk_wrap); err_out1: diff --git a/drivers/soc/pxa/ssp.c b/drivers/soc/pxa/ssp.c index 93449fb3519e..bd029e838241 100644 --- a/drivers/soc/pxa/ssp.c +++ b/drivers/soc/pxa/ssp.c @@ -146,10 +146,8 @@ static int pxa_ssp_probe(struct platform_device *pdev) } ssp->irq = platform_get_irq(pdev, 0); - if (ssp->irq < 0) { - dev_err(dev, "no IRQ resource defined\n"); + if (ssp->irq < 0) return -ENODEV; - } if (dev->of_node) { const struct of_device_id *id = diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 024e420f1bb7..ae504c43d9e7 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -63,6 +63,7 @@ config QCOM_GSBI config QCOM_LLCC tristate "Qualcomm Technologies, Inc. LLCC driver" depends on ARCH_QCOM || COMPILE_TEST + select REGMAP_MMIO help Qualcomm Technologies, Inc. platform specific Last Level Cache Controller(LLCC) driver for platforms such as, @@ -236,6 +237,7 @@ config QCOM_ICC_BWMON tristate "QCOM Interconnect Bandwidth Monitor driver" depends on ARCH_QCOM || COMPILE_TEST select PM_OPP + select REGMAP_MMIO help Sets up driver monitoring bandwidth on various interconnects and based on that voting for interconnect bandwidth, adjusting their diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c index b4046f393575..cd44f17dad3d 100644 --- a/drivers/soc/qcom/apr.c +++ b/drivers/soc/qcom/apr.c @@ -454,11 +454,19 @@ static int apr_add_device(struct device *dev, struct device_node *np, adev->dev.driver = NULL; spin_lock(&apr->svcs_lock); - idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC); + ret = idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC); spin_unlock(&apr->svcs_lock); + if (ret < 0) { + dev_err(dev, "idr_alloc failed: %d\n", ret); + goto out; + } - of_property_read_string_index(np, "qcom,protection-domain", - 1, &adev->service_path); + ret = of_property_read_string_index(np, "qcom,protection-domain", + 1, &adev->service_path); + if (ret < 0) { + dev_err(dev, "Failed to read second value of qcom,protection-domain\n"); + goto out; + } dev_info(dev, "Adding APR/GPR dev: %s\n", dev_name(&adev->dev)); @@ -468,6 +476,7 @@ static int apr_add_device(struct device *dev, struct device_node *np, put_device(&adev->dev); } +out: return ret; } diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c index 629a7188b576..33856abd560c 100644 --- a/drivers/soc/qcom/cmd-db.c +++ b/drivers/soc/qcom/cmd-db.c @@ -338,6 +338,8 @@ static int cmd_db_dev_probe(struct platform_device *pdev) debugfs_create_file("cmd-db", 0400, NULL, NULL, &cmd_db_debugfs_ops); + device_set_pm_not_required(&pdev->dev); + return 0; } diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 8b7e8118f3ce..23ce2f78c4ed 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -21,6 +21,8 @@ #define ACTIVATE BIT(0) #define DEACTIVATE BIT(1) +#define ACT_CLEAR BIT(0) +#define ACT_COMPLETE BIT(4) #define ACT_CTRL_OPCODE_ACTIVATE BIT(0) #define ACT_CTRL_OPCODE_DEACTIVATE BIT(1) #define ACT_CTRL_ACT_TRIG BIT(0) @@ -41,19 +43,30 @@ #define MAX_CAP_TO_BYTES(n) (n * SZ_1K) #define LLCC_TRP_ACT_CTRLn(n) (n * SZ_4K) +#define LLCC_TRP_ACT_CLEARn(n) (8 + n * SZ_4K) #define LLCC_TRP_STATUSn(n) (4 + n * SZ_4K) #define LLCC_TRP_ATTR0_CFGn(n) (0x21000 + SZ_8 * n) #define LLCC_TRP_ATTR1_CFGn(n) (0x21004 + SZ_8 * n) +#define LLCC_TRP_ATTR2_CFGn(n) (0x21100 + SZ_8 * n) #define LLCC_TRP_SCID_DIS_CAP_ALLOC 0x21f00 #define LLCC_TRP_PCB_ACT 0x21f04 +#define LLCC_TRP_ALGO_CFG1 0x21f0c +#define LLCC_TRP_ALGO_CFG2 0x21f10 +#define LLCC_TRP_ALGO_CFG3 0x21f14 +#define LLCC_TRP_ALGO_CFG4 0x21f18 +#define LLCC_TRP_ALGO_CFG5 0x21f1c #define LLCC_TRP_WRSC_EN 0x21f20 +#define LLCC_TRP_ALGO_CFG6 0x21f24 +#define LLCC_TRP_ALGO_CFG7 0x21f28 #define LLCC_TRP_WRSC_CACHEABLE_EN 0x21f2c +#define LLCC_TRP_ALGO_CFG8 0x21f30 #define BANK_OFFSET_STRIDE 0x80000 #define LLCC_VERSION_2_0_0_0 0x02000000 #define LLCC_VERSION_2_1_0_0 0x02010000 +#define LLCC_VERSION_4_1_0_0 0x04010000 /** * struct llcc_slice_config - Data associated with the llcc slice @@ -97,6 +110,14 @@ struct llcc_slice_config { bool activate_on_init; bool write_scid_en; bool write_scid_cacheable_en; + bool stale_en; + bool stale_cap_en; + bool mru_uncap_en; + bool mru_rollover; + bool alloc_oneway_en; + bool ovcap_en; + bool ovcap_prio; + bool vict_prio; }; struct qcom_llcc_config { @@ -297,6 +318,38 @@ static const struct llcc_slice_config sm8450_data[] = { {LLCC_AENPU, 8, 2048, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 }, }; +static const struct llcc_slice_config sm8550_data[] = { + {LLCC_CPUSS, 1, 5120, 1, 0, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_VIDSC0, 2, 512, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_AUDIO, 6, 1024, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_MDMHPGRW, 25, 1024, 4, 0, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_MODHW, 26, 1024, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CMPT, 10, 4096, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_GPUHTW, 11, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_GPU, 9, 3096, 1, 0, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_MMUHWT, 18, 768, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_DISP, 16, 6144, 1, 1, 0xFFFFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_MDMPNG, 27, 1024, 0, 1, 0xF00000, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_AUDHW, 22, 1024, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CVP, 8, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_MODPE, 29, 64, 1, 1, 0xF00000, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, }, + {LLCC_WRCACHE, 31, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CAMEXP0, 4, 256, 4, 1, 0xF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CPUHWT, 5, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CAMEXP1, 7, 3200, 3, 1, 0xFFFFF0, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CMPTHCP, 17, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_LCPDARE, 30, 128, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, }, + {LLCC_AENPU, 3, 3072, 1, 1, 0xFE01FF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_ISLAND1, 12, 1792, 7, 1, 0xFE00, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_ISLAND4, 15, 256, 7, 1, 0x10000, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CAMEXP2, 19, 3200, 3, 1, 0xFFFFF0, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CAMEXP3, 20, 3200, 2, 1, 0xFFFFF0, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CAMEXP4, 21, 3200, 2, 1, 0xFFFFF0, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_DISP_WB, 23, 1024, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_DISP_1, 24, 6144, 1, 1, 0xFFFFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_VIDVSP, 28, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, +}; + static const struct llcc_edac_reg_offset llcc_v1_edac_reg_offset = { .trp_ecc_error_status0 = 0x20344, .trp_ecc_error_status1 = 0x20348, @@ -443,6 +496,14 @@ static const struct qcom_llcc_config sm8450_cfg = { .edac_reg_offset = &llcc_v2_1_edac_reg_offset, }; +static const struct qcom_llcc_config sm8550_cfg = { + .sct_data = sm8550_data, + .size = ARRAY_SIZE(sm8550_data), + .need_llcc_cfg = true, + .reg_offset = llcc_v2_1_reg_offset, + .edac_reg_offset = &llcc_v2_1_edac_reg_offset, +}; + static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER; /** @@ -497,6 +558,7 @@ static int llcc_update_act_ctrl(u32 sid, u32 act_ctrl_reg_val, u32 status) { u32 act_ctrl_reg; + u32 act_clear_reg; u32 status_reg; u32 slice_status; int ret; @@ -505,6 +567,7 @@ static int llcc_update_act_ctrl(u32 sid, return PTR_ERR(drv_data); act_ctrl_reg = LLCC_TRP_ACT_CTRLn(sid); + act_clear_reg = LLCC_TRP_ACT_CLEARn(sid); status_reg = LLCC_TRP_STATUSn(sid); /* Set the ACTIVE trigger */ @@ -521,9 +584,22 @@ static int llcc_update_act_ctrl(u32 sid, if (ret) return ret; + if (drv_data->version >= LLCC_VERSION_4_1_0_0) { + ret = regmap_read_poll_timeout(drv_data->bcast_regmap, status_reg, + slice_status, (slice_status & ACT_COMPLETE), + 0, LLCC_STATUS_READ_DELAY); + if (ret) + return ret; + } + ret = regmap_read_poll_timeout(drv_data->bcast_regmap, status_reg, slice_status, !(slice_status & status), 0, LLCC_STATUS_READ_DELAY); + + if (drv_data->version >= LLCC_VERSION_4_1_0_0) + ret = regmap_write(drv_data->bcast_regmap, act_clear_reg, + ACT_CLEAR); + return ret; } @@ -636,8 +712,10 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, const struct qcom_llcc_config *cfg) { int ret; + u32 attr2_cfg; u32 attr1_cfg; u32 attr0_cfg; + u32 attr2_val; u32 attr1_val; u32 attr0_val; u32 max_cap_cacheline; @@ -667,8 +745,14 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, if (ret) return ret; - attr0_val = config->res_ways & ATTR0_RES_WAYS_MASK; - attr0_val |= config->bonus_ways << ATTR0_BONUS_WAYS_SHIFT; + if (drv_data->version >= LLCC_VERSION_4_1_0_0) { + attr2_cfg = LLCC_TRP_ATTR2_CFGn(config->slice_id); + attr0_val = config->res_ways; + attr2_val = config->bonus_ways; + } else { + attr0_val = config->res_ways & ATTR0_RES_WAYS_MASK; + attr0_val |= config->bonus_ways << ATTR0_BONUS_WAYS_SHIFT; + } attr0_cfg = LLCC_TRP_ATTR0_CFGn(config->slice_id); @@ -676,6 +760,12 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, if (ret) return ret; + if (drv_data->version >= LLCC_VERSION_4_1_0_0) { + ret = regmap_write(drv_data->bcast_regmap, attr2_cfg, attr2_val); + if (ret) + return ret; + } + if (cfg->need_llcc_cfg) { u32 disable_cap_alloc, retain_pc; @@ -685,11 +775,13 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, if (ret) return ret; - retain_pc = config->retain_on_pc << config->slice_id; - ret = regmap_write(drv_data->bcast_regmap, - LLCC_TRP_PCB_ACT, retain_pc); - if (ret) - return ret; + if (drv_data->version < LLCC_VERSION_4_1_0_0) { + retain_pc = config->retain_on_pc << config->slice_id; + ret = regmap_write(drv_data->bcast_regmap, + LLCC_TRP_PCB_ACT, retain_pc); + if (ret) + return ret; + } } if (drv_data->version >= LLCC_VERSION_2_0_0_0) { @@ -712,6 +804,65 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, return ret; } + if (drv_data->version >= LLCC_VERSION_4_1_0_0) { + u32 stale_en; + u32 stale_cap_en; + u32 mru_uncap_en; + u32 mru_rollover; + u32 alloc_oneway_en; + u32 ovcap_en; + u32 ovcap_prio; + u32 vict_prio; + + stale_en = config->stale_en << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_ALGO_CFG1, + BIT(config->slice_id), stale_en); + if (ret) + return ret; + + stale_cap_en = config->stale_cap_en << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_ALGO_CFG2, + BIT(config->slice_id), stale_cap_en); + if (ret) + return ret; + + mru_uncap_en = config->mru_uncap_en << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_ALGO_CFG3, + BIT(config->slice_id), mru_uncap_en); + if (ret) + return ret; + + mru_rollover = config->mru_rollover << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_ALGO_CFG4, + BIT(config->slice_id), mru_rollover); + if (ret) + return ret; + + alloc_oneway_en = config->alloc_oneway_en << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_ALGO_CFG5, + BIT(config->slice_id), alloc_oneway_en); + if (ret) + return ret; + + ovcap_en = config->ovcap_en << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_ALGO_CFG6, + BIT(config->slice_id), ovcap_en); + if (ret) + return ret; + + ovcap_prio = config->ovcap_prio << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_ALGO_CFG7, + BIT(config->slice_id), ovcap_prio); + if (ret) + return ret; + + vict_prio = config->vict_prio << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_ALGO_CFG8, + BIT(config->slice_id), vict_prio); + if (ret) + return ret; + } + if (config->activate_on_init) { desc.slice_id = config->slice_id; ret = llcc_slice_activate(&desc); @@ -849,7 +1000,7 @@ static int qcom_llcc_probe(struct platform_device *pdev) if (ret) goto err; - drv_data->ecc_irq = platform_get_irq(pdev, 0); + drv_data->ecc_irq = platform_get_irq_optional(pdev, 0); if (drv_data->ecc_irq >= 0) { llcc_edac = platform_device_register_data(&pdev->dev, "qcom_llcc_edac", -1, drv_data, @@ -875,6 +1026,7 @@ static const struct of_device_id qcom_llcc_of_match[] = { { .compatible = "qcom,sm8250-llcc", .data = &sm8250_cfg }, { .compatible = "qcom,sm8350-llcc", .data = &sm8350_cfg }, { .compatible = "qcom,sm8450-llcc", .data = &sm8450_cfg }, + { .compatible = "qcom,sm8550-llcc", .data = &sm8550_cfg }, { } }; MODULE_DEVICE_TABLE(of, qcom_llcc_of_match); diff --git a/drivers/soc/qcom/pdr_internal.h b/drivers/soc/qcom/pdr_internal.h index a30422214943..03c282b7f17e 100644 --- a/drivers/soc/qcom/pdr_internal.h +++ b/drivers/soc/qcom/pdr_internal.h @@ -28,7 +28,7 @@ struct servreg_location_entry { u32 instance; }; -static struct qmi_elem_info servreg_location_entry_ei[] = { +static const struct qmi_elem_info servreg_location_entry_ei[] = { { .data_type = QMI_STRING, .elem_len = SERVREG_NAME_LENGTH + 1, @@ -74,7 +74,7 @@ struct servreg_get_domain_list_req { u32 domain_offset; }; -static struct qmi_elem_info servreg_get_domain_list_req_ei[] = { +static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = { { .data_type = QMI_STRING, .elem_len = SERVREG_NAME_LENGTH + 1, @@ -116,7 +116,7 @@ struct servreg_get_domain_list_resp { struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH]; }; -static struct qmi_elem_info servreg_get_domain_list_resp_ei[] = { +static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = { { .data_type = QMI_STRUCT, .elem_len = 1, @@ -199,7 +199,7 @@ struct servreg_register_listener_req { char service_path[SERVREG_NAME_LENGTH + 1]; }; -static struct qmi_elem_info servreg_register_listener_req_ei[] = { +static const struct qmi_elem_info servreg_register_listener_req_ei[] = { { .data_type = QMI_UNSIGNED_1_BYTE, .elem_len = 1, @@ -227,7 +227,7 @@ struct servreg_register_listener_resp { enum servreg_service_state curr_state; }; -static struct qmi_elem_info servreg_register_listener_resp_ei[] = { +static const struct qmi_elem_info servreg_register_listener_resp_ei[] = { { .data_type = QMI_STRUCT, .elem_len = 1, @@ -263,7 +263,7 @@ struct servreg_restart_pd_req { char service_path[SERVREG_NAME_LENGTH + 1]; }; -static struct qmi_elem_info servreg_restart_pd_req_ei[] = { +static const struct qmi_elem_info servreg_restart_pd_req_ei[] = { { .data_type = QMI_STRING, .elem_len = SERVREG_NAME_LENGTH + 1, @@ -280,7 +280,7 @@ struct servreg_restart_pd_resp { struct qmi_response_type_v01 resp; }; -static struct qmi_elem_info servreg_restart_pd_resp_ei[] = { +static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = { { .data_type = QMI_STRUCT, .elem_len = 1, @@ -300,7 +300,7 @@ struct servreg_state_updated_ind { u16 transaction_id; }; -static struct qmi_elem_info servreg_state_updated_ind_ei[] = { +static const struct qmi_elem_info servreg_state_updated_ind_ei[] = { { .data_type = QMI_SIGNED_4_BYTE_ENUM, .elem_len = 1, @@ -336,7 +336,7 @@ struct servreg_set_ack_req { u16 transaction_id; }; -static struct qmi_elem_info servreg_set_ack_req_ei[] = { +static const struct qmi_elem_info servreg_set_ack_req_ei[] = { { .data_type = QMI_STRING, .elem_len = SERVREG_NAME_LENGTH + 1, @@ -362,7 +362,7 @@ struct servreg_set_ack_resp { struct qmi_response_type_v01 resp; }; -static struct qmi_elem_info servreg_set_ack_resp_ei[] = { +static const struct qmi_elem_info servreg_set_ack_resp_ei[] = { { .data_type = QMI_STRUCT, .elem_len = 1, diff --git a/drivers/soc/qcom/qcom_stats.c b/drivers/soc/qcom/qcom_stats.c index 121ea409fafc..6228af057120 100644 --- a/drivers/soc/qcom/qcom_stats.c +++ b/drivers/soc/qcom/qcom_stats.c @@ -217,6 +217,8 @@ static int qcom_stats_probe(struct platform_device *pdev) platform_set_drvdata(pdev, root); + device_set_pm_not_required(&pdev->dev); + return 0; } diff --git a/drivers/soc/qcom/rpmh-internal.h b/drivers/soc/qcom/rpmh-internal.h index 344ba687c13b..e3cf1beff803 100644 --- a/drivers/soc/qcom/rpmh-internal.h +++ b/drivers/soc/qcom/rpmh-internal.h @@ -59,7 +59,6 @@ struct tcs_group { * @cmd: the payload that will be part of the @msg * @completion: triggered when request is done * @dev: the device making the request - * @err: err return from the controller * @needs_free: check to free dynamically allocated request object */ struct rpmh_request { @@ -67,7 +66,6 @@ struct rpmh_request { struct tcs_cmd cmd[MAX_RPMH_PAYLOAD]; struct completion *completion; const struct device *dev; - int err; bool needs_free; }; @@ -86,18 +84,25 @@ struct rpmh_ctrlr { struct list_head batch_cache; }; +struct rsc_ver { + u32 major; + u32 minor; +}; + /** * struct rsc_drv: the Direct Resource Voter (DRV) of the * Resource State Coordinator controller (RSC) * * @name: Controller identifier. + * @base: Start address of the DRV registers in this controller. * @tcs_base: Start address of the TCS registers in this controller. * @id: Instance id in the controller (Direct Resource Voter). * @num_tcs: Number of TCSes in this DRV. * @rsc_pm: CPU PM notifier for controller. * Used when solver mode is not present. * @cpus_in_pm: Number of CPUs not in idle power collapse. - * Used when solver mode is not present. + * Used when solver mode and "power-domains" is not present. + * @genpd_nb: PM Domain notifier for cluster genpd notifications. * @tcs: TCS groups. * @tcs_in_use: S/W state of the TCS; only set for ACTIVE_ONLY * transfers, but might show a sleep/wake TCS in use if @@ -110,27 +115,34 @@ struct rpmh_ctrlr { * @tcs_wait: Wait queue used to wait for @tcs_in_use to free up a * slot * @client: Handle to the DRV's client. + * @dev: RSC device. */ struct rsc_drv { const char *name; + void __iomem *base; void __iomem *tcs_base; int id; int num_tcs; struct notifier_block rsc_pm; + struct notifier_block genpd_nb; atomic_t cpus_in_pm; struct tcs_group tcs[TCS_TYPE_NR]; DECLARE_BITMAP(tcs_in_use, MAX_TCS_NR); spinlock_t lock; wait_queue_head_t tcs_wait; struct rpmh_ctrlr client; + struct device *dev; + struct rsc_ver ver; + u32 *regs; }; int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg); int rpmh_rsc_write_ctrl_data(struct rsc_drv *drv, const struct tcs_request *msg); void rpmh_rsc_invalidate(struct rsc_drv *drv); +void rpmh_rsc_write_next_wakeup(struct rsc_drv *drv); -void rpmh_tx_done(const struct tcs_request *msg, int r); +void rpmh_tx_done(const struct tcs_request *msg); int rpmh_flush(struct rpmh_ctrlr *ctrlr); #endif /* __RPM_INTERNAL_H__ */ diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index 01c2f50cb97e..0f8b2249f889 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -12,16 +12,21 @@ #include <linux/io.h> #include <linux/iopoll.h> #include <linux/kernel.h> +#include <linux/ktime.h> #include <linux/list.h> #include <linux/module.h> +#include <linux/notifier.h> #include <linux/of.h> #include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/platform_device.h> +#include <linux/pm_domain.h> +#include <linux/pm_runtime.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/wait.h> +#include <clocksource/arm_arch_timer.h> #include <soc/qcom/cmd-db.h> #include <soc/qcom/tcs.h> #include <dt-bindings/soc/qcom,rpmh-rsc.h> @@ -31,49 +36,50 @@ #define CREATE_TRACE_POINTS #include "trace-rpmh.h" -#define RSC_DRV_TCS_OFFSET 672 -#define RSC_DRV_CMD_OFFSET 20 + +#define RSC_DRV_ID 0 + +#define MAJOR_VER_MASK 0xFF +#define MAJOR_VER_SHIFT 16 +#define MINOR_VER_MASK 0xFF +#define MINOR_VER_SHIFT 8 + +enum { + RSC_DRV_TCS_OFFSET, + RSC_DRV_CMD_OFFSET, + DRV_SOLVER_CONFIG, + DRV_PRNT_CHLD_CONFIG, + RSC_DRV_IRQ_ENABLE, + RSC_DRV_IRQ_STATUS, + RSC_DRV_IRQ_CLEAR, + RSC_DRV_CMD_WAIT_FOR_CMPL, + RSC_DRV_CONTROL, + RSC_DRV_STATUS, + RSC_DRV_CMD_ENABLE, + RSC_DRV_CMD_MSGID, + RSC_DRV_CMD_ADDR, + RSC_DRV_CMD_DATA, + RSC_DRV_CMD_STATUS, + RSC_DRV_CMD_RESP_DATA, +}; /* DRV HW Solver Configuration Information Register */ -#define DRV_SOLVER_CONFIG 0x04 #define DRV_HW_SOLVER_MASK 1 #define DRV_HW_SOLVER_SHIFT 24 /* DRV TCS Configuration Information Register */ -#define DRV_PRNT_CHLD_CONFIG 0x0C #define DRV_NUM_TCS_MASK 0x3F #define DRV_NUM_TCS_SHIFT 6 #define DRV_NCPT_MASK 0x1F #define DRV_NCPT_SHIFT 27 -/* Offsets for common TCS Registers, one bit per TCS */ -#define RSC_DRV_IRQ_ENABLE 0x00 -#define RSC_DRV_IRQ_STATUS 0x04 -#define RSC_DRV_IRQ_CLEAR 0x08 /* w/o; write 1 to clear */ - -/* - * Offsets for per TCS Registers. - * - * TCSes start at 0x10 from tcs_base and are stored one after another. - * Multiply tcs_id by RSC_DRV_TCS_OFFSET to find a given TCS and add one - * of the below to find a register. - */ -#define RSC_DRV_CMD_WAIT_FOR_CMPL 0x10 /* 1 bit per command */ -#define RSC_DRV_CONTROL 0x14 -#define RSC_DRV_STATUS 0x18 /* zero if tcs is busy */ -#define RSC_DRV_CMD_ENABLE 0x1C /* 1 bit per command */ - -/* - * Offsets for per command in a TCS. - * - * Commands (up to 16) start at 0x30 in a TCS; multiply command index - * by RSC_DRV_CMD_OFFSET and add one of the below to find a register. - */ -#define RSC_DRV_CMD_MSGID 0x30 -#define RSC_DRV_CMD_ADDR 0x34 -#define RSC_DRV_CMD_DATA 0x38 -#define RSC_DRV_CMD_STATUS 0x3C -#define RSC_DRV_CMD_RESP_DATA 0x40 +/* Offsets for CONTROL TCS Registers */ +#define RSC_DRV_CTL_TCS_DATA_HI 0x38 +#define RSC_DRV_CTL_TCS_DATA_HI_MASK 0xFFFFFF +#define RSC_DRV_CTL_TCS_DATA_HI_VALID BIT(31) +#define RSC_DRV_CTL_TCS_DATA_LO 0x40 +#define RSC_DRV_CTL_TCS_DATA_LO_MASK 0xFFFFFFFF +#define RSC_DRV_CTL_TCS_DATA_SIZE 32 #define TCS_AMC_MODE_ENABLE BIT(16) #define TCS_AMC_MODE_TRIGGER BIT(24) @@ -139,16 +145,62 @@ * +---------------------------------------------------+ */ +#define USECS_TO_CYCLES(time_usecs) \ + xloops_to_cycles((time_usecs) * 0x10C7UL) + +static inline unsigned long xloops_to_cycles(u64 xloops) +{ + return (xloops * loops_per_jiffy * HZ) >> 32; +} + +static u32 rpmh_rsc_reg_offset_ver_2_7[] = { + [RSC_DRV_TCS_OFFSET] = 672, + [RSC_DRV_CMD_OFFSET] = 20, + [DRV_SOLVER_CONFIG] = 0x04, + [DRV_PRNT_CHLD_CONFIG] = 0x0C, + [RSC_DRV_IRQ_ENABLE] = 0x00, + [RSC_DRV_IRQ_STATUS] = 0x04, + [RSC_DRV_IRQ_CLEAR] = 0x08, + [RSC_DRV_CMD_WAIT_FOR_CMPL] = 0x10, + [RSC_DRV_CONTROL] = 0x14, + [RSC_DRV_STATUS] = 0x18, + [RSC_DRV_CMD_ENABLE] = 0x1C, + [RSC_DRV_CMD_MSGID] = 0x30, + [RSC_DRV_CMD_ADDR] = 0x34, + [RSC_DRV_CMD_DATA] = 0x38, + [RSC_DRV_CMD_STATUS] = 0x3C, + [RSC_DRV_CMD_RESP_DATA] = 0x40, +}; + +static u32 rpmh_rsc_reg_offset_ver_3_0[] = { + [RSC_DRV_TCS_OFFSET] = 672, + [RSC_DRV_CMD_OFFSET] = 24, + [DRV_SOLVER_CONFIG] = 0x04, + [DRV_PRNT_CHLD_CONFIG] = 0x0C, + [RSC_DRV_IRQ_ENABLE] = 0x00, + [RSC_DRV_IRQ_STATUS] = 0x04, + [RSC_DRV_IRQ_CLEAR] = 0x08, + [RSC_DRV_CMD_WAIT_FOR_CMPL] = 0x20, + [RSC_DRV_CONTROL] = 0x24, + [RSC_DRV_STATUS] = 0x28, + [RSC_DRV_CMD_ENABLE] = 0x2C, + [RSC_DRV_CMD_MSGID] = 0x34, + [RSC_DRV_CMD_ADDR] = 0x38, + [RSC_DRV_CMD_DATA] = 0x3C, + [RSC_DRV_CMD_STATUS] = 0x40, + [RSC_DRV_CMD_RESP_DATA] = 0x44, +}; + static inline void __iomem * tcs_reg_addr(const struct rsc_drv *drv, int reg, int tcs_id) { - return drv->tcs_base + RSC_DRV_TCS_OFFSET * tcs_id + reg; + return drv->tcs_base + drv->regs[RSC_DRV_TCS_OFFSET] * tcs_id + reg; } static inline void __iomem * tcs_cmd_addr(const struct rsc_drv *drv, int reg, int tcs_id, int cmd_id) { - return tcs_reg_addr(drv, reg, tcs_id) + RSC_DRV_CMD_OFFSET * cmd_id; + return tcs_reg_addr(drv, reg, tcs_id) + drv->regs[RSC_DRV_CMD_OFFSET] * cmd_id; } static u32 read_tcs_cmd(const struct rsc_drv *drv, int reg, int tcs_id, @@ -216,7 +268,7 @@ static void tcs_invalidate(struct rsc_drv *drv, int type) return; for (m = tcs->offset; m < tcs->offset + tcs->num_tcs; m++) - write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, m, 0); + write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_ENABLE], m, 0); bitmap_zero(tcs->slots, MAX_TCS_SLOTS); } @@ -330,24 +382,25 @@ static const struct tcs_request *get_req_from_tcs(struct rsc_drv *drv, static void __tcs_set_trigger(struct rsc_drv *drv, int tcs_id, bool trigger) { u32 enable; + u32 reg = drv->regs[RSC_DRV_CONTROL]; /* * HW req: Clear the DRV_CONTROL and enable TCS again * While clearing ensure that the AMC mode trigger is cleared * and then the mode enable is cleared. */ - enable = read_tcs_reg(drv, RSC_DRV_CONTROL, tcs_id); + enable = read_tcs_reg(drv, reg, tcs_id); enable &= ~TCS_AMC_MODE_TRIGGER; - write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable); + write_tcs_reg_sync(drv, reg, tcs_id, enable); enable &= ~TCS_AMC_MODE_ENABLE; - write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable); + write_tcs_reg_sync(drv, reg, tcs_id, enable); if (trigger) { /* Enable the AMC mode on the TCS and then trigger the TCS */ enable = TCS_AMC_MODE_ENABLE; - write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable); + write_tcs_reg_sync(drv, reg, tcs_id, enable); enable |= TCS_AMC_MODE_TRIGGER; - write_tcs_reg(drv, RSC_DRV_CONTROL, tcs_id, enable); + write_tcs_reg(drv, reg, tcs_id, enable); } } @@ -363,13 +416,14 @@ static void __tcs_set_trigger(struct rsc_drv *drv, int tcs_id, bool trigger) static void enable_tcs_irq(struct rsc_drv *drv, int tcs_id, bool enable) { u32 data; + u32 reg = drv->regs[RSC_DRV_IRQ_ENABLE]; - data = readl_relaxed(drv->tcs_base + RSC_DRV_IRQ_ENABLE); + data = readl_relaxed(drv->tcs_base + reg); if (enable) data |= BIT(tcs_id); else data &= ~BIT(tcs_id); - writel_relaxed(data, drv->tcs_base + RSC_DRV_IRQ_ENABLE); + writel_relaxed(data, drv->tcs_base + reg); } /** @@ -385,34 +439,18 @@ static void enable_tcs_irq(struct rsc_drv *drv, int tcs_id, bool enable) static irqreturn_t tcs_tx_done(int irq, void *p) { struct rsc_drv *drv = p; - int i, j, err = 0; + int i; unsigned long irq_status; const struct tcs_request *req; - struct tcs_cmd *cmd; - irq_status = readl_relaxed(drv->tcs_base + RSC_DRV_IRQ_STATUS); + irq_status = readl_relaxed(drv->tcs_base + drv->regs[RSC_DRV_IRQ_STATUS]); for_each_set_bit(i, &irq_status, BITS_PER_TYPE(u32)) { req = get_req_from_tcs(drv, i); if (WARN_ON(!req)) goto skip; - err = 0; - for (j = 0; j < req->num_cmds; j++) { - u32 sts; - - cmd = &req->cmds[j]; - sts = read_tcs_cmd(drv, RSC_DRV_CMD_STATUS, i, j); - if (!(sts & CMD_STATUS_ISSUED) || - ((req->wait_for_compl || cmd->wait) && - !(sts & CMD_STATUS_COMPL))) { - pr_err("Incomplete request: %s: addr=%#x data=%#x", - drv->name, cmd->addr, cmd->data); - err = -EIO; - } - } - - trace_rpmh_tx_done(drv, i, req, err); + trace_rpmh_tx_done(drv, i, req); /* * If wake tcs was re-purposed for sending active @@ -423,8 +461,8 @@ static irqreturn_t tcs_tx_done(int irq, void *p) __tcs_set_trigger(drv, i, false); skip: /* Reclaim the TCS */ - write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, i, 0); - writel_relaxed(BIT(i), drv->tcs_base + RSC_DRV_IRQ_CLEAR); + write_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], i, 0); + writel_relaxed(BIT(i), drv->tcs_base + drv->regs[RSC_DRV_IRQ_CLEAR]); spin_lock(&drv->lock); clear_bit(i, drv->tcs_in_use); /* @@ -437,7 +475,7 @@ skip: spin_unlock(&drv->lock); wake_up(&drv->tcs_wait); if (req) - rpmh_tx_done(req, err); + rpmh_tx_done(req); } return IRQ_HANDLED; @@ -475,14 +513,14 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id, */ msgid |= cmd->wait ? CMD_MSGID_RESP_REQ : 0; - write_tcs_cmd(drv, RSC_DRV_CMD_MSGID, tcs_id, j, msgid); - write_tcs_cmd(drv, RSC_DRV_CMD_ADDR, tcs_id, j, cmd->addr); - write_tcs_cmd(drv, RSC_DRV_CMD_DATA, tcs_id, j, cmd->data); + write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_MSGID], tcs_id, j, msgid); + write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_ADDR], tcs_id, j, cmd->addr); + write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_DATA], tcs_id, j, cmd->data); trace_rpmh_send_msg(drv, tcs_id, j, msgid, cmd); } - cmd_enable |= read_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id); - write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id, cmd_enable); + cmd_enable |= read_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id); + write_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, cmd_enable); } /** @@ -514,10 +552,10 @@ static int check_for_req_inflight(struct rsc_drv *drv, struct tcs_group *tcs, int i = tcs->offset; for_each_set_bit_from(i, drv->tcs_in_use, tcs->offset + tcs->num_tcs) { - curr_enabled = read_tcs_reg(drv, RSC_DRV_CMD_ENABLE, i); + curr_enabled = read_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], i); for_each_set_bit(j, &curr_enabled, MAX_CMDS_PER_TCS) { - addr = read_tcs_cmd(drv, RSC_DRV_CMD_ADDR, i, j); + addr = read_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_ADDR], i, j); for (k = 0; k < msg->num_cmds; k++) { if (addr == msg->cmds[k].addr) return -EBUSY; @@ -628,7 +666,7 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg) * repurposed TCS to avoid triggering them. tcs->slots will be * cleaned from rpmh_flush() by invoking rpmh_rsc_invalidate() */ - write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, tcs_id, 0); + write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, 0); enable_tcs_irq(drv, tcs_id, true); } spin_unlock_irqrestore(&drv->lock, flags); @@ -754,6 +792,48 @@ static bool rpmh_rsc_ctrlr_is_busy(struct rsc_drv *drv) } /** + * rpmh_rsc_write_next_wakeup() - Write next wakeup in CONTROL_TCS. + * @drv: The controller + * + * Writes maximum wakeup cycles when called from suspend. + * Writes earliest hrtimer wakeup when called from idle. + */ +void rpmh_rsc_write_next_wakeup(struct rsc_drv *drv) +{ + ktime_t now, wakeup; + u64 wakeup_us, wakeup_cycles = ~0; + u32 lo, hi; + + if (!drv->tcs[CONTROL_TCS].num_tcs || !drv->genpd_nb.notifier_call) + return; + + /* Set highest time when system (timekeeping) is suspended */ + if (system_state == SYSTEM_SUSPEND) + goto exit; + + /* Find the earliest hrtimer wakeup from online cpus */ + wakeup = dev_pm_genpd_get_next_hrtimer(drv->dev); + + /* Find the relative wakeup in kernel time scale */ + now = ktime_get(); + wakeup = ktime_sub(wakeup, now); + wakeup_us = ktime_to_us(wakeup); + + /* Convert the wakeup to arch timer scale */ + wakeup_cycles = USECS_TO_CYCLES(wakeup_us); + wakeup_cycles += arch_timer_read_counter(); + +exit: + lo = wakeup_cycles & RSC_DRV_CTL_TCS_DATA_LO_MASK; + hi = wakeup_cycles >> RSC_DRV_CTL_TCS_DATA_SIZE; + hi &= RSC_DRV_CTL_TCS_DATA_HI_MASK; + hi |= RSC_DRV_CTL_TCS_DATA_HI_VALID; + + writel_relaxed(lo, drv->base + RSC_DRV_CTL_TCS_DATA_LO); + writel_relaxed(hi, drv->base + RSC_DRV_CTL_TCS_DATA_HI); +} + +/** * rpmh_rsc_cpu_pm_callback() - Check if any of the AMCs are busy. * @nfb: Pointer to the notifier block in struct rsc_drv. * @action: CPU_PM_ENTER, CPU_PM_ENTER_FAILED, or CPU_PM_EXIT. @@ -834,8 +914,51 @@ static int rpmh_rsc_cpu_pm_callback(struct notifier_block *nfb, return ret; } -static int rpmh_probe_tcs_config(struct platform_device *pdev, - struct rsc_drv *drv, void __iomem *base) +/** + * rpmh_rsc_pd_callback() - Check if any of the AMCs are busy. + * @nfb: Pointer to the genpd notifier block in struct rsc_drv. + * @action: GENPD_NOTIFY_PRE_OFF, GENPD_NOTIFY_OFF, GENPD_NOTIFY_PRE_ON or GENPD_NOTIFY_ON. + * @v: Unused + * + * This function is given to dev_pm_genpd_add_notifier() so we can be informed + * about when cluster-pd is going down. When cluster go down we know no more active + * transfers will be started so we write sleep/wake sets. This function gets + * called from cpuidle code paths and also at system suspend time. + * + * If AMCs are not busy then writes cached sleep and wake messages to TCSes. + * The firmware then takes care of triggering them when entering deepest low power modes. + * + * Return: + * * NOTIFY_OK - success + * * NOTIFY_BAD - failure + */ +static int rpmh_rsc_pd_callback(struct notifier_block *nfb, + unsigned long action, void *v) +{ + struct rsc_drv *drv = container_of(nfb, struct rsc_drv, genpd_nb); + + /* We don't need to lock as genpd on/off are serialized */ + if ((action == GENPD_NOTIFY_PRE_OFF) && + (rpmh_rsc_ctrlr_is_busy(drv) || rpmh_flush(&drv->client))) + return NOTIFY_BAD; + + return NOTIFY_OK; +} + +static int rpmh_rsc_pd_attach(struct rsc_drv *drv, struct device *dev) +{ + int ret; + + pm_runtime_enable(dev); + drv->genpd_nb.notifier_call = rpmh_rsc_pd_callback; + ret = dev_pm_genpd_add_notifier(dev, &drv->genpd_nb); + if (ret) + pm_runtime_disable(dev); + + return ret; +} + +static int rpmh_probe_tcs_config(struct platform_device *pdev, struct rsc_drv *drv) { struct tcs_type_config { u32 type; @@ -849,9 +972,9 @@ static int rpmh_probe_tcs_config(struct platform_device *pdev, ret = of_property_read_u32(dn, "qcom,tcs-offset", &offset); if (ret) return ret; - drv->tcs_base = base + offset; + drv->tcs_base = drv->base + offset; - config = readl_relaxed(base + DRV_PRNT_CHLD_CONFIG); + config = readl_relaxed(drv->base + drv->regs[DRV_PRNT_CHLD_CONFIG]); max_tcs = config; max_tcs &= DRV_NUM_TCS_MASK << (DRV_NUM_TCS_SHIFT * drv->id); @@ -913,7 +1036,7 @@ static int rpmh_rsc_probe(struct platform_device *pdev) char drv_id[10] = {0}; int ret, irq; u32 solver_config; - void __iomem *base; + u32 rsc_id; /* * Even though RPMh doesn't directly use cmd-db, all of its children @@ -940,11 +1063,22 @@ static int rpmh_rsc_probe(struct platform_device *pdev) drv->name = dev_name(&pdev->dev); snprintf(drv_id, ARRAY_SIZE(drv_id), "drv-%d", drv->id); - base = devm_platform_ioremap_resource_byname(pdev, drv_id); - if (IS_ERR(base)) - return PTR_ERR(base); + drv->base = devm_platform_ioremap_resource_byname(pdev, drv_id); + if (IS_ERR(drv->base)) + return PTR_ERR(drv->base); + + rsc_id = readl_relaxed(drv->base + RSC_DRV_ID); + drv->ver.major = rsc_id & (MAJOR_VER_MASK << MAJOR_VER_SHIFT); + drv->ver.major >>= MAJOR_VER_SHIFT; + drv->ver.minor = rsc_id & (MINOR_VER_MASK << MINOR_VER_SHIFT); + drv->ver.minor >>= MINOR_VER_SHIFT; + + if (drv->ver.major == 3 && drv->ver.minor == 0) + drv->regs = rpmh_rsc_reg_offset_ver_3_0; + else + drv->regs = rpmh_rsc_reg_offset_ver_2_7; - ret = rpmh_probe_tcs_config(pdev, drv, base); + ret = rpmh_probe_tcs_config(pdev, drv); if (ret) return ret; @@ -963,29 +1097,42 @@ static int rpmh_rsc_probe(struct platform_device *pdev) return ret; /* - * CPU PM notification are not required for controllers that support + * CPU PM/genpd notification are not required for controllers that support * 'HW solver' mode where they can be in autonomous mode executing low * power mode to power down. */ - solver_config = readl_relaxed(base + DRV_SOLVER_CONFIG); + solver_config = readl_relaxed(drv->base + drv->regs[DRV_SOLVER_CONFIG]); solver_config &= DRV_HW_SOLVER_MASK << DRV_HW_SOLVER_SHIFT; solver_config = solver_config >> DRV_HW_SOLVER_SHIFT; if (!solver_config) { - drv->rsc_pm.notifier_call = rpmh_rsc_cpu_pm_callback; - cpu_pm_register_notifier(&drv->rsc_pm); + if (pdev->dev.pm_domain) { + ret = rpmh_rsc_pd_attach(drv, &pdev->dev); + if (ret) + return ret; + } else { + drv->rsc_pm.notifier_call = rpmh_rsc_cpu_pm_callback; + cpu_pm_register_notifier(&drv->rsc_pm); + } } /* Enable the active TCS to send requests immediately */ writel_relaxed(drv->tcs[ACTIVE_TCS].mask, - drv->tcs_base + RSC_DRV_IRQ_ENABLE); + drv->tcs_base + drv->regs[RSC_DRV_IRQ_ENABLE]); spin_lock_init(&drv->client.cache_lock); INIT_LIST_HEAD(&drv->client.cache); INIT_LIST_HEAD(&drv->client.batch_cache); dev_set_drvdata(&pdev->dev, drv); + drv->dev = &pdev->dev; + + ret = devm_of_platform_populate(&pdev->dev); + if (ret && pdev->dev.pm_domain) { + dev_pm_genpd_remove_notifier(&pdev->dev); + pm_runtime_disable(&pdev->dev); + } - return devm_of_platform_populate(&pdev->dev); + return ret; } static const struct of_device_id rpmh_drv_match[] = { diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c index 01765ee9cdfb..08e09642d7f5 100644 --- a/drivers/soc/qcom/rpmh.c +++ b/drivers/soc/qcom/rpmh.c @@ -76,19 +76,13 @@ static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct device *dev) return &drv->client; } -void rpmh_tx_done(const struct tcs_request *msg, int r) +void rpmh_tx_done(const struct tcs_request *msg) { struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request, msg); struct completion *compl = rpm_msg->completion; bool free = rpm_msg->needs_free; - rpm_msg->err = r; - - if (r) - dev_err(rpm_msg->dev, "RPMH TX fail in msg addr=%#x, err=%d\n", - rpm_msg->msg.cmds[0].addr, r); - if (!compl) goto exit; @@ -194,7 +188,7 @@ static int __rpmh_write(const struct device *dev, enum rpmh_state state, } else { /* Clean up our call by spoofing tx_done */ ret = 0; - rpmh_tx_done(&rpm_msg->msg, ret); + rpmh_tx_done(&rpm_msg->msg); } return ret; @@ -450,7 +444,7 @@ int rpmh_flush(struct rpmh_ctrlr *ctrlr) if (!ctrlr->dirty) { pr_debug("Skipping flush, TCS has latest data.\n"); - goto exit; + goto write_next_wakeup; } /* Invalidate the TCSes first to avoid stale data */ @@ -479,6 +473,8 @@ int rpmh_flush(struct rpmh_ctrlr *ctrlr) ctrlr->dirty = false; +write_next_wakeup: + rpmh_rsc_write_next_wakeup(ctrlr_to_drv(ctrlr)); exit: spin_unlock(&ctrlr->cache_lock); return ret; diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c index 092f6ab09acf..4c2d2c296790 100644 --- a/drivers/soc/qcom/rpmhpd.c +++ b/drivers/soc/qcom/rpmhpd.c @@ -39,6 +39,7 @@ * @res_name: Resource name used for cmd-db lookup * @addr: Resource address as looped up using resource name from * cmd-db + * @state_synced: Indicator that sync_state has been invoked for the rpmhpd resource */ struct rpmhpd { struct device *dev; @@ -54,6 +55,7 @@ struct rpmhpd { bool enabled; const char *res_name; u32 addr; + bool state_synced; }; struct rpmhpd_desc { @@ -210,6 +212,23 @@ static const struct rpmhpd_desc sa8540p_desc = { .num_pds = ARRAY_SIZE(sa8540p_rpmhpds), }; +/* SDM670 RPMH powerdomains */ +static struct rpmhpd *sdm670_rpmhpds[] = { + [SDM670_CX] = &cx_w_mx_parent, + [SDM670_CX_AO] = &cx_ao_w_mx_parent, + [SDM670_GFX] = &gfx, + [SDM670_LCX] = &lcx, + [SDM670_LMX] = &lmx, + [SDM670_MSS] = &mss, + [SDM670_MX] = &mx, + [SDM670_MX_AO] = &mx_ao, +}; + +static const struct rpmhpd_desc sdm670_desc = { + .rpmhpds = sdm670_rpmhpds, + .num_pds = ARRAY_SIZE(sdm670_rpmhpds), +}; + /* SDM845 RPMH powerdomains */ static struct rpmhpd *sdm845_rpmhpds[] = { [SDM845_CX] = &cx_w_mx_parent, @@ -353,6 +372,42 @@ static const struct rpmhpd_desc sm8450_desc = { .num_pds = ARRAY_SIZE(sm8450_rpmhpds), }; +/* SM8550 RPMH powerdomains */ +static struct rpmhpd *sm8550_rpmhpds[] = { + [SM8550_CX] = &cx, + [SM8550_CX_AO] = &cx_ao, + [SM8550_EBI] = &ebi, + [SM8550_GFX] = &gfx, + [SM8550_LCX] = &lcx, + [SM8550_LMX] = &lmx, + [SM8550_MMCX] = &mmcx_w_cx_parent, + [SM8550_MMCX_AO] = &mmcx_ao_w_cx_parent, + [SM8550_MSS] = &mss, + [SM8550_MX] = &mx, + [SM8550_MX_AO] = &mx_ao, + [SM8550_MXC] = &mxc, + [SM8550_MXC_AO] = &mxc_ao, + [SM8550_NSP] = &nsp, +}; + +static const struct rpmhpd_desc sm8550_desc = { + .rpmhpds = sm8550_rpmhpds, + .num_pds = ARRAY_SIZE(sm8550_rpmhpds), +}; + +/* QDU1000/QRU1000 RPMH powerdomains */ +static struct rpmhpd *qdu1000_rpmhpds[] = { + [QDU1000_CX] = &cx, + [QDU1000_EBI] = &ebi, + [QDU1000_MSS] = &mss, + [QDU1000_MX] = &mx, +}; + +static const struct rpmhpd_desc qdu1000_desc = { + .rpmhpds = qdu1000_rpmhpds, + .num_pds = ARRAY_SIZE(qdu1000_rpmhpds), +}; + /* SC7180 RPMH powerdomains */ static struct rpmhpd *sc7180_rpmhpds[] = { [SC7180_CX] = &cx_w_mx_parent, @@ -430,11 +485,13 @@ static const struct rpmhpd_desc sc8280xp_desc = { }; static const struct of_device_id rpmhpd_match_table[] = { + { .compatible = "qcom,qdu1000-rpmhpd", .data = &qdu1000_desc }, { .compatible = "qcom,sa8540p-rpmhpd", .data = &sa8540p_desc }, { .compatible = "qcom,sc7180-rpmhpd", .data = &sc7180_desc }, { .compatible = "qcom,sc7280-rpmhpd", .data = &sc7280_desc }, { .compatible = "qcom,sc8180x-rpmhpd", .data = &sc8180x_desc }, { .compatible = "qcom,sc8280xp-rpmhpd", .data = &sc8280xp_desc }, + { .compatible = "qcom,sdm670-rpmhpd", .data = &sdm670_desc }, { .compatible = "qcom,sdm845-rpmhpd", .data = &sdm845_desc }, { .compatible = "qcom,sdx55-rpmhpd", .data = &sdx55_desc}, { .compatible = "qcom,sdx65-rpmhpd", .data = &sdx65_desc}, @@ -443,6 +500,7 @@ static const struct of_device_id rpmhpd_match_table[] = { { .compatible = "qcom,sm8250-rpmhpd", .data = &sm8250_desc }, { .compatible = "qcom,sm8350-rpmhpd", .data = &sm8350_desc }, { .compatible = "qcom,sm8450-rpmhpd", .data = &sm8450_desc }, + { .compatible = "qcom,sm8550-rpmhpd", .data = &sm8550_desc }, { } }; MODULE_DEVICE_TABLE(of, rpmhpd_match_table); @@ -493,7 +551,13 @@ static int rpmhpd_aggregate_corner(struct rpmhpd *pd, unsigned int corner) unsigned int this_active_corner = 0, this_sleep_corner = 0; unsigned int peer_active_corner = 0, peer_sleep_corner = 0; - to_active_sleep(pd, corner, &this_active_corner, &this_sleep_corner); + if (pd->state_synced) { + to_active_sleep(pd, corner, &this_active_corner, &this_sleep_corner); + } else { + /* Clamp to highest corner if sync_state hasn't happened */ + this_active_corner = pd->level_count - 1; + this_sleep_corner = pd->level_count - 1; + } if (peer && peer->enabled) to_active_sleep(peer, peer->corner, &peer_active_corner, @@ -708,11 +772,40 @@ static int rpmhpd_probe(struct platform_device *pdev) return of_genpd_add_provider_onecell(pdev->dev.of_node, data); } +static void rpmhpd_sync_state(struct device *dev) +{ + const struct rpmhpd_desc *desc = of_device_get_match_data(dev); + struct rpmhpd **rpmhpds = desc->rpmhpds; + unsigned int corner; + struct rpmhpd *pd; + unsigned int i; + int ret; + + mutex_lock(&rpmhpd_lock); + for (i = 0; i < desc->num_pds; i++) { + pd = rpmhpds[i]; + if (!pd) + continue; + + pd->state_synced = true; + if (pd->enabled) + corner = max(pd->corner, pd->enable_corner); + else + corner = 0; + + ret = rpmhpd_aggregate_corner(pd, corner); + if (ret) + dev_err(dev, "failed to sync %s\n", pd->res_name); + } + mutex_unlock(&rpmhpd_lock); +} + static struct platform_driver rpmhpd_driver = { .driver = { .name = "qcom-rpmhpd", .of_match_table = rpmhpd_match_table, .suppress_bind_attrs = true, + .sync_state = rpmhpd_sync_state, }, .probe = rpmhpd_probe, }; diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c index 337b1ad1cd3b..f0db6a10cf4e 100644 --- a/drivers/soc/qcom/rpmpd.c +++ b/drivers/soc/qcom/rpmpd.c @@ -471,6 +471,23 @@ static const struct rpmpd_desc qcm2290_desc = { .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR, }; +static struct rpmpd *sm4250_rpmpds[] = { + [SM4250_VDDCX] = &sm6115_vddcx, + [SM4250_VDDCX_AO] = &sm6115_vddcx_ao, + [SM4250_VDDCX_VFL] = &sm6115_vddcx_vfl, + [SM4250_VDDMX] = &sm6115_vddmx, + [SM4250_VDDMX_AO] = &sm6115_vddmx_ao, + [SM4250_VDDMX_VFL] = &sm6115_vddmx_vfl, + [SM4250_VDD_LPI_CX] = &sm6115_vdd_lpi_cx, + [SM4250_VDD_LPI_MX] = &sm6115_vdd_lpi_mx, +}; + +static const struct rpmpd_desc sm4250_desc = { + .rpmpds = sm4250_rpmpds, + .num_pds = ARRAY_SIZE(sm4250_rpmpds), + .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR, +}; + static const struct of_device_id rpmpd_match_table[] = { { .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc }, { .compatible = "qcom,msm8226-rpmpd", .data = &msm8226_desc }, @@ -485,6 +502,7 @@ static const struct of_device_id rpmpd_match_table[] = { { .compatible = "qcom,qcm2290-rpmpd", .data = &qcm2290_desc }, { .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc }, { .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc }, + { .compatible = "qcom,sm4250-rpmpd", .data = &sm4250_desc }, { .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc }, { .compatible = "qcom,sm6125-rpmpd", .data = &sm6125_desc }, { .compatible = "qcom,sm6375-rpmpd", .data = &sm6375_desc }, diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c index 413f9f4ae9cd..7e3b6a7ea34c 100644 --- a/drivers/soc/qcom/smd-rpm.c +++ b/drivers/soc/qcom/smd-rpm.c @@ -75,7 +75,7 @@ struct qcom_rpm_message { __le32 length; union { __le32 msg_id; - u8 message[0]; + DECLARE_FLEX_ARRAY(u8, message); }; }; @@ -246,6 +246,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = { { .compatible = "qcom,rpm-sdm660" }, { .compatible = "qcom,rpm-sm6115" }, { .compatible = "qcom,rpm-sm6125" }, + { .compatible = "qcom,rpm-sm6375" }, { .compatible = "qcom,rpm-qcm2290" }, { .compatible = "qcom,rpm-qcs404" }, {} diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c index d9c28a8a7cbf..e9c8030d50ee 100644 --- a/drivers/soc/qcom/smp2p.c +++ b/drivers/soc/qcom/smp2p.c @@ -422,7 +422,7 @@ static int qcom_smp2p_outbound_entry(struct qcom_smp2p *smp2p, char buf[SMP2P_MAX_ENTRY_NAME] = {}; /* Allocate an entry from the smem item */ - strlcpy(buf, entry->name, SMP2P_MAX_ENTRY_NAME); + strscpy(buf, entry->name, SMP2P_MAX_ENTRY_NAME); memcpy(out->entries[out->valid_entries].name, buf, SMP2P_MAX_ENTRY_NAME); /* Make the logical entry reference the physical value */ diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index aa37e1bad095..ebcbf9b9c18b 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -12,11 +12,14 @@ #include <linux/slab.h> #include <linux/soc/qcom/smem.h> #include <linux/string.h> +#include <linux/stringify.h> #include <linux/sys_soc.h> #include <linux/types.h> #include <asm/unaligned.h> +#include <dt-bindings/arm/qcom,ids.h> + /* * SoC version type with major number in the upper 16 bits and minor * number in the lower 16 bits. @@ -25,6 +28,10 @@ #define SOCINFO_MINOR(ver) ((ver) & 0xffff) #define SOCINFO_VERSION(maj, min) ((((maj) & 0xffff) << 16)|((min) & 0xffff)) +/* Helper macros to create soc_id table */ +#define qcom_board_id(id) QCOM_ID_ ## id, __stringify(id) +#define qcom_board_id_named(id, name) QCOM_ID_ ## id, (name) + #define SMEM_SOCINFO_BUILD_ID_LENGTH 32 #define SMEM_SOCINFO_CHIP_ID_LENGTH 32 @@ -207,135 +214,150 @@ struct soc_id { }; static const struct soc_id soc_id[] = { - { 87, "MSM8960" }, - { 109, "APQ8064" }, - { 122, "MSM8660A" }, - { 123, "MSM8260A" }, - { 124, "APQ8060A" }, - { 126, "MSM8974" }, - { 130, "MPQ8064" }, - { 138, "MSM8960AB" }, - { 139, "APQ8060AB" }, - { 140, "MSM8260AB" }, - { 141, "MSM8660AB" }, - { 145, "MSM8626" }, - { 147, "MSM8610" }, - { 153, "APQ8064AB" }, - { 158, "MSM8226" }, - { 159, "MSM8526" }, - { 161, "MSM8110" }, - { 162, "MSM8210" }, - { 163, "MSM8810" }, - { 164, "MSM8212" }, - { 165, "MSM8612" }, - { 166, "MSM8112" }, - { 168, "MSM8225Q" }, - { 169, "MSM8625Q" }, - { 170, "MSM8125Q" }, - { 172, "APQ8064AA" }, - { 178, "APQ8084" }, - { 184, "APQ8074" }, - { 185, "MSM8274" }, - { 186, "MSM8674" }, - { 194, "MSM8974PRO-AC" }, - { 198, "MSM8126" }, - { 199, "APQ8026" }, - { 200, "MSM8926" }, - { 205, "MSM8326" }, - { 206, "MSM8916" }, - { 207, "MSM8994" }, - { 208, "APQ8074PRO-AA" }, - { 209, "APQ8074PRO-AB" }, - { 210, "APQ8074PRO-AC" }, - { 211, "MSM8274PRO-AA" }, - { 212, "MSM8274PRO-AB" }, - { 213, "MSM8274PRO-AC" }, - { 214, "MSM8674PRO-AA" }, - { 215, "MSM8674PRO-AB" }, - { 216, "MSM8674PRO-AC" }, - { 217, "MSM8974PRO-AA" }, - { 218, "MSM8974PRO-AB" }, - { 219, "APQ8028" }, - { 220, "MSM8128" }, - { 221, "MSM8228" }, - { 222, "MSM8528" }, - { 223, "MSM8628" }, - { 224, "MSM8928" }, - { 225, "MSM8510" }, - { 226, "MSM8512" }, - { 233, "MSM8936" }, - { 239, "MSM8939" }, - { 240, "APQ8036" }, - { 241, "APQ8039" }, - { 246, "MSM8996" }, - { 247, "APQ8016" }, - { 248, "MSM8216" }, - { 249, "MSM8116" }, - { 250, "MSM8616" }, - { 251, "MSM8992" }, - { 253, "APQ8094" }, - { 290, "MDM9607" }, - { 291, "APQ8096" }, - { 292, "MSM8998" }, - { 293, "MSM8953" }, - { 296, "MDM8207" }, - { 297, "MDM9207" }, - { 298, "MDM9307" }, - { 299, "MDM9628" }, - { 304, "APQ8053" }, - { 305, "MSM8996SG" }, - { 310, "MSM8996AU" }, - { 311, "APQ8096AU" }, - { 312, "APQ8096SG" }, - { 317, "SDM660" }, - { 318, "SDM630" }, - { 319, "APQ8098" }, - { 321, "SDM845" }, - { 322, "MDM9206" }, - { 323, "IPQ8074" }, - { 324, "SDA660" }, - { 325, "SDM658" }, - { 326, "SDA658" }, - { 327, "SDA630" }, - { 338, "SDM450" }, - { 341, "SDA845" }, - { 342, "IPQ8072" }, - { 343, "IPQ8076" }, - { 344, "IPQ8078" }, - { 345, "SDM636" }, - { 346, "SDA636" }, - { 349, "SDM632" }, - { 350, "SDA632" }, - { 351, "SDA450" }, - { 356, "SM8250" }, - { 375, "IPQ8070" }, - { 376, "IPQ8071" }, - { 389, "IPQ8072A" }, - { 390, "IPQ8074A" }, - { 391, "IPQ8076A" }, - { 392, "IPQ8078A" }, - { 394, "SM6125" }, - { 395, "IPQ8070A" }, - { 396, "IPQ8071A" }, - { 402, "IPQ6018" }, - { 403, "IPQ6028" }, - { 421, "IPQ6000" }, - { 422, "IPQ6010" }, - { 425, "SC7180" }, - { 434, "SM6350" }, - { 439, "SM8350" }, - { 449, "SC8280XP" }, - { 453, "IPQ6005" }, - { 455, "QRB5165" }, - { 457, "SM8450" }, - { 459, "SM7225" }, - { 460, "SA8295P" }, - { 461, "SA8540P" }, - { 480, "SM8450" }, - { 482, "SM8450" }, - { 487, "SC7280" }, - { 495, "SC7180P" }, - { 507, "SM6375" }, + { qcom_board_id(MSM8960) }, + { qcom_board_id(APQ8064) }, + { qcom_board_id(MSM8660A) }, + { qcom_board_id(MSM8260A) }, + { qcom_board_id(APQ8060A) }, + { qcom_board_id(MSM8974) }, + { qcom_board_id(MPQ8064) }, + { qcom_board_id(MSM8960AB) }, + { qcom_board_id(APQ8060AB) }, + { qcom_board_id(MSM8260AB) }, + { qcom_board_id(MSM8660AB) }, + { qcom_board_id(MSM8626) }, + { qcom_board_id(MSM8610) }, + { qcom_board_id(APQ8064AB) }, + { qcom_board_id(MSM8226) }, + { qcom_board_id(MSM8526) }, + { qcom_board_id(MSM8110) }, + { qcom_board_id(MSM8210) }, + { qcom_board_id(MSM8810) }, + { qcom_board_id(MSM8212) }, + { qcom_board_id(MSM8612) }, + { qcom_board_id(MSM8112) }, + { qcom_board_id(MSM8225Q) }, + { qcom_board_id(MSM8625Q) }, + { qcom_board_id(MSM8125Q) }, + { qcom_board_id(APQ8064AA) }, + { qcom_board_id(APQ8084) }, + { qcom_board_id(APQ8074) }, + { qcom_board_id(MSM8274) }, + { qcom_board_id(MSM8674) }, + { qcom_board_id_named(MSM8974PRO_AC, "MSM8974PRO-AC") }, + { qcom_board_id(MSM8126) }, + { qcom_board_id(APQ8026) }, + { qcom_board_id(MSM8926) }, + { qcom_board_id(MSM8326) }, + { qcom_board_id(MSM8916) }, + { qcom_board_id(MSM8956) }, + { qcom_board_id(MSM8976) }, + { qcom_board_id(MSM8994) }, + { qcom_board_id_named(APQ8074PRO_AA, "APQ8074PRO-AA") }, + { qcom_board_id_named(APQ8074PRO_AB, "APQ8074PRO-AB") }, + { qcom_board_id_named(APQ8074PRO_AC, "APQ8074PRO-AC") }, + { qcom_board_id_named(MSM8274PRO_AA, "MSM8274PRO-AA") }, + { qcom_board_id_named(MSM8274PRO_AB, "MSM8274PRO-AB") }, + { qcom_board_id_named(MSM8274PRO_AC, "MSM8274PRO-AC") }, + { qcom_board_id_named(MSM8674PRO_AA, "MSM8674PRO-AA") }, + { qcom_board_id_named(MSM8674PRO_AB, "MSM8674PRO-AB") }, + { qcom_board_id_named(MSM8674PRO_AC, "MSM8674PRO-AC") }, + { qcom_board_id_named(MSM8974PRO_AA, "MSM8974PRO-AA") }, + { qcom_board_id_named(MSM8974PRO_AB, "MSM8974PRO-AB") }, + { qcom_board_id(APQ8028) }, + { qcom_board_id(MSM8128) }, + { qcom_board_id(MSM8228) }, + { qcom_board_id(MSM8528) }, + { qcom_board_id(MSM8628) }, + { qcom_board_id(MSM8928) }, + { qcom_board_id(MSM8510) }, + { qcom_board_id(MSM8512) }, + { qcom_board_id(MSM8936) }, + { qcom_board_id(MSM8939) }, + { qcom_board_id(APQ8036) }, + { qcom_board_id(APQ8039) }, + { qcom_board_id(MSM8996) }, + { qcom_board_id(APQ8016) }, + { qcom_board_id(MSM8216) }, + { qcom_board_id(MSM8116) }, + { qcom_board_id(MSM8616) }, + { qcom_board_id(MSM8992) }, + { qcom_board_id(APQ8094) }, + { qcom_board_id(MDM9607) }, + { qcom_board_id(APQ8096) }, + { qcom_board_id(MSM8998) }, + { qcom_board_id(MSM8953) }, + { qcom_board_id(MDM8207) }, + { qcom_board_id(MDM9207) }, + { qcom_board_id(MDM9307) }, + { qcom_board_id(MDM9628) }, + { qcom_board_id(APQ8053) }, + { qcom_board_id(MSM8996SG) }, + { qcom_board_id(MSM8996AU) }, + { qcom_board_id(APQ8096AU) }, + { qcom_board_id(APQ8096SG) }, + { qcom_board_id(SDM660) }, + { qcom_board_id(SDM630) }, + { qcom_board_id(APQ8098) }, + { qcom_board_id(SDM845) }, + { qcom_board_id(MDM9206) }, + { qcom_board_id(IPQ8074) }, + { qcom_board_id(SDA660) }, + { qcom_board_id(SDM658) }, + { qcom_board_id(SDA658) }, + { qcom_board_id(SDA630) }, + { qcom_board_id(SDM450) }, + { qcom_board_id(SM8150) }, + { qcom_board_id(SDA845) }, + { qcom_board_id(IPQ8072) }, + { qcom_board_id(IPQ8076) }, + { qcom_board_id(IPQ8078) }, + { qcom_board_id(SDM636) }, + { qcom_board_id(SDA636) }, + { qcom_board_id(SDM632) }, + { qcom_board_id(SDA632) }, + { qcom_board_id(SDA450) }, + { qcom_board_id(SM8250) }, + { qcom_board_id(SA8155) }, + { qcom_board_id(IPQ8070) }, + { qcom_board_id(IPQ8071) }, + { qcom_board_id(IPQ8072A) }, + { qcom_board_id(IPQ8074A) }, + { qcom_board_id(IPQ8076A) }, + { qcom_board_id(IPQ8078A) }, + { qcom_board_id(SM6125) }, + { qcom_board_id(IPQ8070A) }, + { qcom_board_id(IPQ8071A) }, + { qcom_board_id(IPQ6018) }, + { qcom_board_id(IPQ6028) }, + { qcom_board_id(SM4250) }, + { qcom_board_id(IPQ6000) }, + { qcom_board_id(IPQ6010) }, + { qcom_board_id(SC7180) }, + { qcom_board_id(SM6350) }, + { qcom_board_id(SM8350) }, + { qcom_board_id(SM6115) }, + { qcom_board_id(SC8280XP) }, + { qcom_board_id(IPQ6005) }, + { qcom_board_id(QRB5165) }, + { qcom_board_id(SM8450) }, + { qcom_board_id(SM8550) }, + { qcom_board_id(SM7225) }, + { qcom_board_id(SA8295P) }, + { qcom_board_id(SA8540P) }, + { qcom_board_id(QCM4290) }, + { qcom_board_id(QCS4290) }, + { qcom_board_id_named(SM8450_2, "SM8450") }, + { qcom_board_id_named(SM8450_3, "SM8450") }, + { qcom_board_id(SC7280) }, + { qcom_board_id(SC7180P) }, + { qcom_board_id(SM6375) }, + { qcom_board_id(QRU1000) }, + { qcom_board_id(QDU1000) }, + { qcom_board_id(QDU1010) }, + { qcom_board_id(QRU1032) }, + { qcom_board_id(QRU1052) }, + { qcom_board_id(QRU1062) }, }; static const char *socinfo_machine(struct device *dev, unsigned int id) diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c index 484b42b7454e..a6cbeb40831b 100644 --- a/drivers/soc/qcom/spm.c +++ b/drivers/soc/qcom/spm.c @@ -98,6 +98,46 @@ static const struct spm_reg_data spm_reg_8916_cpu = { .start_index[PM_SLEEP_MODE_SPC] = 5, }; +static const struct spm_reg_data spm_reg_8939_cpu = { + .reg_offset = spm_reg_offset_v3_0, + .spm_cfg = 0x1, + .spm_dly = 0x3C102800, + .seq = { 0x60, 0x03, 0x60, 0x0B, 0x0F, 0x20, 0x50, 0x1B, 0x10, 0x80, + 0x30, 0x90, 0x5B, 0x60, 0x50, 0x03, 0x60, 0x76, 0x76, 0x0B, + 0x50, 0x1B, 0x94, 0x5B, 0x80, 0x10, 0x26, 0x30, 0x50, 0x0F }, + .start_index[PM_SLEEP_MODE_STBY] = 0, + .start_index[PM_SLEEP_MODE_SPC] = 5, +}; + +static const u16 spm_reg_offset_v2_3[SPM_REG_NR] = { + [SPM_REG_CFG] = 0x08, + [SPM_REG_SPM_CTL] = 0x30, + [SPM_REG_DLY] = 0x34, + [SPM_REG_PMIC_DATA_0] = 0x40, + [SPM_REG_PMIC_DATA_1] = 0x44, +}; + +/* SPM register data for 8976 */ +static const struct spm_reg_data spm_reg_8976_gold_l2 = { + .reg_offset = spm_reg_offset_v2_3, + .spm_cfg = 0x14, + .spm_dly = 0x3c11840a, + .pmic_data[0] = 0x03030080, + .pmic_data[1] = 0x00030000, + .start_index[PM_SLEEP_MODE_STBY] = 0, + .start_index[PM_SLEEP_MODE_SPC] = 3, +}; + +static const struct spm_reg_data spm_reg_8976_silver_l2 = { + .reg_offset = spm_reg_offset_v2_3, + .spm_cfg = 0x14, + .spm_dly = 0x3c102800, + .pmic_data[0] = 0x03030080, + .pmic_data[1] = 0x00030000, + .start_index[PM_SLEEP_MODE_STBY] = 0, + .start_index[PM_SLEEP_MODE_SPC] = 2, +}; + static const u16 spm_reg_offset_v2_1[SPM_REG_NR] = { [SPM_REG_CFG] = 0x08, [SPM_REG_SPM_CTL] = 0x30, @@ -211,8 +251,14 @@ static const struct of_device_id spm_match_table[] = { .data = &spm_reg_8909_cpu }, { .compatible = "qcom,msm8916-saw2-v3.0-cpu", .data = &spm_reg_8916_cpu }, + { .compatible = "qcom,msm8939-saw2-v3.0-cpu", + .data = &spm_reg_8939_cpu }, { .compatible = "qcom,msm8974-saw2-v2.1-cpu", .data = &spm_reg_8974_8084_cpu }, + { .compatible = "qcom,msm8976-gold-saw2-v2.3-l2", + .data = &spm_reg_8976_gold_l2 }, + { .compatible = "qcom,msm8976-silver-saw2-v2.3-l2", + .data = &spm_reg_8976_silver_l2 }, { .compatible = "qcom,msm8998-gold-saw2-v4.1-l2", .data = &spm_reg_8998_gold_l2 }, { .compatible = "qcom,msm8998-silver-saw2-v4.1-l2", diff --git a/drivers/soc/qcom/trace-rpmh.h b/drivers/soc/qcom/trace-rpmh.h index feb0cb455e37..12b676b20cb2 100644 --- a/drivers/soc/qcom/trace-rpmh.h +++ b/drivers/soc/qcom/trace-rpmh.h @@ -14,16 +14,15 @@ TRACE_EVENT(rpmh_tx_done, - TP_PROTO(struct rsc_drv *d, int m, const struct tcs_request *r, int e), + TP_PROTO(struct rsc_drv *d, int m, const struct tcs_request *r), - TP_ARGS(d, m, r, e), + TP_ARGS(d, m, r), TP_STRUCT__entry( __string(name, d->name) __field(int, m) __field(u32, addr) __field(u32, data) - __field(int, err) ), TP_fast_assign( @@ -31,12 +30,10 @@ TRACE_EVENT(rpmh_tx_done, __entry->m = m; __entry->addr = r->cmds[0].addr; __entry->data = r->cmds[0].data; - __entry->err = e; ), - TP_printk("%s: ack: tcs-m: %d addr: %#x data: %#x errno: %d", - __get_str(name), __entry->m, __entry->addr, __entry->data, - __entry->err) + TP_printk("%s: ack: tcs-m: %d addr: %#x data: %#x", + __get_str(name), __entry->m, __entry->addr, __entry->data) ); TRACE_EVENT(rpmh_send_msg, 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, diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig index 7e2fb1c16af1..e009d9589af4 100644 --- a/drivers/soc/ti/Kconfig +++ b/drivers/soc/ti/Kconfig @@ -63,7 +63,7 @@ config TI_SCI_PM_DOMAINS rootfs may be available. config TI_K3_RINGACC - bool "K3 Ring accelerator Sub System" + tristate "K3 Ring accelerator Sub System" depends on ARCH_K3 || COMPILE_TEST depends on TI_SCI_INTA_IRQCHIP help diff --git a/drivers/soc/ti/k3-ringacc.c b/drivers/soc/ti/k3-ringacc.c index f7bf18b8229a..e01e4d815230 100644 --- a/drivers/soc/ti/k3-ringacc.c +++ b/drivers/soc/ti/k3-ringacc.c @@ -7,7 +7,7 @@ #include <linux/dma-mapping.h> #include <linux/io.h> -#include <linux/init.h> +#include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/platform_device.h> @@ -336,6 +336,9 @@ struct k3_ring *k3_ringacc_request_ring(struct k3_ringacc *ringacc, mutex_lock(&ringacc->req_lock); + if (!try_module_get(ringacc->dev->driver->owner)) + goto err_module_get; + if (id == K3_RINGACC_RING_ID_ANY) { /* Request for any general purpose ring */ struct ti_sci_resource_desc *gp_rings = @@ -380,6 +383,9 @@ out: return &ringacc->rings[id]; error: + module_put(ringacc->dev->driver->owner); + +err_module_get: mutex_unlock(&ringacc->req_lock); return NULL; } @@ -616,6 +622,8 @@ int k3_ringacc_ring_free(struct k3_ring *ring) no_init: clear_bit(ring->ring_id, ringacc->rings_inuse); + module_put(ringacc->dev->driver->owner); + out: mutex_unlock(&ringacc->req_lock); return 0; @@ -1450,6 +1458,7 @@ static const struct of_device_id k3_ringacc_of_match[] = { { .compatible = "ti,am654-navss-ringacc", .data = &k3_ringacc_data, }, {}, }; +MODULE_DEVICE_TABLE(of, k3_ringacc_of_match); struct k3_ringacc *k3_ringacc_dmarings_init(struct platform_device *pdev, struct k3_ringacc_init_data *data) @@ -1544,12 +1553,27 @@ static int k3_ringacc_probe(struct platform_device *pdev) return 0; } +static int k3_ringacc_remove(struct platform_device *pdev) +{ + struct k3_ringacc *ringacc = dev_get_drvdata(&pdev->dev); + + mutex_lock(&k3_ringacc_list_lock); + list_del(&ringacc->list); + mutex_unlock(&k3_ringacc_list_lock); + return 0; +} + static struct platform_driver k3_ringacc_driver = { .probe = k3_ringacc_probe, + .remove = k3_ringacc_remove, .driver = { .name = "k3-ringacc", .of_match_table = k3_ringacc_of_match, .suppress_bind_attrs = true, }, }; -builtin_platform_driver(k3_ringacc_driver); +module_platform_driver(k3_ringacc_driver); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("TI Ringacc driver for K3 SOCs"); +MODULE_AUTHOR("Grygorii Strashko <grygorii.strashko@ti.com>"); diff --git a/drivers/soc/ti/k3-socinfo.c b/drivers/soc/ti/k3-socinfo.c index 91f441ee6175..d15764e19d96 100644 --- a/drivers/soc/ti/k3-socinfo.c +++ b/drivers/soc/ti/k3-socinfo.c @@ -43,6 +43,7 @@ static const struct k3_soc_id { { 0xBB38, "AM64X" }, { 0xBB75, "J721S2"}, { 0xBB7E, "AM62X" }, + { 0xBB8D, "AM62AX" }, }; static int diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c index 92af7d1b6f5b..8fb76908be70 100644 --- a/drivers/soc/ti/knav_qmss_queue.c +++ b/drivers/soc/ti/knav_qmss_queue.c @@ -67,7 +67,7 @@ static DEFINE_MUTEX(knav_dev_lock); * Newest followed by older ones. Search is done from start of the array * until a firmware file is found. */ -const char *knav_acc_firmwares[] = {"ks2_qmss_pdsp_acc48.bin"}; +static const char * const knav_acc_firmwares[] = {"ks2_qmss_pdsp_acc48.bin"}; static bool device_ready; bool knav_qmss_device_ready(void) @@ -1785,6 +1785,7 @@ static int knav_queue_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) { + pm_runtime_disable(&pdev->dev); dev_err(dev, "Failed to enable QMSS\n"); return ret; } diff --git a/drivers/soc/ti/smartreflex.c b/drivers/soc/ti/smartreflex.c index ad2bb72e640c..6a389a6444f3 100644 --- a/drivers/soc/ti/smartreflex.c +++ b/drivers/soc/ti/smartreflex.c @@ -932,6 +932,7 @@ static int omap_sr_probe(struct platform_device *pdev) err_debugfs: debugfs_remove_recursive(sr_info->dbg_dir); err_list_del: + pm_runtime_disable(&pdev->dev); list_del(&sr_info->node); clk_unprepare(sr_info->fck); |