summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-08-01 18:36:01 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-08-01 18:36:01 -0400
commit43a0a98aa8da71583f84b84fd72e265c24d4c5f8 (patch)
tree3830aff2b36f48a67be5f485f00f56cf4269729d /drivers
parent6911a5281430cf6897376487698504620f454791 (diff)
parentf8c6d88b2c874295f49b9ad1ca0826b9a8ef3180 (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: "Driver updates for ARM SoCs. A slew of changes this release cycle. The reset driver tree, that we merge through arm-soc for historical reasons, is also sizable this time around. Among the changes: - clps711x: Treewide changes to compatible strings, merged here for simplicity. - Qualcomm: SCM firmware driver cleanups, move to platform driver - ux500: Major cleanups, removal of old mach-specific infrastructure. - Atmel external bus memory driver - Move of brcmstb platform to the rest of bcm - PMC driver updates for tegra, various fixes and improvements - Samsung platform driver updates to support 64-bit Exynos platforms - Reset controller cleanups moving to devm_reset_controller_register() APIs - Reset controller driver for Amlogic Meson - Reset controller driver for Hisilicon hi6220 - ARM SCPI power domain support" * tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (100 commits) ARM: ux500: consolidate base platform files ARM: ux500: move soc_id driver to drivers/soc ARM: ux500: call ux500_setup_id later ARM: ux500: consolidate soc_device code in id.c ARM: ux500: remove cpu_is_u* helpers ARM: ux500: use CLK_OF_DECLARE() ARM: ux500: move l2x0 init to .init_irq mfd: db8500 stop passing around platform data ASoC: ab8500-codec: remove platform data based probe ARM: ux500: move ab8500_regulator_plat_data into driver ARM: ux500: remove unused regulator data soc: raspberrypi-power: add CONFIG_OF dependency firmware: scpi: add CONFIG_OF dependency video: clps711x-fb: Changing the compatibility string to match with the smallest supported chip input: clps711x-keypad: Changing the compatibility string to match with the smallest supported chip pwm: clps711x: Changing the compatibility string to match with the smallest supported chip serial: clps711x: Changing the compatibility string to match with the smallest supported chip irqchip: clps711x: Changing the compatibility string to match with the smallest supported chip clocksource: clps711x: Changing the compatibility string to match with the smallest supported chip clk: clps711x: Changing the compatibility string to match with the smallest supported chip ...
Diffstat (limited to 'drivers')
-rw-r--r--drivers/bus/Kconfig13
-rw-r--r--drivers/bus/Makefile1
-rw-r--r--drivers/bus/tegra-aconnect.c112
-rw-r--r--drivers/clk/clk-clps711x.c2
-rw-r--r--drivers/clk/ux500/u8500_of_clk.c16
-rw-r--r--drivers/clk/ux500/u8540_clk.c16
-rw-r--r--drivers/clk/ux500/u9540_clk.c4
-rw-r--r--drivers/clocksource/clps711x-timer.c2
-rw-r--r--drivers/cpufreq/s5pv210-cpufreq.c68
-rw-r--r--drivers/firmware/Kconfig12
-rw-r--r--drivers/firmware/Makefile1
-rw-r--r--drivers/firmware/arm_scpi.c42
-rw-r--r--drivers/firmware/qcom_scm-32.c327
-rw-r--r--drivers/firmware/qcom_scm-64.c307
-rw-r--r--drivers/firmware/qcom_scm.c353
-rw-r--r--drivers/firmware/qcom_scm.h47
-rw-r--r--drivers/firmware/scpi_pm_domain.c163
-rw-r--r--drivers/input/keyboard/clps711x-keypad.c4
-rw-r--r--drivers/irqchip/irq-clps711x.c2
-rw-r--r--drivers/media/rc/Kconfig2
-rw-r--r--drivers/media/rc/ir-rx51.c229
-rw-r--r--drivers/memory/Kconfig11
-rw-r--r--drivers/memory/Makefile1
-rw-r--r--drivers/memory/atmel-ebi.c766
-rw-r--r--drivers/memory/atmel-sdramc.c11
-rw-r--r--drivers/memory/omap-gpmc.c136
-rw-r--r--drivers/memory/samsung/exynos-srom.c41
-rw-r--r--drivers/memory/tegra/mc.c10
-rw-r--r--drivers/memory/tegra/tegra124-emc.c8
-rw-r--r--drivers/mfd/ab8500-core.c4
-rw-r--r--drivers/mfd/ab8500-sysctrl.c34
-rw-r--r--drivers/mfd/db8500-prcmu.c10
-rw-r--r--drivers/power/reset/Kconfig10
-rw-r--r--drivers/power/reset/Makefile1
-rw-r--r--drivers/power/reset/brcm-kona-reset.c73
-rw-r--r--drivers/pwm/pwm-clps711x.c2
-rw-r--r--drivers/pwm/pwm-omap-dmtimer.c12
-rw-r--r--drivers/regulator/ab8500-ext.c465
-rw-r--r--drivers/reset/Kconfig14
-rw-r--r--drivers/reset/Makefile2
-rw-r--r--drivers/reset/core.c37
-rw-r--r--drivers/reset/hisilicon/hi6220_reset.c122
-rw-r--r--drivers/reset/reset-ath79.c3
-rw-r--r--drivers/reset/reset-meson.c136
-rw-r--r--drivers/reset/reset-oxnas.c12
-rw-r--r--drivers/reset/reset-pistachio.c12
-rw-r--r--drivers/reset/reset-socfpga.c12
-rw-r--r--drivers/reset/reset-sunxi.c12
-rw-r--r--drivers/reset/reset-ti-syscon.c237
-rw-r--r--drivers/reset/reset-zynq.c12
-rw-r--r--drivers/reset/sti/Kconfig1
-rw-r--r--drivers/soc/Kconfig2
-rw-r--r--drivers/soc/Makefile2
-rw-r--r--drivers/soc/bcm/Kconfig18
-rw-r--r--drivers/soc/bcm/Makefile1
-rw-r--r--drivers/soc/bcm/brcmstb/Makefile (renamed from drivers/soc/brcmstb/Makefile)0
-rw-r--r--drivers/soc/bcm/brcmstb/biuctrl.c (renamed from drivers/soc/brcmstb/biuctrl.c)1
-rw-r--r--drivers/soc/bcm/brcmstb/common.c (renamed from drivers/soc/brcmstb/common.c)0
-rw-r--r--drivers/soc/brcmstb/Kconfig10
-rw-r--r--drivers/soc/qcom/smem_state.c12
-rw-r--r--drivers/soc/qcom/smp2p.c7
-rw-r--r--drivers/soc/qcom/smsm.c2
-rw-r--r--drivers/soc/qcom/wcnss_ctrl.c125
-rw-r--r--drivers/soc/samsung/Kconfig4
-rw-r--r--drivers/soc/samsung/Makefile1
-rw-r--r--drivers/soc/samsung/exynos3250-pmu.c2
-rw-r--r--drivers/soc/samsung/exynos5420-pmu.c2
-rw-r--r--drivers/soc/samsung/pm_domains.c245
-rw-r--r--drivers/soc/tegra/pmc.c149
-rw-r--r--drivers/soc/ux500/Kconfig7
-rw-r--r--drivers/soc/ux500/Makefile1
-rw-r--r--drivers/soc/ux500/ux500-soc-id.c222
-rw-r--r--drivers/tty/serial/clps711x.c2
-rw-r--r--drivers/video/fbdev/clps711x-fb.c4
74 files changed, 4005 insertions, 744 deletions
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index c5a7de9bc783..3b205e212337 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -132,6 +132,19 @@ config SUNXI_RSB
132 with various RSB based devices, such as AXP223, AXP8XX PMICs, 132 with various RSB based devices, such as AXP223, AXP8XX PMICs,
133 and AC100/AC200 ICs. 133 and AC100/AC200 ICs.
134 134
135# TODO: This uses pm_clk_*() symbols that aren't exported in v4.7 and hence
136# the driver will fail to build as a module. However there are patches to
137# address that queued for v4.8, so this can be turned into a tristate symbol
138# after v4.8-rc1.
139config TEGRA_ACONNECT
140 bool "Tegra ACONNECT Bus Driver"
141 depends on ARCH_TEGRA_210_SOC
142 depends on OF && PM
143 select PM_CLK
144 help
145 Driver for the Tegra ACONNECT bus which is used to interface with
146 the devices inside the Audio Processing Engine (APE) for Tegra210.
147
135config UNIPHIER_SYSTEM_BUS 148config UNIPHIER_SYSTEM_BUS
136 tristate "UniPhier System Bus driver" 149 tristate "UniPhier System Bus driver"
137 depends on ARCH_UNIPHIER && OF 150 depends on ARCH_UNIPHIER && OF
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index ccff007ee7e8..ac84cc4348e3 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -17,5 +17,6 @@ obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
17obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o 17obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
18obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o 18obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
19obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o 19obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
20obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o
20obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o 21obj-$(CONFIG_UNIPHIER_SYSTEM_BUS) += uniphier-system-bus.o
21obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o 22obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
diff --git a/drivers/bus/tegra-aconnect.c b/drivers/bus/tegra-aconnect.c
new file mode 100644
index 000000000000..7e4104b74fa8
--- /dev/null
+++ b/drivers/bus/tegra-aconnect.c
@@ -0,0 +1,112 @@
1/*
2 * Tegra ACONNECT Bus Driver
3 *
4 * Copyright (C) 2016, NVIDIA CORPORATION. All rights reserved.
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10
11#include <linux/clk.h>
12#include <linux/module.h>
13#include <linux/of_platform.h>
14#include <linux/platform_device.h>
15#include <linux/pm_clock.h>
16#include <linux/pm_runtime.h>
17
18static int tegra_aconnect_add_clock(struct device *dev, char *name)
19{
20 struct clk *clk;
21 int ret;
22
23 clk = clk_get(dev, name);
24 if (IS_ERR(clk)) {
25 dev_err(dev, "%s clock not found\n", name);
26 return PTR_ERR(clk);
27 }
28
29 ret = pm_clk_add_clk(dev, clk);
30 if (ret)
31 clk_put(clk);
32
33 return ret;
34}
35
36static int tegra_aconnect_probe(struct platform_device *pdev)
37{
38 int ret;
39
40 if (!pdev->dev.of_node)
41 return -EINVAL;
42
43 ret = pm_clk_create(&pdev->dev);
44 if (ret)
45 return ret;
46
47 ret = tegra_aconnect_add_clock(&pdev->dev, "ape");
48 if (ret)
49 goto clk_destroy;
50
51 ret = tegra_aconnect_add_clock(&pdev->dev, "apb2ape");
52 if (ret)
53 goto clk_destroy;
54
55 pm_runtime_enable(&pdev->dev);
56
57 of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
58
59 dev_info(&pdev->dev, "Tegra ACONNECT bus registered\n");
60
61 return 0;
62
63clk_destroy:
64 pm_clk_destroy(&pdev->dev);
65
66 return ret;
67}
68
69static int tegra_aconnect_remove(struct platform_device *pdev)
70{
71 pm_runtime_disable(&pdev->dev);
72
73 pm_clk_destroy(&pdev->dev);
74
75 return 0;
76}
77
78static int tegra_aconnect_runtime_resume(struct device *dev)
79{
80 return pm_clk_resume(dev);
81}
82
83static int tegra_aconnect_runtime_suspend(struct device *dev)
84{
85 return pm_clk_suspend(dev);
86}
87
88static const struct dev_pm_ops tegra_aconnect_pm_ops = {
89 SET_RUNTIME_PM_OPS(tegra_aconnect_runtime_suspend,
90 tegra_aconnect_runtime_resume, NULL)
91};
92
93static const struct of_device_id tegra_aconnect_of_match[] = {
94 { .compatible = "nvidia,tegra210-aconnect", },
95 { }
96};
97MODULE_DEVICE_TABLE(of, tegra_aconnect_of_match);
98
99static struct platform_driver tegra_aconnect_driver = {
100 .probe = tegra_aconnect_probe,
101 .remove = tegra_aconnect_remove,
102 .driver = {
103 .name = "tegra-aconnect",
104 .of_match_table = tegra_aconnect_of_match,
105 .pm = &tegra_aconnect_pm_ops,
106 },
107};
108module_platform_driver(tegra_aconnect_driver);
109
110MODULE_DESCRIPTION("NVIDIA Tegra ACONNECT Bus Driver");
111MODULE_AUTHOR("Jon Hunter <jonathanh@nvidia.com>");
112MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/clk-clps711x.c b/drivers/clk/clk-clps711x.c
index 1f60b02416a7..adaf109f2fe2 100644
--- a/drivers/clk/clk-clps711x.c
+++ b/drivers/clk/clk-clps711x.c
@@ -184,5 +184,5 @@ static void __init clps711x_clk_init_dt(struct device_node *np)
184 of_clk_add_provider(np, of_clk_src_onecell_get, 184 of_clk_add_provider(np, of_clk_src_onecell_get,
185 &clps711x_clk->clk_data); 185 &clps711x_clk->clk_data);
186} 186}
187CLK_OF_DECLARE(clps711x, "cirrus,clps711x-clk", clps711x_clk_init_dt); 187CLK_OF_DECLARE(clps711x, "cirrus,ep7209-clk", clps711x_clk_init_dt);
188#endif 188#endif
diff --git a/drivers/clk/ux500/u8500_of_clk.c b/drivers/clk/ux500/u8500_of_clk.c
index 9a736d939806..e960d686d9db 100644
--- a/drivers/clk/ux500/u8500_of_clk.c
+++ b/drivers/clk/ux500/u8500_of_clk.c
@@ -11,7 +11,6 @@
11#include <linux/of_address.h> 11#include <linux/of_address.h>
12#include <linux/clk-provider.h> 12#include <linux/clk-provider.h>
13#include <linux/mfd/dbx500-prcmu.h> 13#include <linux/mfd/dbx500-prcmu.h>
14#include <linux/platform_data/clk-ux500.h>
15#include "clk.h" 14#include "clk.h"
16 15
17#define PRCC_NUM_PERIPH_CLUSTERS 6 16#define PRCC_NUM_PERIPH_CLUSTERS 6
@@ -48,11 +47,6 @@ static struct clk *ux500_twocell_get(struct of_phandle_args *clkspec,
48 return PRCC_SHOW(clk_data, base, bit); 47 return PRCC_SHOW(clk_data, base, bit);
49} 48}
50 49
51static const struct of_device_id u8500_clk_of_match[] = {
52 { .compatible = "stericsson,u8500-clks", },
53 { },
54};
55
56/* CLKRST4 is missing making it hard to index things */ 50/* CLKRST4 is missing making it hard to index things */
57enum clkrst_index { 51enum clkrst_index {
58 CLKRST1_INDEX = 0, 52 CLKRST1_INDEX = 0,
@@ -63,22 +57,15 @@ enum clkrst_index {
63 CLKRST_MAX, 57 CLKRST_MAX,
64}; 58};
65 59
66void u8500_clk_init(void) 60static void u8500_clk_init(struct device_node *np)
67{ 61{
68 struct prcmu_fw_version *fw_version; 62 struct prcmu_fw_version *fw_version;
69 struct device_node *np = NULL;
70 struct device_node *child = NULL; 63 struct device_node *child = NULL;
71 const char *sgaclk_parent = NULL; 64 const char *sgaclk_parent = NULL;
72 struct clk *clk, *rtc_clk, *twd_clk; 65 struct clk *clk, *rtc_clk, *twd_clk;
73 u32 bases[CLKRST_MAX]; 66 u32 bases[CLKRST_MAX];
74 int i; 67 int i;
75 68
76 if (of_have_populated_dt())
77 np = of_find_matching_node(NULL, u8500_clk_of_match);
78 if (!np) {
79 pr_err("Either DT or U8500 Clock node not found\n");
80 return;
81 }
82 for (i = 0; i < ARRAY_SIZE(bases); i++) { 69 for (i = 0; i < ARRAY_SIZE(bases); i++) {
83 struct resource r; 70 struct resource r;
84 71
@@ -573,3 +560,4 @@ void u8500_clk_init(void)
573 of_clk_add_provider(child, of_clk_src_simple_get, twd_clk); 560 of_clk_add_provider(child, of_clk_src_simple_get, twd_clk);
574 } 561 }
575} 562}
563CLK_OF_DECLARE(u8500_clks, "stericsson,u8500-clks", u8500_clk_init);
diff --git a/drivers/clk/ux500/u8540_clk.c b/drivers/clk/ux500/u8540_clk.c
index 86549e59fb42..133859f0e2bf 100644
--- a/drivers/clk/ux500/u8540_clk.c
+++ b/drivers/clk/ux500/u8540_clk.c
@@ -12,14 +12,8 @@
12#include <linux/clkdev.h> 12#include <linux/clkdev.h>
13#include <linux/clk-provider.h> 13#include <linux/clk-provider.h>
14#include <linux/mfd/dbx500-prcmu.h> 14#include <linux/mfd/dbx500-prcmu.h>
15#include <linux/platform_data/clk-ux500.h>
16#include "clk.h" 15#include "clk.h"
17 16
18static const struct of_device_id u8540_clk_of_match[] = {
19 { .compatible = "stericsson,u8540-clks", },
20 { }
21};
22
23/* CLKRST4 is missing making it hard to index things */ 17/* CLKRST4 is missing making it hard to index things */
24enum clkrst_index { 18enum clkrst_index {
25 CLKRST1_INDEX = 0, 19 CLKRST1_INDEX = 0,
@@ -30,19 +24,12 @@ enum clkrst_index {
30 CLKRST_MAX, 24 CLKRST_MAX,
31}; 25};
32 26
33void u8540_clk_init(void) 27static void u8540_clk_init(struct device_node *np)
34{ 28{
35 struct clk *clk; 29 struct clk *clk;
36 struct device_node *np = NULL;
37 u32 bases[CLKRST_MAX]; 30 u32 bases[CLKRST_MAX];
38 int i; 31 int i;
39 32
40 if (of_have_populated_dt())
41 np = of_find_matching_node(NULL, u8540_clk_of_match);
42 if (!np) {
43 pr_err("Either DT or U8540 Clock node not found\n");
44 return;
45 }
46 for (i = 0; i < ARRAY_SIZE(bases); i++) { 33 for (i = 0; i < ARRAY_SIZE(bases); i++) {
47 struct resource r; 34 struct resource r;
48 35
@@ -607,3 +594,4 @@ void u8540_clk_init(void)
607 bases[CLKRST6_INDEX], BIT(0), CLK_SET_RATE_GATE); 594 bases[CLKRST6_INDEX], BIT(0), CLK_SET_RATE_GATE);
608 clk_register_clkdev(clk, NULL, "rng"); 595 clk_register_clkdev(clk, NULL, "rng");
609} 596}
597CLK_OF_DECLARE(u8540_clks, "stericsson,u8540-clks", u8540_clk_init);
diff --git a/drivers/clk/ux500/u9540_clk.c b/drivers/clk/ux500/u9540_clk.c
index 2138a4c8cbca..7b6bca49ce42 100644
--- a/drivers/clk/ux500/u9540_clk.c
+++ b/drivers/clk/ux500/u9540_clk.c
@@ -9,10 +9,10 @@
9 9
10#include <linux/clk-provider.h> 10#include <linux/clk-provider.h>
11#include <linux/mfd/dbx500-prcmu.h> 11#include <linux/mfd/dbx500-prcmu.h>
12#include <linux/platform_data/clk-ux500.h>
13#include "clk.h" 12#include "clk.h"
14 13
15void u9540_clk_init(void) 14static void u9540_clk_init(struct device_node *np)
16{ 15{
17 /* register clocks here */ 16 /* register clocks here */
18} 17}
18CLK_OF_DECLARE(u9540_clks, "stericsson,u9540-clks", u9540_clk_init);
diff --git a/drivers/clocksource/clps711x-timer.c b/drivers/clocksource/clps711x-timer.c
index 84aed78261e4..24db6d605549 100644
--- a/drivers/clocksource/clps711x-timer.c
+++ b/drivers/clocksource/clps711x-timer.c
@@ -119,5 +119,5 @@ static int __init clps711x_timer_init(struct device_node *np)
119 return -EINVAL; 119 return -EINVAL;
120 } 120 }
121} 121}
122CLOCKSOURCE_OF_DECLARE(clps711x, "cirrus,clps711x-timer", clps711x_timer_init); 122CLOCKSOURCE_OF_DECLARE(clps711x, "cirrus,ep7209-timer", clps711x_timer_init);
123#endif 123#endif
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c
index 9e07588ea9f5..f82074eea779 100644
--- a/drivers/cpufreq/s5pv210-cpufreq.c
+++ b/drivers/cpufreq/s5pv210-cpufreq.c
@@ -220,7 +220,7 @@ static void s5pv210_set_refresh(enum s5pv210_dmc_port ch, unsigned long freq)
220 220
221 tmp1 /= tmp; 221 tmp1 /= tmp;
222 222
223 __raw_writel(tmp1, reg); 223 writel_relaxed(tmp1, reg);
224} 224}
225 225
226static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) 226static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
@@ -296,29 +296,29 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
296 * 1. Temporary Change divider for MFC and G3D 296 * 1. Temporary Change divider for MFC and G3D
297 * SCLKA2M(200/1=200)->(200/4=50)Mhz 297 * SCLKA2M(200/1=200)->(200/4=50)Mhz
298 */ 298 */
299 reg = __raw_readl(S5P_CLK_DIV2); 299 reg = readl_relaxed(S5P_CLK_DIV2);
300 reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK); 300 reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK);
301 reg |= (3 << S5P_CLKDIV2_G3D_SHIFT) | 301 reg |= (3 << S5P_CLKDIV2_G3D_SHIFT) |
302 (3 << S5P_CLKDIV2_MFC_SHIFT); 302 (3 << S5P_CLKDIV2_MFC_SHIFT);
303 __raw_writel(reg, S5P_CLK_DIV2); 303 writel_relaxed(reg, S5P_CLK_DIV2);
304 304
305 /* For MFC, G3D dividing */ 305 /* For MFC, G3D dividing */
306 do { 306 do {
307 reg = __raw_readl(S5P_CLKDIV_STAT0); 307 reg = readl_relaxed(S5P_CLKDIV_STAT0);
308 } while (reg & ((1 << 16) | (1 << 17))); 308 } while (reg & ((1 << 16) | (1 << 17)));
309 309
310 /* 310 /*
311 * 2. Change SCLKA2M(200Mhz)to SCLKMPLL in MFC_MUX, G3D MUX 311 * 2. Change SCLKA2M(200Mhz)to SCLKMPLL in MFC_MUX, G3D MUX
312 * (200/4=50)->(667/4=166)Mhz 312 * (200/4=50)->(667/4=166)Mhz
313 */ 313 */
314 reg = __raw_readl(S5P_CLK_SRC2); 314 reg = readl_relaxed(S5P_CLK_SRC2);
315 reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK); 315 reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK);
316 reg |= (1 << S5P_CLKSRC2_G3D_SHIFT) | 316 reg |= (1 << S5P_CLKSRC2_G3D_SHIFT) |
317 (1 << S5P_CLKSRC2_MFC_SHIFT); 317 (1 << S5P_CLKSRC2_MFC_SHIFT);
318 __raw_writel(reg, S5P_CLK_SRC2); 318 writel_relaxed(reg, S5P_CLK_SRC2);
319 319
320 do { 320 do {
321 reg = __raw_readl(S5P_CLKMUX_STAT1); 321 reg = readl_relaxed(S5P_CLKMUX_STAT1);
322 } while (reg & ((1 << 7) | (1 << 3))); 322 } while (reg & ((1 << 7) | (1 << 3)));
323 323
324 /* 324 /*
@@ -330,19 +330,19 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
330 s5pv210_set_refresh(DMC1, 133000); 330 s5pv210_set_refresh(DMC1, 133000);
331 331
332 /* 4. SCLKAPLL -> SCLKMPLL */ 332 /* 4. SCLKAPLL -> SCLKMPLL */
333 reg = __raw_readl(S5P_CLK_SRC0); 333 reg = readl_relaxed(S5P_CLK_SRC0);
334 reg &= ~(S5P_CLKSRC0_MUX200_MASK); 334 reg &= ~(S5P_CLKSRC0_MUX200_MASK);
335 reg |= (0x1 << S5P_CLKSRC0_MUX200_SHIFT); 335 reg |= (0x1 << S5P_CLKSRC0_MUX200_SHIFT);
336 __raw_writel(reg, S5P_CLK_SRC0); 336 writel_relaxed(reg, S5P_CLK_SRC0);
337 337
338 do { 338 do {
339 reg = __raw_readl(S5P_CLKMUX_STAT0); 339 reg = readl_relaxed(S5P_CLKMUX_STAT0);
340 } while (reg & (0x1 << 18)); 340 } while (reg & (0x1 << 18));
341 341
342 } 342 }
343 343
344 /* Change divider */ 344 /* Change divider */
345 reg = __raw_readl(S5P_CLK_DIV0); 345 reg = readl_relaxed(S5P_CLK_DIV0);
346 346
347 reg &= ~(S5P_CLKDIV0_APLL_MASK | S5P_CLKDIV0_A2M_MASK | 347 reg &= ~(S5P_CLKDIV0_APLL_MASK | S5P_CLKDIV0_A2M_MASK |
348 S5P_CLKDIV0_HCLK200_MASK | S5P_CLKDIV0_PCLK100_MASK | 348 S5P_CLKDIV0_HCLK200_MASK | S5P_CLKDIV0_PCLK100_MASK |
@@ -358,25 +358,25 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
358 (clkdiv_val[index][6] << S5P_CLKDIV0_HCLK133_SHIFT) | 358 (clkdiv_val[index][6] << S5P_CLKDIV0_HCLK133_SHIFT) |
359 (clkdiv_val[index][7] << S5P_CLKDIV0_PCLK66_SHIFT)); 359 (clkdiv_val[index][7] << S5P_CLKDIV0_PCLK66_SHIFT));
360 360
361 __raw_writel(reg, S5P_CLK_DIV0); 361 writel_relaxed(reg, S5P_CLK_DIV0);
362 362
363 do { 363 do {
364 reg = __raw_readl(S5P_CLKDIV_STAT0); 364 reg = readl_relaxed(S5P_CLKDIV_STAT0);
365 } while (reg & 0xff); 365 } while (reg & 0xff);
366 366
367 /* ARM MCS value changed */ 367 /* ARM MCS value changed */
368 reg = __raw_readl(S5P_ARM_MCS_CON); 368 reg = readl_relaxed(S5P_ARM_MCS_CON);
369 reg &= ~0x3; 369 reg &= ~0x3;
370 if (index >= L3) 370 if (index >= L3)
371 reg |= 0x3; 371 reg |= 0x3;
372 else 372 else
373 reg |= 0x1; 373 reg |= 0x1;
374 374
375 __raw_writel(reg, S5P_ARM_MCS_CON); 375 writel_relaxed(reg, S5P_ARM_MCS_CON);
376 376
377 if (pll_changing) { 377 if (pll_changing) {
378 /* 5. Set Lock time = 30us*24Mhz = 0x2cf */ 378 /* 5. Set Lock time = 30us*24Mhz = 0x2cf */
379 __raw_writel(0x2cf, S5P_APLL_LOCK); 379 writel_relaxed(0x2cf, S5P_APLL_LOCK);
380 380
381 /* 381 /*
382 * 6. Turn on APLL 382 * 6. Turn on APLL
@@ -384,12 +384,12 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
384 * 6-2. Wait untile the PLL is locked 384 * 6-2. Wait untile the PLL is locked
385 */ 385 */
386 if (index == L0) 386 if (index == L0)
387 __raw_writel(APLL_VAL_1000, S5P_APLL_CON); 387 writel_relaxed(APLL_VAL_1000, S5P_APLL_CON);
388 else 388 else
389 __raw_writel(APLL_VAL_800, S5P_APLL_CON); 389 writel_relaxed(APLL_VAL_800, S5P_APLL_CON);
390 390
391 do { 391 do {
392 reg = __raw_readl(S5P_APLL_CON); 392 reg = readl_relaxed(S5P_APLL_CON);
393 } while (!(reg & (0x1 << 29))); 393 } while (!(reg & (0x1 << 29)));
394 394
395 /* 395 /*
@@ -397,39 +397,39 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
397 * to SCLKA2M(200Mhz) in MFC_MUX and G3D MUX 397 * to SCLKA2M(200Mhz) in MFC_MUX and G3D MUX
398 * (667/4=166)->(200/4=50)Mhz 398 * (667/4=166)->(200/4=50)Mhz
399 */ 399 */
400 reg = __raw_readl(S5P_CLK_SRC2); 400 reg = readl_relaxed(S5P_CLK_SRC2);
401 reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK); 401 reg &= ~(S5P_CLKSRC2_G3D_MASK | S5P_CLKSRC2_MFC_MASK);
402 reg |= (0 << S5P_CLKSRC2_G3D_SHIFT) | 402 reg |= (0 << S5P_CLKSRC2_G3D_SHIFT) |
403 (0 << S5P_CLKSRC2_MFC_SHIFT); 403 (0 << S5P_CLKSRC2_MFC_SHIFT);
404 __raw_writel(reg, S5P_CLK_SRC2); 404 writel_relaxed(reg, S5P_CLK_SRC2);
405 405
406 do { 406 do {
407 reg = __raw_readl(S5P_CLKMUX_STAT1); 407 reg = readl_relaxed(S5P_CLKMUX_STAT1);
408 } while (reg & ((1 << 7) | (1 << 3))); 408 } while (reg & ((1 << 7) | (1 << 3)));
409 409
410 /* 410 /*
411 * 8. Change divider for MFC and G3D 411 * 8. Change divider for MFC and G3D
412 * (200/4=50)->(200/1=200)Mhz 412 * (200/4=50)->(200/1=200)Mhz
413 */ 413 */
414 reg = __raw_readl(S5P_CLK_DIV2); 414 reg = readl_relaxed(S5P_CLK_DIV2);
415 reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK); 415 reg &= ~(S5P_CLKDIV2_G3D_MASK | S5P_CLKDIV2_MFC_MASK);
416 reg |= (clkdiv_val[index][10] << S5P_CLKDIV2_G3D_SHIFT) | 416 reg |= (clkdiv_val[index][10] << S5P_CLKDIV2_G3D_SHIFT) |
417 (clkdiv_val[index][9] << S5P_CLKDIV2_MFC_SHIFT); 417 (clkdiv_val[index][9] << S5P_CLKDIV2_MFC_SHIFT);
418 __raw_writel(reg, S5P_CLK_DIV2); 418 writel_relaxed(reg, S5P_CLK_DIV2);
419 419
420 /* For MFC, G3D dividing */ 420 /* For MFC, G3D dividing */
421 do { 421 do {
422 reg = __raw_readl(S5P_CLKDIV_STAT0); 422 reg = readl_relaxed(S5P_CLKDIV_STAT0);
423 } while (reg & ((1 << 16) | (1 << 17))); 423 } while (reg & ((1 << 16) | (1 << 17)));
424 424
425 /* 9. Change MPLL to APLL in MSYS_MUX */ 425 /* 9. Change MPLL to APLL in MSYS_MUX */
426 reg = __raw_readl(S5P_CLK_SRC0); 426 reg = readl_relaxed(S5P_CLK_SRC0);
427 reg &= ~(S5P_CLKSRC0_MUX200_MASK); 427 reg &= ~(S5P_CLKSRC0_MUX200_MASK);
428 reg |= (0x0 << S5P_CLKSRC0_MUX200_SHIFT); 428 reg |= (0x0 << S5P_CLKSRC0_MUX200_SHIFT);
429 __raw_writel(reg, S5P_CLK_SRC0); 429 writel_relaxed(reg, S5P_CLK_SRC0);
430 430
431 do { 431 do {
432 reg = __raw_readl(S5P_CLKMUX_STAT0); 432 reg = readl_relaxed(S5P_CLKMUX_STAT0);
433 } while (reg & (0x1 << 18)); 433 } while (reg & (0x1 << 18));
434 434
435 /* 435 /*
@@ -446,13 +446,13 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index)
446 * and memory refresh parameter should be changed 446 * and memory refresh parameter should be changed
447 */ 447 */
448 if (bus_speed_changing) { 448 if (bus_speed_changing) {
449 reg = __raw_readl(S5P_CLK_DIV6); 449 reg = readl_relaxed(S5P_CLK_DIV6);
450 reg &= ~S5P_CLKDIV6_ONEDRAM_MASK; 450 reg &= ~S5P_CLKDIV6_ONEDRAM_MASK;
451 reg |= (clkdiv_val[index][8] << S5P_CLKDIV6_ONEDRAM_SHIFT); 451 reg |= (clkdiv_val[index][8] << S5P_CLKDIV6_ONEDRAM_SHIFT);
452 __raw_writel(reg, S5P_CLK_DIV6); 452 writel_relaxed(reg, S5P_CLK_DIV6);
453 453
454 do { 454 do {
455 reg = __raw_readl(S5P_CLKDIV_STAT1); 455 reg = readl_relaxed(S5P_CLKDIV_STAT1);
456 } while (reg & (1 << 15)); 456 } while (reg & (1 << 15));
457 457
458 /* Reconfigure DRAM refresh counter value */ 458 /* Reconfigure DRAM refresh counter value */
@@ -492,7 +492,7 @@ static int check_mem_type(void __iomem *dmc_reg)
492{ 492{
493 unsigned long val; 493 unsigned long val;
494 494
495 val = __raw_readl(dmc_reg + 0x4); 495 val = readl_relaxed(dmc_reg + 0x4);
496 val = (val & (0xf << 8)); 496 val = (val & (0xf << 8));
497 497
498 return val >> 8; 498 return val >> 8;
@@ -537,10 +537,10 @@ static int s5pv210_cpu_init(struct cpufreq_policy *policy)
537 } 537 }
538 538
539 /* Find current refresh counter and frequency each DMC */ 539 /* Find current refresh counter and frequency each DMC */
540 s5pv210_dram_conf[0].refresh = (__raw_readl(dmc_base[0] + 0x30) * 1000); 540 s5pv210_dram_conf[0].refresh = (readl_relaxed(dmc_base[0] + 0x30) * 1000);
541 s5pv210_dram_conf[0].freq = clk_get_rate(dmc0_clk); 541 s5pv210_dram_conf[0].freq = clk_get_rate(dmc0_clk);
542 542
543 s5pv210_dram_conf[1].refresh = (__raw_readl(dmc_base[1] + 0x30) * 1000); 543 s5pv210_dram_conf[1].refresh = (readl_relaxed(dmc_base[1] + 0x30) * 1000);
544 s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk); 544 s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
545 545
546 policy->suspend_freq = SLEEP_FREQ; 546 policy->suspend_freq = SLEEP_FREQ;
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index 6664f1108c7c..0e22f241403b 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -10,7 +10,7 @@ config ARM_PSCI_FW
10 10
11config ARM_SCPI_PROTOCOL 11config ARM_SCPI_PROTOCOL
12 tristate "ARM System Control and Power Interface (SCPI) Message Protocol" 12 tristate "ARM System Control and Power Interface (SCPI) Message Protocol"
13 depends on ARM_MHU 13 depends on MAILBOX
14 help 14 help
15 System Control and Power Interface (SCPI) Message Protocol is 15 System Control and Power Interface (SCPI) Message Protocol is
16 defined for the purpose of communication between the Application 16 defined for the purpose of communication between the Application
@@ -27,6 +27,15 @@ config ARM_SCPI_PROTOCOL
27 This protocol library provides interface for all the client drivers 27 This protocol library provides interface for all the client drivers
28 making use of the features offered by the SCP. 28 making use of the features offered by the SCP.
29 29
30config ARM_SCPI_POWER_DOMAIN
31 tristate "SCPI power domain driver"
32 depends on ARM_SCPI_PROTOCOL || (COMPILE_TEST && OF)
33 default y
34 select PM_GENERIC_DOMAINS if PM
35 help
36 This enables support for the SCPI power domains which can be
37 enabled or disabled via the SCP firmware
38
30config EDD 39config EDD
31 tristate "BIOS Enhanced Disk Drive calls determine boot disk" 40 tristate "BIOS Enhanced Disk Drive calls determine boot disk"
32 depends on X86 41 depends on X86
@@ -184,6 +193,7 @@ config FW_CFG_SYSFS_CMDLINE
184config QCOM_SCM 193config QCOM_SCM
185 bool 194 bool
186 depends on ARM || ARM64 195 depends on ARM || ARM64
196 select RESET_CONTROLLER
187 197
188config QCOM_SCM_32 198config QCOM_SCM_32
189 def_bool y 199 def_bool y
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 474bada56fcd..44a59dcfc398 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -3,6 +3,7 @@
3# 3#
4obj-$(CONFIG_ARM_PSCI_FW) += psci.o 4obj-$(CONFIG_ARM_PSCI_FW) += psci.o
5obj-$(CONFIG_ARM_SCPI_PROTOCOL) += arm_scpi.o 5obj-$(CONFIG_ARM_SCPI_PROTOCOL) += arm_scpi.o
6obj-$(CONFIG_ARM_SCPI_POWER_DOMAIN) += scpi_pm_domain.o
6obj-$(CONFIG_DMI) += dmi_scan.o 7obj-$(CONFIG_DMI) += dmi_scan.o
7obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o 8obj-$(CONFIG_DMI_SYSFS) += dmi-sysfs.o
8obj-$(CONFIG_EDD) += edd.o 9obj-$(CONFIG_EDD) += edd.o
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 7e3e595c9f30..438893762076 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -210,10 +210,6 @@ struct dvfs_info {
210 } opps[MAX_DVFS_OPPS]; 210 } opps[MAX_DVFS_OPPS];
211} __packed; 211} __packed;
212 212
213struct dvfs_get {
214 u8 index;
215} __packed;
216
217struct dvfs_set { 213struct dvfs_set {
218 u8 domain; 214 u8 domain;
219 u8 index; 215 u8 index;
@@ -235,6 +231,11 @@ struct sensor_value {
235 __le32 hi_val; 231 __le32 hi_val;
236} __packed; 232} __packed;
237 233
234struct dev_pstate_set {
235 u16 dev_id;
236 u8 pstate;
237} __packed;
238
238static struct scpi_drvinfo *scpi_info; 239static struct scpi_drvinfo *scpi_info;
239 240
240static int scpi_linux_errmap[SCPI_ERR_MAX] = { 241static int scpi_linux_errmap[SCPI_ERR_MAX] = {
@@ -431,11 +432,11 @@ static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
431static int scpi_dvfs_get_idx(u8 domain) 432static int scpi_dvfs_get_idx(u8 domain)
432{ 433{
433 int ret; 434 int ret;
434 struct dvfs_get dvfs; 435 u8 dvfs_idx;
435 436
436 ret = scpi_send_message(SCPI_CMD_GET_DVFS, &domain, sizeof(domain), 437 ret = scpi_send_message(SCPI_CMD_GET_DVFS, &domain, sizeof(domain),
437 &dvfs, sizeof(dvfs)); 438 &dvfs_idx, sizeof(dvfs_idx));
438 return ret ? ret : dvfs.index; 439 return ret ? ret : dvfs_idx;
439} 440}
440 441
441static int scpi_dvfs_set_idx(u8 domain, u8 index) 442static int scpi_dvfs_set_idx(u8 domain, u8 index)
@@ -526,7 +527,7 @@ static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info)
526 return ret; 527 return ret;
527} 528}
528 529
529int scpi_sensor_get_value(u16 sensor, u64 *val) 530static int scpi_sensor_get_value(u16 sensor, u64 *val)
530{ 531{
531 __le16 id = cpu_to_le16(sensor); 532 __le16 id = cpu_to_le16(sensor);
532 struct sensor_value buf; 533 struct sensor_value buf;
@@ -541,6 +542,29 @@ int scpi_sensor_get_value(u16 sensor, u64 *val)
541 return ret; 542 return ret;
542} 543}
543 544
545static int scpi_device_get_power_state(u16 dev_id)
546{
547 int ret;
548 u8 pstate;
549 __le16 id = cpu_to_le16(dev_id);
550
551 ret = scpi_send_message(SCPI_CMD_GET_DEVICE_PWR_STATE, &id,
552 sizeof(id), &pstate, sizeof(pstate));
553 return ret ? ret : pstate;
554}
555
556static int scpi_device_set_power_state(u16 dev_id, u8 pstate)
557{
558 int stat;
559 struct dev_pstate_set dev_set = {
560 .dev_id = cpu_to_le16(dev_id),
561 .pstate = pstate,
562 };
563
564 return scpi_send_message(SCPI_CMD_SET_DEVICE_PWR_STATE, &dev_set,
565 sizeof(dev_set), &stat, sizeof(stat));
566}
567
544static struct scpi_ops scpi_ops = { 568static struct scpi_ops scpi_ops = {
545 .get_version = scpi_get_version, 569 .get_version = scpi_get_version,
546 .clk_get_range = scpi_clk_get_range, 570 .clk_get_range = scpi_clk_get_range,
@@ -552,6 +576,8 @@ static struct scpi_ops scpi_ops = {
552 .sensor_get_capability = scpi_sensor_get_capability, 576 .sensor_get_capability = scpi_sensor_get_capability,
553 .sensor_get_info = scpi_sensor_get_info, 577 .sensor_get_info = scpi_sensor_get_info,
554 .sensor_get_value = scpi_sensor_get_value, 578 .sensor_get_value = scpi_sensor_get_value,
579 .device_get_power_state = scpi_device_get_power_state,
580 .device_set_power_state = scpi_device_set_power_state,
555}; 581};
556 582
557struct scpi_ops *get_scpi_ops(void) 583struct scpi_ops *get_scpi_ops(void)
diff --git a/drivers/firmware/qcom_scm-32.c b/drivers/firmware/qcom_scm-32.c
index 0883292f640f..c6aeedbdcbb0 100644
--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -23,8 +23,7 @@
23#include <linux/errno.h> 23#include <linux/errno.h>
24#include <linux/err.h> 24#include <linux/err.h>
25#include <linux/qcom_scm.h> 25#include <linux/qcom_scm.h>
26 26#include <linux/dma-mapping.h>
27#include <asm/cacheflush.h>
28 27
29#include "qcom_scm.h" 28#include "qcom_scm.h"
30 29
@@ -97,44 +96,6 @@ struct qcom_scm_response {
97}; 96};
98 97
99/** 98/**
100 * alloc_qcom_scm_command() - Allocate an SCM command
101 * @cmd_size: size of the command buffer
102 * @resp_size: size of the response buffer
103 *
104 * Allocate an SCM command, including enough room for the command
105 * and response headers as well as the command and response buffers.
106 *
107 * Returns a valid &qcom_scm_command on success or %NULL if the allocation fails.
108 */
109static struct qcom_scm_command *alloc_qcom_scm_command(size_t cmd_size, size_t resp_size)
110{
111 struct qcom_scm_command *cmd;
112 size_t len = sizeof(*cmd) + sizeof(struct qcom_scm_response) + cmd_size +
113 resp_size;
114 u32 offset;
115
116 cmd = kzalloc(PAGE_ALIGN(len), GFP_KERNEL);
117 if (cmd) {
118 cmd->len = cpu_to_le32(len);
119 offset = offsetof(struct qcom_scm_command, buf);
120 cmd->buf_offset = cpu_to_le32(offset);
121 cmd->resp_hdr_offset = cpu_to_le32(offset + cmd_size);
122 }
123 return cmd;
124}
125
126/**
127 * free_qcom_scm_command() - Free an SCM command
128 * @cmd: command to free
129 *
130 * Free an SCM command.
131 */
132static inline void free_qcom_scm_command(struct qcom_scm_command *cmd)
133{
134 kfree(cmd);
135}
136
137/**
138 * qcom_scm_command_to_response() - Get a pointer to a qcom_scm_response 99 * qcom_scm_command_to_response() - Get a pointer to a qcom_scm_response
139 * @cmd: command 100 * @cmd: command
140 * 101 *
@@ -168,23 +129,6 @@ static inline void *qcom_scm_get_response_buffer(const struct qcom_scm_response
168 return (void *)rsp + le32_to_cpu(rsp->buf_offset); 129 return (void *)rsp + le32_to_cpu(rsp->buf_offset);
169} 130}
170 131
171static int qcom_scm_remap_error(int err)
172{
173 pr_err("qcom_scm_call failed with error code %d\n", err);
174 switch (err) {
175 case QCOM_SCM_ERROR:
176 return -EIO;
177 case QCOM_SCM_EINVAL_ADDR:
178 case QCOM_SCM_EINVAL_ARG:
179 return -EINVAL;
180 case QCOM_SCM_EOPNOTSUPP:
181 return -EOPNOTSUPP;
182 case QCOM_SCM_ENOMEM:
183 return -ENOMEM;
184 }
185 return -EINVAL;
186}
187
188static u32 smc(u32 cmd_addr) 132static u32 smc(u32 cmd_addr)
189{ 133{
190 int context_id; 134 int context_id;
@@ -209,45 +153,9 @@ static u32 smc(u32 cmd_addr)
209 return r0; 153 return r0;
210} 154}
211 155
212static int __qcom_scm_call(const struct qcom_scm_command *cmd)
213{
214 int ret;
215 u32 cmd_addr = virt_to_phys(cmd);
216
217 /*
218 * Flush the command buffer so that the secure world sees
219 * the correct data.
220 */
221 secure_flush_area(cmd, cmd->len);
222
223 ret = smc(cmd_addr);
224 if (ret < 0)
225 ret = qcom_scm_remap_error(ret);
226
227 return ret;
228}
229
230static void qcom_scm_inv_range(unsigned long start, unsigned long end)
231{
232 u32 cacheline_size, ctr;
233
234 asm volatile("mrc p15, 0, %0, c0, c0, 1" : "=r" (ctr));
235 cacheline_size = 4 << ((ctr >> 16) & 0xf);
236
237 start = round_down(start, cacheline_size);
238 end = round_up(end, cacheline_size);
239 outer_inv_range(start, end);
240 while (start < end) {
241 asm ("mcr p15, 0, %0, c7, c6, 1" : : "r" (start)
242 : "memory");
243 start += cacheline_size;
244 }
245 dsb();
246 isb();
247}
248
249/** 156/**
250 * qcom_scm_call() - Send an SCM command 157 * qcom_scm_call() - Send an SCM command
158 * @dev: struct device
251 * @svc_id: service identifier 159 * @svc_id: service identifier
252 * @cmd_id: command identifier 160 * @cmd_id: command identifier
253 * @cmd_buf: command buffer 161 * @cmd_buf: command buffer
@@ -264,42 +172,59 @@ static void qcom_scm_inv_range(unsigned long start, unsigned long end)
264 * and response buffers is taken care of by qcom_scm_call; however, callers are 172 * and response buffers is taken care of by qcom_scm_call; however, callers are
265 * responsible for any other cached buffers passed over to the secure world. 173 * responsible for any other cached buffers passed over to the secure world.
266 */ 174 */
267static int qcom_scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, 175static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
268 size_t cmd_len, void *resp_buf, size_t resp_len) 176 const void *cmd_buf, size_t cmd_len, void *resp_buf,
177 size_t resp_len)
269{ 178{
270 int ret; 179 int ret;
271 struct qcom_scm_command *cmd; 180 struct qcom_scm_command *cmd;
272 struct qcom_scm_response *rsp; 181 struct qcom_scm_response *rsp;
273 unsigned long start, end; 182 size_t alloc_len = sizeof(*cmd) + cmd_len + sizeof(*rsp) + resp_len;
183 dma_addr_t cmd_phys;
274 184
275 cmd = alloc_qcom_scm_command(cmd_len, resp_len); 185 cmd = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL);
276 if (!cmd) 186 if (!cmd)
277 return -ENOMEM; 187 return -ENOMEM;
278 188
189 cmd->len = cpu_to_le32(alloc_len);
190 cmd->buf_offset = cpu_to_le32(sizeof(*cmd));
191 cmd->resp_hdr_offset = cpu_to_le32(sizeof(*cmd) + cmd_len);
192
279 cmd->id = cpu_to_le32((svc_id << 10) | cmd_id); 193 cmd->id = cpu_to_le32((svc_id << 10) | cmd_id);
280 if (cmd_buf) 194 if (cmd_buf)
281 memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf, cmd_len); 195 memcpy(qcom_scm_get_command_buffer(cmd), cmd_buf, cmd_len);
282 196
197 rsp = qcom_scm_command_to_response(cmd);
198
199 cmd_phys = dma_map_single(dev, cmd, alloc_len, DMA_TO_DEVICE);
200 if (dma_mapping_error(dev, cmd_phys)) {
201 kfree(cmd);
202 return -ENOMEM;
203 }
204
283 mutex_lock(&qcom_scm_lock); 205 mutex_lock(&qcom_scm_lock);
284 ret = __qcom_scm_call(cmd); 206 ret = smc(cmd_phys);
207 if (ret < 0)
208 ret = qcom_scm_remap_error(ret);
285 mutex_unlock(&qcom_scm_lock); 209 mutex_unlock(&qcom_scm_lock);
286 if (ret) 210 if (ret)
287 goto out; 211 goto out;
288 212
289 rsp = qcom_scm_command_to_response(cmd);
290 start = (unsigned long)rsp;
291
292 do { 213 do {
293 qcom_scm_inv_range(start, start + sizeof(*rsp)); 214 dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len,
215 sizeof(*rsp), DMA_FROM_DEVICE);
294 } while (!rsp->is_complete); 216 } while (!rsp->is_complete);
295 217
296 end = (unsigned long)qcom_scm_get_response_buffer(rsp) + resp_len; 218 if (resp_buf) {
297 qcom_scm_inv_range(start, end); 219 dma_sync_single_for_cpu(dev, cmd_phys + sizeof(*cmd) + cmd_len +
298 220 le32_to_cpu(rsp->buf_offset),
299 if (resp_buf) 221 resp_len, DMA_FROM_DEVICE);
300 memcpy(resp_buf, qcom_scm_get_response_buffer(rsp), resp_len); 222 memcpy(resp_buf, qcom_scm_get_response_buffer(rsp),
223 resp_len);
224 }
301out: 225out:
302 free_qcom_scm_command(cmd); 226 dma_unmap_single(dev, cmd_phys, alloc_len, DMA_TO_DEVICE);
227 kfree(cmd);
303 return ret; 228 return ret;
304} 229}
305 230
@@ -342,6 +267,41 @@ static s32 qcom_scm_call_atomic1(u32 svc, u32 cmd, u32 arg1)
342 return r0; 267 return r0;
343} 268}
344 269
270/**
271 * qcom_scm_call_atomic2() - Send an atomic SCM command with two arguments
272 * @svc_id: service identifier
273 * @cmd_id: command identifier
274 * @arg1: first argument
275 * @arg2: second argument
276 *
277 * This shall only be used with commands that are guaranteed to be
278 * uninterruptable, atomic and SMP safe.
279 */
280static s32 qcom_scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2)
281{
282 int context_id;
283
284 register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 2);
285 register u32 r1 asm("r1") = (u32)&context_id;
286 register u32 r2 asm("r2") = arg1;
287 register u32 r3 asm("r3") = arg2;
288
289 asm volatile(
290 __asmeq("%0", "r0")
291 __asmeq("%1", "r0")
292 __asmeq("%2", "r1")
293 __asmeq("%3", "r2")
294 __asmeq("%4", "r3")
295#ifdef REQUIRES_SEC
296 ".arch_extension sec\n"
297#endif
298 "smc #0 @ switch to secure world\n"
299 : "=r" (r0)
300 : "r" (r0), "r" (r1), "r" (r2), "r" (r3)
301 );
302 return r0;
303}
304
345u32 qcom_scm_get_version(void) 305u32 qcom_scm_get_version(void)
346{ 306{
347 int context_id; 307 int context_id;
@@ -378,22 +338,6 @@ u32 qcom_scm_get_version(void)
378} 338}
379EXPORT_SYMBOL(qcom_scm_get_version); 339EXPORT_SYMBOL(qcom_scm_get_version);
380 340
381/*
382 * Set the cold/warm boot address for one of the CPU cores.
383 */
384static int qcom_scm_set_boot_addr(u32 addr, int flags)
385{
386 struct {
387 __le32 flags;
388 __le32 addr;
389 } cmd;
390
391 cmd.addr = cpu_to_le32(addr);
392 cmd.flags = cpu_to_le32(flags);
393 return qcom_scm_call(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
394 &cmd, sizeof(cmd), NULL, 0);
395}
396
397/** 341/**
398 * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus 342 * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
399 * @entry: Entry point function for the cpus 343 * @entry: Entry point function for the cpus
@@ -423,7 +367,8 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
423 set_cpu_present(cpu, false); 367 set_cpu_present(cpu, false);
424 } 368 }
425 369
426 return qcom_scm_set_boot_addr(virt_to_phys(entry), flags); 370 return qcom_scm_call_atomic2(QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
371 flags, virt_to_phys(entry));
427} 372}
428 373
429/** 374/**
@@ -434,11 +379,16 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
434 * Set the Linux entry point for the SCM to transfer control to when coming 379 * Set the Linux entry point for the SCM to transfer control to when coming
435 * out of a power down. CPU power down may be executed on cpuidle or hotplug. 380 * out of a power down. CPU power down may be executed on cpuidle or hotplug.
436 */ 381 */
437int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus) 382int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
383 const cpumask_t *cpus)
438{ 384{
439 int ret; 385 int ret;
440 int flags = 0; 386 int flags = 0;
441 int cpu; 387 int cpu;
388 struct {
389 __le32 flags;
390 __le32 addr;
391 } cmd;
442 392
443 /* 393 /*
444 * Reassign only if we are switching from hotplug entry point 394 * Reassign only if we are switching from hotplug entry point
@@ -454,7 +404,10 @@ int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
454 if (!flags) 404 if (!flags)
455 return 0; 405 return 0;
456 406
457 ret = qcom_scm_set_boot_addr(virt_to_phys(entry), flags); 407 cmd.addr = cpu_to_le32(virt_to_phys(entry));
408 cmd.flags = cpu_to_le32(flags);
409 ret = qcom_scm_call(dev, QCOM_SCM_SVC_BOOT, QCOM_SCM_BOOT_ADDR,
410 &cmd, sizeof(cmd), NULL, 0);
458 if (!ret) { 411 if (!ret) {
459 for_each_cpu(cpu, cpus) 412 for_each_cpu(cpu, cpus)
460 qcom_scm_wb[cpu].entry = entry; 413 qcom_scm_wb[cpu].entry = entry;
@@ -477,25 +430,133 @@ void __qcom_scm_cpu_power_down(u32 flags)
477 flags & QCOM_SCM_FLUSH_FLAG_MASK); 430 flags & QCOM_SCM_FLUSH_FLAG_MASK);
478} 431}
479 432
480int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id) 433int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id)
481{ 434{
482 int ret; 435 int ret;
483 __le32 svc_cmd = cpu_to_le32((svc_id << 10) | cmd_id); 436 __le32 svc_cmd = cpu_to_le32((svc_id << 10) | cmd_id);
484 __le32 ret_val = 0; 437 __le32 ret_val = 0;
485 438
486 ret = qcom_scm_call(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD, &svc_cmd, 439 ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD,
487 sizeof(svc_cmd), &ret_val, sizeof(ret_val)); 440 &svc_cmd, sizeof(svc_cmd), &ret_val,
441 sizeof(ret_val));
488 if (ret) 442 if (ret)
489 return ret; 443 return ret;
490 444
491 return le32_to_cpu(ret_val); 445 return le32_to_cpu(ret_val);
492} 446}
493 447
494int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) 448int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
449 u32 req_cnt, u32 *resp)
495{ 450{
496 if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT) 451 if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
497 return -ERANGE; 452 return -ERANGE;
498 453
499 return qcom_scm_call(QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP, 454 return qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP,
500 req, req_cnt * sizeof(*req), resp, sizeof(*resp)); 455 req, req_cnt * sizeof(*req), resp, sizeof(*resp));
501} 456}
457
458void __qcom_scm_init(void)
459{
460}
461
462bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral)
463{
464 __le32 out;
465 __le32 in;
466 int ret;
467
468 in = cpu_to_le32(peripheral);
469 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL,
470 QCOM_SCM_PAS_IS_SUPPORTED_CMD,
471 &in, sizeof(in),
472 &out, sizeof(out));
473
474 return ret ? false : !!out;
475}
476
477int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral,
478 dma_addr_t metadata_phys)
479{
480 __le32 scm_ret;
481 int ret;
482 struct {
483 __le32 proc;
484 __le32 image_addr;
485 } request;
486
487 request.proc = cpu_to_le32(peripheral);
488 request.image_addr = cpu_to_le32(metadata_phys);
489
490 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL,
491 QCOM_SCM_PAS_INIT_IMAGE_CMD,
492 &request, sizeof(request),
493 &scm_ret, sizeof(scm_ret));
494
495 return ret ? : le32_to_cpu(scm_ret);
496}
497
498int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral,
499 phys_addr_t addr, phys_addr_t size)
500{
501 __le32 scm_ret;
502 int ret;
503 struct {
504 __le32 proc;
505 __le32 addr;
506 __le32 len;
507 } request;
508
509 request.proc = cpu_to_le32(peripheral);
510 request.addr = cpu_to_le32(addr);
511 request.len = cpu_to_le32(size);
512
513 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL,
514 QCOM_SCM_PAS_MEM_SETUP_CMD,
515 &request, sizeof(request),
516 &scm_ret, sizeof(scm_ret));
517
518 return ret ? : le32_to_cpu(scm_ret);
519}
520
521int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral)
522{
523 __le32 out;
524 __le32 in;
525 int ret;
526
527 in = cpu_to_le32(peripheral);
528 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL,
529 QCOM_SCM_PAS_AUTH_AND_RESET_CMD,
530 &in, sizeof(in),
531 &out, sizeof(out));
532
533 return ret ? : le32_to_cpu(out);
534}
535
536int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral)
537{
538 __le32 out;
539 __le32 in;
540 int ret;
541
542 in = cpu_to_le32(peripheral);
543 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL,
544 QCOM_SCM_PAS_SHUTDOWN_CMD,
545 &in, sizeof(in),
546 &out, sizeof(out));
547
548 return ret ? : le32_to_cpu(out);
549}
550
551int __qcom_scm_pas_mss_reset(struct device *dev, bool reset)
552{
553 __le32 out;
554 __le32 in = cpu_to_le32(reset);
555 int ret;
556
557 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MSS_RESET,
558 &in, sizeof(in),
559 &out, sizeof(out));
560
561 return ret ? : le32_to_cpu(out);
562}
diff --git a/drivers/firmware/qcom_scm-64.c b/drivers/firmware/qcom_scm-64.c
index bb6555f6d63b..4a0f5ead4fb5 100644
--- a/drivers/firmware/qcom_scm-64.c
+++ b/drivers/firmware/qcom_scm-64.c
@@ -12,7 +12,150 @@
12 12
13#include <linux/io.h> 13#include <linux/io.h>
14#include <linux/errno.h> 14#include <linux/errno.h>
15#include <linux/delay.h>
16#include <linux/mutex.h>
17#include <linux/slab.h>
18#include <linux/types.h>
15#include <linux/qcom_scm.h> 19#include <linux/qcom_scm.h>
20#include <linux/arm-smccc.h>
21#include <linux/dma-mapping.h>
22
23#include "qcom_scm.h"
24
25#define QCOM_SCM_FNID(s, c) ((((s) & 0xFF) << 8) | ((c) & 0xFF))
26
27#define MAX_QCOM_SCM_ARGS 10
28#define MAX_QCOM_SCM_RETS 3
29
30enum qcom_scm_arg_types {
31 QCOM_SCM_VAL,
32 QCOM_SCM_RO,
33 QCOM_SCM_RW,
34 QCOM_SCM_BUFVAL,
35};
36
37#define QCOM_SCM_ARGS_IMPL(num, a, b, c, d, e, f, g, h, i, j, ...) (\
38 (((a) & 0x3) << 4) | \
39 (((b) & 0x3) << 6) | \
40 (((c) & 0x3) << 8) | \
41 (((d) & 0x3) << 10) | \
42 (((e) & 0x3) << 12) | \
43 (((f) & 0x3) << 14) | \
44 (((g) & 0x3) << 16) | \
45 (((h) & 0x3) << 18) | \
46 (((i) & 0x3) << 20) | \
47 (((j) & 0x3) << 22) | \
48 ((num) & 0xf))
49
50#define QCOM_SCM_ARGS(...) QCOM_SCM_ARGS_IMPL(__VA_ARGS__, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
51
52/**
53 * struct qcom_scm_desc
54 * @arginfo: Metadata describing the arguments in args[]
55 * @args: The array of arguments for the secure syscall
56 * @res: The values returned by the secure syscall
57 */
58struct qcom_scm_desc {
59 u32 arginfo;
60 u64 args[MAX_QCOM_SCM_ARGS];
61};
62
63static u64 qcom_smccc_convention = -1;
64static DEFINE_MUTEX(qcom_scm_lock);
65
66#define QCOM_SCM_EBUSY_WAIT_MS 30
67#define QCOM_SCM_EBUSY_MAX_RETRY 20
68
69#define N_EXT_QCOM_SCM_ARGS 7
70#define FIRST_EXT_ARG_IDX 3
71#define N_REGISTER_ARGS (MAX_QCOM_SCM_ARGS - N_EXT_QCOM_SCM_ARGS + 1)
72
73/**
74 * qcom_scm_call() - Invoke a syscall in the secure world
75 * @dev: device
76 * @svc_id: service identifier
77 * @cmd_id: command identifier
78 * @desc: Descriptor structure containing arguments and return values
79 *
80 * Sends a command to the SCM and waits for the command to finish processing.
81 * This should *only* be called in pre-emptible context.
82*/
83static int qcom_scm_call(struct device *dev, u32 svc_id, u32 cmd_id,
84 const struct qcom_scm_desc *desc,
85 struct arm_smccc_res *res)
86{
87 int arglen = desc->arginfo & 0xf;
88 int retry_count = 0, i;
89 u32 fn_id = QCOM_SCM_FNID(svc_id, cmd_id);
90 u64 cmd, x5 = desc->args[FIRST_EXT_ARG_IDX];
91 dma_addr_t args_phys = 0;
92 void *args_virt = NULL;
93 size_t alloc_len;
94
95 if (unlikely(arglen > N_REGISTER_ARGS)) {
96 alloc_len = N_EXT_QCOM_SCM_ARGS * sizeof(u64);
97 args_virt = kzalloc(PAGE_ALIGN(alloc_len), GFP_KERNEL);
98
99 if (!args_virt)
100 return -ENOMEM;
101
102 if (qcom_smccc_convention == ARM_SMCCC_SMC_32) {
103 __le32 *args = args_virt;
104
105 for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++)
106 args[i] = cpu_to_le32(desc->args[i +
107 FIRST_EXT_ARG_IDX]);
108 } else {
109 __le64 *args = args_virt;
110
111 for (i = 0; i < N_EXT_QCOM_SCM_ARGS; i++)
112 args[i] = cpu_to_le64(desc->args[i +
113 FIRST_EXT_ARG_IDX]);
114 }
115
116 args_phys = dma_map_single(dev, args_virt, alloc_len,
117 DMA_TO_DEVICE);
118
119 if (dma_mapping_error(dev, args_phys)) {
120 kfree(args_virt);
121 return -ENOMEM;
122 }
123
124 x5 = args_phys;
125 }
126
127 do {
128 mutex_lock(&qcom_scm_lock);
129
130 cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL,
131 qcom_smccc_convention,
132 ARM_SMCCC_OWNER_SIP, fn_id);
133
134 do {
135 arm_smccc_smc(cmd, desc->arginfo, desc->args[0],
136 desc->args[1], desc->args[2], x5, 0, 0,
137 res);
138 } while (res->a0 == QCOM_SCM_INTERRUPTED);
139
140 mutex_unlock(&qcom_scm_lock);
141
142 if (res->a0 == QCOM_SCM_V2_EBUSY) {
143 if (retry_count++ > QCOM_SCM_EBUSY_MAX_RETRY)
144 break;
145 msleep(QCOM_SCM_EBUSY_WAIT_MS);
146 }
147 } while (res->a0 == QCOM_SCM_V2_EBUSY);
148
149 if (args_virt) {
150 dma_unmap_single(dev, args_phys, alloc_len, DMA_TO_DEVICE);
151 kfree(args_virt);
152 }
153
154 if (res->a0 < 0)
155 return qcom_scm_remap_error(res->a0);
156
157 return 0;
158}
16 159
17/** 160/**
18 * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus 161 * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
@@ -29,13 +172,15 @@ int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
29 172
30/** 173/**
31 * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus 174 * qcom_scm_set_warm_boot_addr() - Set the warm boot address for cpus
175 * @dev: Device pointer
32 * @entry: Entry point function for the cpus 176 * @entry: Entry point function for the cpus
33 * @cpus: The cpumask of cpus that will use the entry point 177 * @cpus: The cpumask of cpus that will use the entry point
34 * 178 *
35 * Set the Linux entry point for the SCM to transfer control to when coming 179 * Set the Linux entry point for the SCM to transfer control to when coming
36 * out of a power down. CPU power down may be executed on cpuidle or hotplug. 180 * out of a power down. CPU power down may be executed on cpuidle or hotplug.
37 */ 181 */
38int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus) 182int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
183 const cpumask_t *cpus)
39{ 184{
40 return -ENOTSUPP; 185 return -ENOTSUPP;
41} 186}
@@ -52,12 +197,164 @@ void __qcom_scm_cpu_power_down(u32 flags)
52{ 197{
53} 198}
54 199
55int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id) 200int __qcom_scm_is_call_available(struct device *dev, u32 svc_id, u32 cmd_id)
56{ 201{
57 return -ENOTSUPP; 202 int ret;
203 struct qcom_scm_desc desc = {0};
204 struct arm_smccc_res res;
205
206 desc.arginfo = QCOM_SCM_ARGS(1);
207 desc.args[0] = QCOM_SCM_FNID(svc_id, cmd_id) |
208 (ARM_SMCCC_OWNER_SIP << ARM_SMCCC_OWNER_SHIFT);
209
210 ret = qcom_scm_call(dev, QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD,
211 &desc, &res);
212
213 return ret ? : res.a1;
58} 214}
59 215
60int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) 216int __qcom_scm_hdcp_req(struct device *dev, struct qcom_scm_hdcp_req *req,
217 u32 req_cnt, u32 *resp)
61{ 218{
62 return -ENOTSUPP; 219 int ret;
220 struct qcom_scm_desc desc = {0};
221 struct arm_smccc_res res;
222
223 if (req_cnt > QCOM_SCM_HDCP_MAX_REQ_CNT)
224 return -ERANGE;
225
226 desc.args[0] = req[0].addr;
227 desc.args[1] = req[0].val;
228 desc.args[2] = req[1].addr;
229 desc.args[3] = req[1].val;
230 desc.args[4] = req[2].addr;
231 desc.args[5] = req[2].val;
232 desc.args[6] = req[3].addr;
233 desc.args[7] = req[3].val;
234 desc.args[8] = req[4].addr;
235 desc.args[9] = req[4].val;
236 desc.arginfo = QCOM_SCM_ARGS(10);
237
238 ret = qcom_scm_call(dev, QCOM_SCM_SVC_HDCP, QCOM_SCM_CMD_HDCP, &desc,
239 &res);
240 *resp = res.a1;
241
242 return ret;
243}
244
245void __qcom_scm_init(void)
246{
247 u64 cmd;
248 struct arm_smccc_res res;
249 u32 function = QCOM_SCM_FNID(QCOM_SCM_SVC_INFO, QCOM_IS_CALL_AVAIL_CMD);
250
251 /* First try a SMC64 call */
252 cmd = ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_64,
253 ARM_SMCCC_OWNER_SIP, function);
254
255 arm_smccc_smc(cmd, QCOM_SCM_ARGS(1), cmd & (~BIT(ARM_SMCCC_TYPE_SHIFT)),
256 0, 0, 0, 0, 0, &res);
257
258 if (!res.a0 && res.a1)
259 qcom_smccc_convention = ARM_SMCCC_SMC_64;
260 else
261 qcom_smccc_convention = ARM_SMCCC_SMC_32;
262}
263
264bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral)
265{
266 int ret;
267 struct qcom_scm_desc desc = {0};
268 struct arm_smccc_res res;
269
270 desc.args[0] = peripheral;
271 desc.arginfo = QCOM_SCM_ARGS(1);
272
273 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL,
274 QCOM_SCM_PAS_IS_SUPPORTED_CMD,
275 &desc, &res);
276
277 return ret ? false : !!res.a1;
278}
279
280int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral,
281 dma_addr_t metadata_phys)
282{
283 int ret;
284 struct qcom_scm_desc desc = {0};
285 struct arm_smccc_res res;
286
287 desc.args[0] = peripheral;
288 desc.args[1] = metadata_phys;
289 desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW);
290
291 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_INIT_IMAGE_CMD,
292 &desc, &res);
293
294 return ret ? : res.a1;
295}
296
297int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral,
298 phys_addr_t addr, phys_addr_t size)
299{
300 int ret;
301 struct qcom_scm_desc desc = {0};
302 struct arm_smccc_res res;
303
304 desc.args[0] = peripheral;
305 desc.args[1] = addr;
306 desc.args[2] = size;
307 desc.arginfo = QCOM_SCM_ARGS(3);
308
309 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MEM_SETUP_CMD,
310 &desc, &res);
311
312 return ret ? : res.a1;
313}
314
315int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral)
316{
317 int ret;
318 struct qcom_scm_desc desc = {0};
319 struct arm_smccc_res res;
320
321 desc.args[0] = peripheral;
322 desc.arginfo = QCOM_SCM_ARGS(1);
323
324 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL,
325 QCOM_SCM_PAS_AUTH_AND_RESET_CMD,
326 &desc, &res);
327
328 return ret ? : res.a1;
329}
330
331int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral)
332{
333 int ret;
334 struct qcom_scm_desc desc = {0};
335 struct arm_smccc_res res;
336
337 desc.args[0] = peripheral;
338 desc.arginfo = QCOM_SCM_ARGS(1);
339
340 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_SHUTDOWN_CMD,
341 &desc, &res);
342
343 return ret ? : res.a1;
344}
345
346int __qcom_scm_pas_mss_reset(struct device *dev, bool reset)
347{
348 struct qcom_scm_desc desc = {0};
349 struct arm_smccc_res res;
350 int ret;
351
352 desc.args[0] = reset;
353 desc.args[1] = 0;
354 desc.arginfo = QCOM_SCM_ARGS(2);
355
356 ret = qcom_scm_call(dev, QCOM_SCM_SVC_PIL, QCOM_SCM_PAS_MSS_RESET, &desc,
357 &res);
358
359 return ret ? : res.a1;
63} 360}
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index 45c008d68891..e64a501adbf4 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -10,19 +10,64 @@
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details. 11 * GNU General Public License for more details.
12 * 12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301, USA.
17 */ 13 */
18 14#include <linux/platform_device.h>
15#include <linux/module.h>
19#include <linux/cpumask.h> 16#include <linux/cpumask.h>
20#include <linux/export.h> 17#include <linux/export.h>
18#include <linux/dma-mapping.h>
21#include <linux/types.h> 19#include <linux/types.h>
22#include <linux/qcom_scm.h> 20#include <linux/qcom_scm.h>
21#include <linux/of.h>
22#include <linux/of_platform.h>
23#include <linux/clk.h>
24#include <linux/reset-controller.h>
23 25
24#include "qcom_scm.h" 26#include "qcom_scm.h"
25 27
28struct qcom_scm {
29 struct device *dev;
30 struct clk *core_clk;
31 struct clk *iface_clk;
32 struct clk *bus_clk;
33 struct reset_controller_dev reset;
34};
35
36static struct qcom_scm *__scm;
37
38static int qcom_scm_clk_enable(void)
39{
40 int ret;
41
42 ret = clk_prepare_enable(__scm->core_clk);
43 if (ret)
44 goto bail;
45
46 ret = clk_prepare_enable(__scm->iface_clk);
47 if (ret)
48 goto disable_core;
49
50 ret = clk_prepare_enable(__scm->bus_clk);
51 if (ret)
52 goto disable_iface;
53
54 return 0;
55
56disable_iface:
57 clk_disable_unprepare(__scm->iface_clk);
58disable_core:
59 clk_disable_unprepare(__scm->core_clk);
60bail:
61 return ret;
62}
63
64static void qcom_scm_clk_disable(void)
65{
66 clk_disable_unprepare(__scm->core_clk);
67 clk_disable_unprepare(__scm->iface_clk);
68 clk_disable_unprepare(__scm->bus_clk);
69}
70
26/** 71/**
27 * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus 72 * qcom_scm_set_cold_boot_addr() - Set the cold boot address for cpus
28 * @entry: Entry point function for the cpus 73 * @entry: Entry point function for the cpus
@@ -47,7 +92,7 @@ EXPORT_SYMBOL(qcom_scm_set_cold_boot_addr);
47 */ 92 */
48int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus) 93int qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus)
49{ 94{
50 return __qcom_scm_set_warm_boot_addr(entry, cpus); 95 return __qcom_scm_set_warm_boot_addr(__scm->dev, entry, cpus);
51} 96}
52EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr); 97EXPORT_SYMBOL(qcom_scm_set_warm_boot_addr);
53 98
@@ -72,12 +117,17 @@ EXPORT_SYMBOL(qcom_scm_cpu_power_down);
72 */ 117 */
73bool qcom_scm_hdcp_available(void) 118bool qcom_scm_hdcp_available(void)
74{ 119{
75 int ret; 120 int ret = qcom_scm_clk_enable();
76 121
77 ret = __qcom_scm_is_call_available(QCOM_SCM_SVC_HDCP, 122 if (ret)
78 QCOM_SCM_CMD_HDCP); 123 return ret;
79 124
80 return (ret > 0) ? true : false; 125 ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_HDCP,
126 QCOM_SCM_CMD_HDCP);
127
128 qcom_scm_clk_disable();
129
130 return ret > 0 ? true : false;
81} 131}
82EXPORT_SYMBOL(qcom_scm_hdcp_available); 132EXPORT_SYMBOL(qcom_scm_hdcp_available);
83 133
@@ -91,6 +141,287 @@ EXPORT_SYMBOL(qcom_scm_hdcp_available);
91 */ 141 */
92int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp) 142int qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp)
93{ 143{
94 return __qcom_scm_hdcp_req(req, req_cnt, resp); 144 int ret = qcom_scm_clk_enable();
145
146 if (ret)
147 return ret;
148
149 ret = __qcom_scm_hdcp_req(__scm->dev, req, req_cnt, resp);
150 qcom_scm_clk_disable();
151 return ret;
95} 152}
96EXPORT_SYMBOL(qcom_scm_hdcp_req); 153EXPORT_SYMBOL(qcom_scm_hdcp_req);
154
155/**
156 * qcom_scm_pas_supported() - Check if the peripheral authentication service is
157 * available for the given peripherial
158 * @peripheral: peripheral id
159 *
160 * Returns true if PAS is supported for this peripheral, otherwise false.
161 */
162bool qcom_scm_pas_supported(u32 peripheral)
163{
164 int ret;
165
166 ret = __qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
167 QCOM_SCM_PAS_IS_SUPPORTED_CMD);
168 if (ret <= 0)
169 return false;
170
171 return __qcom_scm_pas_supported(__scm->dev, peripheral);
172}
173EXPORT_SYMBOL(qcom_scm_pas_supported);
174
175/**
176 * qcom_scm_pas_init_image() - Initialize peripheral authentication service
177 * state machine for a given peripheral, using the
178 * metadata
179 * @peripheral: peripheral id
180 * @metadata: pointer to memory containing ELF header, program header table
181 * and optional blob of data used for authenticating the metadata
182 * and the rest of the firmware
183 * @size: size of the metadata
184 *
185 * Returns 0 on success.
186 */
187int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size)
188{
189 dma_addr_t mdata_phys;
190 void *mdata_buf;
191 int ret;
192
193 /*
194 * During the scm call memory protection will be enabled for the meta
195 * data blob, so make sure it's physically contiguous, 4K aligned and
196 * non-cachable to avoid XPU violations.
197 */
198 mdata_buf = dma_alloc_coherent(__scm->dev, size, &mdata_phys,
199 GFP_KERNEL);
200 if (!mdata_buf) {
201 dev_err(__scm->dev, "Allocation of metadata buffer failed.\n");
202 return -ENOMEM;
203 }
204 memcpy(mdata_buf, metadata, size);
205
206 ret = qcom_scm_clk_enable();
207 if (ret)
208 goto free_metadata;
209
210 ret = __qcom_scm_pas_init_image(__scm->dev, peripheral, mdata_phys);
211
212 qcom_scm_clk_disable();
213
214free_metadata:
215 dma_free_coherent(__scm->dev, size, mdata_buf, mdata_phys);
216
217 return ret;
218}
219EXPORT_SYMBOL(qcom_scm_pas_init_image);
220
221/**
222 * qcom_scm_pas_mem_setup() - Prepare the memory related to a given peripheral
223 * for firmware loading
224 * @peripheral: peripheral id
225 * @addr: start address of memory area to prepare
226 * @size: size of the memory area to prepare
227 *
228 * Returns 0 on success.
229 */
230int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size)
231{
232 int ret;
233
234 ret = qcom_scm_clk_enable();
235 if (ret)
236 return ret;
237
238 ret = __qcom_scm_pas_mem_setup(__scm->dev, peripheral, addr, size);
239 qcom_scm_clk_disable();
240
241 return ret;
242}
243EXPORT_SYMBOL(qcom_scm_pas_mem_setup);
244
245/**
246 * qcom_scm_pas_auth_and_reset() - Authenticate the given peripheral firmware
247 * and reset the remote processor
248 * @peripheral: peripheral id
249 *
250 * Return 0 on success.
251 */
252int qcom_scm_pas_auth_and_reset(u32 peripheral)
253{
254 int ret;
255
256 ret = qcom_scm_clk_enable();
257 if (ret)
258 return ret;
259
260 ret = __qcom_scm_pas_auth_and_reset(__scm->dev, peripheral);
261 qcom_scm_clk_disable();
262
263 return ret;
264}
265EXPORT_SYMBOL(qcom_scm_pas_auth_and_reset);
266
267/**
268 * qcom_scm_pas_shutdown() - Shut down the remote processor
269 * @peripheral: peripheral id
270 *
271 * Returns 0 on success.
272 */
273int qcom_scm_pas_shutdown(u32 peripheral)
274{
275 int ret;
276
277 ret = qcom_scm_clk_enable();
278 if (ret)
279 return ret;
280
281 ret = __qcom_scm_pas_shutdown(__scm->dev, peripheral);
282 qcom_scm_clk_disable();
283
284 return ret;
285}
286EXPORT_SYMBOL(qcom_scm_pas_shutdown);
287
288static int qcom_scm_pas_reset_assert(struct reset_controller_dev *rcdev,
289 unsigned long idx)
290{
291 if (idx != 0)
292 return -EINVAL;
293
294 return __qcom_scm_pas_mss_reset(__scm->dev, 1);
295}
296
297static int qcom_scm_pas_reset_deassert(struct reset_controller_dev *rcdev,
298 unsigned long idx)
299{
300 if (idx != 0)
301 return -EINVAL;
302
303 return __qcom_scm_pas_mss_reset(__scm->dev, 0);
304}
305
306static const struct reset_control_ops qcom_scm_pas_reset_ops = {
307 .assert = qcom_scm_pas_reset_assert,
308 .deassert = qcom_scm_pas_reset_deassert,
309};
310
311/**
312 * qcom_scm_is_available() - Checks if SCM is available
313 */
314bool qcom_scm_is_available(void)
315{
316 return !!__scm;
317}
318EXPORT_SYMBOL(qcom_scm_is_available);
319
320static int qcom_scm_probe(struct platform_device *pdev)
321{
322 struct qcom_scm *scm;
323 int ret;
324
325 scm = devm_kzalloc(&pdev->dev, sizeof(*scm), GFP_KERNEL);
326 if (!scm)
327 return -ENOMEM;
328
329 scm->core_clk = devm_clk_get(&pdev->dev, "core");
330 if (IS_ERR(scm->core_clk)) {
331 if (PTR_ERR(scm->core_clk) == -EPROBE_DEFER)
332 return PTR_ERR(scm->core_clk);
333
334 scm->core_clk = NULL;
335 }
336
337 if (of_device_is_compatible(pdev->dev.of_node, "qcom,scm")) {
338 scm->iface_clk = devm_clk_get(&pdev->dev, "iface");
339 if (IS_ERR(scm->iface_clk)) {
340 if (PTR_ERR(scm->iface_clk) != -EPROBE_DEFER)
341 dev_err(&pdev->dev, "failed to acquire iface clk\n");
342 return PTR_ERR(scm->iface_clk);
343 }
344
345 scm->bus_clk = devm_clk_get(&pdev->dev, "bus");
346 if (IS_ERR(scm->bus_clk)) {
347 if (PTR_ERR(scm->bus_clk) != -EPROBE_DEFER)
348 dev_err(&pdev->dev, "failed to acquire bus clk\n");
349 return PTR_ERR(scm->bus_clk);
350 }
351 }
352
353 scm->reset.ops = &qcom_scm_pas_reset_ops;
354 scm->reset.nr_resets = 1;
355 scm->reset.of_node = pdev->dev.of_node;
356 reset_controller_register(&scm->reset);
357
358 /* vote for max clk rate for highest performance */
359 ret = clk_set_rate(scm->core_clk, INT_MAX);
360 if (ret)
361 return ret;
362
363 __scm = scm;
364 __scm->dev = &pdev->dev;
365
366 __qcom_scm_init();
367
368 return 0;
369}
370
371static const struct of_device_id qcom_scm_dt_match[] = {
372 { .compatible = "qcom,scm-apq8064",},
373 { .compatible = "qcom,scm-msm8660",},
374 { .compatible = "qcom,scm-msm8960",},
375 { .compatible = "qcom,scm",},
376 {}
377};
378
379MODULE_DEVICE_TABLE(of, qcom_scm_dt_match);
380
381static struct platform_driver qcom_scm_driver = {
382 .driver = {
383 .name = "qcom_scm",
384 .of_match_table = qcom_scm_dt_match,
385 },
386 .probe = qcom_scm_probe,
387};
388
389static int __init qcom_scm_init(void)
390{
391 struct device_node *np, *fw_np;
392 int ret;
393
394 fw_np = of_find_node_by_name(NULL, "firmware");
395
396 if (!fw_np)
397 return -ENODEV;
398
399 np = of_find_matching_node(fw_np, qcom_scm_dt_match);
400
401 if (!np) {
402 of_node_put(fw_np);
403 return -ENODEV;
404 }
405
406 of_node_put(np);
407
408 ret = of_platform_populate(fw_np, qcom_scm_dt_match, NULL, NULL);
409
410 of_node_put(fw_np);
411
412 if (ret)
413 return ret;
414
415 return platform_driver_register(&qcom_scm_driver);
416}
417
418subsys_initcall(qcom_scm_init);
419
420static void __exit qcom_scm_exit(void)
421{
422 platform_driver_unregister(&qcom_scm_driver);
423}
424module_exit(qcom_scm_exit);
425
426MODULE_DESCRIPTION("Qualcomm SCM driver");
427MODULE_LICENSE("GPL v2");
diff --git a/drivers/firmware/qcom_scm.h b/drivers/firmware/qcom_scm.h
index 2cce75c08b99..3584b00fe7e6 100644
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -19,7 +19,8 @@
19#define QCOM_SCM_FLAG_HLOS 0x01 19#define QCOM_SCM_FLAG_HLOS 0x01
20#define QCOM_SCM_FLAG_COLDBOOT_MC 0x02 20#define QCOM_SCM_FLAG_COLDBOOT_MC 0x02
21#define QCOM_SCM_FLAG_WARMBOOT_MC 0x04 21#define QCOM_SCM_FLAG_WARMBOOT_MC 0x04
22extern int __qcom_scm_set_warm_boot_addr(void *entry, const cpumask_t *cpus); 22extern int __qcom_scm_set_warm_boot_addr(struct device *dev, void *entry,
23 const cpumask_t *cpus);
23extern int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus); 24extern int __qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus);
24 25
25#define QCOM_SCM_CMD_TERMINATE_PC 0x2 26#define QCOM_SCM_CMD_TERMINATE_PC 0x2
@@ -29,14 +30,34 @@ extern void __qcom_scm_cpu_power_down(u32 flags);
29 30
30#define QCOM_SCM_SVC_INFO 0x6 31#define QCOM_SCM_SVC_INFO 0x6
31#define QCOM_IS_CALL_AVAIL_CMD 0x1 32#define QCOM_IS_CALL_AVAIL_CMD 0x1
32extern int __qcom_scm_is_call_available(u32 svc_id, u32 cmd_id); 33extern int __qcom_scm_is_call_available(struct device *dev, u32 svc_id,
34 u32 cmd_id);
33 35
34#define QCOM_SCM_SVC_HDCP 0x11 36#define QCOM_SCM_SVC_HDCP 0x11
35#define QCOM_SCM_CMD_HDCP 0x01 37#define QCOM_SCM_CMD_HDCP 0x01
36extern int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt, 38extern int __qcom_scm_hdcp_req(struct device *dev,
37 u32 *resp); 39 struct qcom_scm_hdcp_req *req, u32 req_cnt, u32 *resp);
40
41extern void __qcom_scm_init(void);
42
43#define QCOM_SCM_SVC_PIL 0x2
44#define QCOM_SCM_PAS_INIT_IMAGE_CMD 0x1
45#define QCOM_SCM_PAS_MEM_SETUP_CMD 0x2
46#define QCOM_SCM_PAS_AUTH_AND_RESET_CMD 0x5
47#define QCOM_SCM_PAS_SHUTDOWN_CMD 0x6
48#define QCOM_SCM_PAS_IS_SUPPORTED_CMD 0x7
49#define QCOM_SCM_PAS_MSS_RESET 0xa
50extern bool __qcom_scm_pas_supported(struct device *dev, u32 peripheral);
51extern int __qcom_scm_pas_init_image(struct device *dev, u32 peripheral,
52 dma_addr_t metadata_phys);
53extern int __qcom_scm_pas_mem_setup(struct device *dev, u32 peripheral,
54 phys_addr_t addr, phys_addr_t size);
55extern int __qcom_scm_pas_auth_and_reset(struct device *dev, u32 peripheral);
56extern int __qcom_scm_pas_shutdown(struct device *dev, u32 peripheral);
57extern int __qcom_scm_pas_mss_reset(struct device *dev, bool reset);
38 58
39/* common error codes */ 59/* common error codes */
60#define QCOM_SCM_V2_EBUSY -12
40#define QCOM_SCM_ENOMEM -5 61#define QCOM_SCM_ENOMEM -5
41#define QCOM_SCM_EOPNOTSUPP -4 62#define QCOM_SCM_EOPNOTSUPP -4
42#define QCOM_SCM_EINVAL_ADDR -3 63#define QCOM_SCM_EINVAL_ADDR -3
@@ -44,4 +65,22 @@ extern int __qcom_scm_hdcp_req(struct qcom_scm_hdcp_req *req, u32 req_cnt,
44#define QCOM_SCM_ERROR -1 65#define QCOM_SCM_ERROR -1
45#define QCOM_SCM_INTERRUPTED 1 66#define QCOM_SCM_INTERRUPTED 1
46 67
68static inline int qcom_scm_remap_error(int err)
69{
70 switch (err) {
71 case QCOM_SCM_ERROR:
72 return -EIO;
73 case QCOM_SCM_EINVAL_ADDR:
74 case QCOM_SCM_EINVAL_ARG:
75 return -EINVAL;
76 case QCOM_SCM_EOPNOTSUPP:
77 return -EOPNOTSUPP;
78 case QCOM_SCM_ENOMEM:
79 return -ENOMEM;
80 case QCOM_SCM_V2_EBUSY:
81 return -EBUSY;
82 }
83 return -EINVAL;
84}
85
47#endif 86#endif
diff --git a/drivers/firmware/scpi_pm_domain.c b/drivers/firmware/scpi_pm_domain.c
new file mode 100644
index 000000000000..f395dec27113
--- /dev/null
+++ b/drivers/firmware/scpi_pm_domain.c
@@ -0,0 +1,163 @@
1/*
2 * SCPI Generic power domain support.
3 *
4 * Copyright (C) 2016 ARM Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/err.h>
20#include <linux/io.h>
21#include <linux/module.h>
22#include <linux/of_platform.h>
23#include <linux/pm_domain.h>
24#include <linux/scpi_protocol.h>
25
26struct scpi_pm_domain {
27 struct generic_pm_domain genpd;
28 struct scpi_ops *ops;
29 u32 domain;
30 char name[30];
31};
32
33/*
34 * These device power state values are not well-defined in the specification.
35 * In case, different implementations use different values, we can make these
36 * specific to compatibles rather than getting these values from device tree.
37 */
38enum scpi_power_domain_state {
39 SCPI_PD_STATE_ON = 0,
40 SCPI_PD_STATE_OFF = 3,
41};
42
43#define to_scpi_pd(gpd) container_of(gpd, struct scpi_pm_domain, genpd)
44
45static int scpi_pd_power(struct scpi_pm_domain *pd, bool power_on)
46{
47 int ret;
48 enum scpi_power_domain_state state;
49
50 if (power_on)
51 state = SCPI_PD_STATE_ON;
52 else
53 state = SCPI_PD_STATE_OFF;
54
55 ret = pd->ops->device_set_power_state(pd->domain, state);
56 if (ret)
57 return ret;
58
59 return !(state == pd->ops->device_get_power_state(pd->domain));
60}
61
62static int scpi_pd_power_on(struct generic_pm_domain *domain)
63{
64 struct scpi_pm_domain *pd = to_scpi_pd(domain);
65
66 return scpi_pd_power(pd, true);
67}
68
69static int scpi_pd_power_off(struct generic_pm_domain *domain)
70{
71 struct scpi_pm_domain *pd = to_scpi_pd(domain);
72
73 return scpi_pd_power(pd, false);
74}
75
76static int scpi_pm_domain_probe(struct platform_device *pdev)
77{
78 struct device *dev = &pdev->dev;
79 struct device_node *np = dev->of_node;
80 struct scpi_pm_domain *scpi_pd;
81 struct genpd_onecell_data *scpi_pd_data;
82 struct generic_pm_domain **domains;
83 struct scpi_ops *scpi_ops;
84 int ret, num_domains, i;
85
86 scpi_ops = get_scpi_ops();
87 if (!scpi_ops)
88 return -EPROBE_DEFER;
89
90 if (!np) {
91 dev_err(dev, "device tree node not found\n");
92 return -ENODEV;
93 }
94
95 if (!scpi_ops->device_set_power_state ||
96 !scpi_ops->device_get_power_state) {
97 dev_err(dev, "power domains not supported in the firmware\n");
98 return -ENODEV;
99 }
100
101 ret = of_property_read_u32(np, "num-domains", &num_domains);
102 if (ret) {
103 dev_err(dev, "number of domains not found\n");
104 return -EINVAL;
105 }
106
107 scpi_pd = devm_kcalloc(dev, num_domains, sizeof(*scpi_pd), GFP_KERNEL);
108 if (!scpi_pd)
109 return -ENOMEM;
110
111 scpi_pd_data = devm_kzalloc(dev, sizeof(*scpi_pd_data), GFP_KERNEL);
112 if (!scpi_pd_data)
113 return -ENOMEM;
114
115 domains = devm_kcalloc(dev, num_domains, sizeof(*domains), GFP_KERNEL);
116 if (!domains)
117 return -ENOMEM;
118
119 for (i = 0; i < num_domains; i++, scpi_pd++) {
120 domains[i] = &scpi_pd->genpd;
121
122 scpi_pd->domain = i;
123 scpi_pd->ops = scpi_ops;
124 sprintf(scpi_pd->name, "%s.%d", np->name, i);
125 scpi_pd->genpd.name = scpi_pd->name;
126 scpi_pd->genpd.power_off = scpi_pd_power_off;
127 scpi_pd->genpd.power_on = scpi_pd_power_on;
128
129 /*
130 * Treat all power domains as off at boot.
131 *
132 * The SCP firmware itself may have switched on some domains,
133 * but for reference counting purpose, keep it this way.
134 */
135 pm_genpd_init(&scpi_pd->genpd, NULL, true);
136 }
137
138 scpi_pd_data->domains = domains;
139 scpi_pd_data->num_domains = num_domains;
140
141 of_genpd_add_provider_onecell(np, scpi_pd_data);
142
143 return 0;
144}
145
146static const struct of_device_id scpi_power_domain_ids[] = {
147 { .compatible = "arm,scpi-power-domains", },
148 { /* sentinel */ }
149};
150MODULE_DEVICE_TABLE(of, scpi_power_domain_ids);
151
152static struct platform_driver scpi_power_domain_driver = {
153 .driver = {
154 .name = "scpi_power_domain",
155 .of_match_table = scpi_power_domain_ids,
156 },
157 .probe = scpi_pm_domain_probe,
158};
159module_platform_driver(scpi_power_domain_driver);
160
161MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
162MODULE_DESCRIPTION("ARM SCPI power domain driver");
163MODULE_LICENSE("GPL v2");
diff --git a/drivers/input/keyboard/clps711x-keypad.c b/drivers/input/keyboard/clps711x-keypad.c
index b637f1af842e..997e3e97f573 100644
--- a/drivers/input/keyboard/clps711x-keypad.c
+++ b/drivers/input/keyboard/clps711x-keypad.c
@@ -101,7 +101,7 @@ static int clps711x_keypad_probe(struct platform_device *pdev)
101 return -ENOMEM; 101 return -ENOMEM;
102 102
103 priv->syscon = 103 priv->syscon =
104 syscon_regmap_lookup_by_compatible("cirrus,clps711x-syscon1"); 104 syscon_regmap_lookup_by_compatible("cirrus,ep7209-syscon1");
105 if (IS_ERR(priv->syscon)) 105 if (IS_ERR(priv->syscon))
106 return PTR_ERR(priv->syscon); 106 return PTR_ERR(priv->syscon);
107 107
@@ -181,7 +181,7 @@ static int clps711x_keypad_remove(struct platform_device *pdev)
181} 181}
182 182
183static const struct of_device_id clps711x_keypad_of_match[] = { 183static const struct of_device_id clps711x_keypad_of_match[] = {
184 { .compatible = "cirrus,clps711x-keypad", }, 184 { .compatible = "cirrus,ep7209-keypad", },
185 { } 185 { }
186}; 186};
187MODULE_DEVICE_TABLE(of, clps711x_keypad_of_match); 187MODULE_DEVICE_TABLE(of, clps711x_keypad_of_match);
diff --git a/drivers/irqchip/irq-clps711x.c b/drivers/irqchip/irq-clps711x.c
index 2223b3f15d68..f913f4db7ae1 100644
--- a/drivers/irqchip/irq-clps711x.c
+++ b/drivers/irqchip/irq-clps711x.c
@@ -234,5 +234,5 @@ static int __init clps711x_intc_init_dt(struct device_node *np,
234 234
235 return _clps711x_intc_init(np, res.start, resource_size(&res)); 235 return _clps711x_intc_init(np, res.start, resource_size(&res));
236} 236}
237IRQCHIP_DECLARE(clps711x, "cirrus,clps711x-intc", clps711x_intc_init_dt); 237IRQCHIP_DECLARE(clps711x, "cirrus,ep7209-intc", clps711x_intc_init_dt);
238#endif 238#endif
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index bd4d68500085..370e16e07867 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -336,7 +336,7 @@ config IR_TTUSBIR
336 336
337config IR_RX51 337config IR_RX51
338 tristate "Nokia N900 IR transmitter diode" 338 tristate "Nokia N900 IR transmitter diode"
339 depends on OMAP_DM_TIMER && ARCH_OMAP2PLUS && LIRC && !ARCH_MULTIPLATFORM 339 depends on OMAP_DM_TIMER && PWM_OMAP_DMTIMER && ARCH_OMAP2PLUS && LIRC
340 ---help--- 340 ---help---
341 Say Y or M here if you want to enable support for the IR 341 Say Y or M here if you want to enable support for the IR
342 transmitter diode built in the Nokia N900 (RX51) device. 342 transmitter diode built in the Nokia N900 (RX51) device.
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
index 4e1711a40466..82fb6f2ca011 100644
--- a/drivers/media/rc/ir-rx51.c
+++ b/drivers/media/rc/ir-rx51.c
@@ -12,22 +12,17 @@
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */ 15 */
21 16#include <linux/clk.h>
22#include <linux/module.h> 17#include <linux/module.h>
23#include <linux/interrupt.h> 18#include <linux/interrupt.h>
24#include <linux/uaccess.h> 19#include <linux/uaccess.h>
25#include <linux/platform_device.h> 20#include <linux/platform_device.h>
26#include <linux/sched.h> 21#include <linux/sched.h>
27#include <linux/wait.h> 22#include <linux/wait.h>
28 23#include <linux/pwm.h>
29#include <plat/dmtimer.h> 24#include <linux/of.h>
30#include <plat/clock.h> 25#include <linux/hrtimer.h>
31 26
32#include <media/lirc.h> 27#include <media/lirc.h>
33#include <media/lirc_dev.h> 28#include <media/lirc_dev.h>
@@ -41,100 +36,51 @@
41 36
42#define WBUF_LEN 256 37#define WBUF_LEN 256
43 38
44#define TIMER_MAX_VALUE 0xffffffff
45
46struct lirc_rx51 { 39struct lirc_rx51 {
47 struct omap_dm_timer *pwm_timer; 40 struct pwm_device *pwm;
48 struct omap_dm_timer *pulse_timer; 41 struct hrtimer timer;
49 struct device *dev; 42 struct device *dev;
50 struct lirc_rx51_platform_data *pdata; 43 struct lirc_rx51_platform_data *pdata;
51 wait_queue_head_t wqueue; 44 wait_queue_head_t wqueue;
52 45
53 unsigned long fclk_khz;
54 unsigned int freq; /* carrier frequency */ 46 unsigned int freq; /* carrier frequency */
55 unsigned int duty_cycle; /* carrier duty cycle */ 47 unsigned int duty_cycle; /* carrier duty cycle */
56 unsigned int irq_num;
57 unsigned int match;
58 int wbuf[WBUF_LEN]; 48 int wbuf[WBUF_LEN];
59 int wbuf_index; 49 int wbuf_index;
60 unsigned long device_is_open; 50 unsigned long device_is_open;
61 int pwm_timer_num;
62}; 51};
63 52
64static void lirc_rx51_on(struct lirc_rx51 *lirc_rx51) 53static inline void lirc_rx51_on(struct lirc_rx51 *lirc_rx51)
65{ 54{
66 omap_dm_timer_set_pwm(lirc_rx51->pwm_timer, 0, 1, 55 pwm_enable(lirc_rx51->pwm);
67 OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
68} 56}
69 57
70static void lirc_rx51_off(struct lirc_rx51 *lirc_rx51) 58static inline void lirc_rx51_off(struct lirc_rx51 *lirc_rx51)
71{ 59{
72 omap_dm_timer_set_pwm(lirc_rx51->pwm_timer, 0, 1, 60 pwm_disable(lirc_rx51->pwm);
73 OMAP_TIMER_TRIGGER_NONE);
74} 61}
75 62
76static int init_timing_params(struct lirc_rx51 *lirc_rx51) 63static int init_timing_params(struct lirc_rx51 *lirc_rx51)
77{ 64{
78 u32 load, match; 65 struct pwm_device *pwm = lirc_rx51->pwm;
66 int duty, period = DIV_ROUND_CLOSEST(NSEC_PER_SEC, lirc_rx51->freq);
79 67
80 load = -(lirc_rx51->fclk_khz * 1000 / lirc_rx51->freq); 68 duty = DIV_ROUND_CLOSEST(lirc_rx51->duty_cycle * period, 100);
81 match = -(lirc_rx51->duty_cycle * -load / 100);
82 omap_dm_timer_set_load(lirc_rx51->pwm_timer, 1, load);
83 omap_dm_timer_set_match(lirc_rx51->pwm_timer, 1, match);
84 omap_dm_timer_write_counter(lirc_rx51->pwm_timer, TIMER_MAX_VALUE - 2);
85 omap_dm_timer_start(lirc_rx51->pwm_timer);
86 omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
87 omap_dm_timer_start(lirc_rx51->pulse_timer);
88 69
89 lirc_rx51->match = 0; 70 pwm_config(pwm, duty, period);
90 71
91 return 0; 72 return 0;
92} 73}
93 74
94#define tics_after(a, b) ((long)(b) - (long)(a) < 0) 75static enum hrtimer_restart lirc_rx51_timer_cb(struct hrtimer *timer)
95
96static int pulse_timer_set_timeout(struct lirc_rx51 *lirc_rx51, int usec)
97{ 76{
98 int counter; 77 struct lirc_rx51 *lirc_rx51 =
99 78 container_of(timer, struct lirc_rx51, timer);
100 BUG_ON(usec < 0); 79 ktime_t now;
101
102 if (lirc_rx51->match == 0)
103 counter = omap_dm_timer_read_counter(lirc_rx51->pulse_timer);
104 else
105 counter = lirc_rx51->match;
106
107 counter += (u32)(lirc_rx51->fclk_khz * usec / (1000));
108 omap_dm_timer_set_match(lirc_rx51->pulse_timer, 1, counter);
109 omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer,
110 OMAP_TIMER_INT_MATCH);
111 if (tics_after(omap_dm_timer_read_counter(lirc_rx51->pulse_timer),
112 counter)) {
113 return 1;
114 }
115 return 0;
116}
117
118static irqreturn_t lirc_rx51_interrupt_handler(int irq, void *ptr)
119{
120 unsigned int retval;
121 struct lirc_rx51 *lirc_rx51 = ptr;
122
123 retval = omap_dm_timer_read_status(lirc_rx51->pulse_timer);
124 if (!retval)
125 return IRQ_NONE;
126 80
127 if (retval & ~OMAP_TIMER_INT_MATCH)
128 dev_err_ratelimited(lirc_rx51->dev,
129 ": Unexpected interrupt source: %x\n", retval);
130
131 omap_dm_timer_write_status(lirc_rx51->pulse_timer,
132 OMAP_TIMER_INT_MATCH |
133 OMAP_TIMER_INT_OVERFLOW |
134 OMAP_TIMER_INT_CAPTURE);
135 if (lirc_rx51->wbuf_index < 0) { 81 if (lirc_rx51->wbuf_index < 0) {
136 dev_err_ratelimited(lirc_rx51->dev, 82 dev_err_ratelimited(lirc_rx51->dev,
137 ": BUG wbuf_index has value of %i\n", 83 "BUG wbuf_index has value of %i\n",
138 lirc_rx51->wbuf_index); 84 lirc_rx51->wbuf_index);
139 goto end; 85 goto end;
140 } 86 }
@@ -144,6 +90,8 @@ static irqreturn_t lirc_rx51_interrupt_handler(int irq, void *ptr)
144 * pulses until we catch up. 90 * pulses until we catch up.
145 */ 91 */
146 do { 92 do {
93 u64 ns;
94
147 if (lirc_rx51->wbuf_index >= WBUF_LEN) 95 if (lirc_rx51->wbuf_index >= WBUF_LEN)
148 goto end; 96 goto end;
149 if (lirc_rx51->wbuf[lirc_rx51->wbuf_index] == -1) 97 if (lirc_rx51->wbuf[lirc_rx51->wbuf_index] == -1)
@@ -154,84 +102,24 @@ static irqreturn_t lirc_rx51_interrupt_handler(int irq, void *ptr)
154 else 102 else
155 lirc_rx51_on(lirc_rx51); 103 lirc_rx51_on(lirc_rx51);
156 104
157 retval = pulse_timer_set_timeout(lirc_rx51, 105 ns = 1000 * lirc_rx51->wbuf[lirc_rx51->wbuf_index];
158 lirc_rx51->wbuf[lirc_rx51->wbuf_index]); 106 hrtimer_add_expires_ns(timer, ns);
107
159 lirc_rx51->wbuf_index++; 108 lirc_rx51->wbuf_index++;
160 109
161 } while (retval); 110 now = timer->base->get_time();
111
112 } while (hrtimer_get_expires_tv64(timer) < now.tv64);
162 113
163 return IRQ_HANDLED; 114 return HRTIMER_RESTART;
164end: 115end:
165 /* Stop TX here */ 116 /* Stop TX here */
166 lirc_rx51_off(lirc_rx51); 117 lirc_rx51_off(lirc_rx51);
167 lirc_rx51->wbuf_index = -1; 118 lirc_rx51->wbuf_index = -1;
168 omap_dm_timer_stop(lirc_rx51->pwm_timer);
169 omap_dm_timer_stop(lirc_rx51->pulse_timer);
170 omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
171 wake_up_interruptible(&lirc_rx51->wqueue);
172
173 return IRQ_HANDLED;
174}
175
176static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
177{
178 struct clk *clk_fclk;
179 int retval, pwm_timer = lirc_rx51->pwm_timer_num;
180
181 lirc_rx51->pwm_timer = omap_dm_timer_request_specific(pwm_timer);
182 if (lirc_rx51->pwm_timer == NULL) {
183 dev_err(lirc_rx51->dev, ": Error requesting GPT%d timer\n",
184 pwm_timer);
185 return -EBUSY;
186 }
187
188 lirc_rx51->pulse_timer = omap_dm_timer_request();
189 if (lirc_rx51->pulse_timer == NULL) {
190 dev_err(lirc_rx51->dev, ": Error requesting pulse timer\n");
191 retval = -EBUSY;
192 goto err1;
193 }
194
195 omap_dm_timer_set_source(lirc_rx51->pwm_timer, OMAP_TIMER_SRC_SYS_CLK);
196 omap_dm_timer_set_source(lirc_rx51->pulse_timer,
197 OMAP_TIMER_SRC_SYS_CLK);
198
199 omap_dm_timer_enable(lirc_rx51->pwm_timer);
200 omap_dm_timer_enable(lirc_rx51->pulse_timer);
201
202 lirc_rx51->irq_num = omap_dm_timer_get_irq(lirc_rx51->pulse_timer);
203 retval = request_irq(lirc_rx51->irq_num, lirc_rx51_interrupt_handler,
204 IRQF_SHARED, "lirc_pulse_timer", lirc_rx51);
205 if (retval) {
206 dev_err(lirc_rx51->dev, ": Failed to request interrupt line\n");
207 goto err2;
208 }
209
210 clk_fclk = omap_dm_timer_get_fclk(lirc_rx51->pwm_timer);
211 lirc_rx51->fclk_khz = clk_fclk->rate / 1000;
212
213 return 0;
214 119
215err2: 120 wake_up_interruptible(&lirc_rx51->wqueue);
216 omap_dm_timer_free(lirc_rx51->pulse_timer);
217err1:
218 omap_dm_timer_free(lirc_rx51->pwm_timer);
219
220 return retval;
221}
222
223static int lirc_rx51_free_port(struct lirc_rx51 *lirc_rx51)
224{
225 omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
226 free_irq(lirc_rx51->irq_num, lirc_rx51);
227 lirc_rx51_off(lirc_rx51);
228 omap_dm_timer_disable(lirc_rx51->pwm_timer);
229 omap_dm_timer_disable(lirc_rx51->pulse_timer);
230 omap_dm_timer_free(lirc_rx51->pwm_timer);
231 omap_dm_timer_free(lirc_rx51->pulse_timer);
232 lirc_rx51->wbuf_index = -1;
233 121
234 return 0; 122 return HRTIMER_NORESTART;
235} 123}
236 124
237static ssize_t lirc_rx51_write(struct file *file, const char *buf, 125static ssize_t lirc_rx51_write(struct file *file, const char *buf,
@@ -270,8 +158,9 @@ static ssize_t lirc_rx51_write(struct file *file, const char *buf,
270 158
271 lirc_rx51_on(lirc_rx51); 159 lirc_rx51_on(lirc_rx51);
272 lirc_rx51->wbuf_index = 1; 160 lirc_rx51->wbuf_index = 1;
273 pulse_timer_set_timeout(lirc_rx51, lirc_rx51->wbuf[0]); 161 hrtimer_start(&lirc_rx51->timer,
274 162 ns_to_ktime(1000 * lirc_rx51->wbuf[0]),
163 HRTIMER_MODE_REL);
275 /* 164 /*
276 * Don't return back to the userspace until the transfer has 165 * Don't return back to the userspace until the transfer has
277 * finished 166 * finished
@@ -371,14 +260,24 @@ static int lirc_rx51_open(struct inode *inode, struct file *file)
371 if (test_and_set_bit(1, &lirc_rx51->device_is_open)) 260 if (test_and_set_bit(1, &lirc_rx51->device_is_open))
372 return -EBUSY; 261 return -EBUSY;
373 262
374 return lirc_rx51_init_port(lirc_rx51); 263 lirc_rx51->pwm = pwm_get(lirc_rx51->dev, NULL);
264 if (IS_ERR(lirc_rx51->pwm)) {
265 int res = PTR_ERR(lirc_rx51->pwm);
266
267 dev_err(lirc_rx51->dev, "pwm_get failed: %d\n", res);
268 return res;
269 }
270
271 return 0;
375} 272}
376 273
377static int lirc_rx51_release(struct inode *inode, struct file *file) 274static int lirc_rx51_release(struct inode *inode, struct file *file)
378{ 275{
379 struct lirc_rx51 *lirc_rx51 = file->private_data; 276 struct lirc_rx51 *lirc_rx51 = file->private_data;
380 277
381 lirc_rx51_free_port(lirc_rx51); 278 hrtimer_cancel(&lirc_rx51->timer);
279 lirc_rx51_off(lirc_rx51);
280 pwm_put(lirc_rx51->pwm);
382 281
383 clear_bit(1, &lirc_rx51->device_is_open); 282 clear_bit(1, &lirc_rx51->device_is_open);
384 283
@@ -386,7 +285,6 @@ static int lirc_rx51_release(struct inode *inode, struct file *file)
386} 285}
387 286
388static struct lirc_rx51 lirc_rx51 = { 287static struct lirc_rx51 lirc_rx51 = {
389 .freq = 38000,
390 .duty_cycle = 50, 288 .duty_cycle = 50,
391 .wbuf_index = -1, 289 .wbuf_index = -1,
392}; 290};
@@ -444,9 +342,32 @@ static int lirc_rx51_resume(struct platform_device *dev)
444 342
445static int lirc_rx51_probe(struct platform_device *dev) 343static int lirc_rx51_probe(struct platform_device *dev)
446{ 344{
345 struct pwm_device *pwm;
346
447 lirc_rx51_driver.features = LIRC_RX51_DRIVER_FEATURES; 347 lirc_rx51_driver.features = LIRC_RX51_DRIVER_FEATURES;
448 lirc_rx51.pdata = dev->dev.platform_data; 348 lirc_rx51.pdata = dev->dev.platform_data;
449 lirc_rx51.pwm_timer_num = lirc_rx51.pdata->pwm_timer; 349
350 if (!lirc_rx51.pdata) {
351 dev_err(&dev->dev, "Platform Data is missing\n");
352 return -ENXIO;
353 }
354
355 pwm = pwm_get(&dev->dev, NULL);
356 if (IS_ERR(pwm)) {
357 int err = PTR_ERR(pwm);
358
359 if (err != -EPROBE_DEFER)
360 dev_err(&dev->dev, "pwm_get failed: %d\n", err);
361 return err;
362 }
363
364 /* Use default, in case userspace does not set the carrier */
365 lirc_rx51.freq = DIV_ROUND_CLOSEST(pwm_get_period(pwm), NSEC_PER_SEC);
366 pwm_put(pwm);
367
368 hrtimer_init(&lirc_rx51.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
369 lirc_rx51.timer.function = lirc_rx51_timer_cb;
370
450 lirc_rx51.dev = &dev->dev; 371 lirc_rx51.dev = &dev->dev;
451 lirc_rx51_driver.dev = &dev->dev; 372 lirc_rx51_driver.dev = &dev->dev;
452 lirc_rx51_driver.minor = lirc_register_driver(&lirc_rx51_driver); 373 lirc_rx51_driver.minor = lirc_register_driver(&lirc_rx51_driver);
@@ -457,8 +378,6 @@ static int lirc_rx51_probe(struct platform_device *dev)
457 lirc_rx51_driver.minor); 378 lirc_rx51_driver.minor);
458 return lirc_rx51_driver.minor; 379 return lirc_rx51_driver.minor;
459 } 380 }
460 dev_info(lirc_rx51.dev, "registration ok, minor: %d, pwm: %d\n",
461 lirc_rx51_driver.minor, lirc_rx51.pwm_timer_num);
462 381
463 return 0; 382 return 0;
464} 383}
@@ -468,6 +387,14 @@ static int lirc_rx51_remove(struct platform_device *dev)
468 return lirc_unregister_driver(lirc_rx51_driver.minor); 387 return lirc_unregister_driver(lirc_rx51_driver.minor);
469} 388}
470 389
390static const struct of_device_id lirc_rx51_match[] = {
391 {
392 .compatible = "nokia,n900-ir",
393 },
394 {},
395};
396MODULE_DEVICE_TABLE(of, lirc_rx51_match);
397
471struct platform_driver lirc_rx51_platform_driver = { 398struct platform_driver lirc_rx51_platform_driver = {
472 .probe = lirc_rx51_probe, 399 .probe = lirc_rx51_probe,
473 .remove = lirc_rx51_remove, 400 .remove = lirc_rx51_remove,
@@ -475,7 +402,7 @@ struct platform_driver lirc_rx51_platform_driver = {
475 .resume = lirc_rx51_resume, 402 .resume = lirc_rx51_resume,
476 .driver = { 403 .driver = {
477 .name = DRIVER_NAME, 404 .name = DRIVER_NAME,
478 .owner = THIS_MODULE, 405 .of_match_table = of_match_ptr(lirc_rx51_match),
479 }, 406 },
480}; 407};
481module_platform_driver(lirc_rx51_platform_driver); 408module_platform_driver(lirc_rx51_platform_driver);
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 81ddb17575a9..133712346911 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -25,6 +25,17 @@ config ATMEL_SDRAMC
25 Starting with the at91sam9g45, this controller supports SDR, DDR and 25 Starting with the at91sam9g45, this controller supports SDR, DDR and
26 LP-DDR memories. 26 LP-DDR memories.
27 27
28config ATMEL_EBI
29 bool "Atmel EBI driver"
30 default y
31 depends on ARCH_AT91 && OF
32 select MFD_SYSCON
33 help
34 Driver for Atmel EBI controller.
35 Used to configure the EBI (external bus interface) when the device-
36 tree is used. This bus supports NANDs, external ethernet controller,
37 SRAMs, ATA devices, etc.
38
28config TI_AEMIF 39config TI_AEMIF
29 tristate "Texas Instruments AEMIF driver" 40 tristate "Texas Instruments AEMIF driver"
30 depends on (ARCH_DAVINCI || ARCH_KEYSTONE) && OF 41 depends on (ARCH_DAVINCI || ARCH_KEYSTONE) && OF
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index cb0b7a1df11a..b20ae38b5bfb 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -7,6 +7,7 @@ obj-$(CONFIG_OF) += of_memory.o
7endif 7endif
8obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o 8obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o
9obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o 9obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o
10obj-$(CONFIG_ATMEL_EBI) += atmel-ebi.o
10obj-$(CONFIG_TI_AEMIF) += ti-aemif.o 11obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
11obj-$(CONFIG_TI_EMIF) += emif.o 12obj-$(CONFIG_TI_EMIF) += emif.o
12obj-$(CONFIG_OMAP_GPMC) += omap-gpmc.o 13obj-$(CONFIG_OMAP_GPMC) += omap-gpmc.o
diff --git a/drivers/memory/atmel-ebi.c b/drivers/memory/atmel-ebi.c
new file mode 100644
index 000000000000..f87ad6f5d2dc
--- /dev/null
+++ b/drivers/memory/atmel-ebi.c
@@ -0,0 +1,766 @@
1/*
2 * EBI driver for Atmel chips
3 * inspired by the fsl weim bus driver
4 *
5 * Copyright (C) 2013 Jean-Jacques Hiblot <jjhiblot@traphandler.com>
6 *
7 * This file is licensed under the terms of the GNU General Public
8 * License version 2. This program is licensed "as is" without any
9 * warranty of any kind, whether express or implied.
10 */
11
12#include <linux/clk.h>
13#include <linux/io.h>
14#include <linux/mfd/syscon.h>
15#include <linux/mfd/syscon/atmel-matrix.h>
16#include <linux/mfd/syscon/atmel-smc.h>
17#include <linux/init.h>
18#include <linux/of_device.h>
19#include <linux/regmap.h>
20
21struct at91sam9_smc_timings {
22 u32 ncs_rd_setup_ns;
23 u32 nrd_setup_ns;
24 u32 ncs_wr_setup_ns;
25 u32 nwe_setup_ns;
26 u32 ncs_rd_pulse_ns;
27 u32 nrd_pulse_ns;
28 u32 ncs_wr_pulse_ns;
29 u32 nwe_pulse_ns;
30 u32 nrd_cycle_ns;
31 u32 nwe_cycle_ns;
32 u32 tdf_ns;
33};
34
35struct at91sam9_smc_generic_fields {
36 struct regmap_field *setup;
37 struct regmap_field *pulse;
38 struct regmap_field *cycle;
39 struct regmap_field *mode;
40};
41
42struct at91sam9_ebi_dev_config {
43 struct at91sam9_smc_timings timings;
44 u32 mode;
45};
46
47struct at91_ebi_dev_config {
48 int cs;
49 union {
50 struct at91sam9_ebi_dev_config sam9;
51 };
52};
53
54struct at91_ebi;
55
56struct at91_ebi_dev {
57 struct list_head node;
58 struct at91_ebi *ebi;
59 u32 mode;
60 int numcs;
61 struct at91_ebi_dev_config configs[];
62};
63
64struct at91_ebi_caps {
65 unsigned int available_cs;
66 const struct reg_field *ebi_csa;
67 void (*get_config)(struct at91_ebi_dev *ebid,
68 struct at91_ebi_dev_config *conf);
69 int (*xlate_config)(struct at91_ebi_dev *ebid,
70 struct device_node *configs_np,
71 struct at91_ebi_dev_config *conf);
72 int (*apply_config)(struct at91_ebi_dev *ebid,
73 struct at91_ebi_dev_config *conf);
74 int (*init)(struct at91_ebi *ebi);
75};
76
77struct at91_ebi {
78 struct clk *clk;
79 struct regmap *smc;
80 struct regmap *matrix;
81
82 struct regmap_field *ebi_csa;
83
84 struct device *dev;
85 const struct at91_ebi_caps *caps;
86 struct list_head devs;
87 union {
88 struct at91sam9_smc_generic_fields sam9;
89 };
90};
91
92static void at91sam9_ebi_get_config(struct at91_ebi_dev *ebid,
93 struct at91_ebi_dev_config *conf)
94{
95 struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9;
96 unsigned int clk_rate = clk_get_rate(ebid->ebi->clk);
97 struct at91sam9_ebi_dev_config *config = &conf->sam9;
98 struct at91sam9_smc_timings *timings = &config->timings;
99 unsigned int val;
100
101 regmap_fields_read(fields->mode, conf->cs, &val);
102 config->mode = val & ~AT91_SMC_TDF;
103
104 val = (val & AT91_SMC_TDF) >> 16;
105 timings->tdf_ns = clk_rate * val;
106
107 regmap_fields_read(fields->setup, conf->cs, &val);
108 timings->ncs_rd_setup_ns = (val >> 24) & 0x1f;
109 timings->ncs_rd_setup_ns += ((val >> 29) & 0x1) * 128;
110 timings->ncs_rd_setup_ns *= clk_rate;
111 timings->nrd_setup_ns = (val >> 16) & 0x1f;
112 timings->nrd_setup_ns += ((val >> 21) & 0x1) * 128;
113 timings->nrd_setup_ns *= clk_rate;
114 timings->ncs_wr_setup_ns = (val >> 8) & 0x1f;
115 timings->ncs_wr_setup_ns += ((val >> 13) & 0x1) * 128;
116 timings->ncs_wr_setup_ns *= clk_rate;
117 timings->nwe_setup_ns = val & 0x1f;
118 timings->nwe_setup_ns += ((val >> 5) & 0x1) * 128;
119 timings->nwe_setup_ns *= clk_rate;
120
121 regmap_fields_read(fields->pulse, conf->cs, &val);
122 timings->ncs_rd_pulse_ns = (val >> 24) & 0x3f;
123 timings->ncs_rd_pulse_ns += ((val >> 30) & 0x1) * 256;
124 timings->ncs_rd_pulse_ns *= clk_rate;
125 timings->nrd_pulse_ns = (val >> 16) & 0x3f;
126 timings->nrd_pulse_ns += ((val >> 22) & 0x1) * 256;
127 timings->nrd_pulse_ns *= clk_rate;
128 timings->ncs_wr_pulse_ns = (val >> 8) & 0x3f;
129 timings->ncs_wr_pulse_ns += ((val >> 14) & 0x1) * 256;
130 timings->ncs_wr_pulse_ns *= clk_rate;
131 timings->nwe_pulse_ns = val & 0x3f;
132 timings->nwe_pulse_ns += ((val >> 6) & 0x1) * 256;
133 timings->nwe_pulse_ns *= clk_rate;
134
135 regmap_fields_read(fields->cycle, conf->cs, &val);
136 timings->nrd_cycle_ns = (val >> 16) & 0x7f;
137 timings->nrd_cycle_ns += ((val >> 23) & 0x3) * 256;
138 timings->nrd_cycle_ns *= clk_rate;
139 timings->nwe_cycle_ns = val & 0x7f;
140 timings->nwe_cycle_ns += ((val >> 7) & 0x3) * 256;
141 timings->nwe_cycle_ns *= clk_rate;
142}
143
144static int at91_xlate_timing(struct device_node *np, const char *prop,
145 u32 *val, bool *required)
146{
147 if (!of_property_read_u32(np, prop, val)) {
148 *required = true;
149 return 0;
150 }
151
152 if (*required)
153 return -EINVAL;
154
155 return 0;
156}
157
158static int at91sam9_smc_xslate_timings(struct at91_ebi_dev *ebid,
159 struct device_node *np,
160 struct at91sam9_smc_timings *timings,
161 bool *required)
162{
163 int ret;
164
165 ret = at91_xlate_timing(np, "atmel,smc-ncs-rd-setup-ns",
166 &timings->ncs_rd_setup_ns, required);
167 if (ret)
168 goto out;
169
170 ret = at91_xlate_timing(np, "atmel,smc-nrd-setup-ns",
171 &timings->nrd_setup_ns, required);
172 if (ret)
173 goto out;
174
175 ret = at91_xlate_timing(np, "atmel,smc-ncs-wr-setup-ns",
176 &timings->ncs_wr_setup_ns, required);
177 if (ret)
178 goto out;
179
180 ret = at91_xlate_timing(np, "atmel,smc-nwe-setup-ns",
181 &timings->nwe_setup_ns, required);
182 if (ret)
183 goto out;
184
185 ret = at91_xlate_timing(np, "atmel,smc-ncs-rd-pulse-ns",
186 &timings->ncs_rd_pulse_ns, required);
187 if (ret)
188 goto out;
189
190 ret = at91_xlate_timing(np, "atmel,smc-nrd-pulse-ns",
191 &timings->nrd_pulse_ns, required);
192 if (ret)
193 goto out;
194
195 ret = at91_xlate_timing(np, "atmel,smc-ncs-wr-pulse-ns",
196 &timings->ncs_wr_pulse_ns, required);
197 if (ret)
198 goto out;
199
200 ret = at91_xlate_timing(np, "atmel,smc-nwe-pulse-ns",
201 &timings->nwe_pulse_ns, required);
202 if (ret)
203 goto out;
204
205 ret = at91_xlate_timing(np, "atmel,smc-nwe-cycle-ns",
206 &timings->nwe_cycle_ns, required);
207 if (ret)
208 goto out;
209
210 ret = at91_xlate_timing(np, "atmel,smc-nrd-cycle-ns",
211 &timings->nrd_cycle_ns, required);
212 if (ret)
213 goto out;
214
215 ret = at91_xlate_timing(np, "atmel,smc-tdf-ns",
216 &timings->tdf_ns, required);
217
218out:
219 if (ret)
220 dev_err(ebid->ebi->dev,
221 "missing or invalid timings definition in %s",
222 np->full_name);
223
224 return ret;
225}
226
227static int at91sam9_ebi_xslate_config(struct at91_ebi_dev *ebid,
228 struct device_node *np,
229 struct at91_ebi_dev_config *conf)
230{
231 struct at91sam9_ebi_dev_config *config = &conf->sam9;
232 bool required = false;
233 const char *tmp_str;
234 u32 tmp;
235 int ret;
236
237 ret = of_property_read_u32(np, "atmel,smc-bus-width", &tmp);
238 if (!ret) {
239 switch (tmp) {
240 case 8:
241 config->mode |= AT91_SMC_DBW_8;
242 break;
243
244 case 16:
245 config->mode |= AT91_SMC_DBW_16;
246 break;
247
248 case 32:
249 config->mode |= AT91_SMC_DBW_32;
250 break;
251
252 default:
253 return -EINVAL;
254 }
255
256 required = true;
257 }
258
259 if (of_property_read_bool(np, "atmel,smc-tdf-optimized")) {
260 config->mode |= AT91_SMC_TDFMODE_OPTIMIZED;
261 required = true;
262 }
263
264 tmp_str = NULL;
265 of_property_read_string(np, "atmel,smc-byte-access-type", &tmp_str);
266 if (tmp_str && !strcmp(tmp_str, "write")) {
267 config->mode |= AT91_SMC_BAT_WRITE;
268 required = true;
269 }
270
271 tmp_str = NULL;
272 of_property_read_string(np, "atmel,smc-read-mode", &tmp_str);
273 if (tmp_str && !strcmp(tmp_str, "nrd")) {
274 config->mode |= AT91_SMC_READMODE_NRD;
275 required = true;
276 }
277
278 tmp_str = NULL;
279 of_property_read_string(np, "atmel,smc-write-mode", &tmp_str);
280 if (tmp_str && !strcmp(tmp_str, "nwe")) {
281 config->mode |= AT91_SMC_WRITEMODE_NWE;
282 required = true;
283 }
284
285 tmp_str = NULL;
286 of_property_read_string(np, "atmel,smc-exnw-mode", &tmp_str);
287 if (tmp_str) {
288 if (!strcmp(tmp_str, "frozen"))
289 config->mode |= AT91_SMC_EXNWMODE_FROZEN;
290 else if (!strcmp(tmp_str, "ready"))
291 config->mode |= AT91_SMC_EXNWMODE_READY;
292 else if (strcmp(tmp_str, "disabled"))
293 return -EINVAL;
294
295 required = true;
296 }
297
298 ret = of_property_read_u32(np, "atmel,smc-page-mode", &tmp);
299 if (!ret) {
300 switch (tmp) {
301 case 4:
302 config->mode |= AT91_SMC_PS_4;
303 break;
304
305 case 8:
306 config->mode |= AT91_SMC_PS_8;
307 break;
308
309 case 16:
310 config->mode |= AT91_SMC_PS_16;
311 break;
312
313 case 32:
314 config->mode |= AT91_SMC_PS_32;
315 break;
316
317 default:
318 return -EINVAL;
319 }
320
321 config->mode |= AT91_SMC_PMEN;
322 required = true;
323 }
324
325 ret = at91sam9_smc_xslate_timings(ebid, np, &config->timings,
326 &required);
327 if (ret)
328 return ret;
329
330 return required;
331}
332
333static int at91sam9_ebi_apply_config(struct at91_ebi_dev *ebid,
334 struct at91_ebi_dev_config *conf)
335{
336 unsigned int clk_rate = clk_get_rate(ebid->ebi->clk);
337 struct at91sam9_ebi_dev_config *config = &conf->sam9;
338 struct at91sam9_smc_timings *timings = &config->timings;
339 struct at91sam9_smc_generic_fields *fields = &ebid->ebi->sam9;
340 u32 coded_val;
341 u32 val;
342
343 coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate,
344 timings->ncs_rd_setup_ns);
345 val = AT91SAM9_SMC_NCS_NRDSETUP(coded_val);
346 coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate,
347 timings->nrd_setup_ns);
348 val |= AT91SAM9_SMC_NRDSETUP(coded_val);
349 coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate,
350 timings->ncs_wr_setup_ns);
351 val |= AT91SAM9_SMC_NCS_WRSETUP(coded_val);
352 coded_val = at91sam9_smc_setup_ns_to_cycles(clk_rate,
353 timings->nwe_setup_ns);
354 val |= AT91SAM9_SMC_NWESETUP(coded_val);
355 regmap_fields_write(fields->setup, conf->cs, val);
356
357 coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate,
358 timings->ncs_rd_pulse_ns);
359 val = AT91SAM9_SMC_NCS_NRDPULSE(coded_val);
360 coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate,
361 timings->nrd_pulse_ns);
362 val |= AT91SAM9_SMC_NRDPULSE(coded_val);
363 coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate,
364 timings->ncs_wr_pulse_ns);
365 val |= AT91SAM9_SMC_NCS_WRPULSE(coded_val);
366 coded_val = at91sam9_smc_pulse_ns_to_cycles(clk_rate,
367 timings->nwe_pulse_ns);
368 val |= AT91SAM9_SMC_NWEPULSE(coded_val);
369 regmap_fields_write(fields->pulse, conf->cs, val);
370
371 coded_val = at91sam9_smc_cycle_ns_to_cycles(clk_rate,
372 timings->nrd_cycle_ns);
373 val = AT91SAM9_SMC_NRDCYCLE(coded_val);
374 coded_val = at91sam9_smc_cycle_ns_to_cycles(clk_rate,
375 timings->nwe_cycle_ns);
376 val |= AT91SAM9_SMC_NWECYCLE(coded_val);
377 regmap_fields_write(fields->cycle, conf->cs, val);
378
379 val = DIV_ROUND_UP(timings->tdf_ns, clk_rate);
380 if (val > AT91_SMC_TDF_MAX)
381 val = AT91_SMC_TDF_MAX;
382 regmap_fields_write(fields->mode, conf->cs,
383 config->mode | AT91_SMC_TDF_(val));
384
385 return 0;
386}
387
388static int at91sam9_ebi_init(struct at91_ebi *ebi)
389{
390 struct at91sam9_smc_generic_fields *fields = &ebi->sam9;
391 struct reg_field field = REG_FIELD(0, 0, 31);
392
393 field.id_size = fls(ebi->caps->available_cs);
394 field.id_offset = AT91SAM9_SMC_GENERIC_BLK_SZ;
395
396 field.reg = AT91SAM9_SMC_SETUP(AT91SAM9_SMC_GENERIC);
397 fields->setup = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
398 if (IS_ERR(fields->setup))
399 return PTR_ERR(fields->setup);
400
401 field.reg = AT91SAM9_SMC_PULSE(AT91SAM9_SMC_GENERIC);
402 fields->pulse = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
403 if (IS_ERR(fields->pulse))
404 return PTR_ERR(fields->pulse);
405
406 field.reg = AT91SAM9_SMC_CYCLE(AT91SAM9_SMC_GENERIC);
407 fields->cycle = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
408 if (IS_ERR(fields->cycle))
409 return PTR_ERR(fields->cycle);
410
411 field.reg = AT91SAM9_SMC_MODE(AT91SAM9_SMC_GENERIC);
412 fields->mode = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
413 if (IS_ERR(fields->mode))
414 return PTR_ERR(fields->mode);
415
416 return 0;
417}
418
419static int sama5d3_ebi_init(struct at91_ebi *ebi)
420{
421 struct at91sam9_smc_generic_fields *fields = &ebi->sam9;
422 struct reg_field field = REG_FIELD(0, 0, 31);
423
424 field.id_size = fls(ebi->caps->available_cs);
425 field.id_offset = SAMA5_SMC_GENERIC_BLK_SZ;
426
427 field.reg = AT91SAM9_SMC_SETUP(SAMA5_SMC_GENERIC);
428 fields->setup = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
429 if (IS_ERR(fields->setup))
430 return PTR_ERR(fields->setup);
431
432 field.reg = AT91SAM9_SMC_PULSE(SAMA5_SMC_GENERIC);
433 fields->pulse = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
434 if (IS_ERR(fields->pulse))
435 return PTR_ERR(fields->pulse);
436
437 field.reg = AT91SAM9_SMC_CYCLE(SAMA5_SMC_GENERIC);
438 fields->cycle = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
439 if (IS_ERR(fields->cycle))
440 return PTR_ERR(fields->cycle);
441
442 field.reg = SAMA5_SMC_MODE(SAMA5_SMC_GENERIC);
443 fields->mode = devm_regmap_field_alloc(ebi->dev, ebi->smc, field);
444 if (IS_ERR(fields->mode))
445 return PTR_ERR(fields->mode);
446
447 return 0;
448}
449
450static int at91_ebi_dev_setup(struct at91_ebi *ebi, struct device_node *np,
451 int reg_cells)
452{
453 const struct at91_ebi_caps *caps = ebi->caps;
454 struct at91_ebi_dev_config conf = { };
455 struct device *dev = ebi->dev;
456 struct at91_ebi_dev *ebid;
457 int ret, numcs = 0, i;
458 bool apply = false;
459
460 numcs = of_property_count_elems_of_size(np, "reg",
461 reg_cells * sizeof(u32));
462 if (numcs <= 0) {
463 dev_err(dev, "invalid reg property in %s\n", np->full_name);
464 return -EINVAL;
465 }
466
467 ebid = devm_kzalloc(ebi->dev,
468 sizeof(*ebid) + (numcs * sizeof(*ebid->configs)),
469 GFP_KERNEL);
470 if (!ebid)
471 return -ENOMEM;
472
473 ebid->ebi = ebi;
474
475 ret = caps->xlate_config(ebid, np, &conf);
476 if (ret < 0)
477 return ret;
478 else if (ret)
479 apply = true;
480
481 for (i = 0; i < numcs; i++) {
482 u32 cs;
483
484 ret = of_property_read_u32_index(np, "reg", i * reg_cells,
485 &cs);
486 if (ret)
487 return ret;
488
489 if (cs > AT91_MATRIX_EBI_NUM_CS ||
490 !(ebi->caps->available_cs & BIT(cs))) {
491 dev_err(dev, "invalid reg property in %s\n",
492 np->full_name);
493 return -EINVAL;
494 }
495
496 ebid->configs[i].cs = cs;
497
498 if (apply) {
499 conf.cs = cs;
500 ret = caps->apply_config(ebid, &conf);
501 if (ret)
502 return ret;
503 }
504
505 caps->get_config(ebid, &ebid->configs[i]);
506
507 /*
508 * Attach the EBI device to the generic SMC logic if at least
509 * one "atmel,smc-" property is present.
510 */
511 if (ebi->ebi_csa && ret)
512 regmap_field_update_bits(ebi->ebi_csa,
513 BIT(cs), 0);
514 }
515
516 list_add_tail(&ebid->node, &ebi->devs);
517
518 return 0;
519}
520
521static const struct reg_field at91sam9260_ebi_csa =
522 REG_FIELD(AT91SAM9260_MATRIX_EBICSA, 0,
523 AT91_MATRIX_EBI_NUM_CS - 1);
524
525static const struct at91_ebi_caps at91sam9260_ebi_caps = {
526 .available_cs = 0xff,
527 .ebi_csa = &at91sam9260_ebi_csa,
528 .get_config = at91sam9_ebi_get_config,
529 .xlate_config = at91sam9_ebi_xslate_config,
530 .apply_config = at91sam9_ebi_apply_config,
531 .init = at91sam9_ebi_init,
532};
533
534static const struct reg_field at91sam9261_ebi_csa =
535 REG_FIELD(AT91SAM9261_MATRIX_EBICSA, 0,
536 AT91_MATRIX_EBI_NUM_CS - 1);
537
538static const struct at91_ebi_caps at91sam9261_ebi_caps = {
539 .available_cs = 0xff,
540 .ebi_csa = &at91sam9261_ebi_csa,
541 .get_config = at91sam9_ebi_get_config,
542 .xlate_config = at91sam9_ebi_xslate_config,
543 .apply_config = at91sam9_ebi_apply_config,
544 .init = at91sam9_ebi_init,
545};
546
547static const struct reg_field at91sam9263_ebi0_csa =
548 REG_FIELD(AT91SAM9263_MATRIX_EBI0CSA, 0,
549 AT91_MATRIX_EBI_NUM_CS - 1);
550
551static const struct at91_ebi_caps at91sam9263_ebi0_caps = {
552 .available_cs = 0x3f,
553 .ebi_csa = &at91sam9263_ebi0_csa,
554 .get_config = at91sam9_ebi_get_config,
555 .xlate_config = at91sam9_ebi_xslate_config,
556 .apply_config = at91sam9_ebi_apply_config,
557 .init = at91sam9_ebi_init,
558};
559
560static const struct reg_field at91sam9263_ebi1_csa =
561 REG_FIELD(AT91SAM9263_MATRIX_EBI1CSA, 0,
562 AT91_MATRIX_EBI_NUM_CS - 1);
563
564static const struct at91_ebi_caps at91sam9263_ebi1_caps = {
565 .available_cs = 0x7,
566 .ebi_csa = &at91sam9263_ebi1_csa,
567 .get_config = at91sam9_ebi_get_config,
568 .xlate_config = at91sam9_ebi_xslate_config,
569 .apply_config = at91sam9_ebi_apply_config,
570 .init = at91sam9_ebi_init,
571};
572
573static const struct reg_field at91sam9rl_ebi_csa =
574 REG_FIELD(AT91SAM9RL_MATRIX_EBICSA, 0,
575 AT91_MATRIX_EBI_NUM_CS - 1);
576
577static const struct at91_ebi_caps at91sam9rl_ebi_caps = {
578 .available_cs = 0x3f,
579 .ebi_csa = &at91sam9rl_ebi_csa,
580 .get_config = at91sam9_ebi_get_config,
581 .xlate_config = at91sam9_ebi_xslate_config,
582 .apply_config = at91sam9_ebi_apply_config,
583 .init = at91sam9_ebi_init,
584};
585
586static const struct reg_field at91sam9g45_ebi_csa =
587 REG_FIELD(AT91SAM9G45_MATRIX_EBICSA, 0,
588 AT91_MATRIX_EBI_NUM_CS - 1);
589
590static const struct at91_ebi_caps at91sam9g45_ebi_caps = {
591 .available_cs = 0x3f,
592 .ebi_csa = &at91sam9g45_ebi_csa,
593 .get_config = at91sam9_ebi_get_config,
594 .xlate_config = at91sam9_ebi_xslate_config,
595 .apply_config = at91sam9_ebi_apply_config,
596 .init = at91sam9_ebi_init,
597};
598
599static const struct at91_ebi_caps at91sam9x5_ebi_caps = {
600 .available_cs = 0x3f,
601 .ebi_csa = &at91sam9263_ebi0_csa,
602 .get_config = at91sam9_ebi_get_config,
603 .xlate_config = at91sam9_ebi_xslate_config,
604 .apply_config = at91sam9_ebi_apply_config,
605 .init = at91sam9_ebi_init,
606};
607
608static const struct at91_ebi_caps sama5d3_ebi_caps = {
609 .available_cs = 0xf,
610 .get_config = at91sam9_ebi_get_config,
611 .xlate_config = at91sam9_ebi_xslate_config,
612 .apply_config = at91sam9_ebi_apply_config,
613 .init = sama5d3_ebi_init,
614};
615
616static const struct of_device_id at91_ebi_id_table[] = {
617 {
618 .compatible = "atmel,at91sam9260-ebi",
619 .data = &at91sam9260_ebi_caps,
620 },
621 {
622 .compatible = "atmel,at91sam9261-ebi",
623 .data = &at91sam9261_ebi_caps,
624 },
625 {
626 .compatible = "atmel,at91sam9263-ebi0",
627 .data = &at91sam9263_ebi0_caps,
628 },
629 {
630 .compatible = "atmel,at91sam9263-ebi1",
631 .data = &at91sam9263_ebi1_caps,
632 },
633 {
634 .compatible = "atmel,at91sam9rl-ebi",
635 .data = &at91sam9rl_ebi_caps,
636 },
637 {
638 .compatible = "atmel,at91sam9g45-ebi",
639 .data = &at91sam9g45_ebi_caps,
640 },
641 {
642 .compatible = "atmel,at91sam9x5-ebi",
643 .data = &at91sam9x5_ebi_caps,
644 },
645 {
646 .compatible = "atmel,sama5d3-ebi",
647 .data = &sama5d3_ebi_caps,
648 },
649 { /* sentinel */ }
650};
651
652static int at91_ebi_dev_disable(struct at91_ebi *ebi, struct device_node *np)
653{
654 struct device *dev = ebi->dev;
655 struct property *newprop;
656
657 newprop = devm_kzalloc(dev, sizeof(*newprop), GFP_KERNEL);
658 if (!newprop)
659 return -ENOMEM;
660
661 newprop->name = devm_kstrdup(dev, "status", GFP_KERNEL);
662 if (!newprop->name)
663 return -ENOMEM;
664
665 newprop->value = devm_kstrdup(dev, "disabled", GFP_KERNEL);
666 if (!newprop->name)
667 return -ENOMEM;
668
669 newprop->length = sizeof("disabled");
670
671 return of_update_property(np, newprop);
672}
673
674static int at91_ebi_probe(struct platform_device *pdev)
675{
676 struct device *dev = &pdev->dev;
677 struct device_node *child, *np = dev->of_node;
678 const struct of_device_id *match;
679 struct at91_ebi *ebi;
680 int ret, reg_cells;
681 struct clk *clk;
682 u32 val;
683
684 match = of_match_device(at91_ebi_id_table, dev);
685 if (!match || !match->data)
686 return -EINVAL;
687
688 ebi = devm_kzalloc(dev, sizeof(*ebi), GFP_KERNEL);
689 if (!ebi)
690 return -ENOMEM;
691
692 INIT_LIST_HEAD(&ebi->devs);
693 ebi->caps = match->data;
694 ebi->dev = dev;
695
696 clk = devm_clk_get(dev, NULL);
697 if (IS_ERR(clk))
698 return PTR_ERR(clk);
699
700 ebi->clk = clk;
701
702 ebi->smc = syscon_regmap_lookup_by_phandle(np, "atmel,smc");
703 if (IS_ERR(ebi->smc))
704 return PTR_ERR(ebi->smc);
705
706 /*
707 * The sama5d3 does not provide an EBICSA register and thus does need
708 * to access the matrix registers.
709 */
710 if (ebi->caps->ebi_csa) {
711 ebi->matrix =
712 syscon_regmap_lookup_by_phandle(np, "atmel,matrix");
713 if (IS_ERR(ebi->matrix))
714 return PTR_ERR(ebi->matrix);
715
716 ebi->ebi_csa = regmap_field_alloc(ebi->matrix,
717 *ebi->caps->ebi_csa);
718 if (IS_ERR(ebi->ebi_csa))
719 return PTR_ERR(ebi->ebi_csa);
720 }
721
722 ret = ebi->caps->init(ebi);
723 if (ret)
724 return ret;
725
726 ret = of_property_read_u32(np, "#address-cells", &val);
727 if (ret) {
728 dev_err(dev, "missing #address-cells property\n");
729 return ret;
730 }
731
732 reg_cells = val;
733
734 ret = of_property_read_u32(np, "#size-cells", &val);
735 if (ret) {
736 dev_err(dev, "missing #address-cells property\n");
737 return ret;
738 }
739
740 reg_cells += val;
741
742 for_each_available_child_of_node(np, child) {
743 if (!of_find_property(child, "reg", NULL))
744 continue;
745
746 ret = at91_ebi_dev_setup(ebi, child, reg_cells);
747 if (ret) {
748 dev_err(dev, "failed to configure EBI bus for %s, disabling the device",
749 child->full_name);
750
751 ret = at91_ebi_dev_disable(ebi, child);
752 if (ret)
753 return ret;
754 }
755 }
756
757 return of_platform_populate(np, NULL, NULL, dev);
758}
759
760static struct platform_driver at91_ebi_driver = {
761 .driver = {
762 .name = "atmel-ebi",
763 .of_match_table = at91_ebi_id_table,
764 },
765};
766builtin_platform_driver_probe(at91_ebi_driver, at91_ebi_probe);
diff --git a/drivers/memory/atmel-sdramc.c b/drivers/memory/atmel-sdramc.c
index a3ebc8a87479..53a341f3b305 100644
--- a/drivers/memory/atmel-sdramc.c
+++ b/drivers/memory/atmel-sdramc.c
@@ -1,6 +1,8 @@
1/* 1/*
2 * Atmel (Multi-port DDR-)SDRAM Controller driver 2 * Atmel (Multi-port DDR-)SDRAM Controller driver
3 * 3 *
4 * Author: Alexandre Belloni <alexandre.belloni@free-electrons.com>
5 *
4 * Copyright (C) 2014 Atmel 6 * Copyright (C) 2014 Atmel
5 * 7 *
6 * This program is free software: you can redistribute it and/or modify 8 * This program is free software: you can redistribute it and/or modify
@@ -20,7 +22,7 @@
20#include <linux/clk.h> 22#include <linux/clk.h>
21#include <linux/err.h> 23#include <linux/err.h>
22#include <linux/kernel.h> 24#include <linux/kernel.h>
23#include <linux/module.h> 25#include <linux/init.h>
24#include <linux/of_platform.h> 26#include <linux/of_platform.h>
25#include <linux/platform_device.h> 27#include <linux/platform_device.h>
26 28
@@ -48,7 +50,6 @@ static const struct of_device_id atmel_ramc_of_match[] = {
48 { .compatible = "atmel,sama5d3-ddramc", .data = &sama5d3_caps, }, 50 { .compatible = "atmel,sama5d3-ddramc", .data = &sama5d3_caps, },
49 {}, 51 {},
50}; 52};
51MODULE_DEVICE_TABLE(of, atmel_ramc_of_match);
52 53
53static int atmel_ramc_probe(struct platform_device *pdev) 54static int atmel_ramc_probe(struct platform_device *pdev)
54{ 55{
@@ -90,8 +91,4 @@ static int __init atmel_ramc_init(void)
90{ 91{
91 return platform_driver_register(&atmel_ramc_driver); 92 return platform_driver_register(&atmel_ramc_driver);
92} 93}
93module_init(atmel_ramc_init); 94device_initcall(atmel_ramc_init);
94
95MODULE_LICENSE("GPL v2");
96MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>");
97MODULE_DESCRIPTION("Atmel (Multi-port DDR-)SDRAM Controller");
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index 4721b591994f..869c83fb3c5d 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -20,7 +20,6 @@
20#include <linux/ioport.h> 20#include <linux/ioport.h>
21#include <linux/spinlock.h> 21#include <linux/spinlock.h>
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/module.h>
24#include <linux/gpio/driver.h> 23#include <linux/gpio/driver.h>
25#include <linux/interrupt.h> 24#include <linux/interrupt.h>
26#include <linux/irqdomain.h> 25#include <linux/irqdomain.h>
@@ -1807,7 +1806,6 @@ static const struct of_device_id gpmc_dt_ids[] = {
1807 { .compatible = "ti,am3352-gpmc" }, /* am335x devices */ 1806 { .compatible = "ti,am3352-gpmc" }, /* am335x devices */
1808 { } 1807 { }
1809}; 1808};
1810MODULE_DEVICE_TABLE(of, gpmc_dt_ids);
1811 1809
1812/** 1810/**
1813 * gpmc_read_settings_dt - read gpmc settings from device-tree 1811 * gpmc_read_settings_dt - read gpmc settings from device-tree
@@ -2154,68 +2152,6 @@ err:
2154 return ret; 2152 return ret;
2155} 2153}
2156 2154
2157static int gpmc_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
2158{
2159 return 1; /* we're input only */
2160}
2161
2162static int gpmc_gpio_direction_input(struct gpio_chip *chip,
2163 unsigned int offset)
2164{
2165 return 0; /* we're input only */
2166}
2167
2168static int gpmc_gpio_direction_output(struct gpio_chip *chip,
2169 unsigned int offset, int value)
2170{
2171 return -EINVAL; /* we're input only */
2172}
2173
2174static void gpmc_gpio_set(struct gpio_chip *chip, unsigned int offset,
2175 int value)
2176{
2177}
2178
2179static int gpmc_gpio_get(struct gpio_chip *chip, unsigned int offset)
2180{
2181 u32 reg;
2182
2183 offset += 8;
2184
2185 reg = gpmc_read_reg(GPMC_STATUS) & BIT(offset);
2186
2187 return !!reg;
2188}
2189
2190static int gpmc_gpio_init(struct gpmc_device *gpmc)
2191{
2192 int ret;
2193
2194 gpmc->gpio_chip.parent = gpmc->dev;
2195 gpmc->gpio_chip.owner = THIS_MODULE;
2196 gpmc->gpio_chip.label = DEVICE_NAME;
2197 gpmc->gpio_chip.ngpio = gpmc_nr_waitpins;
2198 gpmc->gpio_chip.get_direction = gpmc_gpio_get_direction;
2199 gpmc->gpio_chip.direction_input = gpmc_gpio_direction_input;
2200 gpmc->gpio_chip.direction_output = gpmc_gpio_direction_output;
2201 gpmc->gpio_chip.set = gpmc_gpio_set;
2202 gpmc->gpio_chip.get = gpmc_gpio_get;
2203 gpmc->gpio_chip.base = -1;
2204
2205 ret = gpiochip_add(&gpmc->gpio_chip);
2206 if (ret < 0) {
2207 dev_err(gpmc->dev, "could not register gpio chip: %d\n", ret);
2208 return ret;
2209 }
2210
2211 return 0;
2212}
2213
2214static void gpmc_gpio_exit(struct gpmc_device *gpmc)
2215{
2216 gpiochip_remove(&gpmc->gpio_chip);
2217}
2218
2219static int gpmc_probe_dt(struct platform_device *pdev) 2155static int gpmc_probe_dt(struct platform_device *pdev)
2220{ 2156{
2221 int ret; 2157 int ret;
@@ -2280,7 +2216,69 @@ static int gpmc_probe_dt_children(struct platform_device *pdev)
2280{ 2216{
2281 return 0; 2217 return 0;
2282} 2218}
2283#endif 2219#endif /* CONFIG_OF */
2220
2221static int gpmc_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
2222{
2223 return 1; /* we're input only */
2224}
2225
2226static int gpmc_gpio_direction_input(struct gpio_chip *chip,
2227 unsigned int offset)
2228{
2229 return 0; /* we're input only */
2230}
2231
2232static int gpmc_gpio_direction_output(struct gpio_chip *chip,
2233 unsigned int offset, int value)
2234{
2235 return -EINVAL; /* we're input only */
2236}
2237
2238static void gpmc_gpio_set(struct gpio_chip *chip, unsigned int offset,
2239 int value)
2240{
2241}
2242
2243static int gpmc_gpio_get(struct gpio_chip *chip, unsigned int offset)
2244{
2245 u32 reg;
2246
2247 offset += 8;
2248
2249 reg = gpmc_read_reg(GPMC_STATUS) & BIT(offset);
2250
2251 return !!reg;
2252}
2253
2254static int gpmc_gpio_init(struct gpmc_device *gpmc)
2255{
2256 int ret;
2257
2258 gpmc->gpio_chip.parent = gpmc->dev;
2259 gpmc->gpio_chip.owner = THIS_MODULE;
2260 gpmc->gpio_chip.label = DEVICE_NAME;
2261 gpmc->gpio_chip.ngpio = gpmc_nr_waitpins;
2262 gpmc->gpio_chip.get_direction = gpmc_gpio_get_direction;
2263 gpmc->gpio_chip.direction_input = gpmc_gpio_direction_input;
2264 gpmc->gpio_chip.direction_output = gpmc_gpio_direction_output;
2265 gpmc->gpio_chip.set = gpmc_gpio_set;
2266 gpmc->gpio_chip.get = gpmc_gpio_get;
2267 gpmc->gpio_chip.base = -1;
2268
2269 ret = gpiochip_add(&gpmc->gpio_chip);
2270 if (ret < 0) {
2271 dev_err(gpmc->dev, "could not register gpio chip: %d\n", ret);
2272 return ret;
2273 }
2274
2275 return 0;
2276}
2277
2278static void gpmc_gpio_exit(struct gpmc_device *gpmc)
2279{
2280 gpiochip_remove(&gpmc->gpio_chip);
2281}
2284 2282
2285static int gpmc_probe(struct platform_device *pdev) 2283static int gpmc_probe(struct platform_device *pdev)
2286{ 2284{
@@ -2436,15 +2434,7 @@ static __init int gpmc_init(void)
2436{ 2434{
2437 return platform_driver_register(&gpmc_driver); 2435 return platform_driver_register(&gpmc_driver);
2438} 2436}
2439
2440static __exit void gpmc_exit(void)
2441{
2442 platform_driver_unregister(&gpmc_driver);
2443
2444}
2445
2446postcore_initcall(gpmc_init); 2437postcore_initcall(gpmc_init);
2447module_exit(gpmc_exit);
2448 2438
2449static struct omap3_gpmc_regs gpmc_context; 2439static struct omap3_gpmc_regs gpmc_context;
2450 2440
diff --git a/drivers/memory/samsung/exynos-srom.c b/drivers/memory/samsung/exynos-srom.c
index 96756fb4d6bd..bf827a666694 100644
--- a/drivers/memory/samsung/exynos-srom.c
+++ b/drivers/memory/samsung/exynos-srom.c
@@ -11,7 +11,7 @@
11 */ 11 */
12 12
13#include <linux/io.h> 13#include <linux/io.h>
14#include <linux/module.h> 14#include <linux/init.h>
15#include <linux/of.h> 15#include <linux/of.h>
16#include <linux/of_address.h> 16#include <linux/of_address.h>
17#include <linux/of_platform.h> 17#include <linux/of_platform.h>
@@ -91,17 +91,17 @@ static int exynos_srom_configure_bank(struct exynos_srom *srom,
91 if (width == 2) 91 if (width == 2)
92 cs |= 1 << EXYNOS_SROM_BW__DATAWIDTH__SHIFT; 92 cs |= 1 << EXYNOS_SROM_BW__DATAWIDTH__SHIFT;
93 93
94 bw = __raw_readl(srom->reg_base + EXYNOS_SROM_BW); 94 bw = readl_relaxed(srom->reg_base + EXYNOS_SROM_BW);
95 bw = (bw & ~(EXYNOS_SROM_BW__CS_MASK << bank)) | (cs << bank); 95 bw = (bw & ~(EXYNOS_SROM_BW__CS_MASK << bank)) | (cs << bank);
96 __raw_writel(bw, srom->reg_base + EXYNOS_SROM_BW); 96 writel_relaxed(bw, srom->reg_base + EXYNOS_SROM_BW);
97 97
98 __raw_writel(pmc | (timing[0] << EXYNOS_SROM_BCX__TACP__SHIFT) | 98 writel_relaxed(pmc | (timing[0] << EXYNOS_SROM_BCX__TACP__SHIFT) |
99 (timing[1] << EXYNOS_SROM_BCX__TCAH__SHIFT) | 99 (timing[1] << EXYNOS_SROM_BCX__TCAH__SHIFT) |
100 (timing[2] << EXYNOS_SROM_BCX__TCOH__SHIFT) | 100 (timing[2] << EXYNOS_SROM_BCX__TCOH__SHIFT) |
101 (timing[3] << EXYNOS_SROM_BCX__TACC__SHIFT) | 101 (timing[3] << EXYNOS_SROM_BCX__TACC__SHIFT) |
102 (timing[4] << EXYNOS_SROM_BCX__TCOS__SHIFT) | 102 (timing[4] << EXYNOS_SROM_BCX__TCOS__SHIFT) |
103 (timing[5] << EXYNOS_SROM_BCX__TACS__SHIFT), 103 (timing[5] << EXYNOS_SROM_BCX__TACS__SHIFT),
104 srom->reg_base + EXYNOS_SROM_BC0 + bank); 104 srom->reg_base + EXYNOS_SROM_BC0 + bank);
105 105
106 return 0; 106 return 0;
107} 107}
@@ -134,7 +134,7 @@ static int exynos_srom_probe(struct platform_device *pdev)
134 platform_set_drvdata(pdev, srom); 134 platform_set_drvdata(pdev, srom);
135 135
136 srom->reg_offset = exynos_srom_alloc_reg_dump(exynos_srom_offsets, 136 srom->reg_offset = exynos_srom_alloc_reg_dump(exynos_srom_offsets,
137 sizeof(exynos_srom_offsets)); 137 ARRAY_SIZE(exynos_srom_offsets));
138 if (!srom->reg_offset) { 138 if (!srom->reg_offset) {
139 iounmap(srom->reg_base); 139 iounmap(srom->reg_base);
140 return -ENOMEM; 140 return -ENOMEM;
@@ -159,16 +159,6 @@ static int exynos_srom_probe(struct platform_device *pdev)
159 return of_platform_populate(np, NULL, NULL, dev); 159 return of_platform_populate(np, NULL, NULL, dev);
160} 160}
161 161
162static int exynos_srom_remove(struct platform_device *pdev)
163{
164 struct exynos_srom *srom = platform_get_drvdata(pdev);
165
166 kfree(srom->reg_offset);
167 iounmap(srom->reg_base);
168
169 return 0;
170}
171
172#ifdef CONFIG_PM_SLEEP 162#ifdef CONFIG_PM_SLEEP
173static void exynos_srom_save(void __iomem *base, 163static void exynos_srom_save(void __iomem *base,
174 struct exynos_srom_reg_dump *rd, 164 struct exynos_srom_reg_dump *rd,
@@ -211,21 +201,16 @@ static const struct of_device_id of_exynos_srom_ids[] = {
211 }, 201 },
212 {}, 202 {},
213}; 203};
214MODULE_DEVICE_TABLE(of, of_exynos_srom_ids);
215 204
216static SIMPLE_DEV_PM_OPS(exynos_srom_pm_ops, exynos_srom_suspend, exynos_srom_resume); 205static SIMPLE_DEV_PM_OPS(exynos_srom_pm_ops, exynos_srom_suspend, exynos_srom_resume);
217 206
218static struct platform_driver exynos_srom_driver = { 207static struct platform_driver exynos_srom_driver = {
219 .probe = exynos_srom_probe, 208 .probe = exynos_srom_probe,
220 .remove = exynos_srom_remove,
221 .driver = { 209 .driver = {
222 .name = "exynos-srom", 210 .name = "exynos-srom",
223 .of_match_table = of_exynos_srom_ids, 211 .of_match_table = of_exynos_srom_ids,
224 .pm = &exynos_srom_pm_ops, 212 .pm = &exynos_srom_pm_ops,
213 .suppress_bind_attrs = true,
225 }, 214 },
226}; 215};
227module_platform_driver(exynos_srom_driver); 216builtin_platform_driver(exynos_srom_driver);
228
229MODULE_AUTHOR("Pankaj Dubey <pankaj.dubey@samsung.com>");
230MODULE_DESCRIPTION("Exynos SROM Controller Driver");
231MODULE_LICENSE("GPL");
diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
index a1ae0cc2b86d..a4803ac192bb 100644
--- a/drivers/memory/tegra/mc.c
+++ b/drivers/memory/tegra/mc.c
@@ -186,8 +186,10 @@ static int load_timings(struct tegra_mc *mc, struct device_node *node)
186 timing = &mc->timings[i++]; 186 timing = &mc->timings[i++];
187 187
188 err = load_one_timing(mc, timing, child); 188 err = load_one_timing(mc, timing, child);
189 if (err) 189 if (err) {
190 of_node_put(child);
190 return err; 191 return err;
192 }
191 } 193 }
192 194
193 return 0; 195 return 0;
@@ -206,15 +208,13 @@ static int tegra_mc_setup_timings(struct tegra_mc *mc)
206 for_each_child_of_node(mc->dev->of_node, node) { 208 for_each_child_of_node(mc->dev->of_node, node) {
207 err = of_property_read_u32(node, "nvidia,ram-code", 209 err = of_property_read_u32(node, "nvidia,ram-code",
208 &node_ram_code); 210 &node_ram_code);
209 if (err || (node_ram_code != ram_code)) { 211 if (err || (node_ram_code != ram_code))
210 of_node_put(node);
211 continue; 212 continue;
212 }
213 213
214 err = load_timings(mc, node); 214 err = load_timings(mc, node);
215 of_node_put(node);
215 if (err) 216 if (err)
216 return err; 217 return err;
217 of_node_put(node);
218 break; 218 break;
219 } 219 }
220 220
diff --git a/drivers/memory/tegra/tegra124-emc.c b/drivers/memory/tegra/tegra124-emc.c
index 3dac7be39654..06cc781ebac1 100644
--- a/drivers/memory/tegra/tegra124-emc.c
+++ b/drivers/memory/tegra/tegra124-emc.c
@@ -970,8 +970,10 @@ static int tegra_emc_load_timings_from_dt(struct tegra_emc *emc,
970 timing = &emc->timings[i++]; 970 timing = &emc->timings[i++];
971 971
972 err = load_one_timing_from_dt(emc, timing, child); 972 err = load_one_timing_from_dt(emc, timing, child);
973 if (err) 973 if (err) {
974 of_node_put(child);
974 return err; 975 return err;
976 }
975 } 977 }
976 978
977 sort(emc->timings, emc->num_timings, sizeof(*timing), cmp_timings, 979 sort(emc->timings, emc->num_timings, sizeof(*timing), cmp_timings,
@@ -995,10 +997,8 @@ tegra_emc_find_node_by_ram_code(struct device_node *node, u32 ram_code)
995 u32 value; 997 u32 value;
996 998
997 err = of_property_read_u32(np, "nvidia,ram-code", &value); 999 err = of_property_read_u32(np, "nvidia,ram-code", &value);
998 if (err || (value != ram_code)) { 1000 if (err || (value != ram_code))
999 of_node_put(np);
1000 continue; 1001 continue;
1001 }
1002 1002
1003 return np; 1003 return np;
1004 } 1004 }
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index f3d689176fc2..589eebfc13df 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -1087,7 +1087,6 @@ static int ab8500_probe(struct platform_device *pdev)
1087 "Vbus Detect (USB)", 1087 "Vbus Detect (USB)",
1088 "USB ID Detect", 1088 "USB ID Detect",
1089 "UART Factory Mode Detect"}; 1089 "UART Factory Mode Detect"};
1090 struct ab8500_platform_data *plat = dev_get_platdata(&pdev->dev);
1091 const struct platform_device_id *platid = platform_get_device_id(pdev); 1090 const struct platform_device_id *platid = platform_get_device_id(pdev);
1092 enum ab8500_version version = AB8500_VERSION_UNDEFINED; 1091 enum ab8500_version version = AB8500_VERSION_UNDEFINED;
1093 struct device_node *np = pdev->dev.of_node; 1092 struct device_node *np = pdev->dev.of_node;
@@ -1219,9 +1218,6 @@ static int ab8500_probe(struct platform_device *pdev)
1219 pr_cont("None\n"); 1218 pr_cont("None\n");
1220 } 1219 }
1221 1220
1222 if (plat && plat->init)
1223 plat->init(ab8500);
1224
1225 if (is_ab9540(ab8500)) { 1221 if (is_ab9540(ab8500)) {
1226 ret = get_register_interruptible(ab8500, AB8500_CHARGER, 1222 ret = get_register_interruptible(ab8500, AB8500_CHARGER,
1227 AB8500_CH_USBCH_STAT1_REG, &value); 1223 AB8500_CH_USBCH_STAT1_REG, &value);
diff --git a/drivers/mfd/ab8500-sysctrl.c b/drivers/mfd/ab8500-sysctrl.c
index b9f0010309f9..207cc497958a 100644
--- a/drivers/mfd/ab8500-sysctrl.c
+++ b/drivers/mfd/ab8500-sysctrl.c
@@ -127,45 +127,11 @@ EXPORT_SYMBOL(ab8500_sysctrl_write);
127 127
128static int ab8500_sysctrl_probe(struct platform_device *pdev) 128static int ab8500_sysctrl_probe(struct platform_device *pdev)
129{ 129{
130 struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
131 struct ab8500_platform_data *plat;
132 struct ab8500_sysctrl_platform_data *pdata;
133
134 plat = dev_get_platdata(pdev->dev.parent);
135
136 if (!plat)
137 return -EINVAL;
138
139 sysctrl_dev = &pdev->dev; 130 sysctrl_dev = &pdev->dev;
140 131
141 if (!pm_power_off) 132 if (!pm_power_off)
142 pm_power_off = ab8500_power_off; 133 pm_power_off = ab8500_power_off;
143 134
144 pdata = plat->sysctrl;
145 if (pdata) {
146 int last, ret, i, j;
147
148 if (is_ab8505(ab8500))
149 last = AB8500_SYSCLKREQ4RFCLKBUF;
150 else
151 last = AB8500_SYSCLKREQ8RFCLKBUF;
152
153 for (i = AB8500_SYSCLKREQ1RFCLKBUF; i <= last; i++) {
154 j = i - AB8500_SYSCLKREQ1RFCLKBUF;
155 ret = ab8500_sysctrl_write(i, 0xff,
156 pdata->initial_req_buf_config[j]);
157 dev_dbg(&pdev->dev,
158 "Setting SysClkReq%dRfClkBuf 0x%X\n",
159 j + 1,
160 pdata->initial_req_buf_config[j]);
161 if (ret < 0) {
162 dev_err(&pdev->dev,
163 "Can't set sysClkReq%dRfClkBuf: %d\n",
164 j + 1, ret);
165 }
166 }
167 }
168
169 return 0; 135 return 0;
170} 136}
171 137
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index c0a86aeb1733..388e268b9bcf 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -3094,8 +3094,7 @@ static void db8500_prcmu_update_cpufreq(void)
3094 } 3094 }
3095} 3095}
3096 3096
3097static int db8500_prcmu_register_ab8500(struct device *parent, 3097static int db8500_prcmu_register_ab8500(struct device *parent)
3098 struct ab8500_platform_data *pdata)
3099{ 3098{
3100 struct device_node *np; 3099 struct device_node *np;
3101 struct resource ab8500_resource; 3100 struct resource ab8500_resource;
@@ -3103,8 +3102,6 @@ static int db8500_prcmu_register_ab8500(struct device *parent,
3103 .name = "ab8500-core", 3102 .name = "ab8500-core",
3104 .of_compatible = "stericsson,ab8500", 3103 .of_compatible = "stericsson,ab8500",
3105 .id = AB8500_VERSION_AB8500, 3104 .id = AB8500_VERSION_AB8500,
3106 .platform_data = pdata,
3107 .pdata_size = sizeof(struct ab8500_platform_data),
3108 .resources = &ab8500_resource, 3105 .resources = &ab8500_resource,
3109 .num_resources = 1, 3106 .num_resources = 1,
3110 }; 3107 };
@@ -3133,7 +3130,6 @@ static int db8500_prcmu_register_ab8500(struct device *parent,
3133static int db8500_prcmu_probe(struct platform_device *pdev) 3130static int db8500_prcmu_probe(struct platform_device *pdev)
3134{ 3131{
3135 struct device_node *np = pdev->dev.of_node; 3132 struct device_node *np = pdev->dev.of_node;
3136 struct prcmu_pdata *pdata = dev_get_platdata(&pdev->dev);
3137 int irq = 0, err = 0; 3133 int irq = 0, err = 0;
3138 struct resource *res; 3134 struct resource *res;
3139 3135
@@ -3149,7 +3145,7 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
3149 return -ENOMEM; 3145 return -ENOMEM;
3150 } 3146 }
3151 init_prcm_registers(); 3147 init_prcm_registers();
3152 dbx500_fw_version_init(pdev, pdata->version_offset); 3148 dbx500_fw_version_init(pdev, DB8500_PRCMU_FW_VERSION_OFFSET);
3153 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm"); 3149 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "prcmu-tcdm");
3154 if (!res) { 3150 if (!res) {
3155 dev_err(&pdev->dev, "no prcmu tcdm region provided\n"); 3151 dev_err(&pdev->dev, "no prcmu tcdm region provided\n");
@@ -3204,7 +3200,7 @@ static int db8500_prcmu_probe(struct platform_device *pdev)
3204 } 3200 }
3205 } 3201 }
3206 3202
3207 err = db8500_prcmu_register_ab8500(&pdev->dev, pdata->ab_platdata); 3203 err = db8500_prcmu_register_ab8500(&pdev->dev);
3208 if (err) { 3204 if (err) {
3209 mfd_remove_devices(&pdev->dev); 3205 mfd_remove_devices(&pdev->dev);
3210 pr_err("prcmu: Failed to add ab8500 subdevice\n"); 3206 pr_err("prcmu: Failed to add ab8500 subdevice\n");
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index 7053abced0bc..3bfac539334b 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -46,6 +46,16 @@ config POWER_RESET_AXXIA
46 46
47 Say Y if you have an Axxia family SoC. 47 Say Y if you have an Axxia family SoC.
48 48
49config POWER_RESET_BRCMKONA
50 bool "Broadcom Kona reset driver"
51 depends on ARM || COMPILE_TEST
52 default ARCH_BCM_MOBILE
53 help
54 This driver provides restart support for Broadcom Kona chips.
55
56 Say Y here if you have a Broadcom Kona-based board and you wish
57 to have restart support.
58
49config POWER_RESET_BRCMSTB 59config POWER_RESET_BRCMSTB
50 bool "Broadcom STB reset driver" 60 bool "Broadcom STB reset driver"
51 depends on ARM || MIPS || COMPILE_TEST 61 depends on ARM || MIPS || COMPILE_TEST
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index d6b2560d5c4a..1be307c7fc25 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_POWER_RESET_AT91_POWEROFF) += at91-poweroff.o
3obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o 3obj-$(CONFIG_POWER_RESET_AT91_RESET) += at91-reset.o
4obj-$(CONFIG_POWER_RESET_AT91_SAMA5D2_SHDWC) += at91-sama5d2_shdwc.o 4obj-$(CONFIG_POWER_RESET_AT91_SAMA5D2_SHDWC) += at91-sama5d2_shdwc.o
5obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o 5obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
6obj-$(CONFIG_POWER_RESET_BRCMKONA) += brcm-kona-reset.o
6obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o 7obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
7obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o 8obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
8obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o 9obj-$(CONFIG_POWER_RESET_GPIO_RESTART) += gpio-restart.o
diff --git a/drivers/power/reset/brcm-kona-reset.c b/drivers/power/reset/brcm-kona-reset.c
new file mode 100644
index 000000000000..8eaa959d8be6
--- /dev/null
+++ b/drivers/power/reset/brcm-kona-reset.c
@@ -0,0 +1,73 @@
1/*
2 * Copyright (C) 2016 Broadcom
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
7 *
8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9 * kind, whether express or implied; without even the implied warranty
10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/io.h>
15#include <linux/of_address.h>
16#include <linux/of_platform.h>
17#include <linux/reboot.h>
18
19#define RSTMGR_REG_WR_ACCESS_OFFSET 0
20#define RSTMGR_REG_CHIP_SOFT_RST_OFFSET 4
21
22#define RSTMGR_WR_PASSWORD 0xa5a5
23#define RSTMGR_WR_PASSWORD_SHIFT 8
24#define RSTMGR_WR_ACCESS_ENABLE 1
25
26static void __iomem *kona_reset_base;
27
28static int kona_reset_handler(struct notifier_block *this,
29 unsigned long mode, void *cmd)
30{
31 /*
32 * A soft reset is triggered by writing a 0 to bit 0 of the soft reset
33 * register. To write to that register we must first write the password
34 * and the enable bit in the write access enable register.
35 */
36 writel((RSTMGR_WR_PASSWORD << RSTMGR_WR_PASSWORD_SHIFT) |
37 RSTMGR_WR_ACCESS_ENABLE,
38 kona_reset_base + RSTMGR_REG_WR_ACCESS_OFFSET);
39 writel(0, kona_reset_base + RSTMGR_REG_CHIP_SOFT_RST_OFFSET);
40
41 return NOTIFY_DONE;
42}
43
44static struct notifier_block kona_reset_nb = {
45 .notifier_call = kona_reset_handler,
46 .priority = 128,
47};
48
49static int kona_reset_probe(struct platform_device *pdev)
50{
51 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
52
53 kona_reset_base = devm_ioremap_resource(&pdev->dev, res);
54 if (IS_ERR(kona_reset_base))
55 return PTR_ERR(kona_reset_base);
56
57 return register_restart_handler(&kona_reset_nb);
58}
59
60static const struct of_device_id of_match[] = {
61 { .compatible = "brcm,bcm21664-resetmgr" },
62 {},
63};
64
65static struct platform_driver bcm_kona_reset_driver = {
66 .probe = kona_reset_probe,
67 .driver = {
68 .name = "brcm-kona-reset",
69 .of_match_table = of_match,
70 },
71};
72
73builtin_platform_driver(bcm_kona_reset_driver);
diff --git a/drivers/pwm/pwm-clps711x.c b/drivers/pwm/pwm-clps711x.c
index 7d335422cfda..26ec24e457b1 100644
--- a/drivers/pwm/pwm-clps711x.c
+++ b/drivers/pwm/pwm-clps711x.c
@@ -155,7 +155,7 @@ static int clps711x_pwm_remove(struct platform_device *pdev)
155} 155}
156 156
157static const struct of_device_id __maybe_unused clps711x_pwm_dt_ids[] = { 157static const struct of_device_id __maybe_unused clps711x_pwm_dt_ids[] = {
158 { .compatible = "cirrus,clps711x-pwm", }, 158 { .compatible = "cirrus,ep7209-pwm", },
159 { } 159 { }
160}; 160};
161MODULE_DEVICE_TABLE(of, clps711x_pwm_dt_ids); 161MODULE_DEVICE_TABLE(of, clps711x_pwm_dt_ids);
diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c
index 3e95090cd7cf..5ad42f33e70c 100644
--- a/drivers/pwm/pwm-omap-dmtimer.c
+++ b/drivers/pwm/pwm-omap-dmtimer.c
@@ -245,7 +245,7 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
245 struct pwm_omap_dmtimer_chip *omap; 245 struct pwm_omap_dmtimer_chip *omap;
246 struct pwm_omap_dmtimer_pdata *pdata; 246 struct pwm_omap_dmtimer_pdata *pdata;
247 pwm_omap_dmtimer *dm_timer; 247 pwm_omap_dmtimer *dm_timer;
248 u32 prescaler; 248 u32 v;
249 int status; 249 int status;
250 250
251 pdata = dev_get_platdata(&pdev->dev); 251 pdata = dev_get_platdata(&pdev->dev);
@@ -306,10 +306,12 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
306 if (pm_runtime_active(&omap->dm_timer_pdev->dev)) 306 if (pm_runtime_active(&omap->dm_timer_pdev->dev))
307 omap->pdata->stop(omap->dm_timer); 307 omap->pdata->stop(omap->dm_timer);
308 308
309 /* setup dmtimer prescaler */ 309 if (!of_property_read_u32(pdev->dev.of_node, "ti,prescaler", &v))
310 if (!of_property_read_u32(pdev->dev.of_node, "ti,prescaler", 310 omap->pdata->set_prescaler(omap->dm_timer, v);
311 &prescaler)) 311
312 omap->pdata->set_prescaler(omap->dm_timer, prescaler); 312 /* setup dmtimer clock source */
313 if (!of_property_read_u32(pdev->dev.of_node, "ti,clock-source", &v))
314 omap->pdata->set_source(omap->dm_timer, v);
313 315
314 omap->chip.dev = &pdev->dev; 316 omap->chip.dev = &pdev->dev;
315 omap->chip.ops = &pwm_omap_dmtimer_ops; 317 omap->chip.ops = &pwm_omap_dmtimer_ops;
diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c
index 84c1ee39ddae..2ca00045eb99 100644
--- a/drivers/regulator/ab8500-ext.c
+++ b/drivers/regulator/ab8500-ext.c
@@ -25,6 +25,456 @@
25#include <linux/mfd/abx500/ab8500.h> 25#include <linux/mfd/abx500/ab8500.h>
26#include <linux/regulator/ab8500.h> 26#include <linux/regulator/ab8500.h>
27 27
28static struct regulator_consumer_supply ab8500_vaux1_consumers[] = {
29 /* Main display, u8500 R3 uib */
30 REGULATOR_SUPPLY("vddi", "mcde_disp_sony_acx424akp.0"),
31 /* Main display, u8500 uib and ST uib */
32 REGULATOR_SUPPLY("vdd1", "samsung_s6d16d0.0"),
33 /* Secondary display, ST uib */
34 REGULATOR_SUPPLY("vdd1", "samsung_s6d16d0.1"),
35 /* SFH7741 proximity sensor */
36 REGULATOR_SUPPLY("vcc", "gpio-keys.0"),
37 /* BH1780GLS ambient light sensor */
38 REGULATOR_SUPPLY("vcc", "2-0029"),
39 /* lsm303dlh accelerometer */
40 REGULATOR_SUPPLY("vdd", "2-0018"),
41 /* lsm303dlhc accelerometer */
42 REGULATOR_SUPPLY("vdd", "2-0019"),
43 /* lsm303dlh magnetometer */
44 REGULATOR_SUPPLY("vdd", "2-001e"),
45 /* Rohm BU21013 Touchscreen devices */
46 REGULATOR_SUPPLY("avdd", "3-005c"),
47 REGULATOR_SUPPLY("avdd", "3-005d"),
48 /* Synaptics RMI4 Touchscreen device */
49 REGULATOR_SUPPLY("vdd", "3-004b"),
50 /* L3G4200D Gyroscope device */
51 REGULATOR_SUPPLY("vdd", "2-0068"),
52 /* Ambient light sensor device */
53 REGULATOR_SUPPLY("vdd", "3-0029"),
54 /* Pressure sensor device */
55 REGULATOR_SUPPLY("vdd", "2-005c"),
56 /* Cypress TrueTouch Touchscreen device */
57 REGULATOR_SUPPLY("vcpin", "spi8.0"),
58 /* Camera device */
59 REGULATOR_SUPPLY("vaux12v5", "mmio_camera"),
60};
61
62static struct regulator_consumer_supply ab8500_vaux2_consumers[] = {
63 /* On-board eMMC power */
64 REGULATOR_SUPPLY("vmmc", "sdi4"),
65 /* AB8500 audio codec */
66 REGULATOR_SUPPLY("vcc-N2158", "ab8500-codec.0"),
67 /* AB8500 accessory detect 1 */
68 REGULATOR_SUPPLY("vcc-N2158", "ab8500-acc-det.0"),
69 /* AB8500 Tv-out device */
70 REGULATOR_SUPPLY("vcc-N2158", "mcde_tv_ab8500.4"),
71 /* AV8100 HDMI device */
72 REGULATOR_SUPPLY("vcc-N2158", "av8100_hdmi.3"),
73};
74
75static struct regulator_consumer_supply ab8500_vaux3_consumers[] = {
76 REGULATOR_SUPPLY("v-SD-STM", "stm"),
77 /* External MMC slot power */
78 REGULATOR_SUPPLY("vmmc", "sdi0"),
79};
80
81static struct regulator_consumer_supply ab8500_vtvout_consumers[] = {
82 /* TV-out DENC supply */
83 REGULATOR_SUPPLY("vtvout", "ab8500-denc.0"),
84 /* Internal general-purpose ADC */
85 REGULATOR_SUPPLY("vddadc", "ab8500-gpadc.0"),
86 /* ADC for charger */
87 REGULATOR_SUPPLY("vddadc", "ab8500-charger.0"),
88 /* AB8500 Tv-out device */
89 REGULATOR_SUPPLY("vtvout", "mcde_tv_ab8500.4"),
90};
91
92static struct regulator_consumer_supply ab8500_vaud_consumers[] = {
93 /* AB8500 audio-codec main supply */
94 REGULATOR_SUPPLY("vaud", "ab8500-codec.0"),
95};
96
97static struct regulator_consumer_supply ab8500_vamic1_consumers[] = {
98 /* AB8500 audio-codec Mic1 supply */
99 REGULATOR_SUPPLY("vamic1", "ab8500-codec.0"),
100};
101
102static struct regulator_consumer_supply ab8500_vamic2_consumers[] = {
103 /* AB8500 audio-codec Mic2 supply */
104 REGULATOR_SUPPLY("vamic2", "ab8500-codec.0"),
105};
106
107static struct regulator_consumer_supply ab8500_vdmic_consumers[] = {
108 /* AB8500 audio-codec DMic supply */
109 REGULATOR_SUPPLY("vdmic", "ab8500-codec.0"),
110};
111
112static struct regulator_consumer_supply ab8500_vintcore_consumers[] = {
113 /* SoC core supply, no device */
114 REGULATOR_SUPPLY("v-intcore", NULL),
115 /* USB Transceiver */
116 REGULATOR_SUPPLY("vddulpivio18", "ab8500-usb.0"),
117 /* Handled by abx500 clk driver */
118 REGULATOR_SUPPLY("v-intcore", "abx500-clk.0"),
119};
120
121static struct regulator_consumer_supply ab8500_vana_consumers[] = {
122 /* DB8500 DSI */
123 REGULATOR_SUPPLY("vdddsi1v2", "mcde"),
124 REGULATOR_SUPPLY("vdddsi1v2", "b2r2_core"),
125 REGULATOR_SUPPLY("vdddsi1v2", "b2r2_1_core"),
126 REGULATOR_SUPPLY("vdddsi1v2", "dsilink.0"),
127 REGULATOR_SUPPLY("vdddsi1v2", "dsilink.1"),
128 REGULATOR_SUPPLY("vdddsi1v2", "dsilink.2"),
129 /* DB8500 CSI */
130 REGULATOR_SUPPLY("vddcsi1v2", "mmio_camera"),
131};
132
133/* ab8500 regulator register initialization */
134static struct ab8500_regulator_reg_init ab8500_reg_init[] = {
135 /*
136 * VanaRequestCtrl = HP/LP depending on VxRequest
137 * VextSupply1RequestCtrl = HP/LP depending on VxRequest
138 */
139 INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL2, 0xf0, 0x00),
140 /*
141 * VextSupply2RequestCtrl = HP/LP depending on VxRequest
142 * VextSupply3RequestCtrl = HP/LP depending on VxRequest
143 * Vaux1RequestCtrl = HP/LP depending on VxRequest
144 * Vaux2RequestCtrl = HP/LP depending on VxRequest
145 */
146 INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL3, 0xff, 0x00),
147 /*
148 * Vaux3RequestCtrl = HP/LP depending on VxRequest
149 * SwHPReq = Control through SWValid disabled
150 */
151 INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL4, 0x07, 0x00),
152 /*
153 * VanaSysClkReq1HPValid = disabled
154 * Vaux1SysClkReq1HPValid = disabled
155 * Vaux2SysClkReq1HPValid = disabled
156 * Vaux3SysClkReq1HPValid = disabled
157 */
158 INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID1, 0xe8, 0x00),
159 /*
160 * VextSupply1SysClkReq1HPValid = disabled
161 * VextSupply2SysClkReq1HPValid = disabled
162 * VextSupply3SysClkReq1HPValid = SysClkReq1 controlled
163 */
164 INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID2, 0x70, 0x40),
165 /*
166 * VanaHwHPReq1Valid = disabled
167 * Vaux1HwHPreq1Valid = disabled
168 * Vaux2HwHPReq1Valid = disabled
169 * Vaux3HwHPReqValid = disabled
170 */
171 INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID1, 0xe8, 0x00),
172 /*
173 * VextSupply1HwHPReq1Valid = disabled
174 * VextSupply2HwHPReq1Valid = disabled
175 * VextSupply3HwHPReq1Valid = disabled
176 */
177 INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID2, 0x07, 0x00),
178 /*
179 * VanaHwHPReq2Valid = disabled
180 * Vaux1HwHPReq2Valid = disabled
181 * Vaux2HwHPReq2Valid = disabled
182 * Vaux3HwHPReq2Valid = disabled
183 */
184 INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID1, 0xe8, 0x00),
185 /*
186 * VextSupply1HwHPReq2Valid = disabled
187 * VextSupply2HwHPReq2Valid = disabled
188 * VextSupply3HwHPReq2Valid = HWReq2 controlled
189 */
190 INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID2, 0x07, 0x04),
191 /*
192 * VanaSwHPReqValid = disabled
193 * Vaux1SwHPReqValid = disabled
194 */
195 INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID1, 0xa0, 0x00),
196 /*
197 * Vaux2SwHPReqValid = disabled
198 * Vaux3SwHPReqValid = disabled
199 * VextSupply1SwHPReqValid = disabled
200 * VextSupply2SwHPReqValid = disabled
201 * VextSupply3SwHPReqValid = disabled
202 */
203 INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID2, 0x1f, 0x00),
204 /*
205 * SysClkReq2Valid1 = SysClkReq2 controlled
206 * SysClkReq3Valid1 = disabled
207 * SysClkReq4Valid1 = SysClkReq4 controlled
208 * SysClkReq5Valid1 = disabled
209 * SysClkReq6Valid1 = SysClkReq6 controlled
210 * SysClkReq7Valid1 = disabled
211 * SysClkReq8Valid1 = disabled
212 */
213 INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID1, 0xfe, 0x2a),
214 /*
215 * SysClkReq2Valid2 = disabled
216 * SysClkReq3Valid2 = disabled
217 * SysClkReq4Valid2 = disabled
218 * SysClkReq5Valid2 = disabled
219 * SysClkReq6Valid2 = SysClkReq6 controlled
220 * SysClkReq7Valid2 = disabled
221 * SysClkReq8Valid2 = disabled
222 */
223 INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID2, 0xfe, 0x20),
224 /*
225 * VTVoutEna = disabled
226 * Vintcore12Ena = disabled
227 * Vintcore12Sel = 1.25 V
228 * Vintcore12LP = inactive (HP)
229 * VTVoutLP = inactive (HP)
230 */
231 INIT_REGULATOR_REGISTER(AB8500_REGUMISC1, 0xfe, 0x10),
232 /*
233 * VaudioEna = disabled
234 * VdmicEna = disabled
235 * Vamic1Ena = disabled
236 * Vamic2Ena = disabled
237 */
238 INIT_REGULATOR_REGISTER(AB8500_VAUDIOSUPPLY, 0x1e, 0x00),
239 /*
240 * Vamic1_dzout = high-Z when Vamic1 is disabled
241 * Vamic2_dzout = high-Z when Vamic2 is disabled
242 */
243 INIT_REGULATOR_REGISTER(AB8500_REGUCTRL1VAMIC, 0x03, 0x00),
244 /*
245 * VPll = Hw controlled (NOTE! PRCMU bits)
246 * VanaRegu = force off
247 */
248 INIT_REGULATOR_REGISTER(AB8500_VPLLVANAREGU, 0x0f, 0x02),
249 /*
250 * VrefDDREna = disabled
251 * VrefDDRSleepMode = inactive (no pulldown)
252 */
253 INIT_REGULATOR_REGISTER(AB8500_VREFDDR, 0x03, 0x00),
254 /*
255 * VextSupply1Regu = force LP
256 * VextSupply2Regu = force OFF
257 * VextSupply3Regu = force HP (-> STBB2=LP and TPS=LP)
258 * ExtSupply2Bypass = ExtSupply12LPn ball is 0 when Ena is 0
259 * ExtSupply3Bypass = ExtSupply3LPn ball is 0 when Ena is 0
260 */
261 INIT_REGULATOR_REGISTER(AB8500_EXTSUPPLYREGU, 0xff, 0x13),
262 /*
263 * Vaux1Regu = force HP
264 * Vaux2Regu = force off
265 */
266 INIT_REGULATOR_REGISTER(AB8500_VAUX12REGU, 0x0f, 0x01),
267 /*
268 * Vaux3Regu = force off
269 */
270 INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3REGU, 0x03, 0x00),
271 /*
272 * Vaux1Sel = 2.8 V
273 */
274 INIT_REGULATOR_REGISTER(AB8500_VAUX1SEL, 0x0f, 0x0C),
275 /*
276 * Vaux2Sel = 2.9 V
277 */
278 INIT_REGULATOR_REGISTER(AB8500_VAUX2SEL, 0x0f, 0x0d),
279 /*
280 * Vaux3Sel = 2.91 V
281 */
282 INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3SEL, 0x07, 0x07),
283 /*
284 * VextSupply12LP = disabled (no LP)
285 */
286 INIT_REGULATOR_REGISTER(AB8500_REGUCTRL2SPARE, 0x01, 0x00),
287 /*
288 * Vaux1Disch = short discharge time
289 * Vaux2Disch = short discharge time
290 * Vaux3Disch = short discharge time
291 * Vintcore12Disch = short discharge time
292 * VTVoutDisch = short discharge time
293 * VaudioDisch = short discharge time
294 */
295 INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH, 0xfc, 0x00),
296 /*
297 * VanaDisch = short discharge time
298 * VdmicPullDownEna = pulldown disabled when Vdmic is disabled
299 * VdmicDisch = short discharge time
300 */
301 INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH2, 0x16, 0x00),
302};
303
304/* AB8500 regulators */
305static struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
306 /* supplies to the display/camera */
307 [AB8500_LDO_AUX1] = {
308 .supply_regulator = "ab8500-ext-supply3",
309 .constraints = {
310 .name = "V-DISPLAY",
311 .min_uV = 2800000,
312 .max_uV = 3300000,
313 .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
314 REGULATOR_CHANGE_STATUS,
315 .boot_on = 1, /* display is on at boot */
316 },
317 .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers),
318 .consumer_supplies = ab8500_vaux1_consumers,
319 },
320 /* supplies to the on-board eMMC */
321 [AB8500_LDO_AUX2] = {
322 .supply_regulator = "ab8500-ext-supply3",
323 .constraints = {
324 .name = "V-eMMC1",
325 .min_uV = 1100000,
326 .max_uV = 3300000,
327 .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
328 REGULATOR_CHANGE_STATUS |
329 REGULATOR_CHANGE_MODE,
330 .valid_modes_mask = REGULATOR_MODE_NORMAL |
331 REGULATOR_MODE_IDLE,
332 },
333 .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux2_consumers),
334 .consumer_supplies = ab8500_vaux2_consumers,
335 },
336 /* supply for VAUX3, supplies to SDcard slots */
337 [AB8500_LDO_AUX3] = {
338 .supply_regulator = "ab8500-ext-supply3",
339 .constraints = {
340 .name = "V-MMC-SD",
341 .min_uV = 1100000,
342 .max_uV = 3300000,
343 .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
344 REGULATOR_CHANGE_STATUS |
345 REGULATOR_CHANGE_MODE,
346 .valid_modes_mask = REGULATOR_MODE_NORMAL |
347 REGULATOR_MODE_IDLE,
348 },
349 .num_consumer_supplies = ARRAY_SIZE(ab8500_vaux3_consumers),
350 .consumer_supplies = ab8500_vaux3_consumers,
351 },
352 /* supply for tvout, gpadc, TVOUT LDO */
353 [AB8500_LDO_TVOUT] = {
354 .constraints = {
355 .name = "V-TVOUT",
356 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
357 },
358 .num_consumer_supplies = ARRAY_SIZE(ab8500_vtvout_consumers),
359 .consumer_supplies = ab8500_vtvout_consumers,
360 },
361 /* supply for ab8500-vaudio, VAUDIO LDO */
362 [AB8500_LDO_AUDIO] = {
363 .constraints = {
364 .name = "V-AUD",
365 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
366 },
367 .num_consumer_supplies = ARRAY_SIZE(ab8500_vaud_consumers),
368 .consumer_supplies = ab8500_vaud_consumers,
369 },
370 /* supply for v-anamic1 VAMic1-LDO */
371 [AB8500_LDO_ANAMIC1] = {
372 .constraints = {
373 .name = "V-AMIC1",
374 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
375 },
376 .num_consumer_supplies = ARRAY_SIZE(ab8500_vamic1_consumers),
377 .consumer_supplies = ab8500_vamic1_consumers,
378 },
379 /* supply for v-amic2, VAMIC2 LDO, reuse constants for AMIC1 */
380 [AB8500_LDO_ANAMIC2] = {
381 .constraints = {
382 .name = "V-AMIC2",
383 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
384 },
385 .num_consumer_supplies = ARRAY_SIZE(ab8500_vamic2_consumers),
386 .consumer_supplies = ab8500_vamic2_consumers,
387 },
388 /* supply for v-dmic, VDMIC LDO */
389 [AB8500_LDO_DMIC] = {
390 .constraints = {
391 .name = "V-DMIC",
392 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
393 },
394 .num_consumer_supplies = ARRAY_SIZE(ab8500_vdmic_consumers),
395 .consumer_supplies = ab8500_vdmic_consumers,
396 },
397 /* supply for v-intcore12, VINTCORE12 LDO */
398 [AB8500_LDO_INTCORE] = {
399 .constraints = {
400 .name = "V-INTCORE",
401 .min_uV = 1250000,
402 .max_uV = 1350000,
403 .input_uV = 1800000,
404 .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
405 REGULATOR_CHANGE_STATUS |
406 REGULATOR_CHANGE_MODE |
407 REGULATOR_CHANGE_DRMS,
408 .valid_modes_mask = REGULATOR_MODE_NORMAL |
409 REGULATOR_MODE_IDLE,
410 },
411 .num_consumer_supplies = ARRAY_SIZE(ab8500_vintcore_consumers),
412 .consumer_supplies = ab8500_vintcore_consumers,
413 },
414 /* supply for U8500 CSI-DSI, VANA LDO */
415 [AB8500_LDO_ANA] = {
416 .constraints = {
417 .name = "V-CSI-DSI",
418 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
419 },
420 .num_consumer_supplies = ARRAY_SIZE(ab8500_vana_consumers),
421 .consumer_supplies = ab8500_vana_consumers,
422 },
423};
424
425/* supply for VextSupply3 */
426static struct regulator_consumer_supply ab8500_ext_supply3_consumers[] = {
427 /* SIM supply for 3 V SIM cards */
428 REGULATOR_SUPPLY("vinvsim", "sim-detect.0"),
429};
430
431/*
432 * AB8500 external regulators
433 */
434static struct regulator_init_data ab8500_ext_regulators[] = {
435 /* fixed Vbat supplies VSMPS1_EXT_1V8 */
436 [AB8500_EXT_SUPPLY1] = {
437 .constraints = {
438 .name = "ab8500-ext-supply1",
439 .min_uV = 1800000,
440 .max_uV = 1800000,
441 .initial_mode = REGULATOR_MODE_IDLE,
442 .boot_on = 1,
443 .always_on = 1,
444 },
445 },
446 /* fixed Vbat supplies VSMPS2_EXT_1V36 and VSMPS5_EXT_1V15 */
447 [AB8500_EXT_SUPPLY2] = {
448 .constraints = {
449 .name = "ab8500-ext-supply2",
450 .min_uV = 1360000,
451 .max_uV = 1360000,
452 },
453 },
454 /* fixed Vbat supplies VSMPS3_EXT_3V4 and VSMPS4_EXT_3V4 */
455 [AB8500_EXT_SUPPLY3] = {
456 .constraints = {
457 .name = "ab8500-ext-supply3",
458 .min_uV = 3400000,
459 .max_uV = 3400000,
460 .valid_ops_mask = REGULATOR_CHANGE_STATUS,
461 .boot_on = 1,
462 },
463 .num_consumer_supplies =
464 ARRAY_SIZE(ab8500_ext_supply3_consumers),
465 .consumer_supplies = ab8500_ext_supply3_consumers,
466 },
467};
468
469static struct ab8500_regulator_platform_data ab8500_regulator_plat_data = {
470 .reg_init = ab8500_reg_init,
471 .num_reg_init = ARRAY_SIZE(ab8500_reg_init),
472 .regulator = ab8500_regulators,
473 .num_regulator = ARRAY_SIZE(ab8500_regulators),
474 .ext_regulator = ab8500_ext_regulators,
475 .num_ext_regulator = ARRAY_SIZE(ab8500_ext_regulators),
476};
477
28/** 478/**
29 * struct ab8500_ext_regulator_info - ab8500 regulator information 479 * struct ab8500_ext_regulator_info - ab8500 regulator information
30 * @dev: device pointer 480 * @dev: device pointer
@@ -344,8 +794,7 @@ static struct of_regulator_match ab8500_ext_regulator_match[] = {
344static int ab8500_ext_regulator_probe(struct platform_device *pdev) 794static int ab8500_ext_regulator_probe(struct platform_device *pdev)
345{ 795{
346 struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); 796 struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
347 struct ab8500_platform_data *ppdata; 797 struct ab8500_regulator_platform_data *pdata = &ab8500_regulator_plat_data;
348 struct ab8500_regulator_platform_data *pdata;
349 struct device_node *np = pdev->dev.of_node; 798 struct device_node *np = pdev->dev.of_node;
350 struct regulator_config config = { }; 799 struct regulator_config config = { };
351 int i, err; 800 int i, err;
@@ -366,18 +815,6 @@ static int ab8500_ext_regulator_probe(struct platform_device *pdev)
366 return -EINVAL; 815 return -EINVAL;
367 } 816 }
368 817
369 ppdata = dev_get_platdata(ab8500->dev);
370 if (!ppdata) {
371 dev_err(&pdev->dev, "null parent pdata\n");
372 return -EINVAL;
373 }
374
375 pdata = ppdata->regulator;
376 if (!pdata) {
377 dev_err(&pdev->dev, "null pdata\n");
378 return -EINVAL;
379 }
380
381 /* make sure the platform data has the correct size */ 818 /* make sure the platform data has the correct size */
382 if (pdata->num_ext_regulator != ARRAY_SIZE(ab8500_ext_regulator_info)) { 819 if (pdata->num_ext_regulator != ARRAY_SIZE(ab8500_ext_regulator_info)) {
383 dev_err(&pdev->dev, "Configuration error: size mismatch.\n"); 820 dev_err(&pdev->dev, "Configuration error: size mismatch.\n");
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 0b2733db0e9e..4be1b8c21f6f 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -12,8 +12,22 @@ menuconfig RESET_CONTROLLER
12 12
13 If unsure, say no. 13 If unsure, say no.
14 14
15if RESET_CONTROLLER
16
15config RESET_OXNAS 17config RESET_OXNAS
16 bool 18 bool
17 19
20config TI_SYSCON_RESET
21 tristate "TI SYSCON Reset Driver"
22 depends on HAS_IOMEM
23 select MFD_SYSCON
24 help
25 This enables the reset driver support for TI devices with
26 memory-mapped reset registers as part of a syscon device node. If
27 you wish to use the reset framework for such memory-mapped devices,
28 say Y here. Otherwise, say N.
29
18source "drivers/reset/sti/Kconfig" 30source "drivers/reset/sti/Kconfig"
19source "drivers/reset/hisilicon/Kconfig" 31source "drivers/reset/hisilicon/Kconfig"
32
33endif
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index f173fc3847b4..5d65a93d3c43 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -3,9 +3,11 @@ obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o
3obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o 3obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
4obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o 4obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
5obj-$(CONFIG_MACH_PISTACHIO) += reset-pistachio.o 5obj-$(CONFIG_MACH_PISTACHIO) += reset-pistachio.o
6obj-$(CONFIG_ARCH_MESON) += reset-meson.o
6obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o 7obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
7obj-$(CONFIG_ARCH_STI) += sti/ 8obj-$(CONFIG_ARCH_STI) += sti/
8obj-$(CONFIG_ARCH_HISI) += hisilicon/ 9obj-$(CONFIG_ARCH_HISI) += hisilicon/
9obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o 10obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o
10obj-$(CONFIG_ATH79) += reset-ath79.o 11obj-$(CONFIG_ATH79) += reset-ath79.o
11obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o 12obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
13obj-$(CONFIG_TI_SYSCON_RESET) += reset-ti-syscon.o
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
index 72b32bd15549..395dc9ce492e 100644
--- a/drivers/reset/core.c
+++ b/drivers/reset/core.c
@@ -93,6 +93,43 @@ void reset_controller_unregister(struct reset_controller_dev *rcdev)
93} 93}
94EXPORT_SYMBOL_GPL(reset_controller_unregister); 94EXPORT_SYMBOL_GPL(reset_controller_unregister);
95 95
96static void devm_reset_controller_release(struct device *dev, void *res)
97{
98 reset_controller_unregister(*(struct reset_controller_dev **)res);
99}
100
101/**
102 * devm_reset_controller_register - resource managed reset_controller_register()
103 * @dev: device that is registering this reset controller
104 * @rcdev: a pointer to the initialized reset controller device
105 *
106 * Managed reset_controller_register(). For reset controllers registered by
107 * this function, reset_controller_unregister() is automatically called on
108 * driver detach. See reset_controller_register() for more information.
109 */
110int devm_reset_controller_register(struct device *dev,
111 struct reset_controller_dev *rcdev)
112{
113 struct reset_controller_dev **rcdevp;
114 int ret;
115
116 rcdevp = devres_alloc(devm_reset_controller_release, sizeof(*rcdevp),
117 GFP_KERNEL);
118 if (!rcdevp)
119 return -ENOMEM;
120
121 ret = reset_controller_register(rcdev);
122 if (!ret) {
123 *rcdevp = rcdev;
124 devres_add(dev, rcdevp);
125 } else {
126 devres_free(rcdevp);
127 }
128
129 return ret;
130}
131EXPORT_SYMBOL_GPL(devm_reset_controller_register);
132
96/** 133/**
97 * reset_control_reset - reset the controlled device 134 * reset_control_reset - reset the controlled device
98 * @rstc: reset controller 135 * @rstc: reset controller
diff --git a/drivers/reset/hisilicon/hi6220_reset.c b/drivers/reset/hisilicon/hi6220_reset.c
index 8f55fd4a2630..35ce53edabf9 100644
--- a/drivers/reset/hisilicon/hi6220_reset.c
+++ b/drivers/reset/hisilicon/hi6220_reset.c
@@ -1,7 +1,8 @@
1/* 1/*
2 * Hisilicon Hi6220 reset controller driver 2 * Hisilicon Hi6220 reset controller driver
3 * 3 *
4 * Copyright (c) 2015 Hisilicon Limited. 4 * Copyright (c) 2016 Linaro Limited.
5 * Copyright (c) 2015-2016 Hisilicon Limited.
5 * 6 *
6 * Author: Feng Chen <puck.chen@hisilicon.com> 7 * Author: Feng Chen <puck.chen@hisilicon.com>
7 * 8 *
@@ -15,81 +16,130 @@
15#include <linux/module.h> 16#include <linux/module.h>
16#include <linux/bitops.h> 17#include <linux/bitops.h>
17#include <linux/of.h> 18#include <linux/of.h>
19#include <linux/of_device.h>
20#include <linux/regmap.h>
21#include <linux/mfd/syscon.h>
18#include <linux/reset-controller.h> 22#include <linux/reset-controller.h>
19#include <linux/reset.h> 23#include <linux/reset.h>
20#include <linux/platform_device.h> 24#include <linux/platform_device.h>
21 25
22#define ASSERT_OFFSET 0x300 26#define PERIPH_ASSERT_OFFSET 0x300
23#define DEASSERT_OFFSET 0x304 27#define PERIPH_DEASSERT_OFFSET 0x304
24#define MAX_INDEX 0x509 28#define PERIPH_MAX_INDEX 0x509
29
30#define SC_MEDIA_RSTEN 0x052C
31#define SC_MEDIA_RSTDIS 0x0530
32#define MEDIA_MAX_INDEX 8
25 33
26#define to_reset_data(x) container_of(x, struct hi6220_reset_data, rc_dev) 34#define to_reset_data(x) container_of(x, struct hi6220_reset_data, rc_dev)
27 35
36enum hi6220_reset_ctrl_type {
37 PERIPHERAL,
38 MEDIA,
39};
40
28struct hi6220_reset_data { 41struct hi6220_reset_data {
29 void __iomem *assert_base; 42 struct reset_controller_dev rc_dev;
30 void __iomem *deassert_base; 43 struct regmap *regmap;
31 struct reset_controller_dev rc_dev;
32}; 44};
33 45
34static int hi6220_reset_assert(struct reset_controller_dev *rc_dev, 46static int hi6220_peripheral_assert(struct reset_controller_dev *rc_dev,
35 unsigned long idx) 47 unsigned long idx)
36{ 48{
37 struct hi6220_reset_data *data = to_reset_data(rc_dev); 49 struct hi6220_reset_data *data = to_reset_data(rc_dev);
50 struct regmap *regmap = data->regmap;
51 u32 bank = idx >> 8;
52 u32 offset = idx & 0xff;
53 u32 reg = PERIPH_ASSERT_OFFSET + bank * 0x10;
38 54
39 int bank = idx >> 8; 55 return regmap_write(regmap, reg, BIT(offset));
40 int offset = idx & 0xff; 56}
41 57
42 writel(BIT(offset), data->assert_base + (bank * 0x10)); 58static int hi6220_peripheral_deassert(struct reset_controller_dev *rc_dev,
59 unsigned long idx)
60{
61 struct hi6220_reset_data *data = to_reset_data(rc_dev);
62 struct regmap *regmap = data->regmap;
63 u32 bank = idx >> 8;
64 u32 offset = idx & 0xff;
65 u32 reg = PERIPH_DEASSERT_OFFSET + bank * 0x10;
43 66
44 return 0; 67 return regmap_write(regmap, reg, BIT(offset));
45} 68}
46 69
47static int hi6220_reset_deassert(struct reset_controller_dev *rc_dev, 70static const struct reset_control_ops hi6220_peripheral_reset_ops = {
48 unsigned long idx) 71 .assert = hi6220_peripheral_assert,
72 .deassert = hi6220_peripheral_deassert,
73};
74
75static int hi6220_media_assert(struct reset_controller_dev *rc_dev,
76 unsigned long idx)
49{ 77{
50 struct hi6220_reset_data *data = to_reset_data(rc_dev); 78 struct hi6220_reset_data *data = to_reset_data(rc_dev);
79 struct regmap *regmap = data->regmap;
51 80
52 int bank = idx >> 8; 81 return regmap_write(regmap, SC_MEDIA_RSTEN, BIT(idx));
53 int offset = idx & 0xff; 82}
54 83
55 writel(BIT(offset), data->deassert_base + (bank * 0x10)); 84static int hi6220_media_deassert(struct reset_controller_dev *rc_dev,
85 unsigned long idx)
86{
87 struct hi6220_reset_data *data = to_reset_data(rc_dev);
88 struct regmap *regmap = data->regmap;
56 89
57 return 0; 90 return regmap_write(regmap, SC_MEDIA_RSTDIS, BIT(idx));
58} 91}
59 92
60static const struct reset_control_ops hi6220_reset_ops = { 93static const struct reset_control_ops hi6220_media_reset_ops = {
61 .assert = hi6220_reset_assert, 94 .assert = hi6220_media_assert,
62 .deassert = hi6220_reset_deassert, 95 .deassert = hi6220_media_deassert,
63}; 96};
64 97
65static int hi6220_reset_probe(struct platform_device *pdev) 98static int hi6220_reset_probe(struct platform_device *pdev)
66{ 99{
100 struct device_node *np = pdev->dev.of_node;
101 struct device *dev = &pdev->dev;
102 enum hi6220_reset_ctrl_type type;
67 struct hi6220_reset_data *data; 103 struct hi6220_reset_data *data;
68 struct resource *res; 104 struct regmap *regmap;
69 void __iomem *src_base;
70 105
71 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 106 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
72 if (!data) 107 if (!data)
73 return -ENOMEM; 108 return -ENOMEM;
74 109
75 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 110 type = (enum hi6220_reset_ctrl_type)of_device_get_match_data(dev);
76 src_base = devm_ioremap_resource(&pdev->dev, res); 111
77 if (IS_ERR(src_base)) 112 regmap = syscon_node_to_regmap(np);
78 return PTR_ERR(src_base); 113 if (IS_ERR(regmap)) {
114 dev_err(dev, "failed to get reset controller regmap\n");
115 return PTR_ERR(regmap);
116 }
79 117
80 data->assert_base = src_base + ASSERT_OFFSET; 118 data->regmap = regmap;
81 data->deassert_base = src_base + DEASSERT_OFFSET; 119 data->rc_dev.of_node = np;
82 data->rc_dev.nr_resets = MAX_INDEX; 120 if (type == MEDIA) {
83 data->rc_dev.ops = &hi6220_reset_ops; 121 data->rc_dev.ops = &hi6220_media_reset_ops;
84 data->rc_dev.of_node = pdev->dev.of_node; 122 data->rc_dev.nr_resets = MEDIA_MAX_INDEX;
123 } else {
124 data->rc_dev.ops = &hi6220_peripheral_reset_ops;
125 data->rc_dev.nr_resets = PERIPH_MAX_INDEX;
126 }
85 127
86 return reset_controller_register(&data->rc_dev); 128 return reset_controller_register(&data->rc_dev);
87} 129}
88 130
89static const struct of_device_id hi6220_reset_match[] = { 131static const struct of_device_id hi6220_reset_match[] = {
90 { .compatible = "hisilicon,hi6220-sysctrl" }, 132 {
91 { }, 133 .compatible = "hisilicon,hi6220-sysctrl",
134 .data = (void *)PERIPHERAL,
135 },
136 {
137 .compatible = "hisilicon,hi6220-mediactrl",
138 .data = (void *)MEDIA,
139 },
140 { /* sentinel */ },
92}; 141};
142MODULE_DEVICE_TABLE(of, hi6220_reset_match);
93 143
94static struct platform_driver hi6220_reset_driver = { 144static struct platform_driver hi6220_reset_driver = {
95 .probe = hi6220_reset_probe, 145 .probe = hi6220_reset_probe,
diff --git a/drivers/reset/reset-ath79.c b/drivers/reset/reset-ath79.c
index ccb940a8d9fb..16d410cd6146 100644
--- a/drivers/reset/reset-ath79.c
+++ b/drivers/reset/reset-ath79.c
@@ -112,7 +112,7 @@ static int ath79_reset_probe(struct platform_device *pdev)
112 ath79_reset->rcdev.of_reset_n_cells = 1; 112 ath79_reset->rcdev.of_reset_n_cells = 1;
113 ath79_reset->rcdev.nr_resets = 32; 113 ath79_reset->rcdev.nr_resets = 32;
114 114
115 err = reset_controller_register(&ath79_reset->rcdev); 115 err = devm_reset_controller_register(&pdev->dev, &ath79_reset->rcdev);
116 if (err) 116 if (err)
117 return err; 117 return err;
118 118
@@ -131,7 +131,6 @@ static int ath79_reset_remove(struct platform_device *pdev)
131 struct ath79_reset *ath79_reset = platform_get_drvdata(pdev); 131 struct ath79_reset *ath79_reset = platform_get_drvdata(pdev);
132 132
133 unregister_restart_handler(&ath79_reset->restart_nb); 133 unregister_restart_handler(&ath79_reset->restart_nb);
134 reset_controller_unregister(&ath79_reset->rcdev);
135 134
136 return 0; 135 return 0;
137} 136}
diff --git a/drivers/reset/reset-meson.c b/drivers/reset/reset-meson.c
new file mode 100644
index 000000000000..c32f11a30c5f
--- /dev/null
+++ b/drivers/reset/reset-meson.c
@@ -0,0 +1,136 @@
1/*
2 * This file is provided under a dual BSD/GPLv2 license. When using or
3 * redistributing this file, you may do so under either license.
4 *
5 * GPL LICENSE SUMMARY
6 *
7 * Copyright (c) 2016 BayLibre, SAS.
8 * Author: Neil Armstrong <narmstrong@baylibre.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 * The full GNU General Public License is included in this distribution
22 * in the file called COPYING.
23 *
24 * BSD LICENSE
25 *
26 * Copyright (c) 2016 BayLibre, SAS.
27 * Author: Neil Armstrong <narmstrong@baylibre.com>
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 *
33 * * Redistributions of source code must retain the above copyright
34 * notice, this list of conditions and the following disclaimer.
35 * * Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in
37 * the documentation and/or other materials provided with the
38 * distribution.
39 * * Neither the name of Intel Corporation nor the names of its
40 * contributors may be used to endorse or promote products derived
41 * from this software without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
47 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54 */
55#include <linux/err.h>
56#include <linux/module.h>
57#include <linux/io.h>
58#include <linux/of.h>
59#include <linux/platform_device.h>
60#include <linux/reset-controller.h>
61#include <linux/slab.h>
62#include <linux/types.h>
63
64#define REG_COUNT 8
65#define BITS_PER_REG 32
66
67struct meson_reset {
68 void __iomem *reg_base;
69 struct reset_controller_dev rcdev;
70};
71
72static int meson_reset_reset(struct reset_controller_dev *rcdev,
73 unsigned long id)
74{
75 struct meson_reset *data =
76 container_of(rcdev, struct meson_reset, rcdev);
77 unsigned int bank = id / BITS_PER_REG;
78 unsigned int offset = id % BITS_PER_REG;
79 void __iomem *reg_addr = data->reg_base + (bank << 2);
80
81 if (bank >= REG_COUNT)
82 return -EINVAL;
83
84 writel(BIT(offset), reg_addr);
85
86 return 0;
87}
88
89static const struct reset_control_ops meson_reset_ops = {
90 .reset = meson_reset_reset,
91};
92
93static const struct of_device_id meson_reset_dt_ids[] = {
94 { .compatible = "amlogic,meson8b-reset", },
95 { .compatible = "amlogic,meson-gxbb-reset", },
96 { /* sentinel */ },
97};
98MODULE_DEVICE_TABLE(of, meson_reset_dt_ids);
99
100static int meson_reset_probe(struct platform_device *pdev)
101{
102 struct meson_reset *data;
103 struct resource *res;
104
105 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
106 if (!data)
107 return -ENOMEM;
108
109 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
110 data->reg_base = devm_ioremap_resource(&pdev->dev, res);
111 if (IS_ERR(data->reg_base))
112 return PTR_ERR(data->reg_base);
113
114 platform_set_drvdata(pdev, data);
115
116 data->rcdev.owner = THIS_MODULE;
117 data->rcdev.nr_resets = REG_COUNT * BITS_PER_REG;
118 data->rcdev.ops = &meson_reset_ops;
119 data->rcdev.of_node = pdev->dev.of_node;
120
121 return devm_reset_controller_register(&pdev->dev, &data->rcdev);
122}
123
124static struct platform_driver meson_reset_driver = {
125 .probe = meson_reset_probe,
126 .driver = {
127 .name = "meson_reset",
128 .of_match_table = meson_reset_dt_ids,
129 },
130};
131
132module_platform_driver(meson_reset_driver);
133
134MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
135MODULE_DESCRIPTION("Amlogic Meson Reset Controller driver");
136MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/reset/reset-oxnas.c b/drivers/reset/reset-oxnas.c
index c60fb2dace3e..944980572f79 100644
--- a/drivers/reset/reset-oxnas.c
+++ b/drivers/reset/reset-oxnas.c
@@ -112,21 +112,11 @@ static int oxnas_reset_probe(struct platform_device *pdev)
112 data->rcdev.ops = &oxnas_reset_ops; 112 data->rcdev.ops = &oxnas_reset_ops;
113 data->rcdev.of_node = pdev->dev.of_node; 113 data->rcdev.of_node = pdev->dev.of_node;
114 114
115 return reset_controller_register(&data->rcdev); 115 return devm_reset_controller_register(&pdev->dev, &data->rcdev);
116}
117
118static int oxnas_reset_remove(struct platform_device *pdev)
119{
120 struct oxnas_reset *data = platform_get_drvdata(pdev);
121
122 reset_controller_unregister(&data->rcdev);
123
124 return 0;
125} 116}
126 117
127static struct platform_driver oxnas_reset_driver = { 118static struct platform_driver oxnas_reset_driver = {
128 .probe = oxnas_reset_probe, 119 .probe = oxnas_reset_probe,
129 .remove = oxnas_reset_remove,
130 .driver = { 120 .driver = {
131 .name = "oxnas-reset", 121 .name = "oxnas-reset",
132 .of_match_table = oxnas_reset_dt_ids, 122 .of_match_table = oxnas_reset_dt_ids,
diff --git a/drivers/reset/reset-pistachio.c b/drivers/reset/reset-pistachio.c
index 72a97a15a4c8..bbc4c06dd33b 100644
--- a/drivers/reset/reset-pistachio.c
+++ b/drivers/reset/reset-pistachio.c
@@ -121,16 +121,7 @@ static int pistachio_reset_probe(struct platform_device *pdev)
121 rd->rcdev.ops = &pistachio_reset_ops; 121 rd->rcdev.ops = &pistachio_reset_ops;
122 rd->rcdev.of_node = np; 122 rd->rcdev.of_node = np;
123 123
124 return reset_controller_register(&rd->rcdev); 124 return devm_reset_controller_register(dev, &rd->rcdev);
125}
126
127static int pistachio_reset_remove(struct platform_device *pdev)
128{
129 struct pistachio_reset_data *data = platform_get_drvdata(pdev);
130
131 reset_controller_unregister(&data->rcdev);
132
133 return 0;
134} 125}
135 126
136static const struct of_device_id pistachio_reset_dt_ids[] = { 127static const struct of_device_id pistachio_reset_dt_ids[] = {
@@ -141,7 +132,6 @@ MODULE_DEVICE_TABLE(of, pistachio_reset_dt_ids);
141 132
142static struct platform_driver pistachio_reset_driver = { 133static struct platform_driver pistachio_reset_driver = {
143 .probe = pistachio_reset_probe, 134 .probe = pistachio_reset_probe,
144 .remove = pistachio_reset_remove,
145 .driver = { 135 .driver = {
146 .name = "pistachio-reset", 136 .name = "pistachio-reset",
147 .of_match_table = pistachio_reset_dt_ids, 137 .of_match_table = pistachio_reset_dt_ids,
diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
index cd05a7032b17..12add9b0fa49 100644
--- a/drivers/reset/reset-socfpga.c
+++ b/drivers/reset/reset-socfpga.c
@@ -134,16 +134,7 @@ static int socfpga_reset_probe(struct platform_device *pdev)
134 data->rcdev.ops = &socfpga_reset_ops; 134 data->rcdev.ops = &socfpga_reset_ops;
135 data->rcdev.of_node = pdev->dev.of_node; 135 data->rcdev.of_node = pdev->dev.of_node;
136 136
137 return reset_controller_register(&data->rcdev); 137 return devm_reset_controller_register(dev, &data->rcdev);
138}
139
140static int socfpga_reset_remove(struct platform_device *pdev)
141{
142 struct socfpga_reset_data *data = platform_get_drvdata(pdev);
143
144 reset_controller_unregister(&data->rcdev);
145
146 return 0;
147} 138}
148 139
149static const struct of_device_id socfpga_reset_dt_ids[] = { 140static const struct of_device_id socfpga_reset_dt_ids[] = {
@@ -153,7 +144,6 @@ static const struct of_device_id socfpga_reset_dt_ids[] = {
153 144
154static struct platform_driver socfpga_reset_driver = { 145static struct platform_driver socfpga_reset_driver = {
155 .probe = socfpga_reset_probe, 146 .probe = socfpga_reset_probe,
156 .remove = socfpga_reset_remove,
157 .driver = { 147 .driver = {
158 .name = "socfpga-reset", 148 .name = "socfpga-reset",
159 .of_match_table = socfpga_reset_dt_ids, 149 .of_match_table = socfpga_reset_dt_ids,
diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c
index 677f86555212..3080190b3f90 100644
--- a/drivers/reset/reset-sunxi.c
+++ b/drivers/reset/reset-sunxi.c
@@ -165,21 +165,11 @@ static int sunxi_reset_probe(struct platform_device *pdev)
165 data->rcdev.ops = &sunxi_reset_ops; 165 data->rcdev.ops = &sunxi_reset_ops;
166 data->rcdev.of_node = pdev->dev.of_node; 166 data->rcdev.of_node = pdev->dev.of_node;
167 167
168 return reset_controller_register(&data->rcdev); 168 return devm_reset_controller_register(&pdev->dev, &data->rcdev);
169}
170
171static int sunxi_reset_remove(struct platform_device *pdev)
172{
173 struct sunxi_reset_data *data = platform_get_drvdata(pdev);
174
175 reset_controller_unregister(&data->rcdev);
176
177 return 0;
178} 169}
179 170
180static struct platform_driver sunxi_reset_driver = { 171static struct platform_driver sunxi_reset_driver = {
181 .probe = sunxi_reset_probe, 172 .probe = sunxi_reset_probe,
182 .remove = sunxi_reset_remove,
183 .driver = { 173 .driver = {
184 .name = "sunxi-reset", 174 .name = "sunxi-reset",
185 .of_match_table = sunxi_reset_dt_ids, 175 .of_match_table = sunxi_reset_dt_ids,
diff --git a/drivers/reset/reset-ti-syscon.c b/drivers/reset/reset-ti-syscon.c
new file mode 100644
index 000000000000..47f0ffd3b013
--- /dev/null
+++ b/drivers/reset/reset-ti-syscon.c
@@ -0,0 +1,237 @@
1/*
2 * TI SYSCON regmap reset driver
3 *
4 * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
5 * Andrew F. Davis <afd@ti.com>
6 * Suman Anna <afd@ti.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
13 * kind, whether express or implied; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 */
17
18#include <linux/mfd/syscon.h>
19#include <linux/module.h>
20#include <linux/of.h>
21#include <linux/platform_device.h>
22#include <linux/regmap.h>
23#include <linux/reset-controller.h>
24
25#include <dt-bindings/reset/ti-syscon.h>
26
27/**
28 * struct ti_syscon_reset_control - reset control structure
29 * @assert_offset: reset assert control register offset from syscon base
30 * @assert_bit: reset assert bit in the reset assert control register
31 * @deassert_offset: reset deassert control register offset from syscon base
32 * @deassert_bit: reset deassert bit in the reset deassert control register
33 * @status_offset: reset status register offset from syscon base
34 * @status_bit: reset status bit in the reset status register
35 * @flags: reset flag indicating how the (de)assert and status are handled
36 */
37struct ti_syscon_reset_control {
38 unsigned int assert_offset;
39 unsigned int assert_bit;
40 unsigned int deassert_offset;
41 unsigned int deassert_bit;
42 unsigned int status_offset;
43 unsigned int status_bit;
44 u32 flags;
45};
46
47/**
48 * struct ti_syscon_reset_data - reset controller information structure
49 * @rcdev: reset controller entity
50 * @regmap: regmap handle containing the memory-mapped reset registers
51 * @controls: array of reset controls
52 * @nr_controls: number of controls in control array
53 */
54struct ti_syscon_reset_data {
55 struct reset_controller_dev rcdev;
56 struct regmap *regmap;
57 struct ti_syscon_reset_control *controls;
58 unsigned int nr_controls;
59};
60
61#define to_ti_syscon_reset_data(rcdev) \
62 container_of(rcdev, struct ti_syscon_reset_data, rcdev)
63
64/**
65 * ti_syscon_reset_assert() - assert device reset
66 * @rcdev: reset controller entity
67 * @id: ID of the reset to be asserted
68 *
69 * This function implements the reset driver op to assert a device's reset.
70 * This asserts the reset in a manner prescribed by the reset flags.
71 *
72 * Return: 0 for successful request, else a corresponding error value
73 */
74static int ti_syscon_reset_assert(struct reset_controller_dev *rcdev,
75 unsigned long id)
76{
77 struct ti_syscon_reset_data *data = to_ti_syscon_reset_data(rcdev);
78 struct ti_syscon_reset_control *control;
79 unsigned int mask, value;
80
81 if (id >= data->nr_controls)
82 return -EINVAL;
83
84 control = &data->controls[id];
85
86 if (control->flags & ASSERT_NONE)
87 return -ENOTSUPP; /* assert not supported for this reset */
88
89 mask = BIT(control->assert_bit);
90 value = (control->flags & ASSERT_SET) ? mask : 0x0;
91
92 return regmap_update_bits(data->regmap, control->assert_offset, mask, value);
93}
94
95/**
96 * ti_syscon_reset_deassert() - deassert device reset
97 * @rcdev: reset controller entity
98 * @id: ID of reset to be deasserted
99 *
100 * This function implements the reset driver op to deassert a device's reset.
101 * This deasserts the reset in a manner prescribed by the reset flags.
102 *
103 * Return: 0 for successful request, else a corresponding error value
104 */
105static int ti_syscon_reset_deassert(struct reset_controller_dev *rcdev,
106 unsigned long id)
107{
108 struct ti_syscon_reset_data *data = to_ti_syscon_reset_data(rcdev);
109 struct ti_syscon_reset_control *control;
110 unsigned int mask, value;
111
112 if (id >= data->nr_controls)
113 return -EINVAL;
114
115 control = &data->controls[id];
116
117 if (control->flags & DEASSERT_NONE)
118 return -ENOTSUPP; /* deassert not supported for this reset */
119
120 mask = BIT(control->deassert_bit);
121 value = (control->flags & DEASSERT_SET) ? mask : 0x0;
122
123 return regmap_update_bits(data->regmap, control->deassert_offset, mask, value);
124}
125
126/**
127 * ti_syscon_reset_status() - check device reset status
128 * @rcdev: reset controller entity
129 * @id: ID of the reset for which the status is being requested
130 *
131 * This function implements the reset driver op to return the status of a
132 * device's reset.
133 *
134 * Return: 0 if reset is deasserted, true if reset is asserted, else a
135 * corresponding error value
136 */
137static int ti_syscon_reset_status(struct reset_controller_dev *rcdev,
138 unsigned long id)
139{
140 struct ti_syscon_reset_data *data = to_ti_syscon_reset_data(rcdev);
141 struct ti_syscon_reset_control *control;
142 unsigned int reset_state;
143 int ret;
144
145 if (id >= data->nr_controls)
146 return -EINVAL;
147
148 control = &data->controls[id];
149
150 if (control->flags & STATUS_NONE)
151 return -ENOTSUPP; /* status not supported for this reset */
152
153 ret = regmap_read(data->regmap, control->status_offset, &reset_state);
154 if (ret)
155 return ret;
156
157 return (reset_state & BIT(control->status_bit)) &&
158 (control->flags & STATUS_SET);
159}
160
161static struct reset_control_ops ti_syscon_reset_ops = {
162 .assert = ti_syscon_reset_assert,
163 .deassert = ti_syscon_reset_deassert,
164 .status = ti_syscon_reset_status,
165};
166
167static int ti_syscon_reset_probe(struct platform_device *pdev)
168{
169 struct device *dev = &pdev->dev;
170 struct device_node *np = dev->of_node;
171 struct ti_syscon_reset_data *data;
172 struct regmap *regmap;
173 const __be32 *list;
174 struct ti_syscon_reset_control *controls;
175 int size, nr_controls, i;
176
177 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
178 if (!data)
179 return -ENOMEM;
180
181 regmap = syscon_node_to_regmap(np->parent);
182 if (IS_ERR(regmap))
183 return PTR_ERR(regmap);
184
185 list = of_get_property(np, "ti,reset-bits", &size);
186 if (!list || (size / sizeof(*list)) % 7 != 0) {
187 dev_err(dev, "invalid DT reset description\n");
188 return -EINVAL;
189 }
190
191 nr_controls = (size / sizeof(*list)) / 7;
192 controls = devm_kzalloc(dev, nr_controls * sizeof(*controls), GFP_KERNEL);
193 if (!controls)
194 return -ENOMEM;
195
196 for (i = 0; i < nr_controls; i++) {
197 controls[i].assert_offset = be32_to_cpup(list++);
198 controls[i].assert_bit = be32_to_cpup(list++);
199 controls[i].deassert_offset = be32_to_cpup(list++);
200 controls[i].deassert_bit = be32_to_cpup(list++);
201 controls[i].status_offset = be32_to_cpup(list++);
202 controls[i].status_bit = be32_to_cpup(list++);
203 controls[i].flags = be32_to_cpup(list++);
204 }
205
206 data->rcdev.ops = &ti_syscon_reset_ops;
207 data->rcdev.owner = THIS_MODULE;
208 data->rcdev.of_node = np;
209 data->rcdev.nr_resets = nr_controls;
210 data->regmap = regmap;
211 data->controls = controls;
212 data->nr_controls = nr_controls;
213
214 platform_set_drvdata(pdev, data);
215
216 return devm_reset_controller_register(dev, &data->rcdev);
217}
218
219static const struct of_device_id ti_syscon_reset_of_match[] = {
220 { .compatible = "ti,syscon-reset", },
221 { /* sentinel */ },
222};
223MODULE_DEVICE_TABLE(of, ti_syscon_reset_of_match);
224
225static struct platform_driver ti_syscon_reset_driver = {
226 .probe = ti_syscon_reset_probe,
227 .driver = {
228 .name = "ti-syscon-reset",
229 .of_match_table = ti_syscon_reset_of_match,
230 },
231};
232module_platform_driver(ti_syscon_reset_driver);
233
234MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");
235MODULE_AUTHOR("Suman Anna <s-anna@ti.com>");
236MODULE_DESCRIPTION("TI SYSCON Regmap Reset Driver");
237MODULE_LICENSE("GPL v2");
diff --git a/drivers/reset/reset-zynq.c b/drivers/reset/reset-zynq.c
index a7e87bc45885..138f2f205662 100644
--- a/drivers/reset/reset-zynq.c
+++ b/drivers/reset/reset-zynq.c
@@ -122,16 +122,7 @@ static int zynq_reset_probe(struct platform_device *pdev)
122 priv->rcdev.ops = &zynq_reset_ops; 122 priv->rcdev.ops = &zynq_reset_ops;
123 priv->rcdev.of_node = pdev->dev.of_node; 123 priv->rcdev.of_node = pdev->dev.of_node;
124 124
125 return reset_controller_register(&priv->rcdev); 125 return devm_reset_controller_register(&pdev->dev, &priv->rcdev);
126}
127
128static int zynq_reset_remove(struct platform_device *pdev)
129{
130 struct zynq_reset_data *priv = platform_get_drvdata(pdev);
131
132 reset_controller_unregister(&priv->rcdev);
133
134 return 0;
135} 126}
136 127
137static const struct of_device_id zynq_reset_dt_ids[] = { 128static const struct of_device_id zynq_reset_dt_ids[] = {
@@ -141,7 +132,6 @@ static const struct of_device_id zynq_reset_dt_ids[] = {
141 132
142static struct platform_driver zynq_reset_driver = { 133static struct platform_driver zynq_reset_driver = {
143 .probe = zynq_reset_probe, 134 .probe = zynq_reset_probe,
144 .remove = zynq_reset_remove,
145 .driver = { 135 .driver = {
146 .name = KBUILD_MODNAME, 136 .name = KBUILD_MODNAME,
147 .of_match_table = zynq_reset_dt_ids, 137 .of_match_table = zynq_reset_dt_ids,
diff --git a/drivers/reset/sti/Kconfig b/drivers/reset/sti/Kconfig
index f8c15a37fb35..613178553612 100644
--- a/drivers/reset/sti/Kconfig
+++ b/drivers/reset/sti/Kconfig
@@ -2,7 +2,6 @@ if ARCH_STI
2 2
3config STI_RESET_SYSCFG 3config STI_RESET_SYSCFG
4 bool 4 bool
5 select RESET_CONTROLLER
6 5
7config STIH415_RESET 6config STIH415_RESET
8 bool 7 bool
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index cb58ef0d9b2c..fe42a2fdf351 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -1,7 +1,6 @@
1menu "SOC (System On Chip) specific Drivers" 1menu "SOC (System On Chip) specific Drivers"
2 2
3source "drivers/soc/bcm/Kconfig" 3source "drivers/soc/bcm/Kconfig"
4source "drivers/soc/brcmstb/Kconfig"
5source "drivers/soc/fsl/qe/Kconfig" 4source "drivers/soc/fsl/qe/Kconfig"
6source "drivers/soc/mediatek/Kconfig" 5source "drivers/soc/mediatek/Kconfig"
7source "drivers/soc/qcom/Kconfig" 6source "drivers/soc/qcom/Kconfig"
@@ -10,6 +9,7 @@ source "drivers/soc/samsung/Kconfig"
10source "drivers/soc/sunxi/Kconfig" 9source "drivers/soc/sunxi/Kconfig"
11source "drivers/soc/tegra/Kconfig" 10source "drivers/soc/tegra/Kconfig"
12source "drivers/soc/ti/Kconfig" 11source "drivers/soc/ti/Kconfig"
12source "drivers/soc/ux500/Kconfig"
13source "drivers/soc/versatile/Kconfig" 13source "drivers/soc/versatile/Kconfig"
14 14
15endmenu 15endmenu
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 380230f03874..50c23d0bd457 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -3,7 +3,6 @@
3# 3#
4 4
5obj-y += bcm/ 5obj-y += bcm/
6obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
7obj-$(CONFIG_ARCH_DOVE) += dove/ 6obj-$(CONFIG_ARCH_DOVE) += dove/
8obj-$(CONFIG_MACH_DOVE) += dove/ 7obj-$(CONFIG_MACH_DOVE) += dove/
9obj-y += fsl/ 8obj-y += fsl/
@@ -15,4 +14,5 @@ obj-$(CONFIG_SOC_SAMSUNG) += samsung/
15obj-$(CONFIG_ARCH_SUNXI) += sunxi/ 14obj-$(CONFIG_ARCH_SUNXI) += sunxi/
16obj-$(CONFIG_ARCH_TEGRA) += tegra/ 15obj-$(CONFIG_ARCH_TEGRA) += tegra/
17obj-$(CONFIG_SOC_TI) += ti/ 16obj-$(CONFIG_SOC_TI) += ti/
17obj-$(CONFIG_ARCH_U8500) += ux500/
18obj-$(CONFIG_PLAT_VERSATILE) += versatile/ 18obj-$(CONFIG_PLAT_VERSATILE) += versatile/
diff --git a/drivers/soc/bcm/Kconfig b/drivers/soc/bcm/Kconfig
index 3066edea184d..a39b0d58ddd0 100644
--- a/drivers/soc/bcm/Kconfig
+++ b/drivers/soc/bcm/Kconfig
@@ -1,9 +1,23 @@
1menu "Broadcom SoC drivers"
2
1config RASPBERRYPI_POWER 3config RASPBERRYPI_POWER
2 bool "Raspberry Pi power domain driver" 4 bool "Raspberry Pi power domain driver"
3 depends on ARCH_BCM2835 || COMPILE_TEST 5 depends on ARCH_BCM2835 || (COMPILE_TEST && OF)
4 depends on RASPBERRYPI_FIRMWARE=y 6 depends on RASPBERRYPI_FIRMWARE=y
5 select PM_GENERIC_DOMAINS if PM 7 select PM_GENERIC_DOMAINS if PM
6 select PM_GENERIC_DOMAINS_OF if PM
7 help 8 help
8 This enables support for the RPi power domains which can be enabled 9 This enables support for the RPi power domains which can be enabled
9 or disabled via the RPi firmware. 10 or disabled via the RPi firmware.
11
12config SOC_BRCMSTB
13 bool "Broadcom STB SoC drivers"
14 depends on ARM
15 select SOC_BUS
16 help
17 Enables drivers for the Broadcom Set-Top Box (STB) series of chips.
18 This option alone enables only some support code, while the drivers
19 can be enabled individually within this menu.
20
21 If unsure, say N.
22
23endmenu
diff --git a/drivers/soc/bcm/Makefile b/drivers/soc/bcm/Makefile
index 63aa3eb23087..dc4fced72d21 100644
--- a/drivers/soc/bcm/Makefile
+++ b/drivers/soc/bcm/Makefile
@@ -1 +1,2 @@
1obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o 1obj-$(CONFIG_RASPBERRYPI_POWER) += raspberrypi-power.o
2obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
diff --git a/drivers/soc/brcmstb/Makefile b/drivers/soc/bcm/brcmstb/Makefile
index 9120b2715d3e..9120b2715d3e 100644
--- a/drivers/soc/brcmstb/Makefile
+++ b/drivers/soc/bcm/brcmstb/Makefile
diff --git a/drivers/soc/brcmstb/biuctrl.c b/drivers/soc/bcm/brcmstb/biuctrl.c
index 9049c076f9a1..3c39415d484f 100644
--- a/drivers/soc/brcmstb/biuctrl.c
+++ b/drivers/soc/bcm/brcmstb/biuctrl.c
@@ -19,6 +19,7 @@
19#include <linux/io.h> 19#include <linux/io.h>
20#include <linux/of_address.h> 20#include <linux/of_address.h>
21#include <linux/syscore_ops.h> 21#include <linux/syscore_ops.h>
22#include <linux/soc/brcmstb/brcmstb.h>
22 23
23#define CPU_CREDIT_REG_OFFSET 0x184 24#define CPU_CREDIT_REG_OFFSET 0x184
24#define CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK 0x70000000 25#define CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK 0x70000000
diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/bcm/brcmstb/common.c
index 94e7335553f4..94e7335553f4 100644
--- a/drivers/soc/brcmstb/common.c
+++ b/drivers/soc/bcm/brcmstb/common.c
diff --git a/drivers/soc/brcmstb/Kconfig b/drivers/soc/brcmstb/Kconfig
deleted file mode 100644
index 7fec3b4c80a1..000000000000
--- a/drivers/soc/brcmstb/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
1menuconfig SOC_BRCMSTB
2 bool "Broadcom STB SoC drivers"
3 depends on ARM
4 select SOC_BUS
5 help
6 Enables drivers for the Broadcom Set-Top Box (STB) series of chips.
7 This option alone enables only some support code, while the drivers
8 can be enabled individually within this menu.
9
10 If unsure, say N.
diff --git a/drivers/soc/qcom/smem_state.c b/drivers/soc/qcom/smem_state.c
index 54261decb369..d5437ca76ed9 100644
--- a/drivers/soc/qcom/smem_state.c
+++ b/drivers/soc/qcom/smem_state.c
@@ -104,26 +104,26 @@ struct qcom_smem_state *qcom_smem_state_get(struct device *dev,
104 104
105 if (con_id) { 105 if (con_id) {
106 index = of_property_match_string(dev->of_node, 106 index = of_property_match_string(dev->of_node,
107 "qcom,state-names", 107 "qcom,smem-state-names",
108 con_id); 108 con_id);
109 if (index < 0) { 109 if (index < 0) {
110 dev_err(dev, "missing qcom,state-names\n"); 110 dev_err(dev, "missing qcom,smem-state-names\n");
111 return ERR_PTR(index); 111 return ERR_PTR(index);
112 } 112 }
113 } 113 }
114 114
115 ret = of_parse_phandle_with_args(dev->of_node, 115 ret = of_parse_phandle_with_args(dev->of_node,
116 "qcom,state", 116 "qcom,smem-states",
117 "#qcom,state-cells", 117 "#qcom,smem-state-cells",
118 index, 118 index,
119 &args); 119 &args);
120 if (ret) { 120 if (ret) {
121 dev_err(dev, "failed to parse qcom,state property\n"); 121 dev_err(dev, "failed to parse qcom,smem-states property\n");
122 return ERR_PTR(ret); 122 return ERR_PTR(ret);
123 } 123 }
124 124
125 if (args.args_count != 1) { 125 if (args.args_count != 1) {
126 dev_err(dev, "invalid #qcom,state-cells\n"); 126 dev_err(dev, "invalid #qcom,smem-state-cells\n");
127 return ERR_PTR(-EINVAL); 127 return ERR_PTR(-EINVAL);
128 } 128 }
129 129
diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c
index f1eed7f9dd67..f51fb2ea7200 100644
--- a/drivers/soc/qcom/smp2p.c
+++ b/drivers/soc/qcom/smp2p.c
@@ -196,7 +196,7 @@ static irqreturn_t qcom_smp2p_intr(int irq, void *data)
196 /* Match newly created entries */ 196 /* Match newly created entries */
197 for (i = smp2p->valid_entries; i < in->valid_entries; i++) { 197 for (i = smp2p->valid_entries; i < in->valid_entries; i++) {
198 list_for_each_entry(entry, &smp2p->inbound, node) { 198 list_for_each_entry(entry, &smp2p->inbound, node) {
199 memcpy_fromio(buf, in->entries[i].name, sizeof(buf)); 199 memcpy(buf, in->entries[i].name, sizeof(buf));
200 if (!strcmp(buf, entry->name)) { 200 if (!strcmp(buf, entry->name)) {
201 entry->value = &in->entries[i].value; 201 entry->value = &in->entries[i].value;
202 break; 202 break;
@@ -343,12 +343,13 @@ static int qcom_smp2p_outbound_entry(struct qcom_smp2p *smp2p,
343 343
344 /* Allocate an entry from the smem item */ 344 /* Allocate an entry from the smem item */
345 strlcpy(buf, entry->name, SMP2P_MAX_ENTRY_NAME); 345 strlcpy(buf, entry->name, SMP2P_MAX_ENTRY_NAME);
346 memcpy_toio(out->entries[out->valid_entries].name, buf, SMP2P_MAX_ENTRY_NAME); 346 memcpy(out->entries[out->valid_entries].name, buf, SMP2P_MAX_ENTRY_NAME);
347 out->valid_entries++;
348 347
349 /* Make the logical entry reference the physical value */ 348 /* Make the logical entry reference the physical value */
350 entry->value = &out->entries[out->valid_entries].value; 349 entry->value = &out->entries[out->valid_entries].value;
351 350
351 out->valid_entries++;
352
352 entry->state = qcom_smem_state_register(node, &smp2p_state_ops, entry); 353 entry->state = qcom_smem_state_register(node, &smp2p_state_ops, entry);
353 if (IS_ERR(entry->state)) { 354 if (IS_ERR(entry->state)) {
354 dev_err(smp2p->dev, "failed to register qcom_smem_state\n"); 355 dev_err(smp2p->dev, "failed to register qcom_smem_state\n");
diff --git a/drivers/soc/qcom/smsm.c b/drivers/soc/qcom/smsm.c
index 6b777af1bc19..d0337b2a71c8 100644
--- a/drivers/soc/qcom/smsm.c
+++ b/drivers/soc/qcom/smsm.c
@@ -495,7 +495,7 @@ static int qcom_smsm_probe(struct platform_device *pdev)
495 if (!smsm->hosts) 495 if (!smsm->hosts)
496 return -ENOMEM; 496 return -ENOMEM;
497 497
498 local_node = of_find_node_with_property(pdev->dev.of_node, "#qcom,state-cells"); 498 local_node = of_find_node_with_property(pdev->dev.of_node, "#qcom,smem-state-cells");
499 if (!local_node) { 499 if (!local_node) {
500 dev_err(&pdev->dev, "no state entry\n"); 500 dev_err(&pdev->dev, "no state entry\n");
501 return -EINVAL; 501 return -EINVAL;
diff --git a/drivers/soc/qcom/wcnss_ctrl.c b/drivers/soc/qcom/wcnss_ctrl.c
index c544f3d2c6ee..520aedd29965 100644
--- a/drivers/soc/qcom/wcnss_ctrl.c
+++ b/drivers/soc/qcom/wcnss_ctrl.c
@@ -1,4 +1,5 @@
1/* 1/*
2 * Copyright (c) 2016, Linaro Ltd.
2 * Copyright (c) 2015, Sony Mobile Communications Inc. 3 * Copyright (c) 2015, Sony Mobile Communications Inc.
3 * 4 *
4 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
@@ -14,8 +15,16 @@
14#include <linux/module.h> 15#include <linux/module.h>
15#include <linux/slab.h> 16#include <linux/slab.h>
16#include <linux/soc/qcom/smd.h> 17#include <linux/soc/qcom/smd.h>
18#include <linux/io.h>
19#include <linux/of_platform.h>
20#include <linux/platform_device.h>
21#include <linux/soc/qcom/wcnss_ctrl.h>
17 22
18#define WCNSS_REQUEST_TIMEOUT (5 * HZ) 23#define WCNSS_REQUEST_TIMEOUT (5 * HZ)
24#define WCNSS_CBC_TIMEOUT (10 * HZ)
25
26#define WCNSS_ACK_DONE_BOOTING 1
27#define WCNSS_ACK_COLD_BOOTING 2
19 28
20#define NV_FRAGMENT_SIZE 3072 29#define NV_FRAGMENT_SIZE 3072
21#define NVBIN_FILE "wlan/prima/WCNSS_qcom_wlan_nv.bin" 30#define NVBIN_FILE "wlan/prima/WCNSS_qcom_wlan_nv.bin"
@@ -25,17 +34,19 @@
25 * @dev: device handle 34 * @dev: device handle
26 * @channel: SMD channel handle 35 * @channel: SMD channel handle
27 * @ack: completion for outstanding requests 36 * @ack: completion for outstanding requests
37 * @cbc: completion for cbc complete indication
28 * @ack_status: status of the outstanding request 38 * @ack_status: status of the outstanding request
29 * @download_nv_work: worker for uploading nv binary 39 * @probe_work: worker for uploading nv binary
30 */ 40 */
31struct wcnss_ctrl { 41struct wcnss_ctrl {
32 struct device *dev; 42 struct device *dev;
33 struct qcom_smd_channel *channel; 43 struct qcom_smd_channel *channel;
34 44
35 struct completion ack; 45 struct completion ack;
46 struct completion cbc;
36 int ack_status; 47 int ack_status;
37 48
38 struct work_struct download_nv_work; 49 struct work_struct probe_work;
39}; 50};
40 51
41/* message types */ 52/* message types */
@@ -48,6 +59,11 @@ enum {
48 WCNSS_UPLOAD_CAL_RESP, 59 WCNSS_UPLOAD_CAL_RESP,
49 WCNSS_DOWNLOAD_CAL_REQ, 60 WCNSS_DOWNLOAD_CAL_REQ,
50 WCNSS_DOWNLOAD_CAL_RESP, 61 WCNSS_DOWNLOAD_CAL_RESP,
62 WCNSS_VBAT_LEVEL_IND,
63 WCNSS_BUILD_VERSION_REQ,
64 WCNSS_BUILD_VERSION_RESP,
65 WCNSS_PM_CONFIG_REQ,
66 WCNSS_CBC_COMPLETE_IND,
51}; 67};
52 68
53/** 69/**
@@ -128,7 +144,7 @@ static int wcnss_ctrl_smd_callback(struct qcom_smd_channel *channel,
128 version->major, version->minor, 144 version->major, version->minor,
129 version->version, version->revision); 145 version->version, version->revision);
130 146
131 schedule_work(&wcnss->download_nv_work); 147 complete(&wcnss->ack);
132 break; 148 break;
133 case WCNSS_DOWNLOAD_NV_RESP: 149 case WCNSS_DOWNLOAD_NV_RESP:
134 if (count != sizeof(*nvresp)) { 150 if (count != sizeof(*nvresp)) {
@@ -141,6 +157,10 @@ static int wcnss_ctrl_smd_callback(struct qcom_smd_channel *channel,
141 wcnss->ack_status = nvresp->status; 157 wcnss->ack_status = nvresp->status;
142 complete(&wcnss->ack); 158 complete(&wcnss->ack);
143 break; 159 break;
160 case WCNSS_CBC_COMPLETE_IND:
161 dev_dbg(wcnss->dev, "cold boot complete\n");
162 complete(&wcnss->cbc);
163 break;
144 default: 164 default:
145 dev_info(wcnss->dev, "unknown message type %d\n", hdr->type); 165 dev_info(wcnss->dev, "unknown message type %d\n", hdr->type);
146 break; 166 break;
@@ -156,20 +176,32 @@ static int wcnss_ctrl_smd_callback(struct qcom_smd_channel *channel,
156static int wcnss_request_version(struct wcnss_ctrl *wcnss) 176static int wcnss_request_version(struct wcnss_ctrl *wcnss)
157{ 177{
158 struct wcnss_msg_hdr msg; 178 struct wcnss_msg_hdr msg;
179 int ret;
159 180
160 msg.type = WCNSS_VERSION_REQ; 181 msg.type = WCNSS_VERSION_REQ;
161 msg.len = sizeof(msg); 182 msg.len = sizeof(msg);
183 ret = qcom_smd_send(wcnss->channel, &msg, sizeof(msg));
184 if (ret < 0)
185 return ret;
186
187 ret = wait_for_completion_timeout(&wcnss->ack, WCNSS_CBC_TIMEOUT);
188 if (!ret) {
189 dev_err(wcnss->dev, "timeout waiting for version response\n");
190 return -ETIMEDOUT;
191 }
162 192
163 return qcom_smd_send(wcnss->channel, &msg, sizeof(msg)); 193 return 0;
164} 194}
165 195
166/** 196/**
167 * wcnss_download_nv() - send nv binary to WCNSS 197 * wcnss_download_nv() - send nv binary to WCNSS
168 * @work: work struct to acquire wcnss context 198 * @wcnss: wcnss_ctrl state handle
199 * @expect_cbc: indicator to caller that an cbc event is expected
200 *
201 * Returns 0 on success. Negative errno on failure.
169 */ 202 */
170static void wcnss_download_nv(struct work_struct *work) 203static int wcnss_download_nv(struct wcnss_ctrl *wcnss, bool *expect_cbc)
171{ 204{
172 struct wcnss_ctrl *wcnss = container_of(work, struct wcnss_ctrl, download_nv_work);
173 struct wcnss_download_nv_req *req; 205 struct wcnss_download_nv_req *req;
174 const struct firmware *fw; 206 const struct firmware *fw;
175 const void *data; 207 const void *data;
@@ -178,10 +210,10 @@ static void wcnss_download_nv(struct work_struct *work)
178 210
179 req = kzalloc(sizeof(*req) + NV_FRAGMENT_SIZE, GFP_KERNEL); 211 req = kzalloc(sizeof(*req) + NV_FRAGMENT_SIZE, GFP_KERNEL);
180 if (!req) 212 if (!req)
181 return; 213 return -ENOMEM;
182 214
183 ret = request_firmware(&fw, NVBIN_FILE, wcnss->dev); 215 ret = request_firmware(&fw, NVBIN_FILE, wcnss->dev);
184 if (ret) { 216 if (ret < 0) {
185 dev_err(wcnss->dev, "Failed to load nv file %s: %d\n", 217 dev_err(wcnss->dev, "Failed to load nv file %s: %d\n",
186 NVBIN_FILE, ret); 218 NVBIN_FILE, ret);
187 goto free_req; 219 goto free_req;
@@ -207,7 +239,7 @@ static void wcnss_download_nv(struct work_struct *work)
207 memcpy(req->fragment, data, req->frag_size); 239 memcpy(req->fragment, data, req->frag_size);
208 240
209 ret = qcom_smd_send(wcnss->channel, req, req->hdr.len); 241 ret = qcom_smd_send(wcnss->channel, req, req->hdr.len);
210 if (ret) { 242 if (ret < 0) {
211 dev_err(wcnss->dev, "failed to send smd packet\n"); 243 dev_err(wcnss->dev, "failed to send smd packet\n");
212 goto release_fw; 244 goto release_fw;
213 } 245 }
@@ -220,16 +252,58 @@ static void wcnss_download_nv(struct work_struct *work)
220 } while (left > 0); 252 } while (left > 0);
221 253
222 ret = wait_for_completion_timeout(&wcnss->ack, WCNSS_REQUEST_TIMEOUT); 254 ret = wait_for_completion_timeout(&wcnss->ack, WCNSS_REQUEST_TIMEOUT);
223 if (!ret) 255 if (!ret) {
224 dev_err(wcnss->dev, "timeout waiting for nv upload ack\n"); 256 dev_err(wcnss->dev, "timeout waiting for nv upload ack\n");
225 else if (wcnss->ack_status != 1) 257 ret = -ETIMEDOUT;
226 dev_err(wcnss->dev, "nv upload response failed err: %d\n", 258 } else {
227 wcnss->ack_status); 259 *expect_cbc = wcnss->ack_status == WCNSS_ACK_COLD_BOOTING;
260 ret = 0;
261 }
228 262
229release_fw: 263release_fw:
230 release_firmware(fw); 264 release_firmware(fw);
231free_req: 265free_req:
232 kfree(req); 266 kfree(req);
267
268 return ret;
269}
270
271/**
272 * qcom_wcnss_open_channel() - open additional SMD channel to WCNSS
273 * @wcnss: wcnss handle, retrieved from drvdata
274 * @name: SMD channel name
275 * @cb: callback to handle incoming data on the channel
276 */
277struct qcom_smd_channel *qcom_wcnss_open_channel(void *wcnss, const char *name, qcom_smd_cb_t cb)
278{
279 struct wcnss_ctrl *_wcnss = wcnss;
280
281 return qcom_smd_open_channel(_wcnss->channel, name, cb);
282}
283EXPORT_SYMBOL(qcom_wcnss_open_channel);
284
285static void wcnss_async_probe(struct work_struct *work)
286{
287 struct wcnss_ctrl *wcnss = container_of(work, struct wcnss_ctrl, probe_work);
288 bool expect_cbc;
289 int ret;
290
291 ret = wcnss_request_version(wcnss);
292 if (ret < 0)
293 return;
294
295 ret = wcnss_download_nv(wcnss, &expect_cbc);
296 if (ret < 0)
297 return;
298
299 /* Wait for pending cold boot completion if indicated by the nv downloader */
300 if (expect_cbc) {
301 ret = wait_for_completion_timeout(&wcnss->cbc, WCNSS_REQUEST_TIMEOUT);
302 if (!ret)
303 dev_err(wcnss->dev, "expected cold boot completion\n");
304 }
305
306 of_platform_populate(wcnss->dev->of_node, NULL, NULL, wcnss->dev);
233} 307}
234 308
235static int wcnss_ctrl_probe(struct qcom_smd_device *sdev) 309static int wcnss_ctrl_probe(struct qcom_smd_device *sdev)
@@ -244,25 +318,38 @@ static int wcnss_ctrl_probe(struct qcom_smd_device *sdev)
244 wcnss->channel = sdev->channel; 318 wcnss->channel = sdev->channel;
245 319
246 init_completion(&wcnss->ack); 320 init_completion(&wcnss->ack);
247 INIT_WORK(&wcnss->download_nv_work, wcnss_download_nv); 321 init_completion(&wcnss->cbc);
322 INIT_WORK(&wcnss->probe_work, wcnss_async_probe);
248 323
249 qcom_smd_set_drvdata(sdev->channel, wcnss); 324 qcom_smd_set_drvdata(sdev->channel, wcnss);
325 dev_set_drvdata(&sdev->dev, wcnss);
326
327 schedule_work(&wcnss->probe_work);
328
329 return 0;
330}
331
332static void wcnss_ctrl_remove(struct qcom_smd_device *sdev)
333{
334 struct wcnss_ctrl *wcnss = qcom_smd_get_drvdata(sdev->channel);
250 335
251 return wcnss_request_version(wcnss); 336 cancel_work_sync(&wcnss->probe_work);
337 of_platform_depopulate(&sdev->dev);
252} 338}
253 339
254static const struct qcom_smd_id wcnss_ctrl_smd_match[] = { 340static const struct of_device_id wcnss_ctrl_of_match[] = {
255 { .name = "WCNSS_CTRL" }, 341 { .compatible = "qcom,wcnss", },
256 {} 342 {}
257}; 343};
258 344
259static struct qcom_smd_driver wcnss_ctrl_driver = { 345static struct qcom_smd_driver wcnss_ctrl_driver = {
260 .probe = wcnss_ctrl_probe, 346 .probe = wcnss_ctrl_probe,
347 .remove = wcnss_ctrl_remove,
261 .callback = wcnss_ctrl_smd_callback, 348 .callback = wcnss_ctrl_smd_callback,
262 .smd_match_table = wcnss_ctrl_smd_match,
263 .driver = { 349 .driver = {
264 .name = "qcom_wcnss_ctrl", 350 .name = "qcom_wcnss_ctrl",
265 .owner = THIS_MODULE, 351 .owner = THIS_MODULE,
352 .of_match_table = wcnss_ctrl_of_match,
266 }, 353 },
267}; 354};
268 355
diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig
index d7fc123006a3..245533907d1b 100644
--- a/drivers/soc/samsung/Kconfig
+++ b/drivers/soc/samsung/Kconfig
@@ -10,4 +10,8 @@ config EXYNOS_PMU
10 bool "Exynos PMU controller driver" if COMPILE_TEST 10 bool "Exynos PMU controller driver" if COMPILE_TEST
11 depends on (ARM && ARCH_EXYNOS) || ((ARM || ARM64) && COMPILE_TEST) 11 depends on (ARM && ARCH_EXYNOS) || ((ARM || ARM64) && COMPILE_TEST)
12 12
13config EXYNOS_PM_DOMAINS
14 bool "Exynos PM domains" if COMPILE_TEST
15 depends on PM_GENERIC_DOMAINS || COMPILE_TEST
16
13endif 17endif
diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile
index f64ac4d80564..3619f2ecddaa 100644
--- a/drivers/soc/samsung/Makefile
+++ b/drivers/soc/samsung/Makefile
@@ -1,2 +1,3 @@
1obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o exynos3250-pmu.o exynos4-pmu.o \ 1obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o exynos3250-pmu.o exynos4-pmu.o \
2 exynos5250-pmu.o exynos5420-pmu.o 2 exynos5250-pmu.o exynos5420-pmu.o
3obj-$(CONFIG_EXYNOS_PM_DOMAINS) += pm_domains.o
diff --git a/drivers/soc/samsung/exynos3250-pmu.c b/drivers/soc/samsung/exynos3250-pmu.c
index 20b3ab8aa790..af2f54e14b83 100644
--- a/drivers/soc/samsung/exynos3250-pmu.c
+++ b/drivers/soc/samsung/exynos3250-pmu.c
@@ -14,7 +14,7 @@
14 14
15#include "exynos-pmu.h" 15#include "exynos-pmu.h"
16 16
17static struct exynos_pmu_conf exynos3250_pmu_config[] = { 17static const struct exynos_pmu_conf exynos3250_pmu_config[] = {
18 /* { .offset = offset, .val = { AFTR, W-AFTR, SLEEP } */ 18 /* { .offset = offset, .val = { AFTR, W-AFTR, SLEEP } */
19 { EXYNOS3_ARM_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x2} }, 19 { EXYNOS3_ARM_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x2} },
20 { EXYNOS3_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} }, 20 { EXYNOS3_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
diff --git a/drivers/soc/samsung/exynos5420-pmu.c b/drivers/soc/samsung/exynos5420-pmu.c
index b962fb6a5d22..3f2c64180ef8 100644
--- a/drivers/soc/samsung/exynos5420-pmu.c
+++ b/drivers/soc/samsung/exynos5420-pmu.c
@@ -17,7 +17,7 @@
17 17
18#include "exynos-pmu.h" 18#include "exynos-pmu.h"
19 19
20static struct exynos_pmu_conf exynos5420_pmu_config[] = { 20static const struct exynos_pmu_conf exynos5420_pmu_config[] = {
21 /* { .offset = offset, .val = { AFTR, LPA, SLEEP } */ 21 /* { .offset = offset, .val = { AFTR, LPA, SLEEP } */
22 { EXYNOS5_ARM_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x0} }, 22 { EXYNOS5_ARM_CORE0_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
23 { EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} }, 23 { EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG, { 0x0, 0x0, 0x0} },
diff --git a/drivers/soc/samsung/pm_domains.c b/drivers/soc/samsung/pm_domains.c
new file mode 100644
index 000000000000..4822346aadc6
--- /dev/null
+++ b/drivers/soc/samsung/pm_domains.c
@@ -0,0 +1,245 @@
1/*
2 * Exynos Generic power domain support.
3 *
4 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
5 * http://www.samsung.com
6 *
7 * Implementation of Exynos specific power domain control which is used in
8 * conjunction with runtime-pm. Support for both device-tree and non-device-tree
9 * based power domain support is included.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14*/
15
16#include <linux/io.h>
17#include <linux/err.h>
18#include <linux/slab.h>
19#include <linux/pm_domain.h>
20#include <linux/clk.h>
21#include <linux/delay.h>
22#include <linux/of_address.h>
23#include <linux/of_platform.h>
24#include <linux/sched.h>
25
26#define MAX_CLK_PER_DOMAIN 4
27
28struct exynos_pm_domain_config {
29 /* Value for LOCAL_PWR_CFG and STATUS fields for each domain */
30 u32 local_pwr_cfg;
31};
32
33/*
34 * Exynos specific wrapper around the generic power domain
35 */
36struct exynos_pm_domain {
37 void __iomem *base;
38 char const *name;
39 bool is_off;
40 struct generic_pm_domain pd;
41 struct clk *oscclk;
42 struct clk *clk[MAX_CLK_PER_DOMAIN];
43 struct clk *pclk[MAX_CLK_PER_DOMAIN];
44 struct clk *asb_clk[MAX_CLK_PER_DOMAIN];
45 u32 local_pwr_cfg;
46};
47
48static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
49{
50 struct exynos_pm_domain *pd;
51 void __iomem *base;
52 u32 timeout, pwr;
53 char *op;
54 int i;
55
56 pd = container_of(domain, struct exynos_pm_domain, pd);
57 base = pd->base;
58
59 for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
60 if (IS_ERR(pd->asb_clk[i]))
61 break;
62 clk_prepare_enable(pd->asb_clk[i]);
63 }
64
65 /* Set oscclk before powering off a domain*/
66 if (!power_on) {
67 for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
68 if (IS_ERR(pd->clk[i]))
69 break;
70 pd->pclk[i] = clk_get_parent(pd->clk[i]);
71 if (clk_set_parent(pd->clk[i], pd->oscclk))
72 pr_err("%s: error setting oscclk as parent to clock %d\n",
73 pd->name, i);
74 }
75 }
76
77 pwr = power_on ? pd->local_pwr_cfg : 0;
78 writel_relaxed(pwr, base);
79
80 /* Wait max 1ms */
81 timeout = 10;
82
83 while ((readl_relaxed(base + 0x4) & pd->local_pwr_cfg) != pwr) {
84 if (!timeout) {
85 op = (power_on) ? "enable" : "disable";
86 pr_err("Power domain %s %s failed\n", domain->name, op);
87 return -ETIMEDOUT;
88 }
89 timeout--;
90 cpu_relax();
91 usleep_range(80, 100);
92 }
93
94 /* Restore clocks after powering on a domain*/
95 if (power_on) {
96 for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
97 if (IS_ERR(pd->clk[i]))
98 break;
99
100 if (IS_ERR(pd->pclk[i]))
101 continue; /* Skip on first power up */
102 if (clk_set_parent(pd->clk[i], pd->pclk[i]))
103 pr_err("%s: error setting parent to clock%d\n",
104 pd->name, i);
105 }
106 }
107
108 for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
109 if (IS_ERR(pd->asb_clk[i]))
110 break;
111 clk_disable_unprepare(pd->asb_clk[i]);
112 }
113
114 return 0;
115}
116
117static int exynos_pd_power_on(struct generic_pm_domain *domain)
118{
119 return exynos_pd_power(domain, true);
120}
121
122static int exynos_pd_power_off(struct generic_pm_domain *domain)
123{
124 return exynos_pd_power(domain, false);
125}
126
127static const struct exynos_pm_domain_config exynos4210_cfg __initconst = {
128 .local_pwr_cfg = 0x7,
129};
130
131static const struct of_device_id exynos_pm_domain_of_match[] __initconst = {
132 {
133 .compatible = "samsung,exynos4210-pd",
134 .data = &exynos4210_cfg,
135 },
136 { },
137};
138
139static __init int exynos4_pm_init_power_domain(void)
140{
141 struct device_node *np;
142 const struct of_device_id *match;
143
144 for_each_matching_node_and_match(np, exynos_pm_domain_of_match, &match) {
145 const struct exynos_pm_domain_config *pm_domain_cfg;
146 struct exynos_pm_domain *pd;
147 int on, i;
148
149 pm_domain_cfg = match->data;
150
151 pd = kzalloc(sizeof(*pd), GFP_KERNEL);
152 if (!pd) {
153 pr_err("%s: failed to allocate memory for domain\n",
154 __func__);
155 of_node_put(np);
156 return -ENOMEM;
157 }
158 pd->pd.name = kstrdup_const(strrchr(np->full_name, '/') + 1,
159 GFP_KERNEL);
160 if (!pd->pd.name) {
161 kfree(pd);
162 of_node_put(np);
163 return -ENOMEM;
164 }
165
166 pd->name = pd->pd.name;
167 pd->base = of_iomap(np, 0);
168 if (!pd->base) {
169 pr_warn("%s: failed to map memory\n", __func__);
170 kfree_const(pd->pd.name);
171 kfree(pd);
172 continue;
173 }
174
175 pd->pd.power_off = exynos_pd_power_off;
176 pd->pd.power_on = exynos_pd_power_on;
177 pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg;
178
179 for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
180 char clk_name[8];
181
182 snprintf(clk_name, sizeof(clk_name), "asb%d", i);
183 pd->asb_clk[i] = of_clk_get_by_name(np, clk_name);
184 if (IS_ERR(pd->asb_clk[i]))
185 break;
186 }
187
188 pd->oscclk = of_clk_get_by_name(np, "oscclk");
189 if (IS_ERR(pd->oscclk))
190 goto no_clk;
191
192 for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
193 char clk_name[8];
194
195 snprintf(clk_name, sizeof(clk_name), "clk%d", i);
196 pd->clk[i] = of_clk_get_by_name(np, clk_name);
197 if (IS_ERR(pd->clk[i]))
198 break;
199 /*
200 * Skip setting parent on first power up.
201 * The parent at this time may not be useful at all.
202 */
203 pd->pclk[i] = ERR_PTR(-EINVAL);
204 }
205
206 if (IS_ERR(pd->clk[0]))
207 clk_put(pd->oscclk);
208
209no_clk:
210 on = readl_relaxed(pd->base + 0x4) & pd->local_pwr_cfg;
211
212 pm_genpd_init(&pd->pd, NULL, !on);
213 of_genpd_add_provider_simple(np, &pd->pd);
214 }
215
216 /* Assign the child power domains to their parents */
217 for_each_matching_node(np, exynos_pm_domain_of_match) {
218 struct generic_pm_domain *child_domain, *parent_domain;
219 struct of_phandle_args args;
220
221 args.np = np;
222 args.args_count = 0;
223 child_domain = of_genpd_get_from_provider(&args);
224 if (IS_ERR(child_domain))
225 continue;
226
227 if (of_parse_phandle_with_args(np, "power-domains",
228 "#power-domain-cells", 0, &args) != 0)
229 continue;
230
231 parent_domain = of_genpd_get_from_provider(&args);
232 if (IS_ERR(parent_domain))
233 continue;
234
235 if (pm_genpd_add_subdomain(parent_domain, child_domain))
236 pr_warn("%s failed to add subdomain: %s\n",
237 parent_domain->name, child_domain->name);
238 else
239 pr_info("%s has as child subdomain: %s.\n",
240 parent_domain->name, child_domain->name);
241 }
242
243 return 0;
244}
245core_initcall(exynos4_pm_init_power_domain);
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index bb173456bbff..71c834f3847e 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -51,6 +51,7 @@
51#define PMC_CNTRL_CPU_PWRREQ_POLARITY (1 << 15) /* CPU pwr req polarity */ 51#define PMC_CNTRL_CPU_PWRREQ_POLARITY (1 << 15) /* CPU pwr req polarity */
52#define PMC_CNTRL_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */ 52#define PMC_CNTRL_CPU_PWRREQ_OE (1 << 16) /* CPU pwr req enable */
53#define PMC_CNTRL_INTR_POLARITY (1 << 17) /* inverts INTR polarity */ 53#define PMC_CNTRL_INTR_POLARITY (1 << 17) /* inverts INTR polarity */
54#define PMC_CNTRL_MAIN_RST (1 << 4)
54 55
55#define DPD_SAMPLE 0x020 56#define DPD_SAMPLE 0x020
56#define DPD_SAMPLE_ENABLE (1 << 0) 57#define DPD_SAMPLE_ENABLE (1 << 0)
@@ -80,6 +81,14 @@
80#define PMC_SENSOR_CTRL_SCRATCH_WRITE (1 << 2) 81#define PMC_SENSOR_CTRL_SCRATCH_WRITE (1 << 2)
81#define PMC_SENSOR_CTRL_ENABLE_RST (1 << 1) 82#define PMC_SENSOR_CTRL_ENABLE_RST (1 << 1)
82 83
84#define PMC_RST_STATUS 0x1b4
85#define PMC_RST_STATUS_POR 0
86#define PMC_RST_STATUS_WATCHDOG 1
87#define PMC_RST_STATUS_SENSOR 2
88#define PMC_RST_STATUS_SW_MAIN 3
89#define PMC_RST_STATUS_LP0 4
90#define PMC_RST_STATUS_AOTAG 5
91
83#define IO_DPD_REQ 0x1b8 92#define IO_DPD_REQ 0x1b8
84#define IO_DPD_REQ_CODE_IDLE (0 << 30) 93#define IO_DPD_REQ_CODE_IDLE (0 << 30)
85#define IO_DPD_REQ_CODE_OFF (1 << 30) 94#define IO_DPD_REQ_CODE_OFF (1 << 30)
@@ -399,6 +408,7 @@ static int tegra_powergate_power_up(struct tegra_powergate *pg,
399disable_clks: 408disable_clks:
400 tegra_powergate_disable_clocks(pg); 409 tegra_powergate_disable_clocks(pg);
401 usleep_range(10, 20); 410 usleep_range(10, 20);
411
402powergate_off: 412powergate_off:
403 tegra_powergate_set(pg->id, false); 413 tegra_powergate_set(pg->id, false);
404 414
@@ -436,6 +446,7 @@ assert_resets:
436 usleep_range(10, 20); 446 usleep_range(10, 20);
437 tegra_powergate_reset_deassert(pg); 447 tegra_powergate_reset_deassert(pg);
438 usleep_range(10, 20); 448 usleep_range(10, 20);
449
439disable_clks: 450disable_clks:
440 tegra_powergate_disable_clocks(pg); 451 tegra_powergate_disable_clocks(pg);
441 452
@@ -540,6 +551,9 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk,
540 struct tegra_powergate pg; 551 struct tegra_powergate pg;
541 int err; 552 int err;
542 553
554 if (!tegra_powergate_is_available(id))
555 return -EINVAL;
556
543 pg.id = id; 557 pg.id = id;
544 pg.clks = &clk; 558 pg.clks = &clk;
545 pg.num_clks = 1; 559 pg.num_clks = 1;
@@ -638,9 +652,10 @@ static int tegra_pmc_restart_notify(struct notifier_block *this,
638 652
639 tegra_pmc_writel(value, PMC_SCRATCH0); 653 tegra_pmc_writel(value, PMC_SCRATCH0);
640 654
641 value = tegra_pmc_readl(0); 655 /* reset everything but PMC_SCRATCH0 and PMC_RST_STATUS */
642 value |= 0x10; 656 value = tegra_pmc_readl(PMC_CNTRL);
643 tegra_pmc_writel(value, 0); 657 value |= PMC_CNTRL_MAIN_RST;
658 tegra_pmc_writel(value, PMC_CNTRL);
644 659
645 return NOTIFY_DONE; 660 return NOTIFY_DONE;
646} 661}
@@ -722,13 +737,14 @@ static int tegra_powergate_of_get_clks(struct tegra_powergate *pg,
722err: 737err:
723 while (i--) 738 while (i--)
724 clk_put(pg->clks[i]); 739 clk_put(pg->clks[i]);
740
725 kfree(pg->clks); 741 kfree(pg->clks);
726 742
727 return err; 743 return err;
728} 744}
729 745
730static int tegra_powergate_of_get_resets(struct tegra_powergate *pg, 746static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
731 struct device_node *np) 747 struct device_node *np, bool off)
732{ 748{
733 struct reset_control *rst; 749 struct reset_control *rst;
734 unsigned int i, count; 750 unsigned int i, count;
@@ -748,6 +764,16 @@ static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
748 err = PTR_ERR(pg->resets[i]); 764 err = PTR_ERR(pg->resets[i]);
749 goto error; 765 goto error;
750 } 766 }
767
768 if (off)
769 err = reset_control_assert(pg->resets[i]);
770 else
771 err = reset_control_deassert(pg->resets[i]);
772
773 if (err) {
774 reset_control_put(pg->resets[i]);
775 goto error;
776 }
751 } 777 }
752 778
753 pg->num_resets = count; 779 pg->num_resets = count;
@@ -757,6 +783,7 @@ static int tegra_powergate_of_get_resets(struct tegra_powergate *pg,
757error: 783error:
758 while (i--) 784 while (i--)
759 reset_control_put(pg->resets[i]); 785 reset_control_put(pg->resets[i]);
786
760 kfree(pg->resets); 787 kfree(pg->resets);
761 788
762 return err; 789 return err;
@@ -765,16 +792,19 @@ error:
765static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np) 792static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
766{ 793{
767 struct tegra_powergate *pg; 794 struct tegra_powergate *pg;
795 int id, err;
768 bool off; 796 bool off;
769 int id;
770 797
771 pg = kzalloc(sizeof(*pg), GFP_KERNEL); 798 pg = kzalloc(sizeof(*pg), GFP_KERNEL);
772 if (!pg) 799 if (!pg)
773 goto error; 800 return;
774 801
775 id = tegra_powergate_lookup(pmc, np->name); 802 id = tegra_powergate_lookup(pmc, np->name);
776 if (id < 0) 803 if (id < 0) {
804 dev_err(pmc->dev, "powergate lookup failed for %s: %d\n",
805 np->name, id);
777 goto free_mem; 806 goto free_mem;
807 }
778 808
779 /* 809 /*
780 * Clear the bit for this powergate so it cannot be managed 810 * Clear the bit for this powergate so it cannot be managed
@@ -788,31 +818,64 @@ static void tegra_powergate_add(struct tegra_pmc *pmc, struct device_node *np)
788 pg->genpd.power_on = tegra_genpd_power_on; 818 pg->genpd.power_on = tegra_genpd_power_on;
789 pg->pmc = pmc; 819 pg->pmc = pmc;
790 820
791 if (tegra_powergate_of_get_clks(pg, np)) 821 off = !tegra_powergate_is_powered(pg->id);
822
823 err = tegra_powergate_of_get_clks(pg, np);
824 if (err < 0) {
825 dev_err(pmc->dev, "failed to get clocks for %s: %d\n",
826 np->name, err);
792 goto set_available; 827 goto set_available;
828 }
793 829
794 if (tegra_powergate_of_get_resets(pg, np)) 830 err = tegra_powergate_of_get_resets(pg, np, off);
831 if (err < 0) {
832 dev_err(pmc->dev, "failed to get resets for %s: %d\n",
833 np->name, err);
795 goto remove_clks; 834 goto remove_clks;
835 }
796 836
797 off = !tegra_powergate_is_powered(pg->id); 837 if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
838 goto power_on_cleanup;
839
840 /*
841 * FIXME: If XHCI is enabled for Tegra, then power-up the XUSB
842 * host and super-speed partitions. Once the XHCI driver
843 * manages the partitions itself this code can be removed. Note
844 * that we don't register these partitions with the genpd core
845 * to avoid it from powering down the partitions as they appear
846 * to be unused.
847 */
848 if (IS_ENABLED(CONFIG_USB_XHCI_TEGRA) &&
849 (id == TEGRA_POWERGATE_XUSBA || id == TEGRA_POWERGATE_XUSBC))
850 goto power_on_cleanup;
798 851
799 pm_genpd_init(&pg->genpd, NULL, off); 852 pm_genpd_init(&pg->genpd, NULL, off);
800 853
801 if (of_genpd_add_provider_simple(np, &pg->genpd)) 854 err = of_genpd_add_provider_simple(np, &pg->genpd);
855 if (err < 0) {
856 dev_err(pmc->dev, "failed to add genpd provider for %s: %d\n",
857 np->name, err);
802 goto remove_resets; 858 goto remove_resets;
859 }
803 860
804 dev_dbg(pmc->dev, "added power domain %s\n", pg->genpd.name); 861 dev_dbg(pmc->dev, "added power domain %s\n", pg->genpd.name);
805 862
806 return; 863 return;
807 864
865power_on_cleanup:
866 if (off)
867 WARN_ON(tegra_powergate_power_up(pg, true));
868
808remove_resets: 869remove_resets:
809 while (pg->num_resets--) 870 while (pg->num_resets--)
810 reset_control_put(pg->resets[pg->num_resets]); 871 reset_control_put(pg->resets[pg->num_resets]);
872
811 kfree(pg->resets); 873 kfree(pg->resets);
812 874
813remove_clks: 875remove_clks:
814 while (pg->num_clks--) 876 while (pg->num_clks--)
815 clk_put(pg->clks[pg->num_clks]); 877 clk_put(pg->clks[pg->num_clks]);
878
816 kfree(pg->clks); 879 kfree(pg->clks);
817 880
818set_available: 881set_available:
@@ -820,16 +883,20 @@ set_available:
820 883
821free_mem: 884free_mem:
822 kfree(pg); 885 kfree(pg);
823
824error:
825 dev_err(pmc->dev, "failed to create power domain for %s\n", np->name);
826} 886}
827 887
828static void tegra_powergate_init(struct tegra_pmc *pmc) 888static void tegra_powergate_init(struct tegra_pmc *pmc,
889 struct device_node *parent)
829{ 890{
830 struct device_node *np, *child; 891 struct device_node *np, *child;
892 unsigned int i;
893
894 /* Create a bitmap of the available and valid partitions */
895 for (i = 0; i < pmc->soc->num_powergates; i++)
896 if (pmc->soc->powergates[i])
897 set_bit(i, pmc->powergates_available);
831 898
832 np = of_get_child_by_name(pmc->dev->of_node, "powergates"); 899 np = of_get_child_by_name(parent, "powergates");
833 if (!np) 900 if (!np)
834 return; 901 return;
835 902
@@ -1205,6 +1272,14 @@ static int tegra_pmc_probe(struct platform_device *pdev)
1205 struct resource *res; 1272 struct resource *res;
1206 int err; 1273 int err;
1207 1274
1275 /*
1276 * Early initialisation should have configured an initial
1277 * register mapping and setup the soc data pointer. If these
1278 * are not valid then something went badly wrong!
1279 */
1280 if (WARN_ON(!pmc->base || !pmc->soc))
1281 return -ENODEV;
1282
1208 err = tegra_pmc_parse_dt(pmc, pdev->dev.of_node); 1283 err = tegra_pmc_parse_dt(pmc, pdev->dev.of_node);
1209 if (err < 0) 1284 if (err < 0)
1210 return err; 1285 return err;
@@ -1242,8 +1317,6 @@ static int tegra_pmc_probe(struct platform_device *pdev)
1242 return err; 1317 return err;
1243 } 1318 }
1244 1319
1245 tegra_powergate_init(pmc);
1246
1247 mutex_lock(&pmc->powergates_lock); 1320 mutex_lock(&pmc->powergates_lock);
1248 iounmap(pmc->base); 1321 iounmap(pmc->base);
1249 pmc->base = base; 1322 pmc->base = base;
@@ -1477,10 +1550,11 @@ static int __init tegra_pmc_early_init(void)
1477 const struct of_device_id *match; 1550 const struct of_device_id *match;
1478 struct device_node *np; 1551 struct device_node *np;
1479 struct resource regs; 1552 struct resource regs;
1480 unsigned int i;
1481 bool invert; 1553 bool invert;
1482 u32 value; 1554 u32 value;
1483 1555
1556 mutex_init(&pmc->powergates_lock);
1557
1484 np = of_find_matching_node_and_match(NULL, tegra_pmc_match, &match); 1558 np = of_find_matching_node_and_match(NULL, tegra_pmc_match, &match);
1485 if (!np) { 1559 if (!np) {
1486 /* 1560 /*
@@ -1515,39 +1589,40 @@ static int __init tegra_pmc_early_init(void)
1515 */ 1589 */
1516 if (of_address_to_resource(np, 0, &regs) < 0) { 1590 if (of_address_to_resource(np, 0, &regs) < 0) {
1517 pr_err("failed to get PMC registers\n"); 1591 pr_err("failed to get PMC registers\n");
1592 of_node_put(np);
1518 return -ENXIO; 1593 return -ENXIO;
1519 } 1594 }
1520
1521 pmc->soc = match->data;
1522 } 1595 }
1523 1596
1524 pmc->base = ioremap_nocache(regs.start, resource_size(&regs)); 1597 pmc->base = ioremap_nocache(regs.start, resource_size(&regs));
1525 if (!pmc->base) { 1598 if (!pmc->base) {
1526 pr_err("failed to map PMC registers\n"); 1599 pr_err("failed to map PMC registers\n");
1600 of_node_put(np);
1527 return -ENXIO; 1601 return -ENXIO;
1528 } 1602 }
1529 1603
1530 /* Create a bit-map of the available and valid partitions */ 1604 if (np) {
1531 for (i = 0; i < pmc->soc->num_powergates; i++) 1605 pmc->soc = match->data;
1532 if (pmc->soc->powergates[i])
1533 set_bit(i, pmc->powergates_available);
1534 1606
1535 mutex_init(&pmc->powergates_lock); 1607 tegra_powergate_init(pmc, np);
1536 1608
1537 /* 1609 /*
1538 * Invert the interrupt polarity if a PMC device tree node exists and 1610 * Invert the interrupt polarity if a PMC device tree node
1539 * contains the nvidia,invert-interrupt property. 1611 * exists and contains the nvidia,invert-interrupt property.
1540 */ 1612 */
1541 invert = of_property_read_bool(np, "nvidia,invert-interrupt"); 1613 invert = of_property_read_bool(np, "nvidia,invert-interrupt");
1542 1614
1543 value = tegra_pmc_readl(PMC_CNTRL); 1615 value = tegra_pmc_readl(PMC_CNTRL);
1544 1616
1545 if (invert) 1617 if (invert)
1546 value |= PMC_CNTRL_INTR_POLARITY; 1618 value |= PMC_CNTRL_INTR_POLARITY;
1547 else 1619 else
1548 value &= ~PMC_CNTRL_INTR_POLARITY; 1620 value &= ~PMC_CNTRL_INTR_POLARITY;
1549 1621
1550 tegra_pmc_writel(value, PMC_CNTRL); 1622 tegra_pmc_writel(value, PMC_CNTRL);
1623
1624 of_node_put(np);
1625 }
1551 1626
1552 return 0; 1627 return 0;
1553} 1628}
diff --git a/drivers/soc/ux500/Kconfig b/drivers/soc/ux500/Kconfig
new file mode 100644
index 000000000000..025a44aef5db
--- /dev/null
+++ b/drivers/soc/ux500/Kconfig
@@ -0,0 +1,7 @@
1config UX500_SOC_ID
2 bool "SoC bus for ST-Ericsson ux500"
3 depends on ARCH_U8500 || COMPILE_TEST
4 default ARCH_U8500
5 help
6 Include support for the SoC bus on the ARM RealView platforms
7 providing some sysfs information about the ASIC variant.
diff --git a/drivers/soc/ux500/Makefile b/drivers/soc/ux500/Makefile
new file mode 100644
index 000000000000..0b87ad04b018
--- /dev/null
+++ b/drivers/soc/ux500/Makefile
@@ -0,0 +1 @@
obj-$(CONFIG_UX500_SOC_ID) += ux500-soc-id.o
diff --git a/drivers/soc/ux500/ux500-soc-id.c b/drivers/soc/ux500/ux500-soc-id.c
new file mode 100644
index 000000000000..6c1be74e5fcc
--- /dev/null
+++ b/drivers/soc/ux500/ux500-soc-id.c
@@ -0,0 +1,222 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2010
3 *
4 * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
5 * License terms: GNU General Public License (GPL) version 2
6 */
7
8#include <linux/kernel.h>
9#include <linux/init.h>
10#include <linux/io.h>
11#include <linux/module.h>
12#include <linux/random.h>
13#include <linux/slab.h>
14#include <linux/of.h>
15#include <linux/of_address.h>
16#include <linux/sys_soc.h>
17
18#include <asm/cputype.h>
19#include <asm/tlbflush.h>
20#include <asm/cacheflush.h>
21#include <asm/mach/map.h>
22
23/**
24 * struct dbx500_asic_id - fields of the ASIC ID
25 * @process: the manufacturing process, 0x40 is 40 nm 0x00 is "standard"
26 * @partnumber: hithereto 0x8500 for DB8500
27 * @revision: version code in the series
28 */
29struct dbx500_asic_id {
30 u16 partnumber;
31 u8 revision;
32 u8 process;
33};
34
35static struct dbx500_asic_id dbx500_id;
36
37static unsigned int __init ux500_read_asicid(phys_addr_t addr)
38{
39 void __iomem *virt = ioremap(addr, 4);
40 unsigned int asicid;
41
42 if (!virt)
43 return 0;
44
45 asicid = readl(virt);
46 iounmap(virt);
47
48 return asicid;
49}
50
51static void ux500_print_soc_info(unsigned int asicid)
52{
53 unsigned int rev = dbx500_id.revision;
54
55 pr_info("DB%4x ", dbx500_id.partnumber);
56
57 if (rev == 0x01)
58 pr_cont("Early Drop");
59 else if (rev >= 0xA0)
60 pr_cont("v%d.%d" , (rev >> 4) - 0xA + 1, rev & 0xf);
61 else
62 pr_cont("Unknown");
63
64 pr_cont(" [%#010x]\n", asicid);
65}
66
67static unsigned int partnumber(unsigned int asicid)
68{
69 return (asicid >> 8) & 0xffff;
70}
71
72/*
73 * SOC MIDR ASICID ADDRESS ASICID VALUE
74 * DB8500ed 0x410fc090 0x9001FFF4 0x00850001
75 * DB8500v1 0x411fc091 0x9001FFF4 0x008500A0
76 * DB8500v1.1 0x411fc091 0x9001FFF4 0x008500A1
77 * DB8500v2 0x412fc091 0x9001DBF4 0x008500B0
78 * DB8520v2.2 0x412fc091 0x9001DBF4 0x008500B2
79 * DB5500v1 0x412fc091 0x9001FFF4 0x005500A0
80 * DB9540 0x413fc090 0xFFFFDBF4 0x009540xx
81 */
82
83static void __init ux500_setup_id(void)
84{
85 unsigned int cpuid = read_cpuid_id();
86 unsigned int asicid = 0;
87 phys_addr_t addr = 0;
88
89 switch (cpuid) {
90 case 0x410fc090: /* DB8500ed */
91 case 0x411fc091: /* DB8500v1 */
92 addr = 0x9001FFF4;
93 break;
94
95 case 0x412fc091: /* DB8520 / DB8500v2 / DB5500v1 */
96 asicid = ux500_read_asicid(0x9001DBF4);
97 if (partnumber(asicid) == 0x8500 ||
98 partnumber(asicid) == 0x8520)
99 /* DB8500v2 */
100 break;
101
102 /* DB5500v1 */
103 addr = 0x9001FFF4;
104 break;
105
106 case 0x413fc090: /* DB9540 */
107 addr = 0xFFFFDBF4;
108 break;
109 }
110
111 if (addr)
112 asicid = ux500_read_asicid(addr);
113
114 if (!asicid) {
115 pr_err("Unable to identify SoC\n");
116 BUG();
117 }
118
119 dbx500_id.process = asicid >> 24;
120 dbx500_id.partnumber = partnumber(asicid);
121 dbx500_id.revision = asicid & 0xff;
122
123 ux500_print_soc_info(asicid);
124}
125
126static const char * __init ux500_get_machine(void)
127{
128 return kasprintf(GFP_KERNEL, "DB%4x", dbx500_id.partnumber);
129}
130
131static const char * __init ux500_get_family(void)
132{
133 return kasprintf(GFP_KERNEL, "ux500");
134}
135
136static const char * __init ux500_get_revision(void)
137{
138 unsigned int rev = dbx500_id.revision;
139
140 if (rev == 0x01)
141 return kasprintf(GFP_KERNEL, "%s", "ED");
142 else if (rev >= 0xA0)
143 return kasprintf(GFP_KERNEL, "%d.%d",
144 (rev >> 4) - 0xA + 1, rev & 0xf);
145
146 return kasprintf(GFP_KERNEL, "%s", "Unknown");
147}
148
149static ssize_t ux500_get_process(struct device *dev,
150 struct device_attribute *attr,
151 char *buf)
152{
153 if (dbx500_id.process == 0x00)
154 return sprintf(buf, "Standard\n");
155
156 return sprintf(buf, "%02xnm\n", dbx500_id.process);
157}
158
159static const char *db8500_read_soc_id(struct device_node *backupram)
160{
161 void __iomem *base;
162 void __iomem *uid;
163 const char *retstr;
164
165 base = of_iomap(backupram, 0);
166 if (!base)
167 return NULL;
168 uid = base + 0x1fc0;
169
170 /* Throw these device-specific numbers into the entropy pool */
171 add_device_randomness(uid, 0x14);
172 retstr = kasprintf(GFP_KERNEL, "%08x%08x%08x%08x%08x",
173 readl((u32 *)uid+0),
174 readl((u32 *)uid+1), readl((u32 *)uid+2),
175 readl((u32 *)uid+3), readl((u32 *)uid+4));
176 iounmap(base);
177 return retstr;
178}
179
180static void __init soc_info_populate(struct soc_device_attribute *soc_dev_attr,
181 struct device_node *backupram)
182{
183 soc_dev_attr->soc_id = db8500_read_soc_id(backupram);
184 soc_dev_attr->machine = ux500_get_machine();
185 soc_dev_attr->family = ux500_get_family();
186 soc_dev_attr->revision = ux500_get_revision();
187}
188
189static const struct device_attribute ux500_soc_attr =
190 __ATTR(process, S_IRUGO, ux500_get_process, NULL);
191
192static int __init ux500_soc_device_init(void)
193{
194 struct device *parent;
195 struct soc_device *soc_dev;
196 struct soc_device_attribute *soc_dev_attr;
197 struct device_node *backupram;
198
199 backupram = of_find_compatible_node(NULL, NULL, "ste,dbx500-backupram");
200 if (!backupram)
201 return 0;
202
203 ux500_setup_id();
204
205 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
206 if (!soc_dev_attr)
207 return -ENOMEM;
208
209 soc_info_populate(soc_dev_attr, backupram);
210
211 soc_dev = soc_device_register(soc_dev_attr);
212 if (IS_ERR(soc_dev)) {
213 kfree(soc_dev_attr);
214 return PTR_ERR(soc_dev);
215 }
216
217 parent = soc_device_to_device(soc_dev);
218 device_create_file(parent, &ux500_soc_attr);
219
220 return 0;
221}
222subsys_initcall(ux500_soc_device_init);
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index 5beafd2d2218..ac1328629baa 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -539,7 +539,7 @@ static int uart_clps711x_remove(struct platform_device *pdev)
539} 539}
540 540
541static const struct of_device_id __maybe_unused clps711x_uart_dt_ids[] = { 541static const struct of_device_id __maybe_unused clps711x_uart_dt_ids[] = {
542 { .compatible = "cirrus,clps711x-uart", }, 542 { .compatible = "cirrus,ep7209-uart", },
543 { } 543 { }
544}; 544};
545MODULE_DEVICE_TABLE(of, clps711x_uart_dt_ids); 545MODULE_DEVICE_TABLE(of, clps711x_uart_dt_ids);
diff --git a/drivers/video/fbdev/clps711x-fb.c b/drivers/video/fbdev/clps711x-fb.c
index 649b32f78c08..ff561073ee4e 100644
--- a/drivers/video/fbdev/clps711x-fb.c
+++ b/drivers/video/fbdev/clps711x-fb.c
@@ -273,7 +273,7 @@ static int clps711x_fb_probe(struct platform_device *pdev)
273 } 273 }
274 274
275 cfb->syscon = 275 cfb->syscon =
276 syscon_regmap_lookup_by_compatible("cirrus,clps711x-syscon1"); 276 syscon_regmap_lookup_by_compatible("cirrus,ep7209-syscon1");
277 if (IS_ERR(cfb->syscon)) { 277 if (IS_ERR(cfb->syscon)) {
278 ret = PTR_ERR(cfb->syscon); 278 ret = PTR_ERR(cfb->syscon);
279 goto out_fb_release; 279 goto out_fb_release;
@@ -376,7 +376,7 @@ static int clps711x_fb_remove(struct platform_device *pdev)
376} 376}
377 377
378static const struct of_device_id clps711x_fb_dt_ids[] = { 378static const struct of_device_id clps711x_fb_dt_ids[] = {
379 { .compatible = "cirrus,clps711x-fb", }, 379 { .compatible = "cirrus,ep7209-fb", },
380 { } 380 { }
381}; 381};
382MODULE_DEVICE_TABLE(of, clps711x_fb_dt_ids); 382MODULE_DEVICE_TABLE(of, clps711x_fb_dt_ids);