aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-12-31 20:32:35 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-12-31 20:32:35 -0500
commitd36377c6eb071e3d0751e9e0e3c19198c58d9a5d (patch)
treebf1d28abd5fac5c826079c4b760ca34263f0fab4 /drivers
parent0922275ef157ba8ac93e7e7857087eb0442d5397 (diff)
parenta6f119a06960ef1dc30570401e43b71f9ebdd2c2 (diff)
Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC driver updates from Olof Johansson: "Misc driver updates for platforms, many of them power related. - Rockchip adds power domain support for rk3066 and rk3188 - Amlogic adds a power measurement driver - Allwinner adds SRAM support for three platforms (F1C100, H5, A64 C1) - Wakeup and ti-sysc (platform bus) fixes for OMAP/DRA7 - Broadcom fixes suspend/resume with Thumb2 kernels, and improves stability of a handful of firmware/platform interfaces - PXA completes their conversion to dmaengine framework - Renesas does a bunch of PM cleanups across many platforms - Tegra adds support for suspend/resume on T186/T194, which includes some driver cleanups and addition of wake events - Tegra also adds a driver for memory controller (EMC) on Tegra2 - i.MX tweaks power domain bindings, and adds support for i.MX8MQ in GPC - Atmel adds identifiers and LPDDR2 support for a new SoC, SAM9X60 and misc cleanups across several platforms" * tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (73 commits) ARM: at91: add support in soc driver for new SAM9X60 ARM: at91: add support in soc driver for LPDDR2 SiP memory: omap-gpmc: Use of_node_name_eq for node name comparisons bus: ti-sysc: Check for no-reset and no-idle flags at the child level ARM: OMAP2+: Check also the first dts child for hwmod flags soc: amlogic: meson-clk-measure: Add missing REGMAP_MMIO dependency soc: imx: gpc: Increase GPC_CLK_MAX to 7 soc: renesas: rcar-sysc: Fix power domain control after system resume soc: renesas: rcar-sysc: Merge PM Domain registration and linking soc: renesas: rcar-sysc: Remove rcar_sysc_power_{down,up}() helpers soc: renesas: r8a77990-sysc: Fix initialization order of 3DG-{A,B} dt-bindings: sram: sunxi: Add compatible for the A64 SRAM C1 dt-bindings: sram: sunxi: Add bindings for the H5 with SRAM C1 dt-bindings: sram: Add Allwinner suniv F1C100s soc: sunxi: sram: Add support for the H5 SoC system control soc: sunxi: sram: Enable EMAC clock access for H3 variant soc: imx: gpcv2: add support for i.MX8MQ SoC soc: imx: gpcv2: move register access table to domain data soc: imx: gpcv2: prefix i.MX7 specific defines dmaengine: pxa: make the filter function internal ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/bus/brcmstb_gisb.c12
-rw-r--r--drivers/bus/ti-sysc.c55
-rw-r--r--drivers/dma/pxa_dma.c5
-rw-r--r--drivers/firmware/imx/Kconfig6
-rw-r--r--drivers/firmware/imx/Makefile3
-rw-r--r--drivers/firmware/imx/scu-pd.c339
-rw-r--r--drivers/firmware/raspberrypi.c48
-rw-r--r--drivers/firmware/tegra/bpmp-debugfs.c29
-rw-r--r--drivers/firmware/tegra/bpmp.c77
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.c59
-rw-r--r--drivers/memory/omap-gpmc.c8
-rw-r--r--drivers/memory/tegra/Kconfig10
-rw-r--r--drivers/memory/tegra/Makefile1
-rw-r--r--drivers/memory/tegra/tegra20-emc.c591
-rw-r--r--drivers/soc/Makefile2
-rw-r--r--drivers/soc/amlogic/Kconfig9
-rw-r--r--drivers/soc/amlogic/Makefile1
-rw-r--r--drivers/soc/amlogic/meson-clk-measure.c350
-rw-r--r--drivers/soc/atmel/soc.c10
-rw-r--r--drivers/soc/atmel/soc.h7
-rw-r--r--drivers/soc/bcm/brcmstb/common.c6
-rw-r--r--drivers/soc/bcm/brcmstb/pm/pm-arm.c2
-rw-r--r--drivers/soc/bcm/raspberrypi-power.c5
-rw-r--r--drivers/soc/imx/Kconfig6
-rw-r--r--drivers/soc/imx/Makefile2
-rw-r--r--drivers/soc/imx/gpc.c2
-rw-r--r--drivers/soc/imx/gpcv2.c296
-rw-r--r--drivers/soc/mediatek/Kconfig12
-rw-r--r--drivers/soc/mediatek/Makefile1
-rw-r--r--drivers/soc/mediatek/mtk-cmdq-helper.c300
-rw-r--r--drivers/soc/qcom/Kconfig5
-rw-r--r--drivers/soc/qcom/cmd-db.c93
-rw-r--r--drivers/soc/qcom/llcc-slice.c17
-rw-r--r--drivers/soc/qcom/qcom-geni-se.c25
-rw-r--r--drivers/soc/qcom/qmi_interface.c2
-rw-r--r--drivers/soc/qcom/smd-rpm.c1
-rw-r--r--drivers/soc/renesas/r8a77965-sysc.c1
-rw-r--r--drivers/soc/renesas/r8a77970-sysc.c5
-rw-r--r--drivers/soc/renesas/r8a77980-sysc.c10
-rw-r--r--drivers/soc/renesas/r8a77990-sysc.c23
-rw-r--r--drivers/soc/renesas/rcar-sysc.c65
-rw-r--r--drivers/soc/rockchip/pm_domains.c48
-rw-r--r--drivers/soc/sunxi/sunxi_sram.c22
-rw-r--r--drivers/soc/tegra/common.c6
-rw-r--r--drivers/soc/tegra/pmc.c472
-rw-r--r--drivers/soc/ti/wkup_m3_ipc.c1
46 files changed, 2668 insertions, 382 deletions
diff --git a/drivers/bus/brcmstb_gisb.c b/drivers/bus/brcmstb_gisb.c
index 68ac3e93b600..f58ff67e97ac 100644
--- a/drivers/bus/brcmstb_gisb.c
+++ b/drivers/bus/brcmstb_gisb.c
@@ -150,8 +150,7 @@ static ssize_t gisb_arb_get_timeout(struct device *dev,
150 struct device_attribute *attr, 150 struct device_attribute *attr,
151 char *buf) 151 char *buf)
152{ 152{
153 struct platform_device *pdev = to_platform_device(dev); 153 struct brcmstb_gisb_arb_device *gdev = dev_get_drvdata(dev);
154 struct brcmstb_gisb_arb_device *gdev = platform_get_drvdata(pdev);
155 u32 timeout; 154 u32 timeout;
156 155
157 mutex_lock(&gdev->lock); 156 mutex_lock(&gdev->lock);
@@ -165,8 +164,7 @@ static ssize_t gisb_arb_set_timeout(struct device *dev,
165 struct device_attribute *attr, 164 struct device_attribute *attr,
166 const char *buf, size_t count) 165 const char *buf, size_t count)
167{ 166{
168 struct platform_device *pdev = to_platform_device(dev); 167 struct brcmstb_gisb_arb_device *gdev = dev_get_drvdata(dev);
169 struct brcmstb_gisb_arb_device *gdev = platform_get_drvdata(pdev);
170 int val, ret; 168 int val, ret;
171 169
172 ret = kstrtoint(buf, 10, &val); 170 ret = kstrtoint(buf, 10, &val);
@@ -418,8 +416,7 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev)
418#ifdef CONFIG_PM_SLEEP 416#ifdef CONFIG_PM_SLEEP
419static int brcmstb_gisb_arb_suspend(struct device *dev) 417static int brcmstb_gisb_arb_suspend(struct device *dev)
420{ 418{
421 struct platform_device *pdev = to_platform_device(dev); 419 struct brcmstb_gisb_arb_device *gdev = dev_get_drvdata(dev);
422 struct brcmstb_gisb_arb_device *gdev = platform_get_drvdata(pdev);
423 420
424 gdev->saved_timeout = gisb_read(gdev, ARB_TIMER); 421 gdev->saved_timeout = gisb_read(gdev, ARB_TIMER);
425 422
@@ -431,8 +428,7 @@ static int brcmstb_gisb_arb_suspend(struct device *dev)
431 */ 428 */
432static int brcmstb_gisb_arb_resume_noirq(struct device *dev) 429static int brcmstb_gisb_arb_resume_noirq(struct device *dev)
433{ 430{
434 struct platform_device *pdev = to_platform_device(dev); 431 struct brcmstb_gisb_arb_device *gdev = dev_get_drvdata(dev);
435 struct brcmstb_gisb_arb_device *gdev = platform_get_drvdata(pdev);
436 432
437 gisb_write(gdev, gdev->saved_timeout, ARB_TIMER); 433 gisb_write(gdev, gdev->saved_timeout, ARB_TIMER);
438 434
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
index a3a2d39280d9..f94d33525771 100644
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -91,6 +91,9 @@ struct sysc {
91 struct delayed_work idle_work; 91 struct delayed_work idle_work;
92}; 92};
93 93
94static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np,
95 bool is_child);
96
94void sysc_write(struct sysc *ddata, int offset, u32 value) 97void sysc_write(struct sysc *ddata, int offset, u32 value)
95{ 98{
96 writel_relaxed(value, ddata->module_va + offset); 99 writel_relaxed(value, ddata->module_va + offset);
@@ -214,8 +217,13 @@ static int sysc_get_clocks(struct sysc *ddata)
214 if (!ddata->clocks) 217 if (!ddata->clocks)
215 return -ENOMEM; 218 return -ENOMEM;
216 219
217 for (i = 0; i < ddata->nr_clocks; i++) { 220 for (i = 0; i < SYSC_MAX_CLOCKS; i++) {
218 error = sysc_get_one_clock(ddata, ddata->clock_roles[i]); 221 const char *name = ddata->clock_roles[i];
222
223 if (!name)
224 continue;
225
226 error = sysc_get_one_clock(ddata, name);
219 if (error && error != -ENOENT) 227 if (error && error != -ENOENT)
220 return error; 228 return error;
221 } 229 }
@@ -374,6 +382,7 @@ static int sysc_check_one_child(struct sysc *ddata,
374 dev_warn(ddata->dev, "really a child ti,hwmods property?"); 382 dev_warn(ddata->dev, "really a child ti,hwmods property?");
375 383
376 sysc_check_quirk_stdout(ddata, np); 384 sysc_check_quirk_stdout(ddata, np);
385 sysc_parse_dts_quirks(ddata, np, true);
377 386
378 return 0; 387 return 0;
379} 388}
@@ -815,6 +824,7 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
815 SYSC_QUIRK("ocp2scp", 0, 0, 0x10, 0x14, 0x50060005, 0xfffffff0, 0), 824 SYSC_QUIRK("ocp2scp", 0, 0, 0x10, 0x14, 0x50060005, 0xfffffff0, 0),
816 SYSC_QUIRK("ocp2scp", 0, 0, -1, -1, 0x50060007, 0xffffffff, 0), 825 SYSC_QUIRK("ocp2scp", 0, 0, -1, -1, 0x50060007, 0xffffffff, 0),
817 SYSC_QUIRK("padconf", 0, 0, 0x10, -1, 0x4fff0800, 0xffffffff, 0), 826 SYSC_QUIRK("padconf", 0, 0, 0x10, -1, 0x4fff0800, 0xffffffff, 0),
827 SYSC_QUIRK("padconf", 0, 0, -1, -1, 0x40001100, 0xffffffff, 0),
818 SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000100, 0xffffffff, 0), 828 SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000100, 0xffffffff, 0),
819 SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x00004102, 0xffffffff, 0), 829 SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x00004102, 0xffffffff, 0),
820 SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000400, 0xffffffff, 0), 830 SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000400, 0xffffffff, 0),
@@ -833,7 +843,9 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
833 SYSC_QUIRK("rtc", 0, 0x74, 0x78, -1, 0x4eb01908, 0xffff00f0, 0), 843 SYSC_QUIRK("rtc", 0, 0x74, 0x78, -1, 0x4eb01908, 0xffff00f0, 0),
834 SYSC_QUIRK("timer32k", 0, 0, 0x4, -1, 0x00000060, 0xffffffff, 0), 844 SYSC_QUIRK("timer32k", 0, 0, 0x4, -1, 0x00000060, 0xffffffff, 0),
835 SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000004, 0xffffffff, 0), 845 SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000004, 0xffffffff, 0),
846 SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000008, 0xffffffff, 0),
836 SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, 0x14, 0x50700100, 0xffffffff, 0), 847 SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, 0x14, 0x50700100, 0xffffffff, 0),
848 SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, -1, 0x50700101, 0xffffffff, 0),
837 SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050, 849 SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050,
838 0xffffffff, 0), 850 0xffffffff, 0),
839 SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, 0), 851 SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, 0),
@@ -1271,23 +1283,37 @@ static const struct sysc_dts_quirk sysc_dts_quirks[] = {
1271 .mask = SYSC_QUIRK_NO_RESET_ON_INIT, }, 1283 .mask = SYSC_QUIRK_NO_RESET_ON_INIT, },
1272}; 1284};
1273 1285
1274static int sysc_init_dts_quirks(struct sysc *ddata) 1286static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np,
1287 bool is_child)
1275{ 1288{
1276 struct device_node *np = ddata->dev->of_node;
1277 const struct property *prop; 1289 const struct property *prop;
1278 int i, len, error; 1290 int i, len;
1279 u32 val;
1280
1281 ddata->legacy_mode = of_get_property(np, "ti,hwmods", NULL);
1282 1291
1283 for (i = 0; i < ARRAY_SIZE(sysc_dts_quirks); i++) { 1292 for (i = 0; i < ARRAY_SIZE(sysc_dts_quirks); i++) {
1284 prop = of_get_property(np, sysc_dts_quirks[i].name, &len); 1293 const char *name = sysc_dts_quirks[i].name;
1294
1295 prop = of_get_property(np, name, &len);
1285 if (!prop) 1296 if (!prop)
1286 continue; 1297 continue;
1287 1298
1288 ddata->cfg.quirks |= sysc_dts_quirks[i].mask; 1299 ddata->cfg.quirks |= sysc_dts_quirks[i].mask;
1300 if (is_child) {
1301 dev_warn(ddata->dev,
1302 "dts flag should be at module level for %s\n",
1303 name);
1304 }
1289 } 1305 }
1306}
1290 1307
1308static int sysc_init_dts_quirks(struct sysc *ddata)
1309{
1310 struct device_node *np = ddata->dev->of_node;
1311 int error;
1312 u32 val;
1313
1314 ddata->legacy_mode = of_get_property(np, "ti,hwmods", NULL);
1315
1316 sysc_parse_dts_quirks(ddata, np, false);
1291 error = of_property_read_u32(np, "ti,sysc-delay-us", &val); 1317 error = of_property_read_u32(np, "ti,sysc-delay-us", &val);
1292 if (!error) { 1318 if (!error) {
1293 if (val > 255) { 1319 if (val > 255) {
@@ -1498,6 +1524,16 @@ static const struct sysc_regbits sysc_regbits_omap4_mcasp = {
1498static const struct sysc_capabilities sysc_omap4_mcasp = { 1524static const struct sysc_capabilities sysc_omap4_mcasp = {
1499 .type = TI_SYSC_OMAP4_MCASP, 1525 .type = TI_SYSC_OMAP4_MCASP,
1500 .regbits = &sysc_regbits_omap4_mcasp, 1526 .regbits = &sysc_regbits_omap4_mcasp,
1527 .mod_quirks = SYSC_QUIRK_OPT_CLKS_NEEDED,
1528};
1529
1530/*
1531 * McASP found on dra7 and later
1532 */
1533static const struct sysc_capabilities sysc_dra7_mcasp = {
1534 .type = TI_SYSC_OMAP4_SIMPLE,
1535 .regbits = &sysc_regbits_omap4_simple,
1536 .mod_quirks = SYSC_QUIRK_OPT_CLKS_NEEDED,
1501}; 1537};
1502 1538
1503/* 1539/*
@@ -1726,6 +1762,7 @@ static const struct of_device_id sysc_match[] = {
1726 { .compatible = "ti,sysc-omap3-sham", .data = &sysc_omap3_sham, }, 1762 { .compatible = "ti,sysc-omap3-sham", .data = &sysc_omap3_sham, },
1727 { .compatible = "ti,sysc-omap-aes", .data = &sysc_omap3_aes, }, 1763 { .compatible = "ti,sysc-omap-aes", .data = &sysc_omap3_aes, },
1728 { .compatible = "ti,sysc-mcasp", .data = &sysc_omap4_mcasp, }, 1764 { .compatible = "ti,sysc-mcasp", .data = &sysc_omap4_mcasp, },
1765 { .compatible = "ti,sysc-dra7-mcasp", .data = &sysc_dra7_mcasp, },
1729 { .compatible = "ti,sysc-usb-host-fs", 1766 { .compatible = "ti,sysc-usb-host-fs",
1730 .data = &sysc_omap4_usb_host_fs, }, 1767 .data = &sysc_omap4_usb_host_fs, },
1731 { .compatible = "ti,sysc-dra7-mcan", .data = &sysc_dra7_mcan, }, 1768 { .compatible = "ti,sysc-dra7-mcan", .data = &sysc_dra7_mcan, },
diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c
index 825725057e00..c7a328f81485 100644
--- a/drivers/dma/pxa_dma.c
+++ b/drivers/dma/pxa_dma.c
@@ -179,7 +179,7 @@ static unsigned int pxad_drcmr(unsigned int line)
179 return 0x1000 + line * 4; 179 return 0x1000 + line * 4;
180} 180}
181 181
182bool pxad_filter_fn(struct dma_chan *chan, void *param); 182static bool pxad_filter_fn(struct dma_chan *chan, void *param);
183 183
184/* 184/*
185 * Debug fs 185 * Debug fs
@@ -1500,7 +1500,7 @@ static struct platform_driver pxad_driver = {
1500 .remove = pxad_remove, 1500 .remove = pxad_remove,
1501}; 1501};
1502 1502
1503bool pxad_filter_fn(struct dma_chan *chan, void *param) 1503static bool pxad_filter_fn(struct dma_chan *chan, void *param)
1504{ 1504{
1505 struct pxad_chan *c = to_pxad_chan(chan); 1505 struct pxad_chan *c = to_pxad_chan(chan);
1506 struct pxad_param *p = param; 1506 struct pxad_param *p = param;
@@ -1513,7 +1513,6 @@ bool pxad_filter_fn(struct dma_chan *chan, void *param)
1513 1513
1514 return true; 1514 return true;
1515} 1515}
1516EXPORT_SYMBOL_GPL(pxad_filter_fn);
1517 1516
1518module_platform_driver(pxad_driver); 1517module_platform_driver(pxad_driver);
1519 1518
diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig
index b170c2851e48..6a7a7c2c5b5f 100644
--- a/drivers/firmware/imx/Kconfig
+++ b/drivers/firmware/imx/Kconfig
@@ -9,3 +9,9 @@ config IMX_SCU
9 9
10 This driver manages the IPC interface between host CPU and the 10 This driver manages the IPC interface between host CPU and the
11 SCU firmware running on M4. 11 SCU firmware running on M4.
12
13config IMX_SCU_PD
14 bool "IMX SCU Power Domain driver"
15 depends on IMX_SCU
16 help
17 The System Controller Firmware (SCFW) based power domain driver.
diff --git a/drivers/firmware/imx/Makefile b/drivers/firmware/imx/Makefile
index 0ac04dfda8d4..1b2e15b3c9ca 100644
--- a/drivers/firmware/imx/Makefile
+++ b/drivers/firmware/imx/Makefile
@@ -1,2 +1,3 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2obj-$(CONFIG_IMX_SCU) += imx-scu.o misc.o 2obj-$(CONFIG_IMX_SCU) += imx-scu.o misc.o
3obj-$(CONFIG_IMX_SCU_PD) += scu-pd.o
diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c
new file mode 100644
index 000000000000..407245f2efd0
--- /dev/null
+++ b/drivers/firmware/imx/scu-pd.c
@@ -0,0 +1,339 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2016 Freescale Semiconductor, Inc.
4 * Copyright 2017-2018 NXP
5 * Dong Aisheng <aisheng.dong@nxp.com>
6 *
7 * Implementation of the SCU based Power Domains
8 *
9 * NOTE: a better implementation suggested by Ulf Hansson is using a
10 * single global power domain and implement the ->attach|detach_dev()
11 * callback for the genpd and use the regular of_genpd_add_provider_simple().
12 * From within the ->attach_dev(), we could get the OF node for
13 * the device that is being attached and then parse the power-domain
14 * cell containing the "resource id" and store that in the per device
15 * struct generic_pm_domain_data (we have void pointer there for
16 * storing these kind of things).
17 *
18 * Additionally, we need to implement the ->stop() and ->start()
19 * callbacks of genpd, which is where you "power on/off" devices,
20 * rather than using the above ->power_on|off() callbacks.
21 *
22 * However, there're two known issues:
23 * 1. The ->attach_dev() of power domain infrastructure still does
24 * not support multi domains case as the struct device *dev passed
25 * in is a virtual PD device, it does not help for parsing the real
26 * device resource id from device tree, so it's unware of which
27 * real sub power domain of device should be attached.
28 *
29 * The framework needs some proper extension to support multi power
30 * domain cases.
31 *
32 * 2. It also breaks most of current drivers as the driver probe sequence
33 * behavior changed if removing ->power_on|off() callback and use
34 * ->start() and ->stop() instead. genpd_dev_pm_attach will only power
35 * up the domain and attach device, but will not call .start() which
36 * relies on device runtime pm. That means the device power is still
37 * not up before running driver probe function. For SCU enabled
38 * platforms, all device drivers accessing registers/clock without power
39 * domain enabled will trigger a HW access error. That means we need fix
40 * most drivers probe sequence with proper runtime pm.
41 *
42 * In summary, we need fix above two issue before being able to switch to
43 * the "single global power domain" way.
44 *
45 */
46
47#include <dt-bindings/firmware/imx/rsrc.h>
48#include <linux/firmware/imx/sci.h>
49#include <linux/io.h>
50#include <linux/module.h>
51#include <linux/of.h>
52#include <linux/of_address.h>
53#include <linux/of_platform.h>
54#include <linux/platform_device.h>
55#include <linux/pm.h>
56#include <linux/pm_domain.h>
57#include <linux/slab.h>
58
59/* SCU Power Mode Protocol definition */
60struct imx_sc_msg_req_set_resource_power_mode {
61 struct imx_sc_rpc_msg hdr;
62 u16 resource;
63 u8 mode;
64} __packed;
65
66#define IMX_SCU_PD_NAME_SIZE 20
67struct imx_sc_pm_domain {
68 struct generic_pm_domain pd;
69 char name[IMX_SCU_PD_NAME_SIZE];
70 u32 rsrc;
71};
72
73struct imx_sc_pd_range {
74 char *name;
75 u32 rsrc;
76 u8 num;
77 bool postfix;
78};
79
80struct imx_sc_pd_soc {
81 const struct imx_sc_pd_range *pd_ranges;
82 u8 num_ranges;
83};
84
85static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
86 /* LSIO SS */
87 { "lsio-pwm", IMX_SC_R_PWM_0, 8, 1 },
88 { "lsio-gpio", IMX_SC_R_GPIO_0, 8, 1 },
89 { "lsio-gpt", IMX_SC_R_GPT_0, 5, 1 },
90 { "lsio-kpp", IMX_SC_R_KPP, 1, 0 },
91 { "lsio-fspi", IMX_SC_R_FSPI_0, 2, 1 },
92 { "lsio-mu", IMX_SC_R_MU_0A, 14, 1 },
93
94 /* CONN SS */
95 { "con-usb", IMX_SC_R_USB_0, 2, 1 },
96 { "con-usb0phy", IMX_SC_R_USB_0_PHY, 1, 0 },
97 { "con-usb2", IMX_SC_R_USB_2, 1, 0 },
98 { "con-usb2phy", IMX_SC_R_USB_2_PHY, 1, 0 },
99 { "con-sdhc", IMX_SC_R_SDHC_0, 3, 1 },
100 { "con-enet", IMX_SC_R_ENET_0, 2, 1 },
101 { "con-nand", IMX_SC_R_NAND, 1, 0 },
102 { "con-mlb", IMX_SC_R_MLB_0, 1, 1 },
103
104 /* Audio DMA SS */
105 { "adma-audio-pll0", IMX_SC_R_AUDIO_PLL_0, 1, 0 },
106 { "adma-audio-pll1", IMX_SC_R_AUDIO_PLL_1, 1, 0 },
107 { "adma-audio-clk-0", IMX_SC_R_AUDIO_CLK_0, 1, 0 },
108 { "adma-dma0-ch", IMX_SC_R_DMA_0_CH0, 16, 1 },
109 { "adma-dma1-ch", IMX_SC_R_DMA_1_CH0, 16, 1 },
110 { "adma-dma2-ch", IMX_SC_R_DMA_2_CH0, 5, 1 },
111 { "adma-asrc0", IMX_SC_R_ASRC_0, 1, 0 },
112 { "adma-asrc1", IMX_SC_R_ASRC_1, 1, 0 },
113 { "adma-esai0", IMX_SC_R_ESAI_0, 1, 0 },
114 { "adma-spdif0", IMX_SC_R_SPDIF_0, 1, 0 },
115 { "adma-sai", IMX_SC_R_SAI_0, 3, 1 },
116 { "adma-amix", IMX_SC_R_AMIX, 1, 0 },
117 { "adma-mqs0", IMX_SC_R_MQS_0, 1, 0 },
118 { "adma-dsp", IMX_SC_R_DSP, 1, 0 },
119 { "adma-dsp-ram", IMX_SC_R_DSP_RAM, 1, 0 },
120 { "adma-can", IMX_SC_R_CAN_0, 3, 1 },
121 { "adma-ftm", IMX_SC_R_FTM_0, 2, 1 },
122 { "adma-lpi2c", IMX_SC_R_I2C_0, 4, 1 },
123 { "adma-adc", IMX_SC_R_ADC_0, 1, 1 },
124 { "adma-lcd", IMX_SC_R_LCD_0, 1, 1 },
125 { "adma-lcd0-pwm", IMX_SC_R_LCD_0_PWM_0, 1, 1 },
126 { "adma-lpuart", IMX_SC_R_UART_0, 4, 1 },
127 { "adma-lpspi", IMX_SC_R_SPI_0, 4, 1 },
128
129 /* VPU SS */
130 { "vpu", IMX_SC_R_VPU, 1, 0 },
131 { "vpu-pid", IMX_SC_R_VPU_PID0, 8, 1 },
132 { "vpu-dec0", IMX_SC_R_VPU_DEC_0, 1, 0 },
133 { "vpu-enc0", IMX_SC_R_VPU_ENC_0, 1, 0 },
134
135 /* GPU SS */
136 { "gpu0-pid", IMX_SC_R_GPU_0_PID0, 4, 1 },
137
138 /* HSIO SS */
139 { "hsio-pcie-b", IMX_SC_R_PCIE_B, 1, 0 },
140 { "hsio-serdes-1", IMX_SC_R_SERDES_1, 1, 0 },
141 { "hsio-gpio", IMX_SC_R_HSIO_GPIO, 1, 0 },
142
143 /* MIPI/LVDS SS */
144 { "mipi0", IMX_SC_R_MIPI_0, 1, 0 },
145 { "mipi0-pwm0", IMX_SC_R_MIPI_0_PWM_0, 1, 0 },
146 { "mipi0-i2c", IMX_SC_R_MIPI_0_I2C_0, 2, 1 },
147 { "lvds0", IMX_SC_R_LVDS_0, 1, 0 },
148
149 /* DC SS */
150 { "dc0", IMX_SC_R_DC_0, 1, 0 },
151 { "dc0-pll", IMX_SC_R_DC_0_PLL_0, 2, 1 },
152};
153
154static const struct imx_sc_pd_soc imx8qxp_scu_pd = {
155 .pd_ranges = imx8qxp_scu_pd_ranges,
156 .num_ranges = ARRAY_SIZE(imx8qxp_scu_pd_ranges),
157};
158
159static struct imx_sc_ipc *pm_ipc_handle;
160
161static inline struct imx_sc_pm_domain *
162to_imx_sc_pd(struct generic_pm_domain *genpd)
163{
164 return container_of(genpd, struct imx_sc_pm_domain, pd);
165}
166
167static int imx_sc_pd_power(struct generic_pm_domain *domain, bool power_on)
168{
169 struct imx_sc_msg_req_set_resource_power_mode msg;
170 struct imx_sc_rpc_msg *hdr = &msg.hdr;
171 struct imx_sc_pm_domain *pd;
172 int ret;
173
174 pd = to_imx_sc_pd(domain);
175
176 hdr->ver = IMX_SC_RPC_VERSION;
177 hdr->svc = IMX_SC_RPC_SVC_PM;
178 hdr->func = IMX_SC_PM_FUNC_SET_RESOURCE_POWER_MODE;
179 hdr->size = 2;
180
181 msg.resource = pd->rsrc;
182 msg.mode = power_on ? IMX_SC_PM_PW_MODE_ON : IMX_SC_PM_PW_MODE_LP;
183
184 ret = imx_scu_call_rpc(pm_ipc_handle, &msg, true);
185 if (ret)
186 dev_err(&domain->dev, "failed to power %s resource %d ret %d\n",
187 power_on ? "up" : "off", pd->rsrc, ret);
188
189 return ret;
190}
191
192static int imx_sc_pd_power_on(struct generic_pm_domain *domain)
193{
194 return imx_sc_pd_power(domain, true);
195}
196
197static int imx_sc_pd_power_off(struct generic_pm_domain *domain)
198{
199 return imx_sc_pd_power(domain, false);
200}
201
202static struct generic_pm_domain *imx_scu_pd_xlate(struct of_phandle_args *spec,
203 void *data)
204{
205 struct generic_pm_domain *domain = ERR_PTR(-ENOENT);
206 struct genpd_onecell_data *pd_data = data;
207 unsigned int i;
208
209 for (i = 0; i < pd_data->num_domains; i++) {
210 struct imx_sc_pm_domain *sc_pd;
211
212 sc_pd = to_imx_sc_pd(pd_data->domains[i]);
213 if (sc_pd->rsrc == spec->args[0]) {
214 domain = &sc_pd->pd;
215 break;
216 }
217 }
218
219 return domain;
220}
221
222static struct imx_sc_pm_domain *
223imx_scu_add_pm_domain(struct device *dev, int idx,
224 const struct imx_sc_pd_range *pd_ranges)
225{
226 struct imx_sc_pm_domain *sc_pd;
227 int ret;
228
229 sc_pd = devm_kzalloc(dev, sizeof(*sc_pd), GFP_KERNEL);
230 if (!sc_pd)
231 return ERR_PTR(-ENOMEM);
232
233 sc_pd->rsrc = pd_ranges->rsrc + idx;
234 sc_pd->pd.power_off = imx_sc_pd_power_off;
235 sc_pd->pd.power_on = imx_sc_pd_power_on;
236
237 if (pd_ranges->postfix)
238 snprintf(sc_pd->name, sizeof(sc_pd->name),
239 "%s%i", pd_ranges->name, idx);
240 else
241 snprintf(sc_pd->name, sizeof(sc_pd->name),
242 "%s", pd_ranges->name);
243
244 sc_pd->pd.name = sc_pd->name;
245
246 if (sc_pd->rsrc >= IMX_SC_R_LAST) {
247 dev_warn(dev, "invalid pd %s rsrc id %d found",
248 sc_pd->name, sc_pd->rsrc);
249
250 devm_kfree(dev, sc_pd);
251 return NULL;
252 }
253
254 ret = pm_genpd_init(&sc_pd->pd, NULL, true);
255 if (ret) {
256 dev_warn(dev, "failed to init pd %s rsrc id %d",
257 sc_pd->name, sc_pd->rsrc);
258 devm_kfree(dev, sc_pd);
259 return NULL;
260 }
261
262 return sc_pd;
263}
264
265static int imx_scu_init_pm_domains(struct device *dev,
266 const struct imx_sc_pd_soc *pd_soc)
267{
268 const struct imx_sc_pd_range *pd_ranges = pd_soc->pd_ranges;
269 struct generic_pm_domain **domains;
270 struct genpd_onecell_data *pd_data;
271 struct imx_sc_pm_domain *sc_pd;
272 u32 count = 0;
273 int i, j;
274
275 for (i = 0; i < pd_soc->num_ranges; i++)
276 count += pd_ranges[i].num;
277
278 domains = devm_kcalloc(dev, count, sizeof(*domains), GFP_KERNEL);
279 if (!domains)
280 return -ENOMEM;
281
282 pd_data = devm_kzalloc(dev, sizeof(*pd_data), GFP_KERNEL);
283 if (!pd_data)
284 return -ENOMEM;
285
286 count = 0;
287 for (i = 0; i < pd_soc->num_ranges; i++) {
288 for (j = 0; j < pd_ranges[i].num; j++) {
289 sc_pd = imx_scu_add_pm_domain(dev, j, &pd_ranges[i]);
290 if (IS_ERR_OR_NULL(sc_pd))
291 continue;
292
293 domains[count++] = &sc_pd->pd;
294 dev_dbg(dev, "added power domain %s\n", sc_pd->pd.name);
295 }
296 }
297
298 pd_data->domains = domains;
299 pd_data->num_domains = count;
300 pd_data->xlate = imx_scu_pd_xlate;
301
302 of_genpd_add_provider_onecell(dev->of_node, pd_data);
303
304 return 0;
305}
306
307static int imx_sc_pd_probe(struct platform_device *pdev)
308{
309 const struct imx_sc_pd_soc *pd_soc;
310 int ret;
311
312 ret = imx_scu_get_handle(&pm_ipc_handle);
313 if (ret)
314 return ret;
315
316 pd_soc = of_device_get_match_data(&pdev->dev);
317 if (!pd_soc)
318 return -ENODEV;
319
320 return imx_scu_init_pm_domains(&pdev->dev, pd_soc);
321}
322
323static const struct of_device_id imx_sc_pd_match[] = {
324 { .compatible = "fsl,imx8qxp-scu-pd", &imx8qxp_scu_pd},
325 { /* sentinel */ }
326};
327
328static struct platform_driver imx_sc_pd_driver = {
329 .driver = {
330 .name = "imx-scu-pd",
331 .of_match_table = imx_sc_pd_match,
332 },
333 .probe = imx_sc_pd_probe,
334};
335builtin_platform_driver(imx_sc_pd_driver);
336
337MODULE_AUTHOR("Dong Aisheng <aisheng.dong@nxp.com>");
338MODULE_DESCRIPTION("IMX SCU Power Domain driver");
339MODULE_LICENSE("GPL v2");
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index a200a2174611..a13558154ac3 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -1,12 +1,9 @@
1// SPDX-License-Identifier: GPL-2.0
1/* 2/*
2 * Defines interfaces for interacting wtih the Raspberry Pi firmware's 3 * Defines interfaces for interacting wtih the Raspberry Pi firmware's
3 * property channel. 4 * property channel.
4 * 5 *
5 * Copyright © 2015 Broadcom 6 * Copyright © 2015 Broadcom
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */ 7 */
11 8
12#include <linux/dma-mapping.h> 9#include <linux/dma-mapping.h>
@@ -14,6 +11,7 @@
14#include <linux/module.h> 11#include <linux/module.h>
15#include <linux/of_platform.h> 12#include <linux/of_platform.h>
16#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <linux/slab.h>
17#include <soc/bcm2835/raspberrypi-firmware.h> 15#include <soc/bcm2835/raspberrypi-firmware.h>
18 16
19#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf)) 17#define MBOX_MSG(chan, data28) (((data28) & ~0xf) | ((chan) & 0xf))
@@ -21,8 +19,6 @@
21#define MBOX_DATA28(msg) ((msg) & ~0xf) 19#define MBOX_DATA28(msg) ((msg) & ~0xf)
22#define MBOX_CHAN_PROPERTY 8 20#define MBOX_CHAN_PROPERTY 8
23 21
24#define MAX_RPI_FW_PROP_BUF_SIZE 32
25
26static struct platform_device *rpi_hwmon; 22static struct platform_device *rpi_hwmon;
27 23
28struct rpi_firmware { 24struct rpi_firmware {
@@ -56,8 +52,12 @@ rpi_firmware_transaction(struct rpi_firmware *fw, u32 chan, u32 data)
56 reinit_completion(&fw->c); 52 reinit_completion(&fw->c);
57 ret = mbox_send_message(fw->chan, &message); 53 ret = mbox_send_message(fw->chan, &message);
58 if (ret >= 0) { 54 if (ret >= 0) {
59 wait_for_completion(&fw->c); 55 if (wait_for_completion_timeout(&fw->c, HZ)) {
60 ret = 0; 56 ret = 0;
57 } else {
58 ret = -ETIMEDOUT;
59 WARN_ONCE(1, "Firmware transaction timeout");
60 }
61 } else { 61 } else {
62 dev_err(fw->cl.dev, "mbox_send_message returned %d\n", ret); 62 dev_err(fw->cl.dev, "mbox_send_message returned %d\n", ret);
63 } 63 }
@@ -144,28 +144,30 @@ EXPORT_SYMBOL_GPL(rpi_firmware_property_list);
144int rpi_firmware_property(struct rpi_firmware *fw, 144int rpi_firmware_property(struct rpi_firmware *fw,
145 u32 tag, void *tag_data, size_t buf_size) 145 u32 tag, void *tag_data, size_t buf_size)
146{ 146{
147 /* Single tags are very small (generally 8 bytes), so the 147 struct rpi_firmware_property_tag_header *header;
148 * stack should be safe.
149 */
150 u8 data[sizeof(struct rpi_firmware_property_tag_header) +
151 MAX_RPI_FW_PROP_BUF_SIZE];
152 struct rpi_firmware_property_tag_header *header =
153 (struct rpi_firmware_property_tag_header *)data;
154 int ret; 148 int ret;
155 149
156 if (WARN_ON(buf_size > sizeof(data) - sizeof(*header))) 150 /* Some mailboxes can use over 1k bytes. Rather than checking
157 return -EINVAL; 151 * size and using stack or kmalloc depending on requirements,
152 * just use kmalloc. Mailboxes don't get called enough to worry
153 * too much about the time taken in the allocation.
154 */
155 void *data = kmalloc(sizeof(*header) + buf_size, GFP_KERNEL);
158 156
157 if (!data)
158 return -ENOMEM;
159
160 header = data;
159 header->tag = tag; 161 header->tag = tag;
160 header->buf_size = buf_size; 162 header->buf_size = buf_size;
161 header->req_resp_size = 0; 163 header->req_resp_size = 0;
162 memcpy(data + sizeof(struct rpi_firmware_property_tag_header), 164 memcpy(data + sizeof(*header), tag_data, buf_size);
163 tag_data, buf_size); 165
166 ret = rpi_firmware_property_list(fw, data, buf_size + sizeof(*header));
167
168 memcpy(tag_data, data + sizeof(*header), buf_size);
164 169
165 ret = rpi_firmware_property_list(fw, &data, buf_size + sizeof(*header)); 170 kfree(data);
166 memcpy(tag_data,
167 data + sizeof(struct rpi_firmware_property_tag_header),
168 buf_size);
169 171
170 return ret; 172 return ret;
171} 173}
diff --git a/drivers/firmware/tegra/bpmp-debugfs.c b/drivers/firmware/tegra/bpmp-debugfs.c
index f7f6a0a5cb07..a84df1a8ca2b 100644
--- a/drivers/firmware/tegra/bpmp-debugfs.c
+++ b/drivers/firmware/tegra/bpmp-debugfs.c
@@ -379,33 +379,6 @@ static int create_debugfs_mirror(struct tegra_bpmp *bpmp, void *buf,
379 return err; 379 return err;
380} 380}
381 381
382static int mrq_is_supported(struct tegra_bpmp *bpmp, unsigned int mrq)
383{
384 struct mrq_query_abi_request req = { .mrq = cpu_to_le32(mrq) };
385 struct mrq_query_abi_response resp;
386 struct tegra_bpmp_message msg = {
387 .mrq = MRQ_QUERY_ABI,
388 .tx = {
389 .data = &req,
390 .size = sizeof(req),
391 },
392 .rx = {
393 .data = &resp,
394 .size = sizeof(resp),
395 },
396 };
397 int ret;
398
399 ret = tegra_bpmp_transfer(bpmp, &msg);
400 if (ret < 0) {
401 /* something went wrong; assume not supported */
402 dev_warn(bpmp->dev, "tegra_bpmp_transfer failed (%d)\n", ret);
403 return 0;
404 }
405
406 return resp.status ? 0 : 1;
407}
408
409int tegra_bpmp_init_debugfs(struct tegra_bpmp *bpmp) 382int tegra_bpmp_init_debugfs(struct tegra_bpmp *bpmp)
410{ 383{
411 dma_addr_t phys; 384 dma_addr_t phys;
@@ -415,7 +388,7 @@ int tegra_bpmp_init_debugfs(struct tegra_bpmp *bpmp)
415 int ret; 388 int ret;
416 struct dentry *root; 389 struct dentry *root;
417 390
418 if (!mrq_is_supported(bpmp, MRQ_DEBUGFS)) 391 if (!tegra_bpmp_mrq_is_supported(bpmp, MRQ_DEBUGFS))
419 return 0; 392 return 0;
420 393
421 root = debugfs_create_dir("bpmp", NULL); 394 root = debugfs_create_dir("bpmp", NULL);
diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c
index a3d5b518c10e..689478b92bce 100644
--- a/drivers/firmware/tegra/bpmp.c
+++ b/drivers/firmware/tegra/bpmp.c
@@ -28,6 +28,7 @@
28 28
29#define MSG_ACK BIT(0) 29#define MSG_ACK BIT(0)
30#define MSG_RING BIT(1) 30#define MSG_RING BIT(1)
31#define TAG_SZ 32
31 32
32static inline struct tegra_bpmp * 33static inline struct tegra_bpmp *
33mbox_client_to_bpmp(struct mbox_client *client) 34mbox_client_to_bpmp(struct mbox_client *client)
@@ -470,6 +471,31 @@ unlock:
470} 471}
471EXPORT_SYMBOL_GPL(tegra_bpmp_free_mrq); 472EXPORT_SYMBOL_GPL(tegra_bpmp_free_mrq);
472 473
474bool tegra_bpmp_mrq_is_supported(struct tegra_bpmp *bpmp, unsigned int mrq)
475{
476 struct mrq_query_abi_request req = { .mrq = cpu_to_le32(mrq) };
477 struct mrq_query_abi_response resp;
478 struct tegra_bpmp_message msg = {
479 .mrq = MRQ_QUERY_ABI,
480 .tx = {
481 .data = &req,
482 .size = sizeof(req),
483 },
484 .rx = {
485 .data = &resp,
486 .size = sizeof(resp),
487 },
488 };
489 int ret;
490
491 ret = tegra_bpmp_transfer(bpmp, &msg);
492 if (ret || msg.rx.ret)
493 return false;
494
495 return resp.status == 0;
496}
497EXPORT_SYMBOL_GPL(tegra_bpmp_mrq_is_supported);
498
473static void tegra_bpmp_mrq_handle_ping(unsigned int mrq, 499static void tegra_bpmp_mrq_handle_ping(unsigned int mrq,
474 struct tegra_bpmp_channel *channel, 500 struct tegra_bpmp_channel *channel,
475 void *data) 501 void *data)
@@ -521,8 +547,9 @@ static int tegra_bpmp_ping(struct tegra_bpmp *bpmp)
521 return err; 547 return err;
522} 548}
523 549
524static int tegra_bpmp_get_firmware_tag(struct tegra_bpmp *bpmp, char *tag, 550/* deprecated version of tag query */
525 size_t size) 551static int tegra_bpmp_get_firmware_tag_old(struct tegra_bpmp *bpmp, char *tag,
552 size_t size)
526{ 553{
527 struct mrq_query_tag_request request; 554 struct mrq_query_tag_request request;
528 struct tegra_bpmp_message msg; 555 struct tegra_bpmp_message msg;
@@ -531,7 +558,10 @@ static int tegra_bpmp_get_firmware_tag(struct tegra_bpmp *bpmp, char *tag,
531 void *virt; 558 void *virt;
532 int err; 559 int err;
533 560
534 virt = dma_alloc_coherent(bpmp->dev, MSG_DATA_MIN_SZ, &phys, 561 if (size != TAG_SZ)
562 return -EINVAL;
563
564 virt = dma_alloc_coherent(bpmp->dev, TAG_SZ, &phys,
535 GFP_KERNEL | GFP_DMA32); 565 GFP_KERNEL | GFP_DMA32);
536 if (!virt) 566 if (!virt)
537 return -ENOMEM; 567 return -ENOMEM;
@@ -549,13 +579,44 @@ static int tegra_bpmp_get_firmware_tag(struct tegra_bpmp *bpmp, char *tag,
549 local_irq_restore(flags); 579 local_irq_restore(flags);
550 580
551 if (err == 0) 581 if (err == 0)
552 strlcpy(tag, virt, size); 582 memcpy(tag, virt, TAG_SZ);
553 583
554 dma_free_coherent(bpmp->dev, MSG_DATA_MIN_SZ, virt, phys); 584 dma_free_coherent(bpmp->dev, TAG_SZ, virt, phys);
555 585
556 return err; 586 return err;
557} 587}
558 588
589static int tegra_bpmp_get_firmware_tag(struct tegra_bpmp *bpmp, char *tag,
590 size_t size)
591{
592 if (tegra_bpmp_mrq_is_supported(bpmp, MRQ_QUERY_FW_TAG)) {
593 struct mrq_query_fw_tag_response resp;
594 struct tegra_bpmp_message msg = {
595 .mrq = MRQ_QUERY_FW_TAG,
596 .rx = {
597 .data = &resp,
598 .size = sizeof(resp),
599 },
600 };
601 int err;
602
603 if (size != sizeof(resp.tag))
604 return -EINVAL;
605
606 err = tegra_bpmp_transfer(bpmp, &msg);
607
608 if (err)
609 return err;
610 if (msg.rx.ret < 0)
611 return -EINVAL;
612
613 memcpy(tag, resp.tag, sizeof(resp.tag));
614 return 0;
615 }
616
617 return tegra_bpmp_get_firmware_tag_old(bpmp, tag, size);
618}
619
559static void tegra_bpmp_channel_signal(struct tegra_bpmp_channel *channel) 620static void tegra_bpmp_channel_signal(struct tegra_bpmp_channel *channel)
560{ 621{
561 unsigned long flags = channel->ob->flags; 622 unsigned long flags = channel->ob->flags;
@@ -664,7 +725,7 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
664{ 725{
665 struct tegra_bpmp *bpmp; 726 struct tegra_bpmp *bpmp;
666 unsigned int i; 727 unsigned int i;
667 char tag[32]; 728 char tag[TAG_SZ];
668 size_t size; 729 size_t size;
669 int err; 730 int err;
670 731
@@ -792,13 +853,13 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
792 goto free_mrq; 853 goto free_mrq;
793 } 854 }
794 855
795 err = tegra_bpmp_get_firmware_tag(bpmp, tag, sizeof(tag) - 1); 856 err = tegra_bpmp_get_firmware_tag(bpmp, tag, sizeof(tag));
796 if (err < 0) { 857 if (err < 0) {
797 dev_err(&pdev->dev, "failed to get firmware tag: %d\n", err); 858 dev_err(&pdev->dev, "failed to get firmware tag: %d\n", err);
798 goto free_mrq; 859 goto free_mrq;
799 } 860 }
800 861
801 dev_info(&pdev->dev, "firmware: %s\n", tag); 862 dev_info(&pdev->dev, "firmware: %.*s\n", (int)sizeof(tag), tag);
802 863
803 platform_set_drvdata(pdev, bpmp); 864 platform_set_drvdata(pdev, bpmp);
804 865
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index c58e953fefa3..5beb83d1cf87 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -927,26 +927,6 @@ static int a6xx_gmu_memory_probe(struct a6xx_gmu *gmu)
927 return ret; 927 return ret;
928} 928}
929 929
930/* Get the list of RPMh voltage levels from cmd-db */
931static int a6xx_gmu_rpmh_arc_cmds(const char *id, void *vals, int size)
932{
933 u32 len = cmd_db_read_aux_data_len(id);
934
935 if (!len)
936 return 0;
937
938 if (WARN_ON(len > size))
939 return -EINVAL;
940
941 cmd_db_read_aux_data(id, vals, len);
942
943 /*
944 * The data comes back as an array of unsigned shorts so adjust the
945 * count accordingly
946 */
947 return len >> 1;
948}
949
950/* Return the 'arc-level' for the given frequency */ 930/* Return the 'arc-level' for the given frequency */
951static u32 a6xx_gmu_get_arc_level(struct device *dev, unsigned long freq) 931static u32 a6xx_gmu_get_arc_level(struct device *dev, unsigned long freq)
952{ 932{
@@ -974,11 +954,30 @@ static u32 a6xx_gmu_get_arc_level(struct device *dev, unsigned long freq)
974} 954}
975 955
976static int a6xx_gmu_rpmh_arc_votes_init(struct device *dev, u32 *votes, 956static int a6xx_gmu_rpmh_arc_votes_init(struct device *dev, u32 *votes,
977 unsigned long *freqs, int freqs_count, 957 unsigned long *freqs, int freqs_count, const char *id)
978 u16 *pri, int pri_count,
979 u16 *sec, int sec_count)
980{ 958{
981 int i, j; 959 int i, j;
960 const u16 *pri, *sec;
961 size_t pri_count, sec_count;
962
963 pri = cmd_db_read_aux_data(id, &pri_count);
964 if (IS_ERR(pri))
965 return PTR_ERR(pri);
966 /*
967 * The data comes back as an array of unsigned shorts so adjust the
968 * count accordingly
969 */
970 pri_count >>= 1;
971 if (!pri_count)
972 return -EINVAL;
973
974 sec = cmd_db_read_aux_data("mx.lvl", &sec_count);
975 if (IS_ERR(sec))
976 return PTR_ERR(sec);
977
978 sec_count >>= 1;
979 if (!sec_count)
980 return -EINVAL;
982 981
983 /* Construct a vote for each frequency */ 982 /* Construct a vote for each frequency */
984 for (i = 0; i < freqs_count; i++) { 983 for (i = 0; i < freqs_count; i++) {
@@ -1037,25 +1036,15 @@ static int a6xx_gmu_rpmh_votes_init(struct a6xx_gmu *gmu)
1037 struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); 1036 struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu);
1038 struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; 1037 struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
1039 struct msm_gpu *gpu = &adreno_gpu->base; 1038 struct msm_gpu *gpu = &adreno_gpu->base;
1040
1041 u16 gx[16], cx[16], mx[16];
1042 u32 gxcount, cxcount, mxcount;
1043 int ret; 1039 int ret;
1044 1040
1045 /* Get the list of available voltage levels for each component */
1046 gxcount = a6xx_gmu_rpmh_arc_cmds("gfx.lvl", gx, sizeof(gx));
1047 cxcount = a6xx_gmu_rpmh_arc_cmds("cx.lvl", cx, sizeof(cx));
1048 mxcount = a6xx_gmu_rpmh_arc_cmds("mx.lvl", mx, sizeof(mx));
1049
1050 /* Build the GX votes */ 1041 /* Build the GX votes */
1051 ret = a6xx_gmu_rpmh_arc_votes_init(&gpu->pdev->dev, gmu->gx_arc_votes, 1042 ret = a6xx_gmu_rpmh_arc_votes_init(&gpu->pdev->dev, gmu->gx_arc_votes,
1052 gmu->gpu_freqs, gmu->nr_gpu_freqs, 1043 gmu->gpu_freqs, gmu->nr_gpu_freqs, "gfx.lvl");
1053 gx, gxcount, mx, mxcount);
1054 1044
1055 /* Build the CX votes */ 1045 /* Build the CX votes */
1056 ret |= a6xx_gmu_rpmh_arc_votes_init(gmu->dev, gmu->cx_arc_votes, 1046 ret |= a6xx_gmu_rpmh_arc_votes_init(gmu->dev, gmu->cx_arc_votes,
1057 gmu->gmu_freqs, gmu->nr_gmu_freqs, 1047 gmu->gmu_freqs, gmu->nr_gmu_freqs, "cx.lvl");
1058 cx, cxcount, mx, mxcount);
1059 1048
1060 return ret; 1049 return ret;
1061} 1050}
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index a2188f7c04c6..f6297599433f 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -2061,7 +2061,7 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
2061 * timings. 2061 * timings.
2062 */ 2062 */
2063 name = gpmc_cs_get_name(cs); 2063 name = gpmc_cs_get_name(cs);
2064 if (name && of_node_cmp(child->name, name) == 0) 2064 if (name && of_node_name_eq(child, name))
2065 goto no_timings; 2065 goto no_timings;
2066 2066
2067 ret = gpmc_cs_request(cs, resource_size(&res), &base); 2067 ret = gpmc_cs_request(cs, resource_size(&res), &base);
@@ -2069,7 +2069,7 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
2069 dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs); 2069 dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
2070 return ret; 2070 return ret;
2071 } 2071 }
2072 gpmc_cs_set_name(cs, child->name); 2072 gpmc_cs_set_name(cs, child->full_name);
2073 2073
2074 gpmc_read_settings_dt(child, &gpmc_s); 2074 gpmc_read_settings_dt(child, &gpmc_s);
2075 gpmc_read_timings_dt(child, &gpmc_t); 2075 gpmc_read_timings_dt(child, &gpmc_t);
@@ -2114,7 +2114,7 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
2114 goto err; 2114 goto err;
2115 } 2115 }
2116 2116
2117 if (of_node_cmp(child->name, "nand") == 0) { 2117 if (of_node_name_eq(child, "nand")) {
2118 /* Warn about older DT blobs with no compatible property */ 2118 /* Warn about older DT blobs with no compatible property */
2119 if (!of_property_read_bool(child, "compatible")) { 2119 if (!of_property_read_bool(child, "compatible")) {
2120 dev_warn(&pdev->dev, 2120 dev_warn(&pdev->dev,
@@ -2124,7 +2124,7 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
2124 } 2124 }
2125 } 2125 }
2126 2126
2127 if (of_node_cmp(child->name, "onenand") == 0) { 2127 if (of_node_name_eq(child, "onenand")) {
2128 /* Warn about older DT blobs with no compatible property */ 2128 /* Warn about older DT blobs with no compatible property */
2129 if (!of_property_read_bool(child, "compatible")) { 2129 if (!of_property_read_bool(child, "compatible")) {
2130 dev_warn(&pdev->dev, 2130 dev_warn(&pdev->dev,
diff --git a/drivers/memory/tegra/Kconfig b/drivers/memory/tegra/Kconfig
index 6d74e499e18d..34e0b70f5c5f 100644
--- a/drivers/memory/tegra/Kconfig
+++ b/drivers/memory/tegra/Kconfig
@@ -6,6 +6,16 @@ config TEGRA_MC
6 This driver supports the Memory Controller (MC) hardware found on 6 This driver supports the Memory Controller (MC) hardware found on
7 NVIDIA Tegra SoCs. 7 NVIDIA Tegra SoCs.
8 8
9config TEGRA20_EMC
10 bool "NVIDIA Tegra20 External Memory Controller driver"
11 default y
12 depends on ARCH_TEGRA_2x_SOC
13 help
14 This driver is for the External Memory Controller (EMC) found on
15 Tegra20 chips. The EMC controls the external DRAM on the board.
16 This driver is required to change memory timings / clock rate for
17 external memory.
18
9config TEGRA124_EMC 19config TEGRA124_EMC
10 bool "NVIDIA Tegra124 External Memory Controller driver" 20 bool "NVIDIA Tegra124 External Memory Controller driver"
11 default y 21 default y
diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile
index 94ab16ba075b..3971a6b7c487 100644
--- a/drivers/memory/tegra/Makefile
+++ b/drivers/memory/tegra/Makefile
@@ -10,5 +10,6 @@ tegra-mc-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o
10 10
11obj-$(CONFIG_TEGRA_MC) += tegra-mc.o 11obj-$(CONFIG_TEGRA_MC) += tegra-mc.o
12 12
13obj-$(CONFIG_TEGRA20_EMC) += tegra20-emc.o
13obj-$(CONFIG_TEGRA124_EMC) += tegra124-emc.o 14obj-$(CONFIG_TEGRA124_EMC) += tegra124-emc.o
14obj-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186.o 15obj-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186.o
diff --git a/drivers/memory/tegra/tegra20-emc.c b/drivers/memory/tegra/tegra20-emc.c
new file mode 100644
index 000000000000..9ee5bef49e47
--- /dev/null
+++ b/drivers/memory/tegra/tegra20-emc.c
@@ -0,0 +1,591 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Tegra20 External Memory Controller driver
4 *
5 * Author: Dmitry Osipenko <digetx@gmail.com>
6 */
7
8#include <linux/clk.h>
9#include <linux/completion.h>
10#include <linux/err.h>
11#include <linux/interrupt.h>
12#include <linux/iopoll.h>
13#include <linux/kernel.h>
14#include <linux/module.h>
15#include <linux/of.h>
16#include <linux/platform_device.h>
17#include <linux/sort.h>
18#include <linux/types.h>
19
20#include <soc/tegra/fuse.h>
21
22#define EMC_INTSTATUS 0x000
23#define EMC_INTMASK 0x004
24#define EMC_TIMING_CONTROL 0x028
25#define EMC_RC 0x02c
26#define EMC_RFC 0x030
27#define EMC_RAS 0x034
28#define EMC_RP 0x038
29#define EMC_R2W 0x03c
30#define EMC_W2R 0x040
31#define EMC_R2P 0x044
32#define EMC_W2P 0x048
33#define EMC_RD_RCD 0x04c
34#define EMC_WR_RCD 0x050
35#define EMC_RRD 0x054
36#define EMC_REXT 0x058
37#define EMC_WDV 0x05c
38#define EMC_QUSE 0x060
39#define EMC_QRST 0x064
40#define EMC_QSAFE 0x068
41#define EMC_RDV 0x06c
42#define EMC_REFRESH 0x070
43#define EMC_BURST_REFRESH_NUM 0x074
44#define EMC_PDEX2WR 0x078
45#define EMC_PDEX2RD 0x07c
46#define EMC_PCHG2PDEN 0x080
47#define EMC_ACT2PDEN 0x084
48#define EMC_AR2PDEN 0x088
49#define EMC_RW2PDEN 0x08c
50#define EMC_TXSR 0x090
51#define EMC_TCKE 0x094
52#define EMC_TFAW 0x098
53#define EMC_TRPAB 0x09c
54#define EMC_TCLKSTABLE 0x0a0
55#define EMC_TCLKSTOP 0x0a4
56#define EMC_TREFBW 0x0a8
57#define EMC_QUSE_EXTRA 0x0ac
58#define EMC_ODT_WRITE 0x0b0
59#define EMC_ODT_READ 0x0b4
60#define EMC_FBIO_CFG5 0x104
61#define EMC_FBIO_CFG6 0x114
62#define EMC_AUTO_CAL_INTERVAL 0x2a8
63#define EMC_CFG_2 0x2b8
64#define EMC_CFG_DIG_DLL 0x2bc
65#define EMC_DLL_XFORM_DQS 0x2c0
66#define EMC_DLL_XFORM_QUSE 0x2c4
67#define EMC_ZCAL_REF_CNT 0x2e0
68#define EMC_ZCAL_WAIT_CNT 0x2e4
69#define EMC_CFG_CLKTRIM_0 0x2d0
70#define EMC_CFG_CLKTRIM_1 0x2d4
71#define EMC_CFG_CLKTRIM_2 0x2d8
72
73#define EMC_CLKCHANGE_REQ_ENABLE BIT(0)
74#define EMC_CLKCHANGE_PD_ENABLE BIT(1)
75#define EMC_CLKCHANGE_SR_ENABLE BIT(2)
76
77#define EMC_TIMING_UPDATE BIT(0)
78
79#define EMC_REFRESH_OVERFLOW_INT BIT(3)
80#define EMC_CLKCHANGE_COMPLETE_INT BIT(4)
81
82static const u16 emc_timing_registers[] = {
83 EMC_RC,
84 EMC_RFC,
85 EMC_RAS,
86 EMC_RP,
87 EMC_R2W,
88 EMC_W2R,
89 EMC_R2P,
90 EMC_W2P,
91 EMC_RD_RCD,
92 EMC_WR_RCD,
93 EMC_RRD,
94 EMC_REXT,
95 EMC_WDV,
96 EMC_QUSE,
97 EMC_QRST,
98 EMC_QSAFE,
99 EMC_RDV,
100 EMC_REFRESH,
101 EMC_BURST_REFRESH_NUM,
102 EMC_PDEX2WR,
103 EMC_PDEX2RD,
104 EMC_PCHG2PDEN,
105 EMC_ACT2PDEN,
106 EMC_AR2PDEN,
107 EMC_RW2PDEN,
108 EMC_TXSR,
109 EMC_TCKE,
110 EMC_TFAW,
111 EMC_TRPAB,
112 EMC_TCLKSTABLE,
113 EMC_TCLKSTOP,
114 EMC_TREFBW,
115 EMC_QUSE_EXTRA,
116 EMC_FBIO_CFG6,
117 EMC_ODT_WRITE,
118 EMC_ODT_READ,
119 EMC_FBIO_CFG5,
120 EMC_CFG_DIG_DLL,
121 EMC_DLL_XFORM_DQS,
122 EMC_DLL_XFORM_QUSE,
123 EMC_ZCAL_REF_CNT,
124 EMC_ZCAL_WAIT_CNT,
125 EMC_AUTO_CAL_INTERVAL,
126 EMC_CFG_CLKTRIM_0,
127 EMC_CFG_CLKTRIM_1,
128 EMC_CFG_CLKTRIM_2,
129};
130
131struct emc_timing {
132 unsigned long rate;
133 u32 data[ARRAY_SIZE(emc_timing_registers)];
134};
135
136struct tegra_emc {
137 struct device *dev;
138 struct completion clk_handshake_complete;
139 struct notifier_block clk_nb;
140 struct clk *backup_clk;
141 struct clk *emc_mux;
142 struct clk *pll_m;
143 struct clk *clk;
144 void __iomem *regs;
145
146 struct emc_timing *timings;
147 unsigned int num_timings;
148};
149
150static irqreturn_t tegra_emc_isr(int irq, void *data)
151{
152 struct tegra_emc *emc = data;
153 u32 intmask = EMC_REFRESH_OVERFLOW_INT | EMC_CLKCHANGE_COMPLETE_INT;
154 u32 status;
155
156 status = readl_relaxed(emc->regs + EMC_INTSTATUS) & intmask;
157 if (!status)
158 return IRQ_NONE;
159
160 /* notify about EMC-CAR handshake completion */
161 if (status & EMC_CLKCHANGE_COMPLETE_INT)
162 complete(&emc->clk_handshake_complete);
163
164 /* notify about HW problem */
165 if (status & EMC_REFRESH_OVERFLOW_INT)
166 dev_err_ratelimited(emc->dev,
167 "refresh request overflow timeout\n");
168
169 /* clear interrupts */
170 writel_relaxed(status, emc->regs + EMC_INTSTATUS);
171
172 return IRQ_HANDLED;
173}
174
175static struct emc_timing *tegra_emc_find_timing(struct tegra_emc *emc,
176 unsigned long rate)
177{
178 struct emc_timing *timing = NULL;
179 unsigned int i;
180
181 for (i = 0; i < emc->num_timings; i++) {
182 if (emc->timings[i].rate >= rate) {
183 timing = &emc->timings[i];
184 break;
185 }
186 }
187
188 if (!timing) {
189 dev_err(emc->dev, "no timing for rate %lu\n", rate);
190 return NULL;
191 }
192
193 return timing;
194}
195
196static int emc_prepare_timing_change(struct tegra_emc *emc, unsigned long rate)
197{
198 struct emc_timing *timing = tegra_emc_find_timing(emc, rate);
199 unsigned int i;
200
201 if (!timing)
202 return -EINVAL;
203
204 dev_dbg(emc->dev, "%s: using timing rate %lu for requested rate %lu\n",
205 __func__, timing->rate, rate);
206
207 /* program shadow registers */
208 for (i = 0; i < ARRAY_SIZE(timing->data); i++)
209 writel_relaxed(timing->data[i],
210 emc->regs + emc_timing_registers[i]);
211
212 /* wait until programming has settled */
213 readl_relaxed(emc->regs + emc_timing_registers[i - 1]);
214
215 reinit_completion(&emc->clk_handshake_complete);
216
217 return 0;
218}
219
220static int emc_complete_timing_change(struct tegra_emc *emc, bool flush)
221{
222 long timeout;
223
224 dev_dbg(emc->dev, "%s: flush %d\n", __func__, flush);
225
226 if (flush) {
227 /* manually initiate memory timing update */
228 writel_relaxed(EMC_TIMING_UPDATE,
229 emc->regs + EMC_TIMING_CONTROL);
230 return 0;
231 }
232
233 timeout = wait_for_completion_timeout(&emc->clk_handshake_complete,
234 usecs_to_jiffies(100));
235 if (timeout == 0) {
236 dev_err(emc->dev, "EMC-CAR handshake failed\n");
237 return -EIO;
238 } else if (timeout < 0) {
239 dev_err(emc->dev, "failed to wait for EMC-CAR handshake: %ld\n",
240 timeout);
241 return timeout;
242 }
243
244 return 0;
245}
246
247static int tegra_emc_clk_change_notify(struct notifier_block *nb,
248 unsigned long msg, void *data)
249{
250 struct tegra_emc *emc = container_of(nb, struct tegra_emc, clk_nb);
251 struct clk_notifier_data *cnd = data;
252 int err;
253
254 switch (msg) {
255 case PRE_RATE_CHANGE:
256 err = emc_prepare_timing_change(emc, cnd->new_rate);
257 break;
258
259 case ABORT_RATE_CHANGE:
260 err = emc_prepare_timing_change(emc, cnd->old_rate);
261 if (err)
262 break;
263
264 err = emc_complete_timing_change(emc, true);
265 break;
266
267 case POST_RATE_CHANGE:
268 err = emc_complete_timing_change(emc, false);
269 break;
270
271 default:
272 return NOTIFY_DONE;
273 }
274
275 return notifier_from_errno(err);
276}
277
278static int load_one_timing_from_dt(struct tegra_emc *emc,
279 struct emc_timing *timing,
280 struct device_node *node)
281{
282 u32 rate;
283 int err;
284
285 if (!of_device_is_compatible(node, "nvidia,tegra20-emc-table")) {
286 dev_err(emc->dev, "incompatible DT node: %pOF\n", node);
287 return -EINVAL;
288 }
289
290 err = of_property_read_u32(node, "clock-frequency", &rate);
291 if (err) {
292 dev_err(emc->dev, "timing %pOF: failed to read rate: %d\n",
293 node, err);
294 return err;
295 }
296
297 err = of_property_read_u32_array(node, "nvidia,emc-registers",
298 timing->data,
299 ARRAY_SIZE(emc_timing_registers));
300 if (err) {
301 dev_err(emc->dev,
302 "timing %pOF: failed to read emc timing data: %d\n",
303 node, err);
304 return err;
305 }
306
307 /*
308 * The EMC clock rate is twice the bus rate, and the bus rate is
309 * measured in kHz.
310 */
311 timing->rate = rate * 2 * 1000;
312
313 dev_dbg(emc->dev, "%s: %pOF: EMC rate %lu\n",
314 __func__, node, timing->rate);
315
316 return 0;
317}
318
319static int cmp_timings(const void *_a, const void *_b)
320{
321 const struct emc_timing *a = _a;
322 const struct emc_timing *b = _b;
323
324 if (a->rate < b->rate)
325 return -1;
326
327 if (a->rate > b->rate)
328 return 1;
329
330 return 0;
331}
332
333static int tegra_emc_load_timings_from_dt(struct tegra_emc *emc,
334 struct device_node *node)
335{
336 struct device_node *child;
337 struct emc_timing *timing;
338 int child_count;
339 int err;
340
341 child_count = of_get_child_count(node);
342 if (!child_count) {
343 dev_err(emc->dev, "no memory timings in DT node: %pOF\n", node);
344 return -EINVAL;
345 }
346
347 emc->timings = devm_kcalloc(emc->dev, child_count, sizeof(*timing),
348 GFP_KERNEL);
349 if (!emc->timings)
350 return -ENOMEM;
351
352 emc->num_timings = child_count;
353 timing = emc->timings;
354
355 for_each_child_of_node(node, child) {
356 err = load_one_timing_from_dt(emc, timing++, child);
357 if (err) {
358 of_node_put(child);
359 return err;
360 }
361 }
362
363 sort(emc->timings, emc->num_timings, sizeof(*timing), cmp_timings,
364 NULL);
365
366 return 0;
367}
368
369static struct device_node *
370tegra_emc_find_node_by_ram_code(struct device *dev)
371{
372 struct device_node *np;
373 u32 value, ram_code;
374 int err;
375
376 if (!of_property_read_bool(dev->of_node, "nvidia,use-ram-code"))
377 return of_node_get(dev->of_node);
378
379 ram_code = tegra_read_ram_code();
380
381 for (np = of_find_node_by_name(dev->of_node, "emc-tables"); np;
382 np = of_find_node_by_name(np, "emc-tables")) {
383 err = of_property_read_u32(np, "nvidia,ram-code", &value);
384 if (err || value != ram_code) {
385 of_node_put(np);
386 continue;
387 }
388
389 return np;
390 }
391
392 dev_err(dev, "no memory timings for RAM code %u found in device tree\n",
393 ram_code);
394
395 return NULL;
396}
397
398static int emc_setup_hw(struct tegra_emc *emc)
399{
400 u32 intmask = EMC_REFRESH_OVERFLOW_INT | EMC_CLKCHANGE_COMPLETE_INT;
401 u32 emc_cfg;
402
403 emc_cfg = readl_relaxed(emc->regs + EMC_CFG_2);
404
405 /*
406 * Depending on a memory type, DRAM should enter either self-refresh
407 * or power-down state on EMC clock change.
408 */
409 if (!(emc_cfg & EMC_CLKCHANGE_PD_ENABLE) &&
410 !(emc_cfg & EMC_CLKCHANGE_SR_ENABLE)) {
411 dev_err(emc->dev,
412 "bootloader didn't specify DRAM auto-suspend mode\n");
413 return -EINVAL;
414 }
415
416 /* enable EMC and CAR to handshake on PLL divider/source changes */
417 emc_cfg |= EMC_CLKCHANGE_REQ_ENABLE;
418 writel_relaxed(emc_cfg, emc->regs + EMC_CFG_2);
419
420 /* initialize interrupt */
421 writel_relaxed(intmask, emc->regs + EMC_INTMASK);
422 writel_relaxed(intmask, emc->regs + EMC_INTSTATUS);
423
424 return 0;
425}
426
427static int emc_init(struct tegra_emc *emc, unsigned long rate)
428{
429 int err;
430
431 err = clk_set_parent(emc->emc_mux, emc->backup_clk);
432 if (err) {
433 dev_err(emc->dev,
434 "failed to reparent to backup source: %d\n", err);
435 return err;
436 }
437
438 err = clk_set_rate(emc->pll_m, rate);
439 if (err) {
440 dev_err(emc->dev,
441 "failed to change pll_m rate: %d\n", err);
442 return err;
443 }
444
445 err = clk_set_parent(emc->emc_mux, emc->pll_m);
446 if (err) {
447 dev_err(emc->dev,
448 "failed to reparent to pll_m: %d\n", err);
449 return err;
450 }
451
452 err = clk_set_rate(emc->clk, rate);
453 if (err) {
454 dev_err(emc->dev,
455 "failed to change emc rate: %d\n", err);
456 return err;
457 }
458
459 return 0;
460}
461
462static int tegra_emc_probe(struct platform_device *pdev)
463{
464 struct device_node *np;
465 struct tegra_emc *emc;
466 struct resource *res;
467 int irq, err;
468
469 /* driver has nothing to do in a case of memory timing absence */
470 if (of_get_child_count(pdev->dev.of_node) == 0) {
471 dev_info(&pdev->dev,
472 "EMC device tree node doesn't have memory timings\n");
473 return 0;
474 }
475
476 irq = platform_get_irq(pdev, 0);
477 if (irq < 0) {
478 dev_err(&pdev->dev, "interrupt not specified\n");
479 dev_err(&pdev->dev, "please update your device tree\n");
480 return irq;
481 }
482
483 np = tegra_emc_find_node_by_ram_code(&pdev->dev);
484 if (!np)
485 return -EINVAL;
486
487 emc = devm_kzalloc(&pdev->dev, sizeof(*emc), GFP_KERNEL);
488 if (!emc) {
489 of_node_put(np);
490 return -ENOMEM;
491 }
492
493 init_completion(&emc->clk_handshake_complete);
494 emc->clk_nb.notifier_call = tegra_emc_clk_change_notify;
495 emc->dev = &pdev->dev;
496
497 err = tegra_emc_load_timings_from_dt(emc, np);
498 of_node_put(np);
499 if (err)
500 return err;
501
502 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
503 emc->regs = devm_ioremap_resource(&pdev->dev, res);
504 if (IS_ERR(emc->regs))
505 return PTR_ERR(emc->regs);
506
507 err = emc_setup_hw(emc);
508 if (err)
509 return err;
510
511 err = devm_request_irq(&pdev->dev, irq, tegra_emc_isr, 0,
512 dev_name(&pdev->dev), emc);
513 if (err) {
514 dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", irq, err);
515 return err;
516 }
517
518 emc->clk = devm_clk_get(&pdev->dev, "emc");
519 if (IS_ERR(emc->clk)) {
520 err = PTR_ERR(emc->clk);
521 dev_err(&pdev->dev, "failed to get emc clock: %d\n", err);
522 return err;
523 }
524
525 emc->pll_m = clk_get_sys(NULL, "pll_m");
526 if (IS_ERR(emc->pll_m)) {
527 err = PTR_ERR(emc->pll_m);
528 dev_err(&pdev->dev, "failed to get pll_m clock: %d\n", err);
529 return err;
530 }
531
532 emc->backup_clk = clk_get_sys(NULL, "pll_p");
533 if (IS_ERR(emc->backup_clk)) {
534 err = PTR_ERR(emc->backup_clk);
535 dev_err(&pdev->dev, "failed to get pll_p clock: %d\n", err);
536 goto put_pll_m;
537 }
538
539 emc->emc_mux = clk_get_parent(emc->clk);
540 if (IS_ERR(emc->emc_mux)) {
541 err = PTR_ERR(emc->emc_mux);
542 dev_err(&pdev->dev, "failed to get emc_mux clock: %d\n", err);
543 goto put_backup;
544 }
545
546 err = clk_notifier_register(emc->clk, &emc->clk_nb);
547 if (err) {
548 dev_err(&pdev->dev, "failed to register clk notifier: %d\n",
549 err);
550 goto put_backup;
551 }
552
553 /* set DRAM clock rate to maximum */
554 err = emc_init(emc, emc->timings[emc->num_timings - 1].rate);
555 if (err) {
556 dev_err(&pdev->dev, "failed to initialize EMC clock rate: %d\n",
557 err);
558 goto unreg_notifier;
559 }
560
561 return 0;
562
563unreg_notifier:
564 clk_notifier_unregister(emc->clk, &emc->clk_nb);
565put_backup:
566 clk_put(emc->backup_clk);
567put_pll_m:
568 clk_put(emc->pll_m);
569
570 return err;
571}
572
573static const struct of_device_id tegra_emc_of_match[] = {
574 { .compatible = "nvidia,tegra20-emc", },
575 {},
576};
577
578static struct platform_driver tegra_emc_driver = {
579 .probe = tegra_emc_probe,
580 .driver = {
581 .name = "tegra20-emc",
582 .of_match_table = tegra_emc_of_match,
583 .suppress_bind_attrs = true,
584 },
585};
586
587static int __init tegra_emc_init(void)
588{
589 return platform_driver_register(&tegra_emc_driver);
590}
591subsys_initcall(tegra_emc_init);
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 446166ba0bec..90b686e586c6 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -13,7 +13,7 @@ obj-$(CONFIG_ARCH_GEMINI) += gemini/
13obj-$(CONFIG_ARCH_MXC) += imx/ 13obj-$(CONFIG_ARCH_MXC) += imx/
14obj-$(CONFIG_SOC_XWAY) += lantiq/ 14obj-$(CONFIG_SOC_XWAY) += lantiq/
15obj-y += mediatek/ 15obj-y += mediatek/
16obj-$(CONFIG_ARCH_MESON) += amlogic/ 16obj-y += amlogic/
17obj-y += qcom/ 17obj-y += qcom/
18obj-y += renesas/ 18obj-y += renesas/
19obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ 19obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
diff --git a/drivers/soc/amlogic/Kconfig b/drivers/soc/amlogic/Kconfig
index 2f282b472912..5501ad5650b2 100644
--- a/drivers/soc/amlogic/Kconfig
+++ b/drivers/soc/amlogic/Kconfig
@@ -7,6 +7,15 @@ config MESON_CANVAS
7 help 7 help
8 Say yes to support the canvas IP for Amlogic SoCs. 8 Say yes to support the canvas IP for Amlogic SoCs.
9 9
10config MESON_CLK_MEASURE
11 bool "Amlogic Meson SoC Clock Measure driver"
12 depends on ARCH_MESON || COMPILE_TEST
13 default ARCH_MESON
14 select REGMAP_MMIO
15 help
16 Say yes to support of Measuring a set of internal SoC clocks
17 from the debugfs interface.
18
10config MESON_GX_SOCINFO 19config MESON_GX_SOCINFO
11 bool "Amlogic Meson GX SoC Information driver" 20 bool "Amlogic Meson GX SoC Information driver"
12 depends on ARCH_MESON || COMPILE_TEST 21 depends on ARCH_MESON || COMPILE_TEST
diff --git a/drivers/soc/amlogic/Makefile b/drivers/soc/amlogic/Makefile
index 0ab16d35ac36..bf2d109f61e9 100644
--- a/drivers/soc/amlogic/Makefile
+++ b/drivers/soc/amlogic/Makefile
@@ -1,4 +1,5 @@
1obj-$(CONFIG_MESON_CANVAS) += meson-canvas.o 1obj-$(CONFIG_MESON_CANVAS) += meson-canvas.o
2obj-$(CONFIG_MESON_CLK_MEASURE) += meson-clk-measure.o
2obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o 3obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o
3obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o 4obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o
4obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o 5obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o
diff --git a/drivers/soc/amlogic/meson-clk-measure.c b/drivers/soc/amlogic/meson-clk-measure.c
new file mode 100644
index 000000000000..daea191a66fa
--- /dev/null
+++ b/drivers/soc/amlogic/meson-clk-measure.c
@@ -0,0 +1,350 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2018 BayLibre, SAS
4 * Author: Neil Armstrong <narmstrong@baylibre.com>
5 */
6
7#include <linux/of_address.h>
8#include <linux/platform_device.h>
9#include <linux/bitfield.h>
10#include <linux/seq_file.h>
11#include <linux/debugfs.h>
12#include <linux/regmap.h>
13
14#define MSR_CLK_DUTY 0x0
15#define MSR_CLK_REG0 0x4
16#define MSR_CLK_REG1 0x8
17#define MSR_CLK_REG2 0xc
18
19#define MSR_DURATION GENMASK(15, 0)
20#define MSR_ENABLE BIT(16)
21#define MSR_CONT BIT(17) /* continuous measurement */
22#define MSR_INTR BIT(18) /* interrupts */
23#define MSR_RUN BIT(19)
24#define MSR_CLK_SRC GENMASK(26, 20)
25#define MSR_BUSY BIT(31)
26
27#define MSR_VAL_MASK GENMASK(15, 0)
28
29#define DIV_MIN 32
30#define DIV_STEP 32
31#define DIV_MAX 640
32
33#define CLK_MSR_MAX 128
34
35struct meson_msr_id {
36 struct meson_msr *priv;
37 unsigned int id;
38 const char *name;
39};
40
41struct meson_msr {
42 struct regmap *regmap;
43 struct meson_msr_id msr_table[CLK_MSR_MAX];
44};
45
46#define CLK_MSR_ID(__id, __name) \
47 [__id] = {.id = __id, .name = __name,}
48
49static struct meson_msr_id clk_msr_m8[CLK_MSR_MAX] = {
50 CLK_MSR_ID(0, "ring_osc_out_ee0"),
51 CLK_MSR_ID(1, "ring_osc_out_ee1"),
52 CLK_MSR_ID(2, "ring_osc_out_ee2"),
53 CLK_MSR_ID(3, "a9_ring_osck"),
54 CLK_MSR_ID(6, "vid_pll"),
55 CLK_MSR_ID(7, "clk81"),
56 CLK_MSR_ID(8, "encp"),
57 CLK_MSR_ID(9, "encl"),
58 CLK_MSR_ID(11, "eth_rmii"),
59 CLK_MSR_ID(13, "amclk"),
60 CLK_MSR_ID(14, "fec_clk_0"),
61 CLK_MSR_ID(15, "fec_clk_1"),
62 CLK_MSR_ID(16, "fec_clk_2"),
63 CLK_MSR_ID(18, "a9_clk_div16"),
64 CLK_MSR_ID(19, "hdmi_sys"),
65 CLK_MSR_ID(20, "rtc_osc_clk_out"),
66 CLK_MSR_ID(21, "i2s_clk_in_src0"),
67 CLK_MSR_ID(22, "clk_rmii_from_pad"),
68 CLK_MSR_ID(23, "hdmi_ch0_tmds"),
69 CLK_MSR_ID(24, "lvds_fifo"),
70 CLK_MSR_ID(26, "sc_clk_int"),
71 CLK_MSR_ID(28, "sar_adc"),
72 CLK_MSR_ID(30, "mpll_clk_test_out"),
73 CLK_MSR_ID(31, "audac_clkpi"),
74 CLK_MSR_ID(32, "vdac"),
75 CLK_MSR_ID(33, "sdhc_rx"),
76 CLK_MSR_ID(34, "sdhc_sd"),
77 CLK_MSR_ID(35, "mali"),
78 CLK_MSR_ID(36, "hdmi_tx_pixel"),
79 CLK_MSR_ID(38, "vdin_meas"),
80 CLK_MSR_ID(39, "pcm_sclk"),
81 CLK_MSR_ID(40, "pcm_mclk"),
82 CLK_MSR_ID(41, "eth_rx_tx"),
83 CLK_MSR_ID(42, "pwm_d"),
84 CLK_MSR_ID(43, "pwm_c"),
85 CLK_MSR_ID(44, "pwm_b"),
86 CLK_MSR_ID(45, "pwm_a"),
87 CLK_MSR_ID(46, "pcm2_sclk"),
88 CLK_MSR_ID(47, "ddr_dpll_pt"),
89 CLK_MSR_ID(48, "pwm_f"),
90 CLK_MSR_ID(49, "pwm_e"),
91 CLK_MSR_ID(59, "hcodec"),
92 CLK_MSR_ID(60, "usb_32k_alt"),
93 CLK_MSR_ID(61, "gpio"),
94 CLK_MSR_ID(62, "vid2_pll"),
95 CLK_MSR_ID(63, "mipi_csi_cfg"),
96};
97
98static struct meson_msr_id clk_msr_gx[CLK_MSR_MAX] = {
99 CLK_MSR_ID(0, "ring_osc_out_ee_0"),
100 CLK_MSR_ID(1, "ring_osc_out_ee_1"),
101 CLK_MSR_ID(2, "ring_osc_out_ee_2"),
102 CLK_MSR_ID(3, "a53_ring_osc"),
103 CLK_MSR_ID(4, "gp0_pll"),
104 CLK_MSR_ID(6, "enci"),
105 CLK_MSR_ID(7, "clk81"),
106 CLK_MSR_ID(8, "encp"),
107 CLK_MSR_ID(9, "encl"),
108 CLK_MSR_ID(10, "vdac"),
109 CLK_MSR_ID(11, "rgmii_tx"),
110 CLK_MSR_ID(12, "pdm"),
111 CLK_MSR_ID(13, "amclk"),
112 CLK_MSR_ID(14, "fec_0"),
113 CLK_MSR_ID(15, "fec_1"),
114 CLK_MSR_ID(16, "fec_2"),
115 CLK_MSR_ID(17, "sys_pll_div16"),
116 CLK_MSR_ID(18, "sys_cpu_div16"),
117 CLK_MSR_ID(19, "hdmitx_sys"),
118 CLK_MSR_ID(20, "rtc_osc_out"),
119 CLK_MSR_ID(21, "i2s_in_src0"),
120 CLK_MSR_ID(22, "eth_phy_ref"),
121 CLK_MSR_ID(23, "hdmi_todig"),
122 CLK_MSR_ID(26, "sc_int"),
123 CLK_MSR_ID(28, "sar_adc"),
124 CLK_MSR_ID(31, "mpll_test_out"),
125 CLK_MSR_ID(32, "vdec"),
126 CLK_MSR_ID(35, "mali"),
127 CLK_MSR_ID(36, "hdmi_tx_pixel"),
128 CLK_MSR_ID(37, "i958"),
129 CLK_MSR_ID(38, "vdin_meas"),
130 CLK_MSR_ID(39, "pcm_sclk"),
131 CLK_MSR_ID(40, "pcm_mclk"),
132 CLK_MSR_ID(41, "eth_rx_or_rmii"),
133 CLK_MSR_ID(42, "mp0_out"),
134 CLK_MSR_ID(43, "fclk_div5"),
135 CLK_MSR_ID(44, "pwm_b"),
136 CLK_MSR_ID(45, "pwm_a"),
137 CLK_MSR_ID(46, "vpu"),
138 CLK_MSR_ID(47, "ddr_dpll_pt"),
139 CLK_MSR_ID(48, "mp1_out"),
140 CLK_MSR_ID(49, "mp2_out"),
141 CLK_MSR_ID(50, "mp3_out"),
142 CLK_MSR_ID(51, "nand_core"),
143 CLK_MSR_ID(52, "sd_emmc_b"),
144 CLK_MSR_ID(53, "sd_emmc_a"),
145 CLK_MSR_ID(55, "vid_pll_div_out"),
146 CLK_MSR_ID(56, "cci"),
147 CLK_MSR_ID(57, "wave420l_c"),
148 CLK_MSR_ID(58, "wave420l_b"),
149 CLK_MSR_ID(59, "hcodec"),
150 CLK_MSR_ID(60, "alt_32k"),
151 CLK_MSR_ID(61, "gpio_msr"),
152 CLK_MSR_ID(62, "hevc"),
153 CLK_MSR_ID(66, "vid_lock"),
154 CLK_MSR_ID(70, "pwm_f"),
155 CLK_MSR_ID(71, "pwm_e"),
156 CLK_MSR_ID(72, "pwm_d"),
157 CLK_MSR_ID(73, "pwm_c"),
158 CLK_MSR_ID(75, "aoclkx2_int"),
159 CLK_MSR_ID(76, "aoclk_int"),
160 CLK_MSR_ID(77, "rng_ring_osc_0"),
161 CLK_MSR_ID(78, "rng_ring_osc_1"),
162 CLK_MSR_ID(79, "rng_ring_osc_2"),
163 CLK_MSR_ID(80, "rng_ring_osc_3"),
164 CLK_MSR_ID(81, "vapb"),
165 CLK_MSR_ID(82, "ge2d"),
166};
167
168static int meson_measure_id(struct meson_msr_id *clk_msr_id,
169 unsigned int duration)
170{
171 struct meson_msr *priv = clk_msr_id->priv;
172 unsigned int val;
173 int ret;
174
175 regmap_write(priv->regmap, MSR_CLK_REG0, 0);
176
177 /* Set measurement duration */
178 regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_DURATION,
179 FIELD_PREP(MSR_DURATION, duration - 1));
180
181 /* Set ID */
182 regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_CLK_SRC,
183 FIELD_PREP(MSR_CLK_SRC, clk_msr_id->id));
184
185 /* Enable & Start */
186 regmap_update_bits(priv->regmap, MSR_CLK_REG0,
187 MSR_RUN | MSR_ENABLE,
188 MSR_RUN | MSR_ENABLE);
189
190 ret = regmap_read_poll_timeout(priv->regmap, MSR_CLK_REG0,
191 val, !(val & MSR_BUSY), 10, 10000);
192 if (ret)
193 return ret;
194
195 /* Disable */
196 regmap_update_bits(priv->regmap, MSR_CLK_REG0, MSR_ENABLE, 0);
197
198 /* Get the value in multiple of gate time counts */
199 regmap_read(priv->regmap, MSR_CLK_REG2, &val);
200
201 if (val >= MSR_VAL_MASK)
202 return -EINVAL;
203
204 return DIV_ROUND_CLOSEST_ULL((val & MSR_VAL_MASK) * 1000000ULL,
205 duration);
206}
207
208static int meson_measure_best_id(struct meson_msr_id *clk_msr_id,
209 unsigned int *precision)
210{
211 unsigned int duration = DIV_MAX;
212 int ret;
213
214 /* Start from max duration and down to min duration */
215 do {
216 ret = meson_measure_id(clk_msr_id, duration);
217 if (ret >= 0)
218 *precision = (2 * 1000000) / duration;
219 else
220 duration -= DIV_STEP;
221 } while (duration >= DIV_MIN && ret == -EINVAL);
222
223 return ret;
224}
225
226static int clk_msr_show(struct seq_file *s, void *data)
227{
228 struct meson_msr_id *clk_msr_id = s->private;
229 unsigned int precision = 0;
230 int val;
231
232 val = meson_measure_best_id(clk_msr_id, &precision);
233 if (val < 0)
234 return val;
235
236 seq_printf(s, "%d\t+/-%dHz\n", val, precision);
237
238 return 0;
239}
240DEFINE_SHOW_ATTRIBUTE(clk_msr);
241
242static int clk_msr_summary_show(struct seq_file *s, void *data)
243{
244 struct meson_msr_id *msr_table = s->private;
245 unsigned int precision = 0;
246 int val, i;
247
248 seq_puts(s, " clock rate precision\n");
249 seq_puts(s, "---------------------------------------------\n");
250
251 for (i = 0 ; i < CLK_MSR_MAX ; ++i) {
252 if (!msr_table[i].name)
253 continue;
254
255 val = meson_measure_best_id(&msr_table[i], &precision);
256 if (val < 0)
257 return val;
258
259 seq_printf(s, " %-20s %10d +/-%dHz\n",
260 msr_table[i].name, val, precision);
261 }
262
263 return 0;
264}
265DEFINE_SHOW_ATTRIBUTE(clk_msr_summary);
266
267static const struct regmap_config meson_clk_msr_regmap_config = {
268 .reg_bits = 32,
269 .val_bits = 32,
270 .reg_stride = 4,
271 .max_register = MSR_CLK_REG2,
272};
273
274static int meson_msr_probe(struct platform_device *pdev)
275{
276 const struct meson_msr_id *match_data;
277 struct meson_msr *priv;
278 struct resource *res;
279 struct dentry *root, *clks;
280 void __iomem *base;
281 int i;
282
283 priv = devm_kzalloc(&pdev->dev, sizeof(struct meson_msr),
284 GFP_KERNEL);
285 if (!priv)
286 return -ENOMEM;
287
288 match_data = device_get_match_data(&pdev->dev);
289 if (!match_data) {
290 dev_err(&pdev->dev, "failed to get match data\n");
291 return -ENODEV;
292 }
293
294 memcpy(priv->msr_table, match_data, sizeof(priv->msr_table));
295
296 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
297 base = devm_ioremap_resource(&pdev->dev, res);
298 if (IS_ERR(base)) {
299 dev_err(&pdev->dev, "io resource mapping failed\n");
300 return PTR_ERR(base);
301 }
302
303 priv->regmap = devm_regmap_init_mmio(&pdev->dev, base,
304 &meson_clk_msr_regmap_config);
305 if (IS_ERR(priv->regmap))
306 return PTR_ERR(priv->regmap);
307
308 root = debugfs_create_dir("meson-clk-msr", NULL);
309 clks = debugfs_create_dir("clks", root);
310
311 debugfs_create_file("measure_summary", 0444, root,
312 priv->msr_table, &clk_msr_summary_fops);
313
314 for (i = 0 ; i < CLK_MSR_MAX ; ++i) {
315 if (!priv->msr_table[i].name)
316 continue;
317
318 priv->msr_table[i].priv = priv;
319
320 debugfs_create_file(priv->msr_table[i].name, 0444, clks,
321 &priv->msr_table[i], &clk_msr_fops);
322 }
323
324 return 0;
325}
326
327static const struct of_device_id meson_msr_match_table[] = {
328 {
329 .compatible = "amlogic,meson-gx-clk-measure",
330 .data = (void *)clk_msr_gx,
331 },
332 {
333 .compatible = "amlogic,meson8-clk-measure",
334 .data = (void *)clk_msr_m8,
335 },
336 {
337 .compatible = "amlogic,meson8b-clk-measure",
338 .data = (void *)clk_msr_m8,
339 },
340 { /* sentinel */ }
341};
342
343static struct platform_driver meson_msr_driver = {
344 .probe = meson_msr_probe,
345 .driver = {
346 .name = "meson_msr",
347 .of_match_table = meson_msr_match_table,
348 },
349};
350builtin_platform_driver(meson_msr_driver);
diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c
index 4dd03b099c89..096a83cf0caf 100644
--- a/drivers/soc/atmel/soc.c
+++ b/drivers/soc/atmel/soc.c
@@ -66,6 +66,8 @@ static const struct at91_soc __initconst socs[] = {
66 AT91_SOC(AT91SAM9XE128_CIDR_MATCH, 0, "at91sam9xe128", "at91sam9xe128"), 66 AT91_SOC(AT91SAM9XE128_CIDR_MATCH, 0, "at91sam9xe128", "at91sam9xe128"),
67 AT91_SOC(AT91SAM9XE256_CIDR_MATCH, 0, "at91sam9xe256", "at91sam9xe256"), 67 AT91_SOC(AT91SAM9XE256_CIDR_MATCH, 0, "at91sam9xe256", "at91sam9xe256"),
68 AT91_SOC(AT91SAM9XE512_CIDR_MATCH, 0, "at91sam9xe512", "at91sam9xe512"), 68 AT91_SOC(AT91SAM9XE512_CIDR_MATCH, 0, "at91sam9xe512", "at91sam9xe512"),
69 AT91_SOC(SAM9X60_CIDR_MATCH, SAM9X60_EXID_MATCH,
70 "sam9x60", "sam9x60"),
69#endif 71#endif
70#ifdef CONFIG_SOC_SAMA5 72#ifdef CONFIG_SOC_SAMA5
71 AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D21CU_EXID_MATCH, 73 AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D21CU_EXID_MATCH,
@@ -90,12 +92,20 @@ static const struct at91_soc __initconst socs[] = {
90 "sama5d27c 128MiB SiP", "sama5d2"), 92 "sama5d27c 128MiB SiP", "sama5d2"),
91 AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27C_D5M_EXID_MATCH, 93 AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27C_D5M_EXID_MATCH,
92 "sama5d27c 64MiB SiP", "sama5d2"), 94 "sama5d27c 64MiB SiP", "sama5d2"),
95 AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27C_LD1G_EXID_MATCH,
96 "sama5d27c 128MiB LPDDR2 SiP", "sama5d2"),
97 AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27C_LD2G_EXID_MATCH,
98 "sama5d27c 256MiB LPDDR2 SiP", "sama5d2"),
93 AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CU_EXID_MATCH, 99 AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CU_EXID_MATCH,
94 "sama5d28", "sama5d2"), 100 "sama5d28", "sama5d2"),
95 AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CN_EXID_MATCH, 101 AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CN_EXID_MATCH,
96 "sama5d28", "sama5d2"), 102 "sama5d28", "sama5d2"),
97 AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28C_D1G_EXID_MATCH, 103 AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28C_D1G_EXID_MATCH,
98 "sama5d28c 128MiB SiP", "sama5d2"), 104 "sama5d28c 128MiB SiP", "sama5d2"),
105 AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28C_LD1G_EXID_MATCH,
106 "sama5d28c 128MiB LPDDR2 SiP", "sama5d2"),
107 AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28C_LD2G_EXID_MATCH,
108 "sama5d28c 256MiB LPDDR2 SiP", "sama5d2"),
99 AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH, 109 AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH,
100 "sama5d31", "sama5d3"), 110 "sama5d31", "sama5d3"),
101 AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH, 111 AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH,
diff --git a/drivers/soc/atmel/soc.h b/drivers/soc/atmel/soc.h
index 94cd5d1ab502..ee652e4841a5 100644
--- a/drivers/soc/atmel/soc.h
+++ b/drivers/soc/atmel/soc.h
@@ -42,6 +42,7 @@ at91_soc_init(const struct at91_soc *socs);
42#define AT91SAM9G45_CIDR_MATCH 0x019b05a0 42#define AT91SAM9G45_CIDR_MATCH 0x019b05a0
43#define AT91SAM9X5_CIDR_MATCH 0x019a05a0 43#define AT91SAM9X5_CIDR_MATCH 0x019a05a0
44#define AT91SAM9N12_CIDR_MATCH 0x019a07a0 44#define AT91SAM9N12_CIDR_MATCH 0x019a07a0
45#define SAM9X60_CIDR_MATCH 0x019b35a0
45 46
46#define AT91SAM9M11_EXID_MATCH 0x00000001 47#define AT91SAM9M11_EXID_MATCH 0x00000001
47#define AT91SAM9M10_EXID_MATCH 0x00000002 48#define AT91SAM9M10_EXID_MATCH 0x00000002
@@ -58,6 +59,8 @@ at91_soc_init(const struct at91_soc *socs);
58#define AT91SAM9N12_EXID_MATCH 0x00000006 59#define AT91SAM9N12_EXID_MATCH 0x00000006
59#define AT91SAM9CN11_EXID_MATCH 0x00000009 60#define AT91SAM9CN11_EXID_MATCH 0x00000009
60 61
62#define SAM9X60_EXID_MATCH 0x00000000
63
61#define AT91SAM9XE128_CIDR_MATCH 0x329973a0 64#define AT91SAM9XE128_CIDR_MATCH 0x329973a0
62#define AT91SAM9XE256_CIDR_MATCH 0x329a93a0 65#define AT91SAM9XE256_CIDR_MATCH 0x329a93a0
63#define AT91SAM9XE512_CIDR_MATCH 0x329aa3a0 66#define AT91SAM9XE512_CIDR_MATCH 0x329aa3a0
@@ -73,9 +76,13 @@ at91_soc_init(const struct at91_soc *socs);
73#define SAMA5D26CU_EXID_MATCH 0x00000012 76#define SAMA5D26CU_EXID_MATCH 0x00000012
74#define SAMA5D27C_D1G_EXID_MATCH 0x00000033 77#define SAMA5D27C_D1G_EXID_MATCH 0x00000033
75#define SAMA5D27C_D5M_EXID_MATCH 0x00000032 78#define SAMA5D27C_D5M_EXID_MATCH 0x00000032
79#define SAMA5D27C_LD1G_EXID_MATCH 0x00000061
80#define SAMA5D27C_LD2G_EXID_MATCH 0x00000062
76#define SAMA5D27CU_EXID_MATCH 0x00000011 81#define SAMA5D27CU_EXID_MATCH 0x00000011
77#define SAMA5D27CN_EXID_MATCH 0x00000021 82#define SAMA5D27CN_EXID_MATCH 0x00000021
78#define SAMA5D28C_D1G_EXID_MATCH 0x00000013 83#define SAMA5D28C_D1G_EXID_MATCH 0x00000013
84#define SAMA5D28C_LD1G_EXID_MATCH 0x00000071
85#define SAMA5D28C_LD2G_EXID_MATCH 0x00000072
79#define SAMA5D28CU_EXID_MATCH 0x00000010 86#define SAMA5D28CU_EXID_MATCH 0x00000010
80#define SAMA5D28CN_EXID_MATCH 0x00000020 87#define SAMA5D28CN_EXID_MATCH 0x00000020
81 88
diff --git a/drivers/soc/bcm/brcmstb/common.c b/drivers/soc/bcm/brcmstb/common.c
index 14185451901d..bf9123f727e8 100644
--- a/drivers/soc/bcm/brcmstb/common.c
+++ b/drivers/soc/bcm/brcmstb/common.c
@@ -31,13 +31,17 @@ static const struct of_device_id brcmstb_machine_match[] = {
31 31
32bool soc_is_brcmstb(void) 32bool soc_is_brcmstb(void)
33{ 33{
34 const struct of_device_id *match;
34 struct device_node *root; 35 struct device_node *root;
35 36
36 root = of_find_node_by_path("/"); 37 root = of_find_node_by_path("/");
37 if (!root) 38 if (!root)
38 return false; 39 return false;
39 40
40 return of_match_node(brcmstb_machine_match, root) != NULL; 41 match = of_match_node(brcmstb_machine_match, root);
42 of_node_put(root);
43
44 return match != NULL;
41} 45}
42 46
43u32 brcmstb_get_family_id(void) 47u32 brcmstb_get_family_id(void)
diff --git a/drivers/soc/bcm/brcmstb/pm/pm-arm.c b/drivers/soc/bcm/brcmstb/pm/pm-arm.c
index a5577dd5eb08..8ee06347447c 100644
--- a/drivers/soc/bcm/brcmstb/pm/pm-arm.c
+++ b/drivers/soc/bcm/brcmstb/pm/pm-arm.c
@@ -404,7 +404,7 @@ noinline int brcmstb_pm_s3_finish(void)
404{ 404{
405 struct brcmstb_s3_params *params = ctrl.s3_params; 405 struct brcmstb_s3_params *params = ctrl.s3_params;
406 dma_addr_t params_pa = ctrl.s3_params_pa; 406 dma_addr_t params_pa = ctrl.s3_params_pa;
407 phys_addr_t reentry = virt_to_phys(&cpu_resume); 407 phys_addr_t reentry = virt_to_phys(&cpu_resume_arm);
408 enum bsp_initiate_command cmd; 408 enum bsp_initiate_command cmd;
409 u32 flags; 409 u32 flags;
410 410
diff --git a/drivers/soc/bcm/raspberrypi-power.c b/drivers/soc/bcm/raspberrypi-power.c
index a78dfe0a2b50..5d1aacdd84ef 100644
--- a/drivers/soc/bcm/raspberrypi-power.c
+++ b/drivers/soc/bcm/raspberrypi-power.c
@@ -1,9 +1,6 @@
1// SPDX-License-Identifier: GPL-2.0
1/* (C) 2015 Pengutronix, Alexander Aring <aar@pengutronix.de> 2/* (C) 2015 Pengutronix, Alexander Aring <aar@pengutronix.de>
2 * 3 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 *
7 * Authors: 4 * Authors:
8 * Alexander Aring <aar@pengutronix.de> 5 * Alexander Aring <aar@pengutronix.de>
9 * Eric Anholt <eric@anholt.net> 6 * Eric Anholt <eric@anholt.net>
diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig
index a5b86a28f343..2112d18dbb7b 100644
--- a/drivers/soc/imx/Kconfig
+++ b/drivers/soc/imx/Kconfig
@@ -1,8 +1,8 @@
1menu "i.MX SoC drivers" 1menu "i.MX SoC drivers"
2 2
3config IMX7_PM_DOMAINS 3config IMX_GPCV2_PM_DOMAINS
4 bool "i.MX7 PM domains" 4 bool "i.MX GPCv2 PM domains"
5 depends on SOC_IMX7D || (COMPILE_TEST && OF) 5 depends on SOC_IMX7D || SOC_IMX8MQ || (COMPILE_TEST && OF)
6 depends on PM 6 depends on PM
7 select PM_GENERIC_DOMAINS 7 select PM_GENERIC_DOMAINS
8 default y if SOC_IMX7D 8 default y if SOC_IMX7D
diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile
index aab41a5cc317..506a6f3c2b9b 100644
--- a/drivers/soc/imx/Makefile
+++ b/drivers/soc/imx/Makefile
@@ -1,2 +1,2 @@
1obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o 1obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
2obj-$(CONFIG_IMX7_PM_DOMAINS) += gpcv2.o 2obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c
index aa3729ecaa9e..7d14a4b4e82a 100644
--- a/drivers/soc/imx/gpc.c
+++ b/drivers/soc/imx/gpc.c
@@ -35,7 +35,7 @@
35#define GPU_VPU_PUP_REQ BIT(1) 35#define GPU_VPU_PUP_REQ BIT(1)
36#define GPU_VPU_PDN_REQ BIT(0) 36#define GPU_VPU_PDN_REQ BIT(0)
37 37
38#define GPC_CLK_MAX 6 38#define GPC_CLK_MAX 7
39 39
40#define PGC_DOMAIN_FLAG_NO_PD BIT(0) 40#define PGC_DOMAIN_FLAG_NO_PD BIT(0)
41 41
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
index e7b5994fee9d..8b4f48a2ca57 100644
--- a/drivers/soc/imx/gpcv2.c
+++ b/drivers/soc/imx/gpcv2.c
@@ -14,23 +14,54 @@
14#include <linux/regmap.h> 14#include <linux/regmap.h>
15#include <linux/regulator/consumer.h> 15#include <linux/regulator/consumer.h>
16#include <dt-bindings/power/imx7-power.h> 16#include <dt-bindings/power/imx7-power.h>
17#include <dt-bindings/power/imx8mq-power.h>
17 18
18#define GPC_LPCR_A_CORE_BSC 0x000 19#define GPC_LPCR_A_CORE_BSC 0x000
19 20
20#define GPC_PGC_CPU_MAPPING 0x0ec 21#define GPC_PGC_CPU_MAPPING 0x0ec
21#define USB_HSIC_PHY_A_CORE_DOMAIN BIT(6) 22
22#define USB_OTG2_PHY_A_CORE_DOMAIN BIT(5) 23#define IMX7_USB_HSIC_PHY_A_CORE_DOMAIN BIT(6)
23#define USB_OTG1_PHY_A_CORE_DOMAIN BIT(4) 24#define IMX7_USB_OTG2_PHY_A_CORE_DOMAIN BIT(5)
24#define PCIE_PHY_A_CORE_DOMAIN BIT(3) 25#define IMX7_USB_OTG1_PHY_A_CORE_DOMAIN BIT(4)
25#define MIPI_PHY_A_CORE_DOMAIN BIT(2) 26#define IMX7_PCIE_PHY_A_CORE_DOMAIN BIT(3)
27#define IMX7_MIPI_PHY_A_CORE_DOMAIN BIT(2)
28
29#define IMX8M_PCIE2_A53_DOMAIN BIT(15)
30#define IMX8M_MIPI_CSI2_A53_DOMAIN BIT(14)
31#define IMX8M_MIPI_CSI1_A53_DOMAIN BIT(13)
32#define IMX8M_DISP_A53_DOMAIN BIT(12)
33#define IMX8M_HDMI_A53_DOMAIN BIT(11)
34#define IMX8M_VPU_A53_DOMAIN BIT(10)
35#define IMX8M_GPU_A53_DOMAIN BIT(9)
36#define IMX8M_DDR2_A53_DOMAIN BIT(8)
37#define IMX8M_DDR1_A53_DOMAIN BIT(7)
38#define IMX8M_OTG2_A53_DOMAIN BIT(5)
39#define IMX8M_OTG1_A53_DOMAIN BIT(4)
40#define IMX8M_PCIE1_A53_DOMAIN BIT(3)
41#define IMX8M_MIPI_A53_DOMAIN BIT(2)
26 42
27#define GPC_PU_PGC_SW_PUP_REQ 0x0f8 43#define GPC_PU_PGC_SW_PUP_REQ 0x0f8
28#define GPC_PU_PGC_SW_PDN_REQ 0x104 44#define GPC_PU_PGC_SW_PDN_REQ 0x104
29#define USB_HSIC_PHY_SW_Pxx_REQ BIT(4) 45
30#define USB_OTG2_PHY_SW_Pxx_REQ BIT(3) 46#define IMX7_USB_HSIC_PHY_SW_Pxx_REQ BIT(4)
31#define USB_OTG1_PHY_SW_Pxx_REQ BIT(2) 47#define IMX7_USB_OTG2_PHY_SW_Pxx_REQ BIT(3)
32#define PCIE_PHY_SW_Pxx_REQ BIT(1) 48#define IMX7_USB_OTG1_PHY_SW_Pxx_REQ BIT(2)
33#define MIPI_PHY_SW_Pxx_REQ BIT(0) 49#define IMX7_PCIE_PHY_SW_Pxx_REQ BIT(1)
50#define IMX7_MIPI_PHY_SW_Pxx_REQ BIT(0)
51
52#define IMX8M_PCIE2_SW_Pxx_REQ BIT(13)
53#define IMX8M_MIPI_CSI2_SW_Pxx_REQ BIT(12)
54#define IMX8M_MIPI_CSI1_SW_Pxx_REQ BIT(11)
55#define IMX8M_DISP_SW_Pxx_REQ BIT(10)
56#define IMX8M_HDMI_SW_Pxx_REQ BIT(9)
57#define IMX8M_VPU_SW_Pxx_REQ BIT(8)
58#define IMX8M_GPU_SW_Pxx_REQ BIT(7)
59#define IMX8M_DDR2_SW_Pxx_REQ BIT(6)
60#define IMX8M_DDR1_SW_Pxx_REQ BIT(5)
61#define IMX8M_OTG2_SW_Pxx_REQ BIT(3)
62#define IMX8M_OTG1_SW_Pxx_REQ BIT(2)
63#define IMX8M_PCIE1_SW_Pxx_REQ BIT(1)
64#define IMX8M_MIPI_SW_Pxx_REQ BIT(0)
34 65
35#define GPC_M4_PU_PDN_FLG 0x1bc 66#define GPC_M4_PU_PDN_FLG 0x1bc
36 67
@@ -40,9 +71,22 @@
40 * GPC_PGC memory map are incorrect, below offset 71 * GPC_PGC memory map are incorrect, below offset
41 * values are from design RTL. 72 * values are from design RTL.
42 */ 73 */
43#define PGC_MIPI 16 74#define IMX7_PGC_MIPI 16
44#define PGC_PCIE 17 75#define IMX7_PGC_PCIE 17
45#define PGC_USB_HSIC 20 76#define IMX7_PGC_USB_HSIC 20
77
78#define IMX8M_PGC_MIPI 16
79#define IMX8M_PGC_PCIE1 17
80#define IMX8M_PGC_OTG1 18
81#define IMX8M_PGC_OTG2 19
82#define IMX8M_PGC_DDR1 21
83#define IMX8M_PGC_GPU 23
84#define IMX8M_PGC_VPU 24
85#define IMX8M_PGC_DISP 26
86#define IMX8M_PGC_MIPI_CSI1 27
87#define IMX8M_PGC_MIPI_CSI2 28
88#define IMX8M_PGC_PCIE2 29
89
46#define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40) 90#define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40)
47#define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc) 91#define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc)
48 92
@@ -67,6 +111,7 @@ struct imx_pgc_domain {
67struct imx_pgc_domain_data { 111struct imx_pgc_domain_data {
68 const struct imx_pgc_domain *domains; 112 const struct imx_pgc_domain *domains;
69 size_t domains_num; 113 size_t domains_num;
114 const struct regmap_access_table *reg_access_table;
70}; 115};
71 116
72static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd, 117static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
@@ -166,11 +211,11 @@ static const struct imx_pgc_domain imx7_pgc_domains[] = {
166 .name = "mipi-phy", 211 .name = "mipi-phy",
167 }, 212 },
168 .bits = { 213 .bits = {
169 .pxx = MIPI_PHY_SW_Pxx_REQ, 214 .pxx = IMX7_MIPI_PHY_SW_Pxx_REQ,
170 .map = MIPI_PHY_A_CORE_DOMAIN, 215 .map = IMX7_MIPI_PHY_A_CORE_DOMAIN,
171 }, 216 },
172 .voltage = 1000000, 217 .voltage = 1000000,
173 .pgc = PGC_MIPI, 218 .pgc = IMX7_PGC_MIPI,
174 }, 219 },
175 220
176 [IMX7_POWER_DOMAIN_PCIE_PHY] = { 221 [IMX7_POWER_DOMAIN_PCIE_PHY] = {
@@ -178,11 +223,11 @@ static const struct imx_pgc_domain imx7_pgc_domains[] = {
178 .name = "pcie-phy", 223 .name = "pcie-phy",
179 }, 224 },
180 .bits = { 225 .bits = {
181 .pxx = PCIE_PHY_SW_Pxx_REQ, 226 .pxx = IMX7_PCIE_PHY_SW_Pxx_REQ,
182 .map = PCIE_PHY_A_CORE_DOMAIN, 227 .map = IMX7_PCIE_PHY_A_CORE_DOMAIN,
183 }, 228 },
184 .voltage = 1000000, 229 .voltage = 1000000,
185 .pgc = PGC_PCIE, 230 .pgc = IMX7_PGC_PCIE,
186 }, 231 },
187 232
188 [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = { 233 [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = {
@@ -190,17 +235,195 @@ static const struct imx_pgc_domain imx7_pgc_domains[] = {
190 .name = "usb-hsic-phy", 235 .name = "usb-hsic-phy",
191 }, 236 },
192 .bits = { 237 .bits = {
193 .pxx = USB_HSIC_PHY_SW_Pxx_REQ, 238 .pxx = IMX7_USB_HSIC_PHY_SW_Pxx_REQ,
194 .map = USB_HSIC_PHY_A_CORE_DOMAIN, 239 .map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN,
195 }, 240 },
196 .voltage = 1200000, 241 .voltage = 1200000,
197 .pgc = PGC_USB_HSIC, 242 .pgc = IMX7_PGC_USB_HSIC,
198 }, 243 },
199}; 244};
200 245
246static const struct regmap_range imx7_yes_ranges[] = {
247 regmap_reg_range(GPC_LPCR_A_CORE_BSC,
248 GPC_M4_PU_PDN_FLG),
249 regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_MIPI),
250 GPC_PGC_SR(IMX7_PGC_MIPI)),
251 regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_PCIE),
252 GPC_PGC_SR(IMX7_PGC_PCIE)),
253 regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_USB_HSIC),
254 GPC_PGC_SR(IMX7_PGC_USB_HSIC)),
255};
256
257static const struct regmap_access_table imx7_access_table = {
258 .yes_ranges = imx7_yes_ranges,
259 .n_yes_ranges = ARRAY_SIZE(imx7_yes_ranges),
260};
261
201static const struct imx_pgc_domain_data imx7_pgc_domain_data = { 262static const struct imx_pgc_domain_data imx7_pgc_domain_data = {
202 .domains = imx7_pgc_domains, 263 .domains = imx7_pgc_domains,
203 .domains_num = ARRAY_SIZE(imx7_pgc_domains), 264 .domains_num = ARRAY_SIZE(imx7_pgc_domains),
265 .reg_access_table = &imx7_access_table,
266};
267
268static const struct imx_pgc_domain imx8m_pgc_domains[] = {
269 [IMX8M_POWER_DOMAIN_MIPI] = {
270 .genpd = {
271 .name = "mipi",
272 },
273 .bits = {
274 .pxx = IMX8M_MIPI_SW_Pxx_REQ,
275 .map = IMX8M_MIPI_A53_DOMAIN,
276 },
277 .pgc = IMX8M_PGC_MIPI,
278 },
279
280 [IMX8M_POWER_DOMAIN_PCIE1] = {
281 .genpd = {
282 .name = "pcie1",
283 },
284 .bits = {
285 .pxx = IMX8M_PCIE1_SW_Pxx_REQ,
286 .map = IMX8M_PCIE1_A53_DOMAIN,
287 },
288 .pgc = IMX8M_PGC_PCIE1,
289 },
290
291 [IMX8M_POWER_DOMAIN_USB_OTG1] = {
292 .genpd = {
293 .name = "usb-otg1",
294 },
295 .bits = {
296 .pxx = IMX8M_OTG1_SW_Pxx_REQ,
297 .map = IMX8M_OTG1_A53_DOMAIN,
298 },
299 .pgc = IMX8M_PGC_OTG1,
300 },
301
302 [IMX8M_POWER_DOMAIN_USB_OTG2] = {
303 .genpd = {
304 .name = "usb-otg2",
305 },
306 .bits = {
307 .pxx = IMX8M_OTG2_SW_Pxx_REQ,
308 .map = IMX8M_OTG2_A53_DOMAIN,
309 },
310 .pgc = IMX8M_PGC_OTG2,
311 },
312
313 [IMX8M_POWER_DOMAIN_DDR1] = {
314 .genpd = {
315 .name = "ddr1",
316 },
317 .bits = {
318 .pxx = IMX8M_DDR1_SW_Pxx_REQ,
319 .map = IMX8M_DDR2_A53_DOMAIN,
320 },
321 .pgc = IMX8M_PGC_DDR1,
322 },
323
324 [IMX8M_POWER_DOMAIN_GPU] = {
325 .genpd = {
326 .name = "gpu",
327 },
328 .bits = {
329 .pxx = IMX8M_GPU_SW_Pxx_REQ,
330 .map = IMX8M_GPU_A53_DOMAIN,
331 },
332 .pgc = IMX8M_PGC_GPU,
333 },
334
335 [IMX8M_POWER_DOMAIN_VPU] = {
336 .genpd = {
337 .name = "vpu",
338 },
339 .bits = {
340 .pxx = IMX8M_VPU_SW_Pxx_REQ,
341 .map = IMX8M_VPU_A53_DOMAIN,
342 },
343 .pgc = IMX8M_PGC_VPU,
344 },
345
346 [IMX8M_POWER_DOMAIN_DISP] = {
347 .genpd = {
348 .name = "disp",
349 },
350 .bits = {
351 .pxx = IMX8M_DISP_SW_Pxx_REQ,
352 .map = IMX8M_DISP_A53_DOMAIN,
353 },
354 .pgc = IMX8M_PGC_DISP,
355 },
356
357 [IMX8M_POWER_DOMAIN_MIPI_CSI1] = {
358 .genpd = {
359 .name = "mipi-csi1",
360 },
361 .bits = {
362 .pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ,
363 .map = IMX8M_MIPI_CSI1_A53_DOMAIN,
364 },
365 .pgc = IMX8M_PGC_MIPI_CSI1,
366 },
367
368 [IMX8M_POWER_DOMAIN_MIPI_CSI2] = {
369 .genpd = {
370 .name = "mipi-csi2",
371 },
372 .bits = {
373 .pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ,
374 .map = IMX8M_MIPI_CSI2_A53_DOMAIN,
375 },
376 .pgc = IMX8M_PGC_MIPI_CSI2,
377 },
378
379 [IMX8M_POWER_DOMAIN_PCIE2] = {
380 .genpd = {
381 .name = "pcie2",
382 },
383 .bits = {
384 .pxx = IMX8M_PCIE2_SW_Pxx_REQ,
385 .map = IMX8M_PCIE2_A53_DOMAIN,
386 },
387 .pgc = IMX8M_PGC_PCIE2,
388 },
389};
390
391static const struct regmap_range imx8m_yes_ranges[] = {
392 regmap_reg_range(GPC_LPCR_A_CORE_BSC,
393 GPC_M4_PU_PDN_FLG),
394 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI),
395 GPC_PGC_SR(IMX8M_PGC_MIPI)),
396 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE1),
397 GPC_PGC_SR(IMX8M_PGC_PCIE1)),
398 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG1),
399 GPC_PGC_SR(IMX8M_PGC_OTG1)),
400 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG2),
401 GPC_PGC_SR(IMX8M_PGC_OTG2)),
402 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DDR1),
403 GPC_PGC_SR(IMX8M_PGC_DDR1)),
404 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_GPU),
405 GPC_PGC_SR(IMX8M_PGC_GPU)),
406 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_VPU),
407 GPC_PGC_SR(IMX8M_PGC_VPU)),
408 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DISP),
409 GPC_PGC_SR(IMX8M_PGC_DISP)),
410 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI1),
411 GPC_PGC_SR(IMX8M_PGC_MIPI_CSI1)),
412 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI2),
413 GPC_PGC_SR(IMX8M_PGC_MIPI_CSI2)),
414 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE2),
415 GPC_PGC_SR(IMX8M_PGC_PCIE2)),
416};
417
418static const struct regmap_access_table imx8m_access_table = {
419 .yes_ranges = imx8m_yes_ranges,
420 .n_yes_ranges = ARRAY_SIZE(imx8m_yes_ranges),
421};
422
423static const struct imx_pgc_domain_data imx8m_pgc_domain_data = {
424 .domains = imx8m_pgc_domains,
425 .domains_num = ARRAY_SIZE(imx8m_pgc_domains),
426 .reg_access_table = &imx8m_access_table,
204}; 427};
205 428
206static int imx_pgc_domain_probe(struct platform_device *pdev) 429static int imx_pgc_domain_probe(struct platform_device *pdev)
@@ -217,7 +440,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
217 dev_err(domain->dev, "Failed to get domain's regulator\n"); 440 dev_err(domain->dev, "Failed to get domain's regulator\n");
218 return PTR_ERR(domain->regulator); 441 return PTR_ERR(domain->regulator);
219 } 442 }
220 } else { 443 } else if (domain->voltage) {
221 regulator_set_voltage(domain->regulator, 444 regulator_set_voltage(domain->regulator,
222 domain->voltage, domain->voltage); 445 domain->voltage, domain->voltage);
223 } 446 }
@@ -265,27 +488,15 @@ builtin_platform_driver(imx_pgc_domain_driver)
265 488
266static int imx_gpcv2_probe(struct platform_device *pdev) 489static int imx_gpcv2_probe(struct platform_device *pdev)
267{ 490{
268 static const struct imx_pgc_domain_data *domain_data; 491 const struct imx_pgc_domain_data *domain_data =
269 static const struct regmap_range yes_ranges[] = { 492 of_device_get_match_data(&pdev->dev);
270 regmap_reg_range(GPC_LPCR_A_CORE_BSC, 493
271 GPC_M4_PU_PDN_FLG), 494 struct regmap_config regmap_config = {
272 regmap_reg_range(GPC_PGC_CTRL(PGC_MIPI),
273 GPC_PGC_SR(PGC_MIPI)),
274 regmap_reg_range(GPC_PGC_CTRL(PGC_PCIE),
275 GPC_PGC_SR(PGC_PCIE)),
276 regmap_reg_range(GPC_PGC_CTRL(PGC_USB_HSIC),
277 GPC_PGC_SR(PGC_USB_HSIC)),
278 };
279 static const struct regmap_access_table access_table = {
280 .yes_ranges = yes_ranges,
281 .n_yes_ranges = ARRAY_SIZE(yes_ranges),
282 };
283 static const struct regmap_config regmap_config = {
284 .reg_bits = 32, 495 .reg_bits = 32,
285 .val_bits = 32, 496 .val_bits = 32,
286 .reg_stride = 4, 497 .reg_stride = 4,
287 .rd_table = &access_table, 498 .rd_table = domain_data->reg_access_table,
288 .wr_table = &access_table, 499 .wr_table = domain_data->reg_access_table,
289 .max_register = SZ_4K, 500 .max_register = SZ_4K,
290 }; 501 };
291 struct device *dev = &pdev->dev; 502 struct device *dev = &pdev->dev;
@@ -313,8 +524,6 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
313 return ret; 524 return ret;
314 } 525 }
315 526
316 domain_data = of_device_get_match_data(&pdev->dev);
317
318 for_each_child_of_node(pgc_np, np) { 527 for_each_child_of_node(pgc_np, np) {
319 struct platform_device *pd_pdev; 528 struct platform_device *pd_pdev;
320 struct imx_pgc_domain *domain; 529 struct imx_pgc_domain *domain;
@@ -372,6 +581,7 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
372 581
373static const struct of_device_id imx_gpcv2_dt_ids[] = { 582static const struct of_device_id imx_gpcv2_dt_ids[] = {
374 { .compatible = "fsl,imx7d-gpc", .data = &imx7_pgc_domain_data, }, 583 { .compatible = "fsl,imx7d-gpc", .data = &imx7_pgc_domain_data, },
584 { .compatible = "fsl,imx8mq-gpc", .data = &imx8m_pgc_domain_data, },
375 { } 585 { }
376}; 586};
377 587
diff --git a/drivers/soc/mediatek/Kconfig b/drivers/soc/mediatek/Kconfig
index a7d0667338f2..17bd7590464f 100644
--- a/drivers/soc/mediatek/Kconfig
+++ b/drivers/soc/mediatek/Kconfig
@@ -4,6 +4,18 @@
4menu "MediaTek SoC drivers" 4menu "MediaTek SoC drivers"
5 depends on ARCH_MEDIATEK || COMPILE_TEST 5 depends on ARCH_MEDIATEK || COMPILE_TEST
6 6
7config MTK_CMDQ
8 tristate "MediaTek CMDQ Support"
9 depends on ARCH_MEDIATEK || COMPILE_TEST
10 select MAILBOX
11 select MTK_CMDQ_MBOX
12 select MTK_INFRACFG
13 help
14 Say yes here to add support for the MediaTek Command Queue (CMDQ)
15 driver. The CMDQ is used to help read/write registers with critical
16 time limitation, such as updating display configuration during the
17 vblank.
18
7config MTK_INFRACFG 19config MTK_INFRACFG
8 bool "MediaTek INFRACFG Support" 20 bool "MediaTek INFRACFG Support"
9 select REGMAP 21 select REGMAP
diff --git a/drivers/soc/mediatek/Makefile b/drivers/soc/mediatek/Makefile
index 12998b08819e..64ce5eeaba32 100644
--- a/drivers/soc/mediatek/Makefile
+++ b/drivers/soc/mediatek/Makefile
@@ -1,3 +1,4 @@
1obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
1obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o 2obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
2obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o 3obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
3obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o 4obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
diff --git a/drivers/soc/mediatek/mtk-cmdq-helper.c b/drivers/soc/mediatek/mtk-cmdq-helper.c
new file mode 100644
index 000000000000..ff9fef5a032b
--- /dev/null
+++ b/drivers/soc/mediatek/mtk-cmdq-helper.c
@@ -0,0 +1,300 @@
1// SPDX-License-Identifier: GPL-2.0
2//
3// Copyright (c) 2018 MediaTek Inc.
4
5#include <linux/completion.h>
6#include <linux/errno.h>
7#include <linux/dma-mapping.h>
8#include <linux/module.h>
9#include <linux/mailbox_controller.h>
10#include <linux/soc/mediatek/mtk-cmdq.h>
11
12#define CMDQ_ARG_A_WRITE_MASK 0xffff
13#define CMDQ_WRITE_ENABLE_MASK BIT(0)
14#define CMDQ_EOC_IRQ_EN BIT(0)
15#define CMDQ_EOC_CMD ((u64)((CMDQ_CODE_EOC << CMDQ_OP_CODE_SHIFT)) \
16 << 32 | CMDQ_EOC_IRQ_EN)
17
18static void cmdq_client_timeout(struct timer_list *t)
19{
20 struct cmdq_client *client = from_timer(client, t, timer);
21
22 dev_err(client->client.dev, "cmdq timeout!\n");
23}
24
25struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 timeout)
26{
27 struct cmdq_client *client;
28
29 client = kzalloc(sizeof(*client), GFP_KERNEL);
30 if (!client)
31 return (struct cmdq_client *)-ENOMEM;
32
33 client->timeout_ms = timeout;
34 if (timeout != CMDQ_NO_TIMEOUT) {
35 spin_lock_init(&client->lock);
36 timer_setup(&client->timer, cmdq_client_timeout, 0);
37 }
38 client->pkt_cnt = 0;
39 client->client.dev = dev;
40 client->client.tx_block = false;
41 client->chan = mbox_request_channel(&client->client, index);
42
43 if (IS_ERR(client->chan)) {
44 long err;
45
46 dev_err(dev, "failed to request channel\n");
47 err = PTR_ERR(client->chan);
48 kfree(client);
49
50 return ERR_PTR(err);
51 }
52
53 return client;
54}
55EXPORT_SYMBOL(cmdq_mbox_create);
56
57void cmdq_mbox_destroy(struct cmdq_client *client)
58{
59 if (client->timeout_ms != CMDQ_NO_TIMEOUT) {
60 spin_lock(&client->lock);
61 del_timer_sync(&client->timer);
62 spin_unlock(&client->lock);
63 }
64 mbox_free_channel(client->chan);
65 kfree(client);
66}
67EXPORT_SYMBOL(cmdq_mbox_destroy);
68
69struct cmdq_pkt *cmdq_pkt_create(struct cmdq_client *client, size_t size)
70{
71 struct cmdq_pkt *pkt;
72 struct device *dev;
73 dma_addr_t dma_addr;
74
75 pkt = kzalloc(sizeof(*pkt), GFP_KERNEL);
76 if (!pkt)
77 return ERR_PTR(-ENOMEM);
78 pkt->va_base = kzalloc(size, GFP_KERNEL);
79 if (!pkt->va_base) {
80 kfree(pkt);
81 return ERR_PTR(-ENOMEM);
82 }
83 pkt->buf_size = size;
84 pkt->cl = (void *)client;
85
86 dev = client->chan->mbox->dev;
87 dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size,
88 DMA_TO_DEVICE);
89 if (dma_mapping_error(dev, dma_addr)) {
90 dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size);
91 kfree(pkt->va_base);
92 kfree(pkt);
93 return ERR_PTR(-ENOMEM);
94 }
95
96 pkt->pa_base = dma_addr;
97
98 return pkt;
99}
100EXPORT_SYMBOL(cmdq_pkt_create);
101
102void cmdq_pkt_destroy(struct cmdq_pkt *pkt)
103{
104 struct cmdq_client *client = (struct cmdq_client *)pkt->cl;
105
106 dma_unmap_single(client->chan->mbox->dev, pkt->pa_base, pkt->buf_size,
107 DMA_TO_DEVICE);
108 kfree(pkt->va_base);
109 kfree(pkt);
110}
111EXPORT_SYMBOL(cmdq_pkt_destroy);
112
113static int cmdq_pkt_append_command(struct cmdq_pkt *pkt, enum cmdq_code code,
114 u32 arg_a, u32 arg_b)
115{
116 u64 *cmd_ptr;
117
118 if (unlikely(pkt->cmd_buf_size + CMDQ_INST_SIZE > pkt->buf_size)) {
119 /*
120 * In the case of allocated buffer size (pkt->buf_size) is used
121 * up, the real required size (pkt->cmdq_buf_size) is still
122 * increased, so that the user knows how much memory should be
123 * ultimately allocated after appending all commands and
124 * flushing the command packet. Therefor, the user can call
125 * cmdq_pkt_create() again with the real required buffer size.
126 */
127 pkt->cmd_buf_size += CMDQ_INST_SIZE;
128 WARN_ONCE(1, "%s: buffer size %u is too small !\n",
129 __func__, (u32)pkt->buf_size);
130 return -ENOMEM;
131 }
132 cmd_ptr = pkt->va_base + pkt->cmd_buf_size;
133 (*cmd_ptr) = (u64)((code << CMDQ_OP_CODE_SHIFT) | arg_a) << 32 | arg_b;
134 pkt->cmd_buf_size += CMDQ_INST_SIZE;
135
136 return 0;
137}
138
139int cmdq_pkt_write(struct cmdq_pkt *pkt, u32 value, u32 subsys, u32 offset)
140{
141 u32 arg_a = (offset & CMDQ_ARG_A_WRITE_MASK) |
142 (subsys << CMDQ_SUBSYS_SHIFT);
143
144 return cmdq_pkt_append_command(pkt, CMDQ_CODE_WRITE, arg_a, value);
145}
146EXPORT_SYMBOL(cmdq_pkt_write);
147
148int cmdq_pkt_write_mask(struct cmdq_pkt *pkt, u32 value,
149 u32 subsys, u32 offset, u32 mask)
150{
151 u32 offset_mask = offset;
152 int err = 0;
153
154 if (mask != 0xffffffff) {
155 err = cmdq_pkt_append_command(pkt, CMDQ_CODE_MASK, 0, ~mask);
156 offset_mask |= CMDQ_WRITE_ENABLE_MASK;
157 }
158 err |= cmdq_pkt_write(pkt, value, subsys, offset_mask);
159
160 return err;
161}
162EXPORT_SYMBOL(cmdq_pkt_write_mask);
163
164int cmdq_pkt_wfe(struct cmdq_pkt *pkt, u32 event)
165{
166 u32 arg_b;
167
168 if (event >= CMDQ_MAX_EVENT)
169 return -EINVAL;
170
171 /*
172 * WFE arg_b
173 * bit 0-11: wait value
174 * bit 15: 1 - wait, 0 - no wait
175 * bit 16-27: update value
176 * bit 31: 1 - update, 0 - no update
177 */
178 arg_b = CMDQ_WFE_UPDATE | CMDQ_WFE_WAIT | CMDQ_WFE_WAIT_VALUE;
179
180 return cmdq_pkt_append_command(pkt, CMDQ_CODE_WFE, event, arg_b);
181}
182EXPORT_SYMBOL(cmdq_pkt_wfe);
183
184int cmdq_pkt_clear_event(struct cmdq_pkt *pkt, u32 event)
185{
186 if (event >= CMDQ_MAX_EVENT)
187 return -EINVAL;
188
189 return cmdq_pkt_append_command(pkt, CMDQ_CODE_WFE, event,
190 CMDQ_WFE_UPDATE);
191}
192EXPORT_SYMBOL(cmdq_pkt_clear_event);
193
194static int cmdq_pkt_finalize(struct cmdq_pkt *pkt)
195{
196 int err;
197
198 /* insert EOC and generate IRQ for each command iteration */
199 err = cmdq_pkt_append_command(pkt, CMDQ_CODE_EOC, 0, CMDQ_EOC_IRQ_EN);
200
201 /* JUMP to end */
202 err |= cmdq_pkt_append_command(pkt, CMDQ_CODE_JUMP, 0, CMDQ_JUMP_PASS);
203
204 return err;
205}
206
207static void cmdq_pkt_flush_async_cb(struct cmdq_cb_data data)
208{
209 struct cmdq_pkt *pkt = (struct cmdq_pkt *)data.data;
210 struct cmdq_task_cb *cb = &pkt->cb;
211 struct cmdq_client *client = (struct cmdq_client *)pkt->cl;
212
213 if (client->timeout_ms != CMDQ_NO_TIMEOUT) {
214 unsigned long flags = 0;
215
216 spin_lock_irqsave(&client->lock, flags);
217 if (--client->pkt_cnt == 0)
218 del_timer(&client->timer);
219 else
220 mod_timer(&client->timer, jiffies +
221 msecs_to_jiffies(client->timeout_ms));
222 spin_unlock_irqrestore(&client->lock, flags);
223 }
224
225 dma_sync_single_for_cpu(client->chan->mbox->dev, pkt->pa_base,
226 pkt->cmd_buf_size, DMA_TO_DEVICE);
227 if (cb->cb) {
228 data.data = cb->data;
229 cb->cb(data);
230 }
231}
232
233int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb,
234 void *data)
235{
236 int err;
237 unsigned long flags = 0;
238 struct cmdq_client *client = (struct cmdq_client *)pkt->cl;
239
240 err = cmdq_pkt_finalize(pkt);
241 if (err < 0)
242 return err;
243
244 pkt->cb.cb = cb;
245 pkt->cb.data = data;
246 pkt->async_cb.cb = cmdq_pkt_flush_async_cb;
247 pkt->async_cb.data = pkt;
248
249 dma_sync_single_for_device(client->chan->mbox->dev, pkt->pa_base,
250 pkt->cmd_buf_size, DMA_TO_DEVICE);
251
252 if (client->timeout_ms != CMDQ_NO_TIMEOUT) {
253 spin_lock_irqsave(&client->lock, flags);
254 if (client->pkt_cnt++ == 0)
255 mod_timer(&client->timer, jiffies +
256 msecs_to_jiffies(client->timeout_ms));
257 spin_unlock_irqrestore(&client->lock, flags);
258 }
259
260 mbox_send_message(client->chan, pkt);
261 /* We can send next packet immediately, so just call txdone. */
262 mbox_client_txdone(client->chan, 0);
263
264 return 0;
265}
266EXPORT_SYMBOL(cmdq_pkt_flush_async);
267
268struct cmdq_flush_completion {
269 struct completion cmplt;
270 bool err;
271};
272
273static void cmdq_pkt_flush_cb(struct cmdq_cb_data data)
274{
275 struct cmdq_flush_completion *cmplt;
276
277 cmplt = (struct cmdq_flush_completion *)data.data;
278 if (data.sta != CMDQ_CB_NORMAL)
279 cmplt->err = true;
280 else
281 cmplt->err = false;
282 complete(&cmplt->cmplt);
283}
284
285int cmdq_pkt_flush(struct cmdq_pkt *pkt)
286{
287 struct cmdq_flush_completion cmplt;
288 int err;
289
290 init_completion(&cmplt.cmplt);
291 err = cmdq_pkt_flush_async(pkt, cmdq_pkt_flush_cb, &cmplt);
292 if (err < 0)
293 return err;
294 wait_for_completion(&cmplt.cmplt);
295
296 return cmplt.err ? -EFAULT : 0;
297}
298EXPORT_SYMBOL(cmdq_pkt_flush);
299
300MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 684cb51694d1..fcbf8a2e4080 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -75,11 +75,6 @@ config QCOM_QMI_HELPERS
75 tristate 75 tristate
76 depends on ARCH_QCOM || COMPILE_TEST 76 depends on ARCH_QCOM || COMPILE_TEST
77 depends on NET 77 depends on NET
78 help
79 Helper library for handling QMI encoded messages. QMI encoded
80 messages are used in communication between the majority of QRTR
81 clients and this helpers provide the common functionality needed for
82 doing this from a kernel driver.
83 78
84config QCOM_RMTFS_MEM 79config QCOM_RMTFS_MEM
85 tristate "Qualcomm Remote Filesystem memory driver" 80 tristate "Qualcomm Remote Filesystem memory driver"
diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index a6f646295f06..c701b3b010f1 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -101,8 +101,7 @@ static bool cmd_db_magic_matches(const struct cmd_db_header *header)
101 101
102static struct cmd_db_header *cmd_db_header; 102static struct cmd_db_header *cmd_db_header;
103 103
104 104static inline const void *rsc_to_entry_header(const struct rsc_hdr *hdr)
105static inline void *rsc_to_entry_header(struct rsc_hdr *hdr)
106{ 105{
107 u16 offset = le16_to_cpu(hdr->header_offset); 106 u16 offset = le16_to_cpu(hdr->header_offset);
108 107
@@ -110,7 +109,7 @@ static inline void *rsc_to_entry_header(struct rsc_hdr *hdr)
110} 109}
111 110
112static inline void * 111static inline void *
113rsc_offset(struct rsc_hdr *hdr, struct entry_header *ent) 112rsc_offset(const struct rsc_hdr *hdr, const struct entry_header *ent)
114{ 113{
115 u16 offset = le16_to_cpu(hdr->data_offset); 114 u16 offset = le16_to_cpu(hdr->data_offset);
116 u16 loffset = le16_to_cpu(ent->offset); 115 u16 loffset = le16_to_cpu(ent->offset);
@@ -134,11 +133,11 @@ int cmd_db_ready(void)
134} 133}
135EXPORT_SYMBOL(cmd_db_ready); 134EXPORT_SYMBOL(cmd_db_ready);
136 135
137static int cmd_db_get_header(const char *id, struct entry_header *eh, 136static int cmd_db_get_header(const char *id, const struct entry_header **eh,
138 struct rsc_hdr *rh) 137 const struct rsc_hdr **rh)
139{ 138{
140 struct rsc_hdr *rsc_hdr; 139 const struct rsc_hdr *rsc_hdr;
141 struct entry_header *ent; 140 const struct entry_header *ent;
142 int ret, i, j; 141 int ret, i, j;
143 u8 query[8]; 142 u8 query[8];
144 143
@@ -146,9 +145,6 @@ static int cmd_db_get_header(const char *id, struct entry_header *eh,
146 if (ret) 145 if (ret)
147 return ret; 146 return ret;
148 147
149 if (!eh || !rh)
150 return -EINVAL;
151
152 /* Pad out query string to same length as in DB */ 148 /* Pad out query string to same length as in DB */
153 strncpy(query, id, sizeof(query)); 149 strncpy(query, id, sizeof(query));
154 150
@@ -159,14 +155,13 @@ static int cmd_db_get_header(const char *id, struct entry_header *eh,
159 155
160 ent = rsc_to_entry_header(rsc_hdr); 156 ent = rsc_to_entry_header(rsc_hdr);
161 for (j = 0; j < le16_to_cpu(rsc_hdr->cnt); j++, ent++) { 157 for (j = 0; j < le16_to_cpu(rsc_hdr->cnt); j++, ent++) {
162 if (memcmp(ent->id, query, sizeof(ent->id)) == 0) 158 if (memcmp(ent->id, query, sizeof(ent->id)) == 0) {
163 break; 159 if (eh)
164 } 160 *eh = ent;
165 161 if (rh)
166 if (j < le16_to_cpu(rsc_hdr->cnt)) { 162 *rh = rsc_hdr;
167 memcpy(eh, ent, sizeof(*ent)); 163 return 0;
168 memcpy(rh, rsc_hdr, sizeof(*rh)); 164 }
169 return 0;
170 } 165 }
171 } 166 }
172 167
@@ -186,69 +181,40 @@ static int cmd_db_get_header(const char *id, struct entry_header *eh,
186u32 cmd_db_read_addr(const char *id) 181u32 cmd_db_read_addr(const char *id)
187{ 182{
188 int ret; 183 int ret;
189 struct entry_header ent; 184 const struct entry_header *ent;
190 struct rsc_hdr rsc_hdr;
191 185
192 ret = cmd_db_get_header(id, &ent, &rsc_hdr); 186 ret = cmd_db_get_header(id, &ent, NULL);
193 187
194 return ret < 0 ? 0 : le32_to_cpu(ent.addr); 188 return ret < 0 ? 0 : le32_to_cpu(ent->addr);
195} 189}
196EXPORT_SYMBOL(cmd_db_read_addr); 190EXPORT_SYMBOL(cmd_db_read_addr);
197 191
198/** 192/**
199 * cmd_db_read_aux_data() - Query command db for aux data. 193 * cmd_db_read_aux_data() - Query command db for aux data.
200 * 194 *
201 * @id: Resource to retrieve AUX Data on. 195 * @id: Resource to retrieve AUX Data on
202 * @data: Data buffer to copy returned aux data to. Returns size on NULL 196 * @len: size of data buffer returned
203 * @len: Caller provides size of data buffer passed in.
204 * 197 *
205 * Return: size of data on success, errno otherwise 198 * Return: pointer to data on success, error pointer otherwise
206 */ 199 */
207int cmd_db_read_aux_data(const char *id, u8 *data, size_t len) 200const void *cmd_db_read_aux_data(const char *id, size_t *len)
208{ 201{
209 int ret; 202 int ret;
210 struct entry_header ent; 203 const struct entry_header *ent;
211 struct rsc_hdr rsc_hdr; 204 const struct rsc_hdr *rsc_hdr;
212 u16 ent_len;
213
214 if (!data)
215 return -EINVAL;
216 205
217 ret = cmd_db_get_header(id, &ent, &rsc_hdr); 206 ret = cmd_db_get_header(id, &ent, &rsc_hdr);
218 if (ret) 207 if (ret)
219 return ret; 208 return ERR_PTR(ret);
220 209
221 ent_len = le16_to_cpu(ent.len); 210 if (len)
222 if (len < ent_len) 211 *len = le16_to_cpu(ent->len);
223 return -EINVAL;
224
225 len = min_t(u16, ent_len, len);
226 memcpy(data, rsc_offset(&rsc_hdr, &ent), len);
227 212
228 return len; 213 return rsc_offset(rsc_hdr, ent);
229} 214}
230EXPORT_SYMBOL(cmd_db_read_aux_data); 215EXPORT_SYMBOL(cmd_db_read_aux_data);
231 216
232/** 217/**
233 * cmd_db_read_aux_data_len - Get the length of the auxiliary data stored in DB.
234 *
235 * @id: Resource to retrieve AUX Data.
236 *
237 * Return: size on success, 0 on error
238 */
239size_t cmd_db_read_aux_data_len(const char *id)
240{
241 int ret;
242 struct entry_header ent;
243 struct rsc_hdr rsc_hdr;
244
245 ret = cmd_db_get_header(id, &ent, &rsc_hdr);
246
247 return ret < 0 ? 0 : le16_to_cpu(ent.len);
248}
249EXPORT_SYMBOL(cmd_db_read_aux_data_len);
250
251/**
252 * cmd_db_read_slave_id - Get the slave ID for a given resource address 218 * cmd_db_read_slave_id - Get the slave ID for a given resource address
253 * 219 *
254 * @id: Resource id to query the DB for version 220 * @id: Resource id to query the DB for version
@@ -258,15 +224,14 @@ EXPORT_SYMBOL(cmd_db_read_aux_data_len);
258enum cmd_db_hw_type cmd_db_read_slave_id(const char *id) 224enum cmd_db_hw_type cmd_db_read_slave_id(const char *id)
259{ 225{
260 int ret; 226 int ret;
261 struct entry_header ent; 227 const struct entry_header *ent;
262 struct rsc_hdr rsc_hdr;
263 u32 addr; 228 u32 addr;
264 229
265 ret = cmd_db_get_header(id, &ent, &rsc_hdr); 230 ret = cmd_db_get_header(id, &ent, NULL);
266 if (ret < 0) 231 if (ret < 0)
267 return CMD_DB_HW_INVALID; 232 return CMD_DB_HW_INVALID;
268 233
269 addr = le32_to_cpu(ent.addr); 234 addr = le32_to_cpu(ent->addr);
270 return (addr >> SLAVE_ID_SHIFT) & SLAVE_ID_MASK; 235 return (addr >> SLAVE_ID_SHIFT) & SLAVE_ID_MASK;
271} 236}
272EXPORT_SYMBOL(cmd_db_read_slave_id); 237EXPORT_SYMBOL(cmd_db_read_slave_id);
diff --git a/drivers/soc/qcom/llcc-slice.c b/drivers/soc/qcom/llcc-slice.c
index 192ca761b2cb..80667f7be52c 100644
--- a/drivers/soc/qcom/llcc-slice.c
+++ b/drivers/soc/qcom/llcc-slice.c
@@ -95,7 +95,8 @@ EXPORT_SYMBOL_GPL(llcc_slice_getd);
95 */ 95 */
96void llcc_slice_putd(struct llcc_slice_desc *desc) 96void llcc_slice_putd(struct llcc_slice_desc *desc)
97{ 97{
98 kfree(desc); 98 if (!IS_ERR_OR_NULL(desc))
99 kfree(desc);
99} 100}
100EXPORT_SYMBOL_GPL(llcc_slice_putd); 101EXPORT_SYMBOL_GPL(llcc_slice_putd);
101 102
@@ -142,6 +143,9 @@ int llcc_slice_activate(struct llcc_slice_desc *desc)
142 int ret; 143 int ret;
143 u32 act_ctrl_val; 144 u32 act_ctrl_val;
144 145
146 if (IS_ERR_OR_NULL(desc))
147 return -EINVAL;
148
145 mutex_lock(&drv_data->lock); 149 mutex_lock(&drv_data->lock);
146 if (test_bit(desc->slice_id, drv_data->bitmap)) { 150 if (test_bit(desc->slice_id, drv_data->bitmap)) {
147 mutex_unlock(&drv_data->lock); 151 mutex_unlock(&drv_data->lock);
@@ -176,6 +180,9 @@ int llcc_slice_deactivate(struct llcc_slice_desc *desc)
176 u32 act_ctrl_val; 180 u32 act_ctrl_val;
177 int ret; 181 int ret;
178 182
183 if (IS_ERR_OR_NULL(desc))
184 return -EINVAL;
185
179 mutex_lock(&drv_data->lock); 186 mutex_lock(&drv_data->lock);
180 if (!test_bit(desc->slice_id, drv_data->bitmap)) { 187 if (!test_bit(desc->slice_id, drv_data->bitmap)) {
181 mutex_unlock(&drv_data->lock); 188 mutex_unlock(&drv_data->lock);
@@ -203,6 +210,9 @@ EXPORT_SYMBOL_GPL(llcc_slice_deactivate);
203 */ 210 */
204int llcc_get_slice_id(struct llcc_slice_desc *desc) 211int llcc_get_slice_id(struct llcc_slice_desc *desc)
205{ 212{
213 if (IS_ERR_OR_NULL(desc))
214 return -EINVAL;
215
206 return desc->slice_id; 216 return desc->slice_id;
207} 217}
208EXPORT_SYMBOL_GPL(llcc_get_slice_id); 218EXPORT_SYMBOL_GPL(llcc_get_slice_id);
@@ -213,6 +223,9 @@ EXPORT_SYMBOL_GPL(llcc_get_slice_id);
213 */ 223 */
214size_t llcc_get_slice_size(struct llcc_slice_desc *desc) 224size_t llcc_get_slice_size(struct llcc_slice_desc *desc)
215{ 225{
226 if (IS_ERR_OR_NULL(desc))
227 return 0;
228
216 return desc->slice_size; 229 return desc->slice_size;
217} 230}
218EXPORT_SYMBOL_GPL(llcc_get_slice_size); 231EXPORT_SYMBOL_GPL(llcc_get_slice_size);
@@ -360,5 +373,5 @@ int qcom_llcc_probe(struct platform_device *pdev,
360 return ret; 373 return ret;
361} 374}
362EXPORT_SYMBOL_GPL(qcom_llcc_probe); 375EXPORT_SYMBOL_GPL(qcom_llcc_probe);
363
364MODULE_LICENSE("GPL v2"); 376MODULE_LICENSE("GPL v2");
377MODULE_DESCRIPTION("Qualcomm Last Level Cache Controller");
diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c
index ee89ffb6dde8..6b8ef01472e9 100644
--- a/drivers/soc/qcom/qcom-geni-se.c
+++ b/drivers/soc/qcom/qcom-geni-se.c
@@ -215,6 +215,16 @@ static void geni_se_io_init(void __iomem *base)
215 writel_relaxed(FORCE_DEFAULT, base + GENI_FORCE_DEFAULT_REG); 215 writel_relaxed(FORCE_DEFAULT, base + GENI_FORCE_DEFAULT_REG);
216} 216}
217 217
218static void geni_se_irq_clear(struct geni_se *se)
219{
220 writel_relaxed(0, se->base + SE_GSI_EVENT_EN);
221 writel_relaxed(0xffffffff, se->base + SE_GENI_M_IRQ_CLEAR);
222 writel_relaxed(0xffffffff, se->base + SE_GENI_S_IRQ_CLEAR);
223 writel_relaxed(0xffffffff, se->base + SE_DMA_TX_IRQ_CLR);
224 writel_relaxed(0xffffffff, se->base + SE_DMA_RX_IRQ_CLR);
225 writel_relaxed(0xffffffff, se->base + SE_IRQ_EN);
226}
227
218/** 228/**
219 * geni_se_init() - Initialize the GENI serial engine 229 * geni_se_init() - Initialize the GENI serial engine
220 * @se: Pointer to the concerned serial engine. 230 * @se: Pointer to the concerned serial engine.
@@ -228,6 +238,7 @@ void geni_se_init(struct geni_se *se, u32 rx_wm, u32 rx_rfr)
228{ 238{
229 u32 val; 239 u32 val;
230 240
241 geni_se_irq_clear(se);
231 geni_se_io_init(se->base); 242 geni_se_io_init(se->base);
232 geni_se_io_set_mode(se->base); 243 geni_se_io_set_mode(se->base);
233 244
@@ -249,12 +260,7 @@ static void geni_se_select_fifo_mode(struct geni_se *se)
249 u32 proto = geni_se_read_proto(se); 260 u32 proto = geni_se_read_proto(se);
250 u32 val; 261 u32 val;
251 262
252 writel_relaxed(0, se->base + SE_GSI_EVENT_EN); 263 geni_se_irq_clear(se);
253 writel_relaxed(0xffffffff, se->base + SE_GENI_M_IRQ_CLEAR);
254 writel_relaxed(0xffffffff, se->base + SE_GENI_S_IRQ_CLEAR);
255 writel_relaxed(0xffffffff, se->base + SE_DMA_TX_IRQ_CLR);
256 writel_relaxed(0xffffffff, se->base + SE_DMA_RX_IRQ_CLR);
257 writel_relaxed(0xffffffff, se->base + SE_IRQ_EN);
258 264
259 val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN); 265 val = readl_relaxed(se->base + SE_GENI_M_IRQ_EN);
260 if (proto != GENI_SE_UART) { 266 if (proto != GENI_SE_UART) {
@@ -277,12 +283,7 @@ static void geni_se_select_dma_mode(struct geni_se *se)
277{ 283{
278 u32 val; 284 u32 val;
279 285
280 writel_relaxed(0, se->base + SE_GSI_EVENT_EN); 286 geni_se_irq_clear(se);
281 writel_relaxed(0xffffffff, se->base + SE_GENI_M_IRQ_CLEAR);
282 writel_relaxed(0xffffffff, se->base + SE_GENI_S_IRQ_CLEAR);
283 writel_relaxed(0xffffffff, se->base + SE_DMA_TX_IRQ_CLR);
284 writel_relaxed(0xffffffff, se->base + SE_DMA_RX_IRQ_CLR);
285 writel_relaxed(0xffffffff, se->base + SE_IRQ_EN);
286 287
287 val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN); 288 val = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
288 val |= GENI_DMA_MODE_EN; 289 val |= GENI_DMA_MODE_EN;
diff --git a/drivers/soc/qcom/qmi_interface.c b/drivers/soc/qcom/qmi_interface.c
index 938ca41c56cd..c239a28e503f 100644
--- a/drivers/soc/qcom/qmi_interface.c
+++ b/drivers/soc/qcom/qmi_interface.c
@@ -318,7 +318,7 @@ int qmi_txn_init(struct qmi_handle *qmi, struct qmi_txn *txn,
318 txn->dest = c_struct; 318 txn->dest = c_struct;
319 319
320 mutex_lock(&qmi->txn_lock); 320 mutex_lock(&qmi->txn_lock);
321 ret = idr_alloc_cyclic(&qmi->txns, txn, 0, INT_MAX, GFP_KERNEL); 321 ret = idr_alloc_cyclic(&qmi->txns, txn, 0, U16_MAX, GFP_KERNEL);
322 if (ret < 0) 322 if (ret < 0)
323 pr_err("failed to allocate transaction id\n"); 323 pr_err("failed to allocate transaction id\n");
324 324
diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index 93517ed83355..b8e63724a49d 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -227,6 +227,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = {
227 { .compatible = "qcom,rpm-msm8974" }, 227 { .compatible = "qcom,rpm-msm8974" },
228 { .compatible = "qcom,rpm-msm8996" }, 228 { .compatible = "qcom,rpm-msm8996" },
229 { .compatible = "qcom,rpm-msm8998" }, 229 { .compatible = "qcom,rpm-msm8998" },
230 { .compatible = "qcom,rpm-qcs404" },
230 {} 231 {}
231}; 232};
232MODULE_DEVICE_TABLE(of, qcom_smd_rpm_of_match); 233MODULE_DEVICE_TABLE(of, qcom_smd_rpm_of_match);
diff --git a/drivers/soc/renesas/r8a77965-sysc.c b/drivers/soc/renesas/r8a77965-sysc.c
index d7f7928e3c07..e0533beb50fd 100644
--- a/drivers/soc/renesas/r8a77965-sysc.c
+++ b/drivers/soc/renesas/r8a77965-sysc.c
@@ -28,7 +28,6 @@ static const struct rcar_sysc_area r8a77965_areas[] __initconst = {
28 { "a2vc1", 0x3c0, 1, R8A77965_PD_A2VC1, R8A77965_PD_A3VC }, 28 { "a2vc1", 0x3c0, 1, R8A77965_PD_A2VC1, R8A77965_PD_A3VC },
29 { "3dg-a", 0x100, 0, R8A77965_PD_3DG_A, R8A77965_PD_ALWAYS_ON }, 29 { "3dg-a", 0x100, 0, R8A77965_PD_3DG_A, R8A77965_PD_ALWAYS_ON },
30 { "3dg-b", 0x100, 1, R8A77965_PD_3DG_B, R8A77965_PD_3DG_A }, 30 { "3dg-b", 0x100, 1, R8A77965_PD_3DG_B, R8A77965_PD_3DG_A },
31 { "a3ir", 0x180, 0, R8A77965_PD_A3IR, R8A77965_PD_ALWAYS_ON },
32}; 31};
33 32
34const struct rcar_sysc_info r8a77965_sysc_info __initconst = { 33const struct rcar_sysc_info r8a77965_sysc_info __initconst = {
diff --git a/drivers/soc/renesas/r8a77970-sysc.c b/drivers/soc/renesas/r8a77970-sysc.c
index 35b30d6a8958..280c48b80f24 100644
--- a/drivers/soc/renesas/r8a77970-sysc.c
+++ b/drivers/soc/renesas/r8a77970-sysc.c
@@ -20,12 +20,11 @@ static const struct rcar_sysc_area r8a77970_areas[] __initconst = {
20 PD_CPU_NOCR }, 20 PD_CPU_NOCR },
21 { "ca53-cpu1", 0x200, 1, R8A77970_PD_CA53_CPU1, R8A77970_PD_CA53_SCU, 21 { "ca53-cpu1", 0x200, 1, R8A77970_PD_CA53_CPU1, R8A77970_PD_CA53_SCU,
22 PD_CPU_NOCR }, 22 PD_CPU_NOCR },
23 { "cr7", 0x240, 0, R8A77970_PD_CR7, R8A77970_PD_ALWAYS_ON },
24 { "a3ir", 0x180, 0, R8A77970_PD_A3IR, R8A77970_PD_ALWAYS_ON }, 23 { "a3ir", 0x180, 0, R8A77970_PD_A3IR, R8A77970_PD_ALWAYS_ON },
25 { "a2ir0", 0x400, 0, R8A77970_PD_A2IR0, R8A77970_PD_A3IR }, 24 { "a2ir0", 0x400, 0, R8A77970_PD_A2IR0, R8A77970_PD_A3IR },
26 { "a2ir1", 0x400, 1, R8A77970_PD_A2IR1, R8A77970_PD_A3IR }, 25 { "a2ir1", 0x400, 1, R8A77970_PD_A2IR1, R8A77970_PD_A3IR },
27 { "a2ir2", 0x400, 2, R8A77970_PD_A2IR2, R8A77970_PD_A3IR }, 26 { "a2dp", 0x400, 2, R8A77970_PD_A2DP, R8A77970_PD_A3IR },
28 { "a2ir3", 0x400, 3, R8A77970_PD_A2IR3, R8A77970_PD_A3IR }, 27 { "a2cn", 0x400, 3, R8A77970_PD_A2CN, R8A77970_PD_A3IR },
29 { "a2sc0", 0x400, 4, R8A77970_PD_A2SC0, R8A77970_PD_A3IR }, 28 { "a2sc0", 0x400, 4, R8A77970_PD_A2SC0, R8A77970_PD_A3IR },
30 { "a2sc1", 0x400, 5, R8A77970_PD_A2SC1, R8A77970_PD_A3IR }, 29 { "a2sc1", 0x400, 5, R8A77970_PD_A2SC1, R8A77970_PD_A3IR },
31}; 30};
diff --git a/drivers/soc/renesas/r8a77980-sysc.c b/drivers/soc/renesas/r8a77980-sysc.c
index 9265fb525ef3..a8dbe55e8ba8 100644
--- a/drivers/soc/renesas/r8a77980-sysc.c
+++ b/drivers/soc/renesas/r8a77980-sysc.c
@@ -38,12 +38,12 @@ static const struct rcar_sysc_area r8a77980_areas[] __initconst = {
38 { "a2sc2", 0x400, 8, R8A77980_PD_A2SC2, R8A77980_PD_A3IR }, 38 { "a2sc2", 0x400, 8, R8A77980_PD_A2SC2, R8A77980_PD_A3IR },
39 { "a2sc3", 0x400, 9, R8A77980_PD_A2SC3, R8A77980_PD_A3IR }, 39 { "a2sc3", 0x400, 9, R8A77980_PD_A2SC3, R8A77980_PD_A3IR },
40 { "a2sc4", 0x400, 10, R8A77980_PD_A2SC4, R8A77980_PD_A3IR }, 40 { "a2sc4", 0x400, 10, R8A77980_PD_A2SC4, R8A77980_PD_A3IR },
41 { "a2pd0", 0x400, 11, R8A77980_PD_A2PD0, R8A77980_PD_A3IR }, 41 { "a2dp0", 0x400, 11, R8A77980_PD_A2DP0, R8A77980_PD_A3IR },
42 { "a2pd1", 0x400, 12, R8A77980_PD_A2PD1, R8A77980_PD_A3IR }, 42 { "a2dp1", 0x400, 12, R8A77980_PD_A2DP1, R8A77980_PD_A3IR },
43 { "a2cn", 0x400, 13, R8A77980_PD_A2CN, R8A77980_PD_A3IR }, 43 { "a2cn", 0x400, 13, R8A77980_PD_A2CN, R8A77980_PD_A3IR },
44 { "a3vip", 0x2c0, 0, R8A77980_PD_A3VIP, R8A77980_PD_ALWAYS_ON }, 44 { "a3vip0", 0x2c0, 0, R8A77980_PD_A3VIP0, R8A77980_PD_ALWAYS_ON },
45 { "a3vip1", 0x300, 0, R8A77980_PD_A3VIP1, R8A77980_PD_A3VIP }, 45 { "a3vip1", 0x300, 0, R8A77980_PD_A3VIP1, R8A77980_PD_ALWAYS_ON },
46 { "a3vip2", 0x280, 0, R8A77980_PD_A3VIP2, R8A77980_PD_A3VIP }, 46 { "a3vip2", 0x280, 0, R8A77980_PD_A3VIP2, R8A77980_PD_ALWAYS_ON },
47}; 47};
48 48
49const struct rcar_sysc_info r8a77980_sysc_info __initconst = { 49const struct rcar_sysc_info r8a77980_sysc_info __initconst = {
diff --git a/drivers/soc/renesas/r8a77990-sysc.c b/drivers/soc/renesas/r8a77990-sysc.c
index 15579ebc5ed2..664b244eb1dd 100644
--- a/drivers/soc/renesas/r8a77990-sysc.c
+++ b/drivers/soc/renesas/r8a77990-sysc.c
@@ -28,19 +28,6 @@ static struct rcar_sysc_area r8a77990_areas[] __initdata = {
28 { "3dg-b", 0x100, 1, R8A77990_PD_3DG_B, R8A77990_PD_3DG_A }, 28 { "3dg-b", 0x100, 1, R8A77990_PD_3DG_B, R8A77990_PD_3DG_A },
29}; 29};
30 30
31static void __init rcar_sysc_fix_parent(struct rcar_sysc_area *areas,
32 unsigned int num_areas, u8 id,
33 int new_parent)
34{
35 unsigned int i;
36
37 for (i = 0; i < num_areas; i++)
38 if (areas[i].isr_bit == id) {
39 areas[i].parent = new_parent;
40 return;
41 }
42}
43
44/* Fixups for R-Car E3 ES1.0 revision */ 31/* Fixups for R-Car E3 ES1.0 revision */
45static const struct soc_device_attribute r8a77990[] __initconst = { 32static const struct soc_device_attribute r8a77990[] __initconst = {
46 { .soc_id = "r8a77990", .revision = "ES1.0" }, 33 { .soc_id = "r8a77990", .revision = "ES1.0" },
@@ -50,12 +37,10 @@ static const struct soc_device_attribute r8a77990[] __initconst = {
50static int __init r8a77990_sysc_init(void) 37static int __init r8a77990_sysc_init(void)
51{ 38{
52 if (soc_device_match(r8a77990)) { 39 if (soc_device_match(r8a77990)) {
53 rcar_sysc_fix_parent(r8a77990_areas, 40 /* Fix incorrect 3DG hierarchy */
54 ARRAY_SIZE(r8a77990_areas), 41 swap(r8a77990_areas[7], r8a77990_areas[8]);
55 R8A77990_PD_3DG_A, R8A77990_PD_3DG_B); 42 r8a77990_areas[7].parent = R8A77990_PD_ALWAYS_ON;
56 rcar_sysc_fix_parent(r8a77990_areas, 43 r8a77990_areas[8].parent = R8A77990_PD_3DG_B;
57 ARRAY_SIZE(r8a77990_areas),
58 R8A77990_PD_3DG_B, R8A77990_PD_ALWAYS_ON);
59 } 44 }
60 45
61 return 0; 46 return 0;
diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c
index af53363eda03..0c80fab4f8de 100644
--- a/drivers/soc/renesas/rcar-sysc.c
+++ b/drivers/soc/renesas/rcar-sysc.c
@@ -105,6 +105,15 @@ static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on)
105 105
106 spin_lock_irqsave(&rcar_sysc_lock, flags); 106 spin_lock_irqsave(&rcar_sysc_lock, flags);
107 107
108 /*
109 * The interrupt source needs to be enabled, but masked, to prevent the
110 * CPU from receiving it.
111 */
112 iowrite32(ioread32(rcar_sysc_base + SYSCIMR) | isr_mask,
113 rcar_sysc_base + SYSCIMR);
114 iowrite32(ioread32(rcar_sysc_base + SYSCIER) | isr_mask,
115 rcar_sysc_base + SYSCIER);
116
108 iowrite32(isr_mask, rcar_sysc_base + SYSCISCR); 117 iowrite32(isr_mask, rcar_sysc_base + SYSCISCR);
109 118
110 /* Submit power shutoff or resume request until it was accepted */ 119 /* Submit power shutoff or resume request until it was accepted */
@@ -146,16 +155,6 @@ static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on)
146 return ret; 155 return ret;
147} 156}
148 157
149static int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch)
150{
151 return rcar_sysc_power(sysc_ch, false);
152}
153
154static int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch)
155{
156 return rcar_sysc_power(sysc_ch, true);
157}
158
159static bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch) 158static bool rcar_sysc_power_is_off(const struct rcar_sysc_ch *sysc_ch)
160{ 159{
161 unsigned int st; 160 unsigned int st;
@@ -184,7 +183,7 @@ static int rcar_sysc_pd_power_off(struct generic_pm_domain *genpd)
184 struct rcar_sysc_pd *pd = to_rcar_pd(genpd); 183 struct rcar_sysc_pd *pd = to_rcar_pd(genpd);
185 184
186 pr_debug("%s: %s\n", __func__, genpd->name); 185 pr_debug("%s: %s\n", __func__, genpd->name);
187 return rcar_sysc_power_down(&pd->ch); 186 return rcar_sysc_power(&pd->ch, false);
188} 187}
189 188
190static int rcar_sysc_pd_power_on(struct generic_pm_domain *genpd) 189static int rcar_sysc_pd_power_on(struct generic_pm_domain *genpd)
@@ -192,7 +191,7 @@ static int rcar_sysc_pd_power_on(struct generic_pm_domain *genpd)
192 struct rcar_sysc_pd *pd = to_rcar_pd(genpd); 191 struct rcar_sysc_pd *pd = to_rcar_pd(genpd);
193 192
194 pr_debug("%s: %s\n", __func__, genpd->name); 193 pr_debug("%s: %s\n", __func__, genpd->name);
195 return rcar_sysc_power_up(&pd->ch); 194 return rcar_sysc_power(&pd->ch, true);
196} 195}
197 196
198static bool has_cpg_mstp; 197static bool has_cpg_mstp;
@@ -252,7 +251,7 @@ static int __init rcar_sysc_pd_setup(struct rcar_sysc_pd *pd)
252 goto finalize; 251 goto finalize;
253 } 252 }
254 253
255 rcar_sysc_power_up(&pd->ch); 254 rcar_sysc_power(&pd->ch, true);
256 255
257finalize: 256finalize:
258 error = pm_genpd_init(genpd, gov, false); 257 error = pm_genpd_init(genpd, gov, false);
@@ -334,7 +333,6 @@ static int __init rcar_sysc_pd_init(void)
334 const struct of_device_id *match; 333 const struct of_device_id *match;
335 struct rcar_pm_domains *domains; 334 struct rcar_pm_domains *domains;
336 struct device_node *np; 335 struct device_node *np;
337 u32 syscier, syscimr;
338 void __iomem *base; 336 void __iomem *base;
339 unsigned int i; 337 unsigned int i;
340 int error; 338 int error;
@@ -373,27 +371,6 @@ static int __init rcar_sysc_pd_init(void)
373 domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains); 371 domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains);
374 rcar_sysc_onecell_data = &domains->onecell_data; 372 rcar_sysc_onecell_data = &domains->onecell_data;
375 373
376 for (i = 0, syscier = 0; i < info->num_areas; i++)
377 syscier |= BIT(info->areas[i].isr_bit);
378
379 /*
380 * Mask all interrupt sources to prevent the CPU from receiving them.
381 * Make sure not to clear reserved bits that were set before.
382 */
383 syscimr = ioread32(base + SYSCIMR);
384 syscimr |= syscier;
385 pr_debug("%pOF: syscimr = 0x%08x\n", np, syscimr);
386 iowrite32(syscimr, base + SYSCIMR);
387
388 /*
389 * SYSC needs all interrupt sources enabled to control power.
390 */
391 pr_debug("%pOF: syscier = 0x%08x\n", np, syscier);
392 iowrite32(syscier, base + SYSCIER);
393
394 /*
395 * First, create all PM domains
396 */
397 for (i = 0; i < info->num_areas; i++) { 374 for (i = 0; i < info->num_areas; i++) {
398 const struct rcar_sysc_area *area = &info->areas[i]; 375 const struct rcar_sysc_area *area = &info->areas[i];
399 struct rcar_sysc_pd *pd; 376 struct rcar_sysc_pd *pd;
@@ -421,22 +398,17 @@ static int __init rcar_sysc_pd_init(void)
421 goto out_put; 398 goto out_put;
422 399
423 domains->domains[area->isr_bit] = &pd->genpd; 400 domains->domains[area->isr_bit] = &pd->genpd;
424 }
425 401
426 /* 402 if (area->parent < 0)
427 * Second, link all PM domains to their parents
428 */
429 for (i = 0; i < info->num_areas; i++) {
430 const struct rcar_sysc_area *area = &info->areas[i];
431
432 if (!area->name || area->parent < 0)
433 continue; 403 continue;
434 404
435 error = pm_genpd_add_subdomain(domains->domains[area->parent], 405 error = pm_genpd_add_subdomain(domains->domains[area->parent],
436 domains->domains[area->isr_bit]); 406 &pd->genpd);
437 if (error) 407 if (error) {
438 pr_warn("Failed to add PM subdomain %s to parent %u\n", 408 pr_warn("Failed to add PM subdomain %s to parent %u\n",
439 area->name, area->parent); 409 area->name, area->parent);
410 goto out_put;
411 }
440 } 412 }
441 413
442 error = of_genpd_add_provider_onecell(np, &domains->onecell_data); 414 error = of_genpd_add_provider_onecell(np, &domains->onecell_data);
@@ -478,8 +450,7 @@ static int rcar_sysc_power_cpu(unsigned int idx, bool on)
478 if (!(pd->flags & PD_CPU) || pd->ch.chan_bit != idx) 450 if (!(pd->flags & PD_CPU) || pd->ch.chan_bit != idx)
479 continue; 451 continue;
480 452
481 return on ? rcar_sysc_power_up(&pd->ch) 453 return rcar_sysc_power(&pd->ch, on);
482 : rcar_sysc_power_down(&pd->ch);
483 } 454 }
484 455
485 return -ENOENT; 456 return -ENOENT;
diff --git a/drivers/soc/rockchip/pm_domains.c b/drivers/soc/rockchip/pm_domains.c
index 6f86a726bb45..847c7c482b26 100644
--- a/drivers/soc/rockchip/pm_domains.c
+++ b/drivers/soc/rockchip/pm_domains.c
@@ -21,7 +21,9 @@
21#include <linux/mfd/syscon.h> 21#include <linux/mfd/syscon.h>
22#include <dt-bindings/power/px30-power.h> 22#include <dt-bindings/power/px30-power.h>
23#include <dt-bindings/power/rk3036-power.h> 23#include <dt-bindings/power/rk3036-power.h>
24#include <dt-bindings/power/rk3066-power.h>
24#include <dt-bindings/power/rk3128-power.h> 25#include <dt-bindings/power/rk3128-power.h>
26#include <dt-bindings/power/rk3188-power.h>
25#include <dt-bindings/power/rk3228-power.h> 27#include <dt-bindings/power/rk3228-power.h>
26#include <dt-bindings/power/rk3288-power.h> 28#include <dt-bindings/power/rk3288-power.h>
27#include <dt-bindings/power/rk3328-power.h> 29#include <dt-bindings/power/rk3328-power.h>
@@ -737,6 +739,14 @@ static const struct rockchip_domain_info rk3036_pm_domains[] = {
737 [RK3036_PD_SYS] = DOMAIN_RK3036(8, 22, 29, false), 739 [RK3036_PD_SYS] = DOMAIN_RK3036(8, 22, 29, false),
738}; 740};
739 741
742static const struct rockchip_domain_info rk3066_pm_domains[] = {
743 [RK3066_PD_GPU] = DOMAIN(9, 9, 3, 24, 29, false),
744 [RK3066_PD_VIDEO] = DOMAIN(8, 8, 4, 23, 28, false),
745 [RK3066_PD_VIO] = DOMAIN(7, 7, 5, 22, 27, false),
746 [RK3066_PD_PERI] = DOMAIN(6, 6, 2, 25, 30, false),
747 [RK3066_PD_CPU] = DOMAIN(-1, 5, 1, 26, 31, false),
748};
749
740static const struct rockchip_domain_info rk3128_pm_domains[] = { 750static const struct rockchip_domain_info rk3128_pm_domains[] = {
741 [RK3128_PD_CORE] = DOMAIN_RK3288(0, 0, 4, false), 751 [RK3128_PD_CORE] = DOMAIN_RK3288(0, 0, 4, false),
742 [RK3128_PD_MSCH] = DOMAIN_RK3288(-1, -1, 6, true), 752 [RK3128_PD_MSCH] = DOMAIN_RK3288(-1, -1, 6, true),
@@ -745,6 +755,14 @@ static const struct rockchip_domain_info rk3128_pm_domains[] = {
745 [RK3128_PD_GPU] = DOMAIN_RK3288(1, 1, 3, false), 755 [RK3128_PD_GPU] = DOMAIN_RK3288(1, 1, 3, false),
746}; 756};
747 757
758static const struct rockchip_domain_info rk3188_pm_domains[] = {
759 [RK3188_PD_GPU] = DOMAIN(9, 9, 3, 24, 29, false),
760 [RK3188_PD_VIDEO] = DOMAIN(8, 8, 4, 23, 28, false),
761 [RK3188_PD_VIO] = DOMAIN(7, 7, 5, 22, 27, false),
762 [RK3188_PD_PERI] = DOMAIN(6, 6, 2, 25, 30, false),
763 [RK3188_PD_CPU] = DOMAIN(5, 5, 1, 26, 31, false),
764};
765
748static const struct rockchip_domain_info rk3228_pm_domains[] = { 766static const struct rockchip_domain_info rk3228_pm_domains[] = {
749 [RK3228_PD_CORE] = DOMAIN_RK3036(0, 0, 16, true), 767 [RK3228_PD_CORE] = DOMAIN_RK3036(0, 0, 16, true),
750 [RK3228_PD_MSCH] = DOMAIN_RK3036(1, 1, 17, true), 768 [RK3228_PD_MSCH] = DOMAIN_RK3036(1, 1, 17, true),
@@ -846,6 +864,17 @@ static const struct rockchip_pmu_info rk3036_pmu = {
846 .domain_info = rk3036_pm_domains, 864 .domain_info = rk3036_pm_domains,
847}; 865};
848 866
867static const struct rockchip_pmu_info rk3066_pmu = {
868 .pwr_offset = 0x08,
869 .status_offset = 0x0c,
870 .req_offset = 0x38, /* PMU_MISC_CON1 */
871 .idle_offset = 0x0c,
872 .ack_offset = 0x0c,
873
874 .num_domains = ARRAY_SIZE(rk3066_pm_domains),
875 .domain_info = rk3066_pm_domains,
876};
877
849static const struct rockchip_pmu_info rk3128_pmu = { 878static const struct rockchip_pmu_info rk3128_pmu = {
850 .pwr_offset = 0x04, 879 .pwr_offset = 0x04,
851 .status_offset = 0x08, 880 .status_offset = 0x08,
@@ -857,6 +886,17 @@ static const struct rockchip_pmu_info rk3128_pmu = {
857 .domain_info = rk3128_pm_domains, 886 .domain_info = rk3128_pm_domains,
858}; 887};
859 888
889static const struct rockchip_pmu_info rk3188_pmu = {
890 .pwr_offset = 0x08,
891 .status_offset = 0x0c,
892 .req_offset = 0x38, /* PMU_MISC_CON1 */
893 .idle_offset = 0x0c,
894 .ack_offset = 0x0c,
895
896 .num_domains = ARRAY_SIZE(rk3188_pm_domains),
897 .domain_info = rk3188_pm_domains,
898};
899
860static const struct rockchip_pmu_info rk3228_pmu = { 900static const struct rockchip_pmu_info rk3228_pmu = {
861 .req_offset = 0x40c, 901 .req_offset = 0x40c,
862 .idle_offset = 0x488, 902 .idle_offset = 0x488,
@@ -949,10 +989,18 @@ static const struct of_device_id rockchip_pm_domain_dt_match[] = {
949 .data = (void *)&rk3036_pmu, 989 .data = (void *)&rk3036_pmu,
950 }, 990 },
951 { 991 {
992 .compatible = "rockchip,rk3066-power-controller",
993 .data = (void *)&rk3066_pmu,
994 },
995 {
952 .compatible = "rockchip,rk3128-power-controller", 996 .compatible = "rockchip,rk3128-power-controller",
953 .data = (void *)&rk3128_pmu, 997 .data = (void *)&rk3128_pmu,
954 }, 998 },
955 { 999 {
1000 .compatible = "rockchip,rk3188-power-controller",
1001 .data = (void *)&rk3188_pmu,
1002 },
1003 {
956 .compatible = "rockchip,rk3228-power-controller", 1004 .compatible = "rockchip,rk3228-power-controller",
957 .data = (void *)&rk3228_pmu, 1005 .data = (void *)&rk3228_pmu,
958 }, 1006 },
diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
index b4b0f3480bd3..1b0d50f36349 100644
--- a/drivers/soc/sunxi/sunxi_sram.c
+++ b/drivers/soc/sunxi/sunxi_sram.c
@@ -155,17 +155,7 @@ static int sunxi_sram_show(struct seq_file *s, void *data)
155 return 0; 155 return 0;
156} 156}
157 157
158static int sunxi_sram_open(struct inode *inode, struct file *file) 158DEFINE_SHOW_ATTRIBUTE(sunxi_sram);
159{
160 return single_open(file, sunxi_sram_show, inode->i_private);
161}
162
163static const struct file_operations sunxi_sram_fops = {
164 .open = sunxi_sram_open,
165 .read = seq_read,
166 .llseek = seq_lseek,
167 .release = single_release,
168};
169 159
170static inline struct sunxi_sram_desc *to_sram_desc(const struct sunxi_sram_data *data) 160static inline struct sunxi_sram_desc *to_sram_desc(const struct sunxi_sram_data *data)
171{ 161{
@@ -300,6 +290,10 @@ static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
300 /* Nothing special */ 290 /* Nothing special */
301}; 291};
302 292
293static const struct sunxi_sramc_variant sun8i_h3_sramc_variant = {
294 .has_emac_clock = true,
295};
296
303static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = { 297static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = {
304 .has_emac_clock = true, 298 .has_emac_clock = true,
305}; 299};
@@ -379,7 +373,7 @@ static const struct of_device_id sunxi_sram_dt_match[] = {
379 }, 373 },
380 { 374 {
381 .compatible = "allwinner,sun8i-h3-system-control", 375 .compatible = "allwinner,sun8i-h3-system-control",
382 .data = &sun4i_a10_sramc_variant, 376 .data = &sun8i_h3_sramc_variant,
383 }, 377 },
384 { 378 {
385 .compatible = "allwinner,sun50i-a64-sram-controller", 379 .compatible = "allwinner,sun50i-a64-sram-controller",
@@ -389,6 +383,10 @@ static const struct of_device_id sunxi_sram_dt_match[] = {
389 .compatible = "allwinner,sun50i-a64-system-control", 383 .compatible = "allwinner,sun50i-a64-system-control",
390 .data = &sun50i_a64_sramc_variant, 384 .data = &sun50i_a64_sramc_variant,
391 }, 385 },
386 {
387 .compatible = "allwinner,sun50i-h5-system-control",
388 .data = &sun50i_a64_sramc_variant,
389 },
392 { }, 390 { },
393}; 391};
394MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match); 392MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match);
diff --git a/drivers/soc/tegra/common.c b/drivers/soc/tegra/common.c
index cd8f41351add..7bfb154d6fa5 100644
--- a/drivers/soc/tegra/common.c
+++ b/drivers/soc/tegra/common.c
@@ -22,11 +22,15 @@ static const struct of_device_id tegra_machine_match[] = {
22 22
23bool soc_is_tegra(void) 23bool soc_is_tegra(void)
24{ 24{
25 const struct of_device_id *match;
25 struct device_node *root; 26 struct device_node *root;
26 27
27 root = of_find_node_by_path("/"); 28 root = of_find_node_by_path("/");
28 if (!root) 29 if (!root)
29 return false; 30 return false;
30 31
31 return of_match_node(tegra_machine_match, root) != NULL; 32 match = of_match_node(tegra_machine_match, root);
33 of_node_put(root);
34
35 return match != NULL;
32} 36}
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index b30af18516d6..7ea3280279ff 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -2,6 +2,7 @@
2 * drivers/soc/tegra/pmc.c 2 * drivers/soc/tegra/pmc.c
3 * 3 *
4 * Copyright (c) 2010 Google, Inc 4 * Copyright (c) 2010 Google, Inc
5 * Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
5 * 6 *
6 * Author: 7 * Author:
7 * Colin Cross <ccross@google.com> 8 * Colin Cross <ccross@google.com>
@@ -29,9 +30,12 @@
29#include <linux/init.h> 30#include <linux/init.h>
30#include <linux/io.h> 31#include <linux/io.h>
31#include <linux/iopoll.h> 32#include <linux/iopoll.h>
33#include <linux/irq.h>
34#include <linux/irqdomain.h>
32#include <linux/of.h> 35#include <linux/of.h>
33#include <linux/of_address.h> 36#include <linux/of_address.h>
34#include <linux/of_clk.h> 37#include <linux/of_clk.h>
38#include <linux/of_irq.h>
35#include <linux/of_platform.h> 39#include <linux/of_platform.h>
36#include <linux/pinctrl/pinctrl.h> 40#include <linux/pinctrl/pinctrl.h>
37#include <linux/pinctrl/pinconf.h> 41#include <linux/pinctrl/pinconf.h>
@@ -48,7 +52,10 @@
48#include <soc/tegra/fuse.h> 52#include <soc/tegra/fuse.h>
49#include <soc/tegra/pmc.h> 53#include <soc/tegra/pmc.h>
50 54
55#include <dt-bindings/interrupt-controller/arm-gic.h>
51#include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h> 56#include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h>
57#include <dt-bindings/gpio/tegra186-gpio.h>
58#include <dt-bindings/gpio/tegra194-gpio.h>
52 59
53#define PMC_CNTRL 0x0 60#define PMC_CNTRL 0x0
54#define PMC_CNTRL_INTR_POLARITY BIT(17) /* inverts INTR polarity */ 61#define PMC_CNTRL_INTR_POLARITY BIT(17) /* inverts INTR polarity */
@@ -92,7 +99,6 @@
92#define PMC_SENSOR_CTRL_SCRATCH_WRITE BIT(2) 99#define PMC_SENSOR_CTRL_SCRATCH_WRITE BIT(2)
93#define PMC_SENSOR_CTRL_ENABLE_RST BIT(1) 100#define PMC_SENSOR_CTRL_ENABLE_RST BIT(1)
94 101
95#define PMC_RST_STATUS 0x1b4
96#define PMC_RST_STATUS_POR 0 102#define PMC_RST_STATUS_POR 0
97#define PMC_RST_STATUS_WATCHDOG 1 103#define PMC_RST_STATUS_WATCHDOG 1
98#define PMC_RST_STATUS_SENSOR 2 104#define PMC_RST_STATUS_SENSOR 2
@@ -126,6 +132,16 @@
126#define GPU_RG_CNTRL 0x2d4 132#define GPU_RG_CNTRL 0x2d4
127 133
128/* Tegra186 and later */ 134/* Tegra186 and later */
135#define WAKE_AOWAKE_CNTRL(x) (0x000 + ((x) << 2))
136#define WAKE_AOWAKE_CNTRL_LEVEL (1 << 3)
137#define WAKE_AOWAKE_MASK_W(x) (0x180 + ((x) << 2))
138#define WAKE_AOWAKE_MASK_R(x) (0x300 + ((x) << 2))
139#define WAKE_AOWAKE_STATUS_W(x) (0x30c + ((x) << 2))
140#define WAKE_AOWAKE_STATUS_R(x) (0x48c + ((x) << 2))
141#define WAKE_AOWAKE_TIER0_ROUTING(x) (0x4b4 + ((x) << 2))
142#define WAKE_AOWAKE_TIER1_ROUTING(x) (0x4c0 + ((x) << 2))
143#define WAKE_AOWAKE_TIER2_ROUTING(x) (0x4cc + ((x) << 2))
144
129#define WAKE_AOWAKE_CTRL 0x4f4 145#define WAKE_AOWAKE_CTRL 0x4f4
130#define WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0) 146#define WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0)
131 147
@@ -151,8 +167,45 @@ struct tegra_pmc_regs {
151 unsigned int dpd_status; 167 unsigned int dpd_status;
152 unsigned int dpd2_req; 168 unsigned int dpd2_req;
153 unsigned int dpd2_status; 169 unsigned int dpd2_status;
170 unsigned int rst_status;
171 unsigned int rst_source_shift;
172 unsigned int rst_source_mask;
173 unsigned int rst_level_shift;
174 unsigned int rst_level_mask;
175};
176
177struct tegra_wake_event {
178 const char *name;
179 unsigned int id;
180 unsigned int irq;
181 struct {
182 unsigned int instance;
183 unsigned int pin;
184 } gpio;
154}; 185};
155 186
187#define TEGRA_WAKE_IRQ(_name, _id, _irq) \
188 { \
189 .name = _name, \
190 .id = _id, \
191 .irq = _irq, \
192 .gpio = { \
193 .instance = UINT_MAX, \
194 .pin = UINT_MAX, \
195 }, \
196 }
197
198#define TEGRA_WAKE_GPIO(_name, _id, _instance, _pin) \
199 { \
200 .name = _name, \
201 .id = _id, \
202 .irq = 0, \
203 .gpio = { \
204 .instance = _instance, \
205 .pin = _pin, \
206 }, \
207 }
208
156struct tegra_pmc_soc { 209struct tegra_pmc_soc {
157 unsigned int num_powergates; 210 unsigned int num_powergates;
158 const char *const *powergates; 211 const char *const *powergates;
@@ -175,6 +228,45 @@ struct tegra_pmc_soc {
175 void (*setup_irq_polarity)(struct tegra_pmc *pmc, 228 void (*setup_irq_polarity)(struct tegra_pmc *pmc,
176 struct device_node *np, 229 struct device_node *np,
177 bool invert); 230 bool invert);
231
232 const char * const *reset_sources;
233 unsigned int num_reset_sources;
234 const char * const *reset_levels;
235 unsigned int num_reset_levels;
236
237 const struct tegra_wake_event *wake_events;
238 unsigned int num_wake_events;
239};
240
241static const char * const tegra186_reset_sources[] = {
242 "SYS_RESET",
243 "AOWDT",
244 "MCCPLEXWDT",
245 "BPMPWDT",
246 "SCEWDT",
247 "SPEWDT",
248 "APEWDT",
249 "BCCPLEXWDT",
250 "SENSOR",
251 "AOTAG",
252 "VFSENSOR",
253 "SWREST",
254 "SC7",
255 "HSM",
256 "CORESIGHT"
257};
258
259static const char * const tegra186_reset_levels[] = {
260 "L0", "L1", "L2", "WARM"
261};
262
263static const char * const tegra30_reset_sources[] = {
264 "POWER_ON_RESET",
265 "WATCHDOG",
266 "SENSOR",
267 "SW_MAIN",
268 "LP0",
269 "AOTAG"
178}; 270};
179 271
180/** 272/**
@@ -230,6 +322,9 @@ struct tegra_pmc {
230 struct mutex powergates_lock; 322 struct mutex powergates_lock;
231 323
232 struct pinctrl_dev *pctl_dev; 324 struct pinctrl_dev *pctl_dev;
325
326 struct irq_domain *domain;
327 struct irq_chip irq;
233}; 328};
234 329
235static struct tegra_pmc *pmc = &(struct tegra_pmc) { 330static struct tegra_pmc *pmc = &(struct tegra_pmc) {
@@ -538,16 +633,10 @@ EXPORT_SYMBOL(tegra_powergate_power_off);
538 */ 633 */
539int tegra_powergate_is_powered(unsigned int id) 634int tegra_powergate_is_powered(unsigned int id)
540{ 635{
541 int status;
542
543 if (!tegra_powergate_is_valid(id)) 636 if (!tegra_powergate_is_valid(id))
544 return -EINVAL; 637 return -EINVAL;
545 638
546 mutex_lock(&pmc->powergates_lock); 639 return tegra_powergate_state(id);
547 status = tegra_powergate_state(id);
548 mutex_unlock(&pmc->powergates_lock);
549
550 return status;
551} 640}
552 641
553/** 642/**
@@ -715,17 +804,7 @@ static int powergate_show(struct seq_file *s, void *data)
715 return 0; 804 return 0;
716} 805}
717 806
718static int powergate_open(struct inode *inode, struct file *file) 807DEFINE_SHOW_ATTRIBUTE(powergate);
719{
720 return single_open(file, powergate_show, inode->i_private);
721}
722
723static const struct file_operations powergate_fops = {
724 .open = powergate_open,
725 .read = seq_read,
726 .llseek = seq_lseek,
727 .release = single_release,
728};
729 808
730static int tegra_powergate_debugfs_init(void) 809static int tegra_powergate_debugfs_init(void)
731{ 810{
@@ -845,22 +924,6 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
845 goto remove_resets; 924 goto remove_resets;
846 } 925 }
847 926
848 /*
849 * FIXME: If XHCI is enabled for Tegra, then power-up the XUSB
850 * host and super-speed partitions. Once the XHCI driver
851 * manages the partitions itself this code can be removed. Note
852 * that we don't register these partitions with the genpd core
853 * to avoid it from powering down the partitions as they appear
854 * to be unused.
855 */
856 if (IS_ENABLED(CONFIG_USB_XHCI_TEGRA) &&
857 (id == TEGRA_POWERGATE_XUSBA || id == TEGRA_POWERGATE_XUSBC)) {
858 if (off)
859 WARN_ON(tegra_powergate_power_up(pg, true));
860
861 goto remove_resets;
862 }
863
864 err = pm_genpd_init(&pg->genpd, NULL, off); 927 err = pm_genpd_init(&pg->genpd, NULL, off);
865 if (err < 0) { 928 if (err < 0) {
866 pr_err("failed to initialise PM domain %pOFn: %d\n", np, 929 pr_err("failed to initialise PM domain %pOFn: %d\n", np,
@@ -1541,6 +1604,225 @@ static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc)
1541 return err; 1604 return err;
1542} 1605}
1543 1606
1607static ssize_t reset_reason_show(struct device *dev,
1608 struct device_attribute *attr, char *buf)
1609{
1610 u32 value, rst_src;
1611
1612 value = tegra_pmc_readl(pmc->soc->regs->rst_status);
1613 rst_src = (value & pmc->soc->regs->rst_source_mask) >>
1614 pmc->soc->regs->rst_source_shift;
1615
1616 return sprintf(buf, "%s\n", pmc->soc->reset_sources[rst_src]);
1617}
1618
1619static DEVICE_ATTR_RO(reset_reason);
1620
1621static ssize_t reset_level_show(struct device *dev,
1622 struct device_attribute *attr, char *buf)
1623{
1624 u32 value, rst_lvl;
1625
1626 value = tegra_pmc_readl(pmc->soc->regs->rst_status);
1627 rst_lvl = (value & pmc->soc->regs->rst_level_mask) >>
1628 pmc->soc->regs->rst_level_shift;
1629
1630 return sprintf(buf, "%s\n", pmc->soc->reset_levels[rst_lvl]);
1631}
1632
1633static DEVICE_ATTR_RO(reset_level);
1634
1635static void tegra_pmc_reset_sysfs_init(struct tegra_pmc *pmc)
1636{
1637 struct device *dev = pmc->dev;
1638 int err = 0;
1639
1640 if (pmc->soc->reset_sources) {
1641 err = device_create_file(dev, &dev_attr_reset_reason);
1642 if (err < 0)
1643 dev_warn(dev,
1644 "failed to create attr \"reset_reason\": %d\n",
1645 err);
1646 }
1647
1648 if (pmc->soc->reset_levels) {
1649 err = device_create_file(dev, &dev_attr_reset_level);
1650 if (err < 0)
1651 dev_warn(dev,
1652 "failed to create attr \"reset_level\": %d\n",
1653 err);
1654 }
1655}
1656
1657static int tegra_pmc_irq_translate(struct irq_domain *domain,
1658 struct irq_fwspec *fwspec,
1659 unsigned long *hwirq,
1660 unsigned int *type)
1661{
1662 if (WARN_ON(fwspec->param_count < 2))
1663 return -EINVAL;
1664
1665 *hwirq = fwspec->param[0];
1666 *type = fwspec->param[1];
1667
1668 return 0;
1669}
1670
1671static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq,
1672 unsigned int num_irqs, void *data)
1673{
1674 struct tegra_pmc *pmc = domain->host_data;
1675 const struct tegra_pmc_soc *soc = pmc->soc;
1676 struct irq_fwspec *fwspec = data;
1677 unsigned int i;
1678 int err = 0;
1679
1680 for (i = 0; i < soc->num_wake_events; i++) {
1681 const struct tegra_wake_event *event = &soc->wake_events[i];
1682
1683 if (fwspec->param_count == 2) {
1684 struct irq_fwspec spec;
1685
1686 if (event->id != fwspec->param[0])
1687 continue;
1688
1689 err = irq_domain_set_hwirq_and_chip(domain, virq,
1690 event->id,
1691 &pmc->irq, pmc);
1692 if (err < 0)
1693 break;
1694
1695 spec.fwnode = &pmc->dev->of_node->fwnode;
1696 spec.param_count = 3;
1697 spec.param[0] = GIC_SPI;
1698 spec.param[1] = event->irq;
1699 spec.param[2] = fwspec->param[1];
1700
1701 err = irq_domain_alloc_irqs_parent(domain, virq,
1702 num_irqs, &spec);
1703
1704 break;
1705 }
1706
1707 if (fwspec->param_count == 3) {
1708 if (event->gpio.instance != fwspec->param[0] ||
1709 event->gpio.pin != fwspec->param[1])
1710 continue;
1711
1712 err = irq_domain_set_hwirq_and_chip(domain, virq,
1713 event->id,
1714 &pmc->irq, pmc);
1715
1716 break;
1717 }
1718 }
1719
1720 if (i == soc->num_wake_events)
1721 err = irq_domain_set_hwirq_and_chip(domain, virq, ULONG_MAX,
1722 &pmc->irq, pmc);
1723
1724 return err;
1725}
1726
1727static const struct irq_domain_ops tegra_pmc_irq_domain_ops = {
1728 .translate = tegra_pmc_irq_translate,
1729 .alloc = tegra_pmc_irq_alloc,
1730};
1731
1732static int tegra_pmc_irq_set_wake(struct irq_data *data, unsigned int on)
1733{
1734 struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
1735 unsigned int offset, bit;
1736 u32 value;
1737
1738 offset = data->hwirq / 32;
1739 bit = data->hwirq % 32;
1740
1741 /* clear wake status */
1742 writel(0x1, pmc->wake + WAKE_AOWAKE_STATUS_W(data->hwirq));
1743
1744 /* route wake to tier 2 */
1745 value = readl(pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(offset));
1746
1747 if (!on)
1748 value &= ~(1 << bit);
1749 else
1750 value |= 1 << bit;
1751
1752 writel(value, pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(offset));
1753
1754 /* enable wakeup event */
1755 writel(!!on, pmc->wake + WAKE_AOWAKE_MASK_W(data->hwirq));
1756
1757 return 0;
1758}
1759
1760static int tegra_pmc_irq_set_type(struct irq_data *data, unsigned int type)
1761{
1762 struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data);
1763 u32 value;
1764
1765 if (data->hwirq == ULONG_MAX)
1766 return 0;
1767
1768 value = readl(pmc->wake + WAKE_AOWAKE_CNTRL(data->hwirq));
1769
1770 switch (type) {
1771 case IRQ_TYPE_EDGE_RISING:
1772 case IRQ_TYPE_LEVEL_HIGH:
1773 value |= WAKE_AOWAKE_CNTRL_LEVEL;
1774 break;
1775
1776 case IRQ_TYPE_EDGE_FALLING:
1777 case IRQ_TYPE_LEVEL_LOW:
1778 value &= ~WAKE_AOWAKE_CNTRL_LEVEL;
1779 break;
1780
1781 case IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING:
1782 value ^= WAKE_AOWAKE_CNTRL_LEVEL;
1783 break;
1784
1785 default:
1786 return -EINVAL;
1787 }
1788
1789 writel(value, pmc->wake + WAKE_AOWAKE_CNTRL(data->hwirq));
1790
1791 return 0;
1792}
1793
1794static int tegra_pmc_irq_init(struct tegra_pmc *pmc)
1795{
1796 struct irq_domain *parent = NULL;
1797 struct device_node *np;
1798
1799 np = of_irq_find_parent(pmc->dev->of_node);
1800 if (np) {
1801 parent = irq_find_host(np);
1802 of_node_put(np);
1803 }
1804
1805 if (!parent)
1806 return 0;
1807
1808 pmc->irq.name = dev_name(pmc->dev);
1809 pmc->irq.irq_mask = irq_chip_mask_parent;
1810 pmc->irq.irq_unmask = irq_chip_unmask_parent;
1811 pmc->irq.irq_eoi = irq_chip_eoi_parent;
1812 pmc->irq.irq_set_affinity = irq_chip_set_affinity_parent;
1813 pmc->irq.irq_set_type = tegra_pmc_irq_set_type;
1814 pmc->irq.irq_set_wake = tegra_pmc_irq_set_wake;
1815
1816 pmc->domain = irq_domain_add_hierarchy(parent, 0, 96, pmc->dev->of_node,
1817 &tegra_pmc_irq_domain_ops, pmc);
1818 if (!pmc->domain) {
1819 dev_err(pmc->dev, "failed to allocate domain\n");
1820 return -ENOMEM;
1821 }
1822
1823 return 0;
1824}
1825
1544static int tegra_pmc_probe(struct platform_device *pdev) 1826static int tegra_pmc_probe(struct platform_device *pdev)
1545{ 1827{
1546 void __iomem *base; 1828 void __iomem *base;
@@ -1610,6 +1892,8 @@ static int tegra_pmc_probe(struct platform_device *pdev)
1610 1892
1611 tegra_pmc_init_tsense_reset(pmc); 1893 tegra_pmc_init_tsense_reset(pmc);
1612 1894
1895 tegra_pmc_reset_sysfs_init(pmc);
1896
1613 if (IS_ENABLED(CONFIG_DEBUG_FS)) { 1897 if (IS_ENABLED(CONFIG_DEBUG_FS)) {
1614 err = tegra_powergate_debugfs_init(); 1898 err = tegra_powergate_debugfs_init();
1615 if (err < 0) 1899 if (err < 0)
@@ -1627,6 +1911,10 @@ static int tegra_pmc_probe(struct platform_device *pdev)
1627 if (err) 1911 if (err)
1628 goto cleanup_restart_handler; 1912 goto cleanup_restart_handler;
1629 1913
1914 err = tegra_pmc_irq_init(pmc);
1915 if (err < 0)
1916 goto cleanup_restart_handler;
1917
1630 mutex_lock(&pmc->powergates_lock); 1918 mutex_lock(&pmc->powergates_lock);
1631 iounmap(pmc->base); 1919 iounmap(pmc->base);
1632 pmc->base = base; 1920 pmc->base = base;
@@ -1676,6 +1964,11 @@ static const struct tegra_pmc_regs tegra20_pmc_regs = {
1676 .dpd_status = 0x1bc, 1964 .dpd_status = 0x1bc,
1677 .dpd2_req = 0x1c0, 1965 .dpd2_req = 0x1c0,
1678 .dpd2_status = 0x1c4, 1966 .dpd2_status = 0x1c4,
1967 .rst_status = 0x1b4,
1968 .rst_source_shift = 0x0,
1969 .rst_source_mask = 0x7,
1970 .rst_level_shift = 0x0,
1971 .rst_level_mask = 0x0,
1679}; 1972};
1680 1973
1681static void tegra20_pmc_init(struct tegra_pmc *pmc) 1974static void tegra20_pmc_init(struct tegra_pmc *pmc)
@@ -1733,6 +2026,10 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = {
1733 .regs = &tegra20_pmc_regs, 2026 .regs = &tegra20_pmc_regs,
1734 .init = tegra20_pmc_init, 2027 .init = tegra20_pmc_init,
1735 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, 2028 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
2029 .reset_sources = NULL,
2030 .num_reset_sources = 0,
2031 .reset_levels = NULL,
2032 .num_reset_levels = 0,
1736}; 2033};
1737 2034
1738static const char * const tegra30_powergates[] = { 2035static const char * const tegra30_powergates[] = {
@@ -1774,6 +2071,10 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = {
1774 .regs = &tegra20_pmc_regs, 2071 .regs = &tegra20_pmc_regs,
1775 .init = tegra20_pmc_init, 2072 .init = tegra20_pmc_init,
1776 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, 2073 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
2074 .reset_sources = tegra30_reset_sources,
2075 .num_reset_sources = 5,
2076 .reset_levels = NULL,
2077 .num_reset_levels = 0,
1777}; 2078};
1778 2079
1779static const char * const tegra114_powergates[] = { 2080static const char * const tegra114_powergates[] = {
@@ -1819,6 +2120,10 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = {
1819 .regs = &tegra20_pmc_regs, 2120 .regs = &tegra20_pmc_regs,
1820 .init = tegra20_pmc_init, 2121 .init = tegra20_pmc_init,
1821 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, 2122 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
2123 .reset_sources = tegra30_reset_sources,
2124 .num_reset_sources = 5,
2125 .reset_levels = NULL,
2126 .num_reset_levels = 0,
1822}; 2127};
1823 2128
1824static const char * const tegra124_powergates[] = { 2129static const char * const tegra124_powergates[] = {
@@ -1924,6 +2229,10 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
1924 .regs = &tegra20_pmc_regs, 2229 .regs = &tegra20_pmc_regs,
1925 .init = tegra20_pmc_init, 2230 .init = tegra20_pmc_init,
1926 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, 2231 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
2232 .reset_sources = tegra30_reset_sources,
2233 .num_reset_sources = 5,
2234 .reset_levels = NULL,
2235 .num_reset_levels = 0,
1927}; 2236};
1928 2237
1929static const char * const tegra210_powergates[] = { 2238static const char * const tegra210_powergates[] = {
@@ -2025,6 +2334,10 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = {
2025 .regs = &tegra20_pmc_regs, 2334 .regs = &tegra20_pmc_regs,
2026 .init = tegra20_pmc_init, 2335 .init = tegra20_pmc_init,
2027 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, 2336 .setup_irq_polarity = tegra20_pmc_setup_irq_polarity,
2337 .reset_sources = tegra30_reset_sources,
2338 .num_reset_sources = 5,
2339 .reset_levels = NULL,
2340 .num_reset_levels = 0,
2028}; 2341};
2029 2342
2030#define TEGRA186_IO_PAD_TABLE(_pad) \ 2343#define TEGRA186_IO_PAD_TABLE(_pad) \
@@ -2082,6 +2395,11 @@ static const struct tegra_pmc_regs tegra186_pmc_regs = {
2082 .dpd_status = 0x78, 2395 .dpd_status = 0x78,
2083 .dpd2_req = 0x7c, 2396 .dpd2_req = 0x7c,
2084 .dpd2_status = 0x80, 2397 .dpd2_status = 0x80,
2398 .rst_status = 0x70,
2399 .rst_source_shift = 0x2,
2400 .rst_source_mask = 0x3C,
2401 .rst_level_shift = 0x0,
2402 .rst_level_mask = 0x3,
2085}; 2403};
2086 2404
2087static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc, 2405static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
@@ -2119,6 +2437,11 @@ static void tegra186_pmc_setup_irq_polarity(struct tegra_pmc *pmc,
2119 iounmap(wake); 2437 iounmap(wake);
2120} 2438}
2121 2439
2440static const struct tegra_wake_event tegra186_wake_events[] = {
2441 TEGRA_WAKE_GPIO("power", 29, 1, TEGRA_AON_GPIO(FF, 0)),
2442 TEGRA_WAKE_IRQ("rtc", 73, 10),
2443};
2444
2122static const struct tegra_pmc_soc tegra186_pmc_soc = { 2445static const struct tegra_pmc_soc tegra186_pmc_soc = {
2123 .num_powergates = 0, 2446 .num_powergates = 0,
2124 .powergates = NULL, 2447 .powergates = NULL,
@@ -2134,10 +2457,87 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = {
2134 .regs = &tegra186_pmc_regs, 2457 .regs = &tegra186_pmc_regs,
2135 .init = NULL, 2458 .init = NULL,
2136 .setup_irq_polarity = tegra186_pmc_setup_irq_polarity, 2459 .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
2460 .reset_sources = tegra186_reset_sources,
2461 .num_reset_sources = 14,
2462 .reset_levels = tegra186_reset_levels,
2463 .num_reset_levels = 3,
2464 .num_wake_events = ARRAY_SIZE(tegra186_wake_events),
2465 .wake_events = tegra186_wake_events,
2466};
2467
2468static const struct tegra_io_pad_soc tegra194_io_pads[] = {
2469 { .id = TEGRA_IO_PAD_CSIA, .dpd = 0, .voltage = UINT_MAX },
2470 { .id = TEGRA_IO_PAD_CSIB, .dpd = 1, .voltage = UINT_MAX },
2471 { .id = TEGRA_IO_PAD_MIPI_BIAS, .dpd = 3, .voltage = UINT_MAX },
2472 { .id = TEGRA_IO_PAD_PEX_CLK_BIAS, .dpd = 4, .voltage = UINT_MAX },
2473 { .id = TEGRA_IO_PAD_PEX_CLK3, .dpd = 5, .voltage = UINT_MAX },
2474 { .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 6, .voltage = UINT_MAX },
2475 { .id = TEGRA_IO_PAD_PEX_CLK1, .dpd = 7, .voltage = UINT_MAX },
2476 { .id = TEGRA_IO_PAD_EQOS, .dpd = 8, .voltage = UINT_MAX },
2477 { .id = TEGRA_IO_PAD_PEX_CLK2_BIAS, .dpd = 9, .voltage = UINT_MAX },
2478 { .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 10, .voltage = UINT_MAX },
2479 { .id = TEGRA_IO_PAD_DAP3, .dpd = 11, .voltage = UINT_MAX },
2480 { .id = TEGRA_IO_PAD_DAP5, .dpd = 12, .voltage = UINT_MAX },
2481 { .id = TEGRA_IO_PAD_UART, .dpd = 14, .voltage = UINT_MAX },
2482 { .id = TEGRA_IO_PAD_PWR_CTL, .dpd = 15, .voltage = UINT_MAX },
2483 { .id = TEGRA_IO_PAD_SOC_GPIO53, .dpd = 16, .voltage = UINT_MAX },
2484 { .id = TEGRA_IO_PAD_AUDIO, .dpd = 17, .voltage = UINT_MAX },
2485 { .id = TEGRA_IO_PAD_GP_PWM2, .dpd = 18, .voltage = UINT_MAX },
2486 { .id = TEGRA_IO_PAD_GP_PWM3, .dpd = 19, .voltage = UINT_MAX },
2487 { .id = TEGRA_IO_PAD_SOC_GPIO12, .dpd = 20, .voltage = UINT_MAX },
2488 { .id = TEGRA_IO_PAD_SOC_GPIO13, .dpd = 21, .voltage = UINT_MAX },
2489 { .id = TEGRA_IO_PAD_SOC_GPIO10, .dpd = 22, .voltage = UINT_MAX },
2490 { .id = TEGRA_IO_PAD_UART4, .dpd = 23, .voltage = UINT_MAX },
2491 { .id = TEGRA_IO_PAD_UART5, .dpd = 24, .voltage = UINT_MAX },
2492 { .id = TEGRA_IO_PAD_DBG, .dpd = 25, .voltage = UINT_MAX },
2493 { .id = TEGRA_IO_PAD_HDMI_DP3, .dpd = 26, .voltage = UINT_MAX },
2494 { .id = TEGRA_IO_PAD_HDMI_DP2, .dpd = 27, .voltage = UINT_MAX },
2495 { .id = TEGRA_IO_PAD_HDMI_DP0, .dpd = 28, .voltage = UINT_MAX },
2496 { .id = TEGRA_IO_PAD_HDMI_DP1, .dpd = 29, .voltage = UINT_MAX },
2497 { .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = 32, .voltage = UINT_MAX },
2498 { .id = TEGRA_IO_PAD_PEX_CTL2, .dpd = 33, .voltage = UINT_MAX },
2499 { .id = TEGRA_IO_PAD_PEX_L0_RST_N, .dpd = 34, .voltage = UINT_MAX },
2500 { .id = TEGRA_IO_PAD_PEX_L1_RST_N, .dpd = 35, .voltage = UINT_MAX },
2501 { .id = TEGRA_IO_PAD_SDMMC4, .dpd = 36, .voltage = UINT_MAX },
2502 { .id = TEGRA_IO_PAD_PEX_L5_RST_N, .dpd = 37, .voltage = UINT_MAX },
2503 { .id = TEGRA_IO_PAD_CSIC, .dpd = 43, .voltage = UINT_MAX },
2504 { .id = TEGRA_IO_PAD_CSID, .dpd = 44, .voltage = UINT_MAX },
2505 { .id = TEGRA_IO_PAD_CSIE, .dpd = 45, .voltage = UINT_MAX },
2506 { .id = TEGRA_IO_PAD_CSIF, .dpd = 46, .voltage = UINT_MAX },
2507 { .id = TEGRA_IO_PAD_SPI, .dpd = 47, .voltage = UINT_MAX },
2508 { .id = TEGRA_IO_PAD_UFS, .dpd = 49, .voltage = UINT_MAX },
2509 { .id = TEGRA_IO_PAD_CSIG, .dpd = 50, .voltage = UINT_MAX },
2510 { .id = TEGRA_IO_PAD_CSIH, .dpd = 51, .voltage = UINT_MAX },
2511 { .id = TEGRA_IO_PAD_EDP, .dpd = 53, .voltage = UINT_MAX },
2512 { .id = TEGRA_IO_PAD_SDMMC1_HV, .dpd = 55, .voltage = UINT_MAX },
2513 { .id = TEGRA_IO_PAD_SDMMC3_HV, .dpd = 56, .voltage = UINT_MAX },
2514 { .id = TEGRA_IO_PAD_CONN, .dpd = 60, .voltage = UINT_MAX },
2515 { .id = TEGRA_IO_PAD_AUDIO_HV, .dpd = 61, .voltage = UINT_MAX },
2516};
2517
2518static const struct tegra_wake_event tegra194_wake_events[] = {
2519 TEGRA_WAKE_GPIO("power", 29, 1, TEGRA194_AON_GPIO(EE, 4)),
2520 TEGRA_WAKE_IRQ("rtc", 73, 10),
2521};
2522
2523static const struct tegra_pmc_soc tegra194_pmc_soc = {
2524 .num_powergates = 0,
2525 .powergates = NULL,
2526 .num_cpu_powergates = 0,
2527 .cpu_powergates = NULL,
2528 .has_tsense_reset = false,
2529 .has_gpu_clamps = false,
2530 .num_io_pads = ARRAY_SIZE(tegra194_io_pads),
2531 .io_pads = tegra194_io_pads,
2532 .regs = &tegra186_pmc_regs,
2533 .init = NULL,
2534 .setup_irq_polarity = tegra186_pmc_setup_irq_polarity,
2535 .num_wake_events = ARRAY_SIZE(tegra194_wake_events),
2536 .wake_events = tegra194_wake_events,
2137}; 2537};
2138 2538
2139static const struct of_device_id tegra_pmc_match[] = { 2539static const struct of_device_id tegra_pmc_match[] = {
2140 { .compatible = "nvidia,tegra194-pmc", .data = &tegra186_pmc_soc }, 2540 { .compatible = "nvidia,tegra194-pmc", .data = &tegra194_pmc_soc },
2141 { .compatible = "nvidia,tegra186-pmc", .data = &tegra186_pmc_soc }, 2541 { .compatible = "nvidia,tegra186-pmc", .data = &tegra186_pmc_soc },
2142 { .compatible = "nvidia,tegra210-pmc", .data = &tegra210_pmc_soc }, 2542 { .compatible = "nvidia,tegra210-pmc", .data = &tegra210_pmc_soc },
2143 { .compatible = "nvidia,tegra132-pmc", .data = &tegra124_pmc_soc }, 2543 { .compatible = "nvidia,tegra132-pmc", .data = &tegra124_pmc_soc },
diff --git a/drivers/soc/ti/wkup_m3_ipc.c b/drivers/soc/ti/wkup_m3_ipc.c
index f5cb8c0af09f..d65e361c5de1 100644
--- a/drivers/soc/ti/wkup_m3_ipc.c
+++ b/drivers/soc/ti/wkup_m3_ipc.c
@@ -57,6 +57,7 @@
57static struct wkup_m3_ipc *m3_ipc_state; 57static struct wkup_m3_ipc *m3_ipc_state;
58 58
59static const struct wkup_m3_wakeup_src wakeups[] = { 59static const struct wkup_m3_wakeup_src wakeups[] = {
60 {.irq_nr = 16, .src = "PRCM"},
60 {.irq_nr = 35, .src = "USB0_PHY"}, 61 {.irq_nr = 35, .src = "USB0_PHY"},
61 {.irq_nr = 36, .src = "USB1_PHY"}, 62 {.irq_nr = 36, .src = "USB1_PHY"},
62 {.irq_nr = 40, .src = "I2C0"}, 63 {.irq_nr = 40, .src = "I2C0"},