aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/clock/renesas,r8a7778-cpg-clocks.txt29
-rw-r--r--Documentation/devicetree/bindings/clock/renesas,r8a7779-cpg-clocks.txt30
-rw-r--r--Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt26
-rw-r--r--Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt29
-rw-r--r--Documentation/devicetree/bindings/cpufreq/tegra124-cpufreq.txt44
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/arm,pl172.txt125
-rw-r--r--Documentation/devicetree/bindings/reset/ath79-reset.txt20
-rw-r--r--Documentation/devicetree/bindings/reset/nxp,lpc1850-rgu.txt84
-rw-r--r--Documentation/devicetree/bindings/reset/st,sti-picophyreset.txt2
-rw-r--r--Documentation/devicetree/bindings/reset/st,sti-powerdown.txt4
-rw-r--r--Documentation/devicetree/bindings/reset/st,sti-softreset.txt4
-rw-r--r--Documentation/devicetree/bindings/reset/zynq-reset.txt68
-rw-r--r--Documentation/devicetree/bindings/soc/qcom,smd-rpm.txt117
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt79
-rw-r--r--MAINTAINERS1
-rw-r--r--arch/arm/boot/dts/stih407-family.dtsi2
-rw-r--r--arch/arm/boot/dts/stih415.dtsi2
-rw-r--r--arch/arm/boot/dts/stih416.dtsi2
-rw-r--r--arch/arm/mach-mvebu/Kconfig1
-rw-r--r--arch/arm/mach-mvebu/dove.c2
-rw-r--r--arch/arm/mach-shmobile/Kconfig2
-rw-r--r--arch/arm/mach-tegra/cpuidle-tegra114.c19
-rw-r--r--arch/arm/mach-tegra/iomap.h3
-rw-r--r--arch/mips/Kconfig1
-rw-r--r--arch/mips/boot/dts/qca/ar9132.dtsi8
-rw-r--r--drivers/clk/shmobile/clk-mstp.c87
-rw-r--r--drivers/clk/shmobile/clk-r8a7778.c2
-rw-r--r--drivers/clk/shmobile/clk-r8a7779.c2
-rw-r--r--drivers/clk/shmobile/clk-rcar-gen2.c2
-rw-r--r--drivers/clk/shmobile/clk-rz.c3
-rw-r--r--drivers/cpufreq/Kconfig.arm13
-rw-r--r--drivers/cpufreq/Makefile3
-rw-r--r--drivers/cpufreq/tegra124-cpufreq.c214
-rw-r--r--drivers/cpufreq/tegra20-cpufreq.c (renamed from drivers/cpufreq/tegra-cpufreq.c)0
-rw-r--r--drivers/iommu/Kconfig2
-rw-r--r--drivers/memory/Kconfig8
-rw-r--r--drivers/memory/Makefile1
-rw-r--r--drivers/memory/pl172.c301
-rw-r--r--drivers/memory/tegra/Makefile1
-rw-r--r--drivers/memory/tegra/mc.c8
-rw-r--r--drivers/memory/tegra/mc.h4
-rw-r--r--drivers/memory/tegra/tegra114.c1
-rw-r--r--drivers/memory/tegra/tegra124-emc.c42
-rw-r--r--drivers/memory/tegra/tegra124.c2
-rw-r--r--drivers/memory/tegra/tegra210.c1080
-rw-r--r--drivers/memory/tegra/tegra30.c1
-rw-r--r--drivers/reset/Makefile3
-rw-r--r--drivers/reset/reset-ath79.c128
-rw-r--r--drivers/reset/reset-lpc18xx.c258
-rw-r--r--drivers/reset/reset-socfpga.c19
-rw-r--r--drivers/reset/reset-zynq.c155
-rw-r--r--drivers/reset/sti/reset-stih407.c4
-rw-r--r--drivers/reset/sti/reset-stih415.c4
-rw-r--r--drivers/reset/sti/reset-stih416.c4
-rw-r--r--drivers/soc/Makefile1
-rw-r--r--drivers/soc/dove/Makefile1
-rw-r--r--drivers/soc/dove/pmu.c412
-rw-r--r--drivers/soc/qcom/Kconfig31
-rw-r--r--drivers/soc/qcom/Makefile3
-rw-r--r--drivers/soc/qcom/smd-rpm.c244
-rw-r--r--drivers/soc/qcom/smd.c1319
-rw-r--r--drivers/soc/qcom/smem.c775
-rw-r--r--drivers/soc/tegra/Makefile6
-rw-r--r--drivers/soc/tegra/common.c2
-rw-r--r--drivers/soc/tegra/fuse/Makefile2
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra.c257
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra20.c175
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra30.c232
-rw-r--r--drivers/soc/tegra/fuse/fuse.h95
-rw-r--r--drivers/soc/tegra/fuse/speedo-tegra114.c22
-rw-r--r--drivers/soc/tegra/fuse/speedo-tegra124.c26
-rw-r--r--drivers/soc/tegra/fuse/speedo-tegra20.c28
-rw-r--r--drivers/soc/tegra/fuse/speedo-tegra210.c184
-rw-r--r--drivers/soc/tegra/fuse/speedo-tegra30.c48
-rw-r--r--drivers/soc/tegra/fuse/tegra-apbmisc.c76
-rw-r--r--drivers/soc/tegra/pmc.c125
-rw-r--r--include/dt-bindings/memory/tegra210-mc.h36
-rw-r--r--include/dt-bindings/reset/stih407-resets.h (renamed from include/dt-bindings/reset-controller/stih407-resets.h)0
-rw-r--r--include/dt-bindings/reset/stih415-resets.h (renamed from include/dt-bindings/reset-controller/stih415-resets.h)0
-rw-r--r--include/dt-bindings/reset/stih416-resets.h (renamed from include/dt-bindings/reset-controller/stih416-resets.h)0
-rw-r--r--include/linux/clk/shmobile.h12
-rw-r--r--include/linux/soc/dove/pmu.h6
-rw-r--r--include/linux/soc/qcom/smd-rpm.h35
-rw-r--r--include/linux/soc/qcom/smd.h46
-rw-r--r--include/linux/soc/qcom/smem.h11
-rw-r--r--include/soc/tegra/fuse.h6
-rw-r--r--include/soc/tegra/mc.h2
-rw-r--r--include/soc/tegra/pmc.h5
88 files changed, 6781 insertions, 498 deletions
diff --git a/Documentation/devicetree/bindings/clock/renesas,r8a7778-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,r8a7778-cpg-clocks.txt
index 2f3747fdcf1c..e4cdaf1cb333 100644
--- a/Documentation/devicetree/bindings/clock/renesas,r8a7778-cpg-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,r8a7778-cpg-clocks.txt
@@ -1,7 +1,9 @@
1* Renesas R8A7778 Clock Pulse Generator (CPG) 1* Renesas R8A7778 Clock Pulse Generator (CPG)
2 2
3The CPG generates core clocks for the R8A7778. It includes two PLLs and 3The CPG generates core clocks for the R8A7778. It includes two PLLs and
4several fixed ratio dividers 4several fixed ratio dividers.
5The CPG also provides a Clock Domain for SoC devices, in combination with the
6CPG Module Stop (MSTP) Clocks.
5 7
6Required Properties: 8Required Properties:
7 9
@@ -10,10 +12,18 @@ Required Properties:
10 - #clock-cells: Must be 1 12 - #clock-cells: Must be 1
11 - clock-output-names: The names of the clocks. Supported clocks are 13 - clock-output-names: The names of the clocks. Supported clocks are
12 "plla", "pllb", "b", "out", "p", "s", and "s1". 14 "plla", "pllb", "b", "out", "p", "s", and "s1".
15 - #power-domain-cells: Must be 0
13 16
17SoC devices that are part of the CPG/MSTP Clock Domain and can be power-managed
18through an MSTP clock should refer to the CPG device node in their
19"power-domains" property, as documented by the generic PM domain bindings in
20Documentation/devicetree/bindings/power/power_domain.txt.
14 21
15Example 22
16------- 23Examples
24--------
25
26 - CPG device node:
17 27
18 cpg_clocks: cpg_clocks@ffc80000 { 28 cpg_clocks: cpg_clocks@ffc80000 {
19 compatible = "renesas,r8a7778-cpg-clocks"; 29 compatible = "renesas,r8a7778-cpg-clocks";
@@ -22,4 +32,17 @@ Example
22 clocks = <&extal_clk>; 32 clocks = <&extal_clk>;
23 clock-output-names = "plla", "pllb", "b", 33 clock-output-names = "plla", "pllb", "b",
24 "out", "p", "s", "s1"; 34 "out", "p", "s", "s1";
35 #power-domain-cells = <0>;
36 };
37
38
39 - CPG/MSTP Clock Domain member device node:
40
41 sdhi0: sd@ffe4c000 {
42 compatible = "renesas,sdhi-r8a7778";
43 reg = <0xffe4c000 0x100>;
44 interrupts = <0 87 IRQ_TYPE_LEVEL_HIGH>;
45 clocks = <&mstp3_clks R8A7778_CLK_SDHI0>;
46 power-domains = <&cpg_clocks>;
47 status = "disabled";
25 }; 48 };
diff --git a/Documentation/devicetree/bindings/clock/renesas,r8a7779-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,r8a7779-cpg-clocks.txt
index ed3c8cb12f4e..8c81547c29f5 100644
--- a/Documentation/devicetree/bindings/clock/renesas,r8a7779-cpg-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,r8a7779-cpg-clocks.txt
@@ -1,7 +1,9 @@
1* Renesas R8A7779 Clock Pulse Generator (CPG) 1* Renesas R8A7779 Clock Pulse Generator (CPG)
2 2
3The CPG generates core clocks for the R8A7779. It includes one PLL and 3The CPG generates core clocks for the R8A7779. It includes one PLL and
4several fixed ratio dividers 4several fixed ratio dividers.
5The CPG also provides a Clock Domain for SoC devices, in combination with the
6CPG Module Stop (MSTP) Clocks.
5 7
6Required Properties: 8Required Properties:
7 9
@@ -12,16 +14,36 @@ Required Properties:
12 - #clock-cells: Must be 1 14 - #clock-cells: Must be 1
13 - clock-output-names: The names of the clocks. Supported clocks are "plla", 15 - clock-output-names: The names of the clocks. Supported clocks are "plla",
14 "z", "zs", "s", "s1", "p", "b", "out". 16 "z", "zs", "s", "s1", "p", "b", "out".
17 - #power-domain-cells: Must be 0
15 18
19SoC devices that are part of the CPG/MSTP Clock Domain and can be power-managed
20through an MSTP clock should refer to the CPG device node in their
21"power-domains" property, as documented by the generic PM domain bindings in
22Documentation/devicetree/bindings/power/power_domain.txt.
16 23
17Example 24
18------- 25Examples
26--------
27
28 - CPG device node:
19 29
20 cpg_clocks: cpg_clocks@ffc80000 { 30 cpg_clocks: cpg_clocks@ffc80000 {
21 compatible = "renesas,r8a7779-cpg-clocks"; 31 compatible = "renesas,r8a7779-cpg-clocks";
22 reg = <0 0xffc80000 0 0x30>; 32 reg = <0xffc80000 0x30>;
23 clocks = <&extal_clk>; 33 clocks = <&extal_clk>;
24 #clock-cells = <1>; 34 #clock-cells = <1>;
25 clock-output-names = "plla", "z", "zs", "s", "s1", "p", 35 clock-output-names = "plla", "z", "zs", "s", "s1", "p",
26 "b", "out"; 36 "b", "out";
37 #power-domain-cells = <0>;
38 };
39
40
41 - CPG/MSTP Clock Domain member device node:
42
43 sata: sata@fc600000 {
44 compatible = "renesas,sata-r8a7779", "renesas,rcar-sata";
45 reg = <0xfc600000 0x2000>;
46 interrupts = <0 100 IRQ_TYPE_LEVEL_HIGH>;
47 clocks = <&mstp1_clks R8A7779_CLK_SATA>;
48 power-domains = <&cpg_clocks>;
27 }; 49 };
diff --git a/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt
index 56f111bd3e45..2a9a8edc8f35 100644
--- a/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,rcar-gen2-cpg-clocks.txt
@@ -2,6 +2,8 @@
2 2
3The CPG generates core clocks for the R-Car Gen2 SoCs. It includes three PLLs 3The CPG generates core clocks for the R-Car Gen2 SoCs. It includes three PLLs
4and several fixed ratio dividers. 4and several fixed ratio dividers.
5The CPG also provides a Clock Domain for SoC devices, in combination with the
6CPG Module Stop (MSTP) Clocks.
5 7
6Required Properties: 8Required Properties:
7 9
@@ -20,10 +22,18 @@ Required Properties:
20 - clock-output-names: The names of the clocks. Supported clocks are "main", 22 - clock-output-names: The names of the clocks. Supported clocks are "main",
21 "pll0", "pll1", "pll3", "lb", "qspi", "sdh", "sd0", "sd1", "z", "rcan", and 23 "pll0", "pll1", "pll3", "lb", "qspi", "sdh", "sd0", "sd1", "z", "rcan", and
22 "adsp" 24 "adsp"
25 - #power-domain-cells: Must be 0
23 26
27SoC devices that are part of the CPG/MSTP Clock Domain and can be power-managed
28through an MSTP clock should refer to the CPG device node in their
29"power-domains" property, as documented by the generic PM domain bindings in
30Documentation/devicetree/bindings/power/power_domain.txt.
24 31
25Example 32
26------- 33Examples
34--------
35
36 - CPG device node:
27 37
28 cpg_clocks: cpg_clocks@e6150000 { 38 cpg_clocks: cpg_clocks@e6150000 {
29 compatible = "renesas,r8a7790-cpg-clocks", 39 compatible = "renesas,r8a7790-cpg-clocks",
@@ -34,4 +44,16 @@ Example
34 clock-output-names = "main", "pll0, "pll1", "pll3", 44 clock-output-names = "main", "pll0, "pll1", "pll3",
35 "lb", "qspi", "sdh", "sd0", "sd1", "z", 45 "lb", "qspi", "sdh", "sd0", "sd1", "z",
36 "rcan", "adsp"; 46 "rcan", "adsp";
47 #power-domain-cells = <0>;
48 };
49
50
51 - CPG/MSTP Clock Domain member device node:
52
53 thermal@e61f0000 {
54 compatible = "renesas,thermal-r8a7790", "renesas,rcar-thermal";
55 reg = <0 0xe61f0000 0 0x14>, <0 0xe61f0100 0 0x38>;
56 interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
57 clocks = <&mstp5_clks R8A7790_CLK_THERMAL>;
58 power-domains = <&cpg_clocks>;
37 }; 59 };
diff --git a/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt b/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt
index b0f7ddb8cdb1..bb51a33a1fbf 100644
--- a/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt
+++ b/Documentation/devicetree/bindings/clock/renesas,rz-cpg-clocks.txt
@@ -2,6 +2,8 @@
2 2
3The CPG generates core clocks for the RZ SoCs. It includes the PLL, variable 3The CPG generates core clocks for the RZ SoCs. It includes the PLL, variable
4CPU and GPU clocks, and several fixed ratio dividers. 4CPU and GPU clocks, and several fixed ratio dividers.
5The CPG also provides a Clock Domain for SoC devices, in combination with the
6CPG Module Stop (MSTP) Clocks.
5 7
6Required Properties: 8Required Properties:
7 9
@@ -14,10 +16,18 @@ Required Properties:
14 - #clock-cells: Must be 1 16 - #clock-cells: Must be 1
15 - clock-output-names: The names of the clocks. Supported clocks are "pll", 17 - clock-output-names: The names of the clocks. Supported clocks are "pll",
16 "i", and "g" 18 "i", and "g"
19 - #power-domain-cells: Must be 0
17 20
21SoC devices that are part of the CPG/MSTP Clock Domain and can be power-managed
22through an MSTP clock should refer to the CPG device node in their
23"power-domains" property, as documented by the generic PM domain bindings in
24Documentation/devicetree/bindings/power/power_domain.txt.
18 25
19Example 26
20------- 27Examples
28--------
29
30 - CPG device node:
21 31
22 cpg_clocks: cpg_clocks@fcfe0000 { 32 cpg_clocks: cpg_clocks@fcfe0000 {
23 #clock-cells = <1>; 33 #clock-cells = <1>;
@@ -26,4 +36,19 @@ Example
26 reg = <0xfcfe0000 0x18>; 36 reg = <0xfcfe0000 0x18>;
27 clocks = <&extal_clk>, <&usb_x1_clk>; 37 clocks = <&extal_clk>, <&usb_x1_clk>;
28 clock-output-names = "pll", "i", "g"; 38 clock-output-names = "pll", "i", "g";
39 #power-domain-cells = <0>;
40 };
41
42
43 - CPG/MSTP Clock Domain member device node:
44
45 mtu2: timer@fcff0000 {
46 compatible = "renesas,mtu2-r7s72100", "renesas,mtu2";
47 reg = <0xfcff0000 0x400>;
48 interrupts = <0 107 IRQ_TYPE_LEVEL_HIGH>;
49 interrupt-names = "tgi0a";
50 clocks = <&mstp3_clks R7S72100_CLK_MTU2>;
51 clock-names = "fck";
52 power-domains = <&cpg_clocks>;
53 status = "disabled";
29 }; 54 };
diff --git a/Documentation/devicetree/bindings/cpufreq/tegra124-cpufreq.txt b/Documentation/devicetree/bindings/cpufreq/tegra124-cpufreq.txt
new file mode 100644
index 000000000000..b1669fbfb740
--- /dev/null
+++ b/Documentation/devicetree/bindings/cpufreq/tegra124-cpufreq.txt
@@ -0,0 +1,44 @@
1Tegra124 CPU frequency scaling driver bindings
2----------------------------------------------
3
4Both required and optional properties listed below must be defined
5under node /cpus/cpu@0.
6
7Required properties:
8- clocks: Must contain an entry for each entry in clock-names.
9 See ../clocks/clock-bindings.txt for details.
10- clock-names: Must include the following entries:
11 - cpu_g: Clock mux for the fast CPU cluster.
12 - cpu_lp: Clock mux for the low-power CPU cluster.
13 - pll_x: Fast PLL clocksource.
14 - pll_p: Auxiliary PLL used during fast PLL rate changes.
15 - dfll: Fast DFLL clocksource that also automatically scales CPU voltage.
16- vdd-cpu-supply: Regulator for CPU voltage
17
18Optional properties:
19- clock-latency: Specify the possible maximum transition latency for clock,
20 in unit of nanoseconds.
21
22Example:
23--------
24cpus {
25 #address-cells = <1>;
26 #size-cells = <0>;
27
28 cpu@0 {
29 device_type = "cpu";
30 compatible = "arm,cortex-a15";
31 reg = <0>;
32
33 clocks = <&tegra_car TEGRA124_CLK_CCLK_G>,
34 <&tegra_car TEGRA124_CLK_CCLK_LP>,
35 <&tegra_car TEGRA124_CLK_PLL_X>,
36 <&tegra_car TEGRA124_CLK_PLL_P>,
37 <&dfll>;
38 clock-names = "cpu_g", "cpu_lp", "pll_x", "pll_p", "dfll";
39 clock-latency = <300000>;
40 vdd-cpu-supply: <&vdd_cpu>;
41 };
42
43 <...>
44};
diff --git a/Documentation/devicetree/bindings/memory-controllers/arm,pl172.txt b/Documentation/devicetree/bindings/memory-controllers/arm,pl172.txt
new file mode 100644
index 000000000000..e6df32f9986d
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/arm,pl172.txt
@@ -0,0 +1,125 @@
1* Device tree bindings for ARM PL172 MultiPort Memory Controller
2
3Required properties:
4
5- compatible: "arm,pl172", "arm,primecell"
6
7- reg: Must contains offset/length value for controller.
8
9- #address-cells: Must be 2. The partition number has to be encoded in the
10 first address cell and it may accept values 0..N-1
11 (N - total number of partitions). The second cell is the
12 offset into the partition.
13
14- #size-cells: Must be set to 1.
15
16- ranges: Must contain one or more chip select memory regions.
17
18- clocks: Must contain references to controller clocks.
19
20- clock-names: Must contain "mpmcclk" and "apb_pclk".
21
22- clock-ranges: Empty property indicating that child nodes can inherit
23 named clocks. Required only if clock tree data present
24 in device tree.
25 See clock-bindings.txt
26
27Child chip-select (cs) nodes contain the memory devices nodes connected to
28such as NOR (e.g. cfi-flash) and NAND.
29
30Required child cs node properties:
31
32- #address-cells: Must be 2.
33
34- #size-cells: Must be 1.
35
36- ranges: Empty property indicating that child nodes can inherit
37 memory layout.
38
39- clock-ranges: Empty property indicating that child nodes can inherit
40 named clocks. Required only if clock tree data present
41 in device tree.
42
43- mpmc,cs: Chip select number. Indicates to the pl0172 driver
44 which chipselect is used for accessing the memory.
45
46- mpmc,memory-width: Width of the chip select memory. Must be equal to
47 either 8, 16 or 32.
48
49Optional child cs node config properties:
50
51- mpmc,async-page-mode: Enable asynchronous page mode.
52
53- mpmc,cs-active-high: Set chip select polarity to active high.
54
55- mpmc,byte-lane-low: Set byte lane state to low.
56
57- mpmc,extended-wait: Enable extended wait.
58
59- mpmc,buffer-enable: Enable write buffer.
60
61- mpmc,write-protect: Enable write protect.
62
63Optional child cs node timing properties:
64
65- mpmc,write-enable-delay: Delay from chip select assertion to write
66 enable (WE signal) in nano seconds.
67
68- mpmc,output-enable-delay: Delay from chip select assertion to output
69 enable (OE signal) in nano seconds.
70
71- mpmc,write-access-delay: Delay from chip select assertion to write
72 access in nano seconds.
73
74- mpmc,read-access-delay: Delay from chip select assertion to read
75 access in nano seconds.
76
77- mpmc,page-mode-read-delay: Delay for asynchronous page mode sequential
78 accesses in nano seconds.
79
80- mpmc,turn-round-delay: Delay between access to memory banks in nano
81 seconds.
82
83If any of the above timing parameters are absent, current parameter value will
84be taken from the corresponding HW reg.
85
86Example for pl172 with nor flash on chip select 0 shown below.
87
88emc: memory-controller@40005000 {
89 compatible = "arm,pl172", "arm,primecell";
90 reg = <0x40005000 0x1000>;
91 clocks = <&ccu1 CLK_CPU_EMCDIV>, <&ccu1 CLK_CPU_EMC>;
92 clock-names = "mpmcclk", "apb_pclk";
93 #address-cells = <2>;
94 #size-cells = <1>;
95 ranges = <0 0 0x1c000000 0x1000000
96 1 0 0x1d000000 0x1000000
97 2 0 0x1e000000 0x1000000
98 3 0 0x1f000000 0x1000000>;
99
100 cs0 {
101 #address-cells = <2>;
102 #size-cells = <1>;
103 ranges;
104
105 mpmc,cs = <0>;
106 mpmc,memory-width = <16>;
107 mpmc,byte-lane-low;
108 mpmc,write-enable-delay = <0>;
109 mpmc,output-enable-delay = <0>;
110 mpmc,read-enable-delay = <70>;
111 mpmc,page-mode-read-delay = <70>;
112
113 flash@0,0 {
114 compatible = "sst,sst39vf320", "cfi-flash";
115 reg = <0 0 0x400000>;
116 bank-width = <2>;
117 #address-cells = <1>;
118 #size-cells = <1>;
119 partition@0 {
120 label = "data";
121 reg = <0 0x400000>;
122 };
123 };
124 };
125};
diff --git a/Documentation/devicetree/bindings/reset/ath79-reset.txt b/Documentation/devicetree/bindings/reset/ath79-reset.txt
new file mode 100644
index 000000000000..4c56330bf398
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/ath79-reset.txt
@@ -0,0 +1,20 @@
1Binding for Qualcomm Atheros AR7xxx/AR9XXX reset controller
2
3Please also refer to reset.txt in this directory for common reset
4controller binding usage.
5
6Required Properties:
7- compatible: has to be "qca,<soctype>-reset", "qca,ar7100-reset"
8 as fallback
9- reg: Base address and size of the controllers memory area
10- #reset-cells : Specifies the number of cells needed to encode reset
11 line, should be 1
12
13Example:
14
15 reset-controller@1806001c {
16 compatible = "qca,ar9132-reset", "qca,ar7100-reset";
17 reg = <0x1806001c 0x4>;
18
19 #reset-cells = <1>;
20 };
diff --git a/Documentation/devicetree/bindings/reset/nxp,lpc1850-rgu.txt b/Documentation/devicetree/bindings/reset/nxp,lpc1850-rgu.txt
new file mode 100644
index 000000000000..b4e96a278445
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/nxp,lpc1850-rgu.txt
@@ -0,0 +1,84 @@
1NXP LPC1850 Reset Generation Unit (RGU)
2========================================
3
4Please also refer to reset.txt in this directory for common reset
5controller binding usage.
6
7Required properties:
8- compatible: Should be "nxp,lpc1850-rgu"
9- reg: register base and length
10- clocks: phandle and clock specifier to RGU clocks
11- clock-names: should contain "delay" and "reg"
12- #reset-cells: should be 1
13
14See table below for valid peripheral reset numbers. Numbers not
15in the table below are either reserved or not applicable for
16normal operation.
17
18Reset Peripheral
19 9 System control unit (SCU)
20 12 ARM Cortex-M0 subsystem core (LPC43xx only)
21 13 CPU core
22 16 LCD controller
23 17 USB0
24 18 USB1
25 19 DMA
26 20 SDIO
27 21 External memory controller (EMC)
28 22 Ethernet
29 25 Flash bank A
30 27 EEPROM
31 28 GPIO
32 29 Flash bank B
33 32 Timer0
34 33 Timer1
35 34 Timer2
36 35 Timer3
37 36 Repetitive Interrupt timer (RIT)
38 37 State Configurable Timer (SCT)
39 38 Motor control PWM (MCPWM)
40 39 QEI
41 40 ADC0
42 41 ADC1
43 42 DAC
44 44 USART0
45 45 UART1
46 46 USART2
47 47 USART3
48 48 I2C0
49 49 I2C1
50 50 SSP0
51 51 SSP1
52 52 I2S0 and I2S1
53 53 Serial Flash Interface (SPIFI)
54 54 C_CAN1
55 55 C_CAN0
56 56 ARM Cortex-M0 application core (LPC4370 only)
57 57 SGPIO (LPC43xx only)
58 58 SPI (LPC43xx only)
59 60 ADCHS (12-bit ADC) (LPC4370 only)
60
61Refer to NXP LPC18xx or LPC43xx user manual for more details about
62the reset signals and the connected block/peripheral.
63
64Reset provider example:
65rgu: reset-controller@40053000 {
66 compatible = "nxp,lpc1850-rgu";
67 reg = <0x40053000 0x1000>;
68 clocks = <&cgu BASE_SAFE_CLK>, <&ccu1 CLK_CPU_BUS>;
69 clock-names = "delay", "reg";
70 #reset-cells = <1>;
71};
72
73Reset consumer example:
74mac: ethernet@40010000 {
75 compatible = "nxp,lpc1850-dwmac", "snps,dwmac-3.611", "snps,dwmac";
76 reg = <0x40010000 0x2000>;
77 interrupts = <5>;
78 interrupt-names = "macirq";
79 clocks = <&ccu1 CLK_CPU_ETHERNET>;
80 clock-names = "stmmaceth";
81 resets = <&rgu 22>;
82 reset-names = "stmmaceth";
83 status = "disabled";
84};
diff --git a/Documentation/devicetree/bindings/reset/st,sti-picophyreset.txt b/Documentation/devicetree/bindings/reset/st,sti-picophyreset.txt
index 54ae9f747e45..9ca27761f811 100644
--- a/Documentation/devicetree/bindings/reset/st,sti-picophyreset.txt
+++ b/Documentation/devicetree/bindings/reset/st,sti-picophyreset.txt
@@ -39,4 +39,4 @@ Example:
39 }; 39 };
40 40
41Macro definitions for the supported reset channels can be found in: 41Macro definitions for the supported reset channels can be found in:
42include/dt-bindings/reset-controller/stih407-resets.h 42include/dt-bindings/reset/stih407-resets.h
diff --git a/Documentation/devicetree/bindings/reset/st,sti-powerdown.txt b/Documentation/devicetree/bindings/reset/st,sti-powerdown.txt
index 5ab26b7e9d35..1cfd21d1dfa1 100644
--- a/Documentation/devicetree/bindings/reset/st,sti-powerdown.txt
+++ b/Documentation/devicetree/bindings/reset/st,sti-powerdown.txt
@@ -43,5 +43,5 @@ example:
43 43
44Macro definitions for the supported reset channels can be found in: 44Macro definitions for the supported reset channels can be found in:
45 45
46include/dt-bindings/reset-controller/stih415-resets.h 46include/dt-bindings/reset/stih415-resets.h
47include/dt-bindings/reset-controller/stih416-resets.h 47include/dt-bindings/reset/stih416-resets.h
diff --git a/Documentation/devicetree/bindings/reset/st,sti-softreset.txt b/Documentation/devicetree/bindings/reset/st,sti-softreset.txt
index a8d3d3c25ca2..891a2fd85ed6 100644
--- a/Documentation/devicetree/bindings/reset/st,sti-softreset.txt
+++ b/Documentation/devicetree/bindings/reset/st,sti-softreset.txt
@@ -42,5 +42,5 @@ example:
42 42
43Macro definitions for the supported reset channels can be found in: 43Macro definitions for the supported reset channels can be found in:
44 44
45include/dt-bindings/reset-controller/stih415-resets.h 45include/dt-bindings/reset/stih415-resets.h
46include/dt-bindings/reset-controller/stih416-resets.h 46include/dt-bindings/reset/stih416-resets.h
diff --git a/Documentation/devicetree/bindings/reset/zynq-reset.txt b/Documentation/devicetree/bindings/reset/zynq-reset.txt
new file mode 100644
index 000000000000..5860120e3064
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/zynq-reset.txt
@@ -0,0 +1,68 @@
1Xilinx Zynq Reset Manager
2
3The Zynq AP-SoC has several different resets.
4
5See Chapter 26 of the Zynq TRM (UG585) for more information about Zynq resets.
6
7Required properties:
8- compatible: "xlnx,zynq-reset"
9- reg: SLCR offset and size taken via syscon <0x200 0x48>
10- syscon: <&slcr>
11 This should be a phandle to the Zynq's SLCR registers.
12- #reset-cells: Must be 1
13
14The Zynq Reset Manager needs to be a childnode of the SLCR.
15
16Example:
17 rstc: rstc@200 {
18 compatible = "xlnx,zynq-reset";
19 reg = <0x200 0x48>;
20 #reset-cells = <1>;
21 syscon = <&slcr>;
22 };
23
24Reset outputs:
25 0 : soft reset
26 32 : ddr reset
27 64 : topsw reset
28 96 : dmac reset
29 128: usb0 reset
30 129: usb1 reset
31 160: gem0 reset
32 161: gem1 reset
33 164: gem0 rx reset
34 165: gem1 rx reset
35 166: gem0 ref reset
36 167: gem1 ref reset
37 192: sdio0 reset
38 193: sdio1 reset
39 196: sdio0 ref reset
40 197: sdio1 ref reset
41 224: spi0 reset
42 225: spi1 reset
43 226: spi0 ref reset
44 227: spi1 ref reset
45 256: can0 reset
46 257: can1 reset
47 258: can0 ref reset
48 259: can1 ref reset
49 288: i2c0 reset
50 289: i2c1 reset
51 320: uart0 reset
52 321: uart1 reset
53 322: uart0 ref reset
54 323: uart1 ref reset
55 352: gpio reset
56 384: lqspi reset
57 385: qspi ref reset
58 416: smc reset
59 417: smc ref reset
60 448: ocm reset
61 512: fpga0 out reset
62 513: fpga1 out reset
63 514: fpga2 out reset
64 515: fpga3 out reset
65 544: a9 reset 0
66 545: a9 reset 1
67 552: peri reset
68
diff --git a/Documentation/devicetree/bindings/soc/qcom,smd-rpm.txt b/Documentation/devicetree/bindings/soc/qcom,smd-rpm.txt
new file mode 100644
index 000000000000..e27f5c4c54fd
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom,smd-rpm.txt
@@ -0,0 +1,117 @@
1Qualcomm Resource Power Manager (RPM) over SMD
2
3This driver is used to interface with the Resource Power Manager (RPM) found in
4various Qualcomm platforms. The RPM allows each component in the system to vote
5for state of the system resources, such as clocks, regulators and bus
6frequencies.
7
8- compatible:
9 Usage: required
10 Value type: <string>
11 Definition: must be one of:
12 "qcom,rpm-msm8974"
13
14- qcom,smd-channels:
15 Usage: required
16 Value type: <stringlist>
17 Definition: Shared Memory channel used for communication with the RPM
18
19= SUBDEVICES
20
21The RPM exposes resources to its subnodes. The below bindings specify the set
22of valid subnodes that can operate on these resources.
23
24== Regulators
25
26Regulator nodes are identified by their compatible:
27
28- compatible:
29 Usage: required
30 Value type: <string>
31 Definition: must be one of:
32 "qcom,rpm-pm8841-regulators"
33 "qcom,rpm-pm8941-regulators"
34
35- vdd_s1-supply:
36- vdd_s2-supply:
37- vdd_s3-supply:
38- vdd_s4-supply:
39- vdd_s5-supply:
40- vdd_s6-supply:
41- vdd_s7-supply:
42- vdd_s8-supply:
43 Usage: optional (pm8841 only)
44 Value type: <phandle>
45 Definition: reference to regulator supplying the input pin, as
46 described in the data sheet
47
48- vdd_s1-supply:
49- vdd_s2-supply:
50- vdd_s3-supply:
51- vdd_l1_l3-supply:
52- vdd_l2_lvs1_2_3-supply:
53- vdd_l4_l11-supply:
54- vdd_l5_l7-supply:
55- vdd_l6_l12_l14_l15-supply:
56- vdd_l8_l16_l18_l19-supply:
57- vdd_l9_l10_l17_l22-supply:
58- vdd_l13_l20_l23_l24-supply:
59- vdd_l21-supply:
60- vin_5vs-supply:
61 Usage: optional (pm8941 only)
62 Value type: <phandle>
63 Definition: reference to regulator supplying the input pin, as
64 described in the data sheet
65
66The regulator node houses sub-nodes for each regulator within the device. Each
67sub-node is identified using the node's name, with valid values listed for each
68of the pmics below.
69
70pm8841:
71 s1, s2, s3, s4, s5, s6, s7, s8
72
73pm8941:
74 s1, s2, s3, s4, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11, l12, l13,
75 l14, l15, l16, l17, l18, l19, l20, l21, l22, l23, l24, lvs1, lvs2,
76 lvs3, 5vs1, 5vs2
77
78The content of each sub-node is defined by the standard binding for regulators -
79see regulator.txt.
80
81= EXAMPLE
82
83 smd {
84 compatible = "qcom,smd";
85
86 rpm {
87 interrupts = <0 168 1>;
88 qcom,ipc = <&apcs 8 0>;
89 qcom,smd-edge = <15>;
90
91 rpm_requests {
92 compatible = "qcom,rpm-msm8974";
93 qcom,smd-channels = "rpm_requests";
94
95 pm8941-regulators {
96 compatible = "qcom,rpm-pm8941-regulators";
97 vdd_l13_l20_l23_l24-supply = <&pm8941_boost>;
98
99 pm8941_s3: s3 {
100 regulator-min-microvolt = <1800000>;
101 regulator-max-microvolt = <1800000>;
102 };
103
104 pm8941_boost: s4 {
105 regulator-min-microvolt = <5000000>;
106 regulator-max-microvolt = <5000000>;
107 };
108
109 pm8941_l20: l20 {
110 regulator-min-microvolt = <2950000>;
111 regulator-max-microvolt = <2950000>;
112 };
113 };
114 };
115 };
116 };
117
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt
new file mode 100644
index 000000000000..f65c76db9859
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smd.txt
@@ -0,0 +1,79 @@
1Qualcomm Shared Memory Driver (SMD) binding
2
3This binding describes the Qualcomm Shared Memory Driver, a fifo based
4communication channel for sending data between the various subsystems in
5Qualcomm platforms.
6
7- compatible:
8 Usage: required
9 Value type: <stringlist>
10 Definition: must be "qcom,smd"
11
12= EDGES
13
14Each subnode of the SMD node represents a remote subsystem or a remote
15processor of some sort - or in SMD language an "edge". The name of the edges
16are not important.
17The edge is described by the following properties:
18
19- interrupts:
20 Usage: required
21 Value type: <prop-encoded-array>
22 Definition: should specify the IRQ used by the remote processor to
23 signal this processor about communication related updates
24
25- qcom,ipc:
26 Usage: required
27 Value type: <prop-encoded-array>
28 Definition: three entries specifying the outgoing ipc bit used for
29 signaling the remote processor:
30 - phandle to a syscon node representing the apcs registers
31 - u32 representing offset to the register within the syscon
32 - u32 representing the ipc bit within the register
33
34- qcom,smd-edge:
35 Usage: required
36 Value type: <u32>
37 Definition: the identifier of the remote processor in the smd channel
38 allocation table
39
40= SMD DEVICES
41
42In turn, subnodes of the "edges" represent devices tied to SMD channels on that
43"edge". The names of the devices are not important. The properties of these
44nodes are defined by the individual bindings for the SMD devices - but must
45contain the following property:
46
47- qcom,smd-channels:
48 Usage: required
49 Value type: <stringlist>
50 Definition: a list of channels tied to this device, used for matching
51 the device to channels
52
53= EXAMPLE
54
55The following example represents a smd node, with one edge representing the
56"rpm" subsystem. For the "rpm" subsystem we have a device tied to the
57"rpm_request" channel.
58
59 apcs: syscon@f9011000 {
60 compatible = "syscon";
61 reg = <0xf9011000 0x1000>;
62 };
63
64 smd {
65 compatible = "qcom,smd";
66
67 rpm {
68 interrupts = <0 168 1>;
69 qcom,ipc = <&apcs 8 0>;
70 qcom,smd-edge = <15>;
71
72 rpm_requests {
73 compatible = "qcom,rpm-msm8974";
74 qcom,smd-channels = "rpm_requests";
75
76 ...
77 };
78 };
79 };
diff --git a/MAINTAINERS b/MAINTAINERS
index b772b8502e66..248b46b223b6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8613,6 +8613,7 @@ M: Philipp Zabel <p.zabel@pengutronix.de>
8613S: Maintained 8613S: Maintained
8614F: drivers/reset/ 8614F: drivers/reset/
8615F: Documentation/devicetree/bindings/reset/ 8615F: Documentation/devicetree/bindings/reset/
8616F: include/dt-bindings/reset/
8616F: include/linux/reset.h 8617F: include/linux/reset.h
8617F: include/linux/reset-controller.h 8618F: include/linux/reset-controller.h
8618 8619
diff --git a/arch/arm/boot/dts/stih407-family.dtsi b/arch/arm/boot/dts/stih407-family.dtsi
index 838b812cbda1..eab3477e0a0e 100644
--- a/arch/arm/boot/dts/stih407-family.dtsi
+++ b/arch/arm/boot/dts/stih407-family.dtsi
@@ -9,7 +9,7 @@
9#include "stih407-pinctrl.dtsi" 9#include "stih407-pinctrl.dtsi"
10#include <dt-bindings/mfd/st-lpc.h> 10#include <dt-bindings/mfd/st-lpc.h>
11#include <dt-bindings/phy/phy.h> 11#include <dt-bindings/phy/phy.h>
12#include <dt-bindings/reset-controller/stih407-resets.h> 12#include <dt-bindings/reset/stih407-resets.h>
13#include <dt-bindings/interrupt-controller/irq-st.h> 13#include <dt-bindings/interrupt-controller/irq-st.h>
14/ { 14/ {
15 #address-cells = <1>; 15 #address-cells = <1>;
diff --git a/arch/arm/boot/dts/stih415.dtsi b/arch/arm/boot/dts/stih415.dtsi
index 19b019b5f30e..12427e651e5e 100644
--- a/arch/arm/boot/dts/stih415.dtsi
+++ b/arch/arm/boot/dts/stih415.dtsi
@@ -10,7 +10,7 @@
10#include "stih415-clock.dtsi" 10#include "stih415-clock.dtsi"
11#include "stih415-pinctrl.dtsi" 11#include "stih415-pinctrl.dtsi"
12#include <dt-bindings/interrupt-controller/arm-gic.h> 12#include <dt-bindings/interrupt-controller/arm-gic.h>
13#include <dt-bindings/reset-controller/stih415-resets.h> 13#include <dt-bindings/reset/stih415-resets.h>
14/ { 14/ {
15 15
16 L2: cache-controller { 16 L2: cache-controller {
diff --git a/arch/arm/boot/dts/stih416.dtsi b/arch/arm/boot/dts/stih416.dtsi
index 9dca173e694a..9e3170ccd18c 100644
--- a/arch/arm/boot/dts/stih416.dtsi
+++ b/arch/arm/boot/dts/stih416.dtsi
@@ -12,7 +12,7 @@
12 12
13#include <dt-bindings/phy/phy.h> 13#include <dt-bindings/phy/phy.h>
14#include <dt-bindings/interrupt-controller/arm-gic.h> 14#include <dt-bindings/interrupt-controller/arm-gic.h>
15#include <dt-bindings/reset-controller/stih416-resets.h> 15#include <dt-bindings/reset/stih416-resets.h>
16#include <dt-bindings/interrupt-controller/irq-st.h> 16#include <dt-bindings/interrupt-controller/irq-st.h>
17/ { 17/ {
18 L2: cache-controller { 18 L2: cache-controller {
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 97473168d6b6..c86a5a0aefac 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -96,6 +96,7 @@ config MACH_DOVE
96 select MACH_MVEBU_ANY 96 select MACH_MVEBU_ANY
97 select ORION_IRQCHIP 97 select ORION_IRQCHIP
98 select ORION_TIMER 98 select ORION_TIMER
99 select PM_GENERIC_DOMAINS if PM
99 select PINCTRL_DOVE 100 select PINCTRL_DOVE
100 help 101 help
101 Say 'Y' here if you want your kernel to support the 102 Say 'Y' here if you want your kernel to support the
diff --git a/arch/arm/mach-mvebu/dove.c b/arch/arm/mach-mvebu/dove.c
index 5a1741500a30..1aebb82e3d7b 100644
--- a/arch/arm/mach-mvebu/dove.c
+++ b/arch/arm/mach-mvebu/dove.c
@@ -12,6 +12,7 @@
12#include <linux/mbus.h> 12#include <linux/mbus.h>
13#include <linux/of.h> 13#include <linux/of.h>
14#include <linux/of_platform.h> 14#include <linux/of_platform.h>
15#include <linux/soc/dove/pmu.h>
15#include <asm/hardware/cache-tauros2.h> 16#include <asm/hardware/cache-tauros2.h>
16#include <asm/mach/arch.h> 17#include <asm/mach/arch.h>
17#include "common.h" 18#include "common.h"
@@ -24,6 +25,7 @@ static void __init dove_init(void)
24 tauros2_init(0); 25 tauros2_init(0);
25#endif 26#endif
26 BUG_ON(mvebu_mbus_dt_init(false)); 27 BUG_ON(mvebu_mbus_dt_init(false));
28 dove_init_pmu();
27 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); 29 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
28} 30}
29 31
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index aa38a438af89..926e336d6aeb 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -4,6 +4,7 @@ config ARCH_SHMOBILE
4 4
5config PM_RCAR 5config PM_RCAR
6 bool 6 bool
7 select PM_GENERIC_DOMAINS if PM
7 8
8config PM_RMOBILE 9config PM_RMOBILE
9 bool 10 bool
@@ -50,6 +51,7 @@ config ARCH_EMEV2
50 51
51config ARCH_R7S72100 52config ARCH_R7S72100
52 bool "RZ/A1H (R7S72100)" 53 bool "RZ/A1H (R7S72100)"
54 select PM_GENERIC_DOMAINS if PM
53 select SYS_SUPPORTS_SH_MTU2 55 select SYS_SUPPORTS_SH_MTU2
54 56
55config ARCH_R8A73A4 57config ARCH_R8A73A4
diff --git a/arch/arm/mach-tegra/cpuidle-tegra114.c b/arch/arm/mach-tegra/cpuidle-tegra114.c
index 155807fa6fdd..9157546fe68c 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra114.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra114.c
@@ -24,6 +24,7 @@
24#include <asm/cpuidle.h> 24#include <asm/cpuidle.h>
25#include <asm/smp_plat.h> 25#include <asm/smp_plat.h>
26#include <asm/suspend.h> 26#include <asm/suspend.h>
27#include <asm/psci.h>
27 28
28#include "pm.h" 29#include "pm.h"
29#include "sleep.h" 30#include "sleep.h"
@@ -44,16 +45,12 @@ static int tegra114_idle_power_down(struct cpuidle_device *dev,
44 tegra_set_cpu_in_lp2(); 45 tegra_set_cpu_in_lp2();
45 cpu_pm_enter(); 46 cpu_pm_enter();
46 47
47 tick_broadcast_enter();
48
49 call_firmware_op(prepare_idle); 48 call_firmware_op(prepare_idle);
50 49
51 /* Do suspend by ourselves if the firmware does not implement it */ 50 /* Do suspend by ourselves if the firmware does not implement it */
52 if (call_firmware_op(do_idle, 0) == -ENOSYS) 51 if (call_firmware_op(do_idle, 0) == -ENOSYS)
53 cpu_suspend(0, tegra30_sleep_cpu_secondary_finish); 52 cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
54 53
55 tick_broadcast_exit();
56
57 cpu_pm_exit(); 54 cpu_pm_exit();
58 tegra_clear_cpu_in_lp2(); 55 tegra_clear_cpu_in_lp2();
59 56
@@ -61,6 +58,13 @@ static int tegra114_idle_power_down(struct cpuidle_device *dev,
61 58
62 return index; 59 return index;
63} 60}
61
62static void tegra114_idle_enter_freeze(struct cpuidle_device *dev,
63 struct cpuidle_driver *drv,
64 int index)
65{
66 tegra114_idle_power_down(dev, drv, index);
67}
64#endif 68#endif
65 69
66static struct cpuidle_driver tegra_idle_driver = { 70static struct cpuidle_driver tegra_idle_driver = {
@@ -72,8 +76,10 @@ static struct cpuidle_driver tegra_idle_driver = {
72#ifdef CONFIG_PM_SLEEP 76#ifdef CONFIG_PM_SLEEP
73 [1] = { 77 [1] = {
74 .enter = tegra114_idle_power_down, 78 .enter = tegra114_idle_power_down,
79 .enter_freeze = tegra114_idle_enter_freeze,
75 .exit_latency = 500, 80 .exit_latency = 500,
76 .target_residency = 1000, 81 .target_residency = 1000,
82 .flags = CPUIDLE_FLAG_TIMER_STOP,
77 .power_usage = 0, 83 .power_usage = 0,
78 .name = "powered-down", 84 .name = "powered-down",
79 .desc = "CPU power gated", 85 .desc = "CPU power gated",
@@ -84,5 +90,8 @@ static struct cpuidle_driver tegra_idle_driver = {
84 90
85int __init tegra114_cpuidle_init(void) 91int __init tegra114_cpuidle_init(void)
86{ 92{
87 return cpuidle_register(&tegra_idle_driver, NULL); 93 if (!psci_smp_available())
94 return cpuidle_register(&tegra_idle_driver, NULL);
95
96 return 0;
88} 97}
diff --git a/arch/arm/mach-tegra/iomap.h b/arch/arm/mach-tegra/iomap.h
index 81dc950b4881..9e5b2f869fc8 100644
--- a/arch/arm/mach-tegra/iomap.h
+++ b/arch/arm/mach-tegra/iomap.h
@@ -82,9 +82,6 @@
82#define TEGRA_EMC_BASE 0x7000F400 82#define TEGRA_EMC_BASE 0x7000F400
83#define TEGRA_EMC_SIZE SZ_1K 83#define TEGRA_EMC_SIZE SZ_1K
84 84
85#define TEGRA_FUSE_BASE 0x7000F800
86#define TEGRA_FUSE_SIZE SZ_1K
87
88#define TEGRA_EMC0_BASE 0x7001A000 85#define TEGRA_EMC0_BASE 0x7001A000
89#define TEGRA_EMC0_SIZE SZ_2K 86#define TEGRA_EMC0_SIZE SZ_2K
90 87
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 199a8357838c..c6d28bce0b40 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -118,6 +118,7 @@ config ATH25
118 118
119config ATH79 119config ATH79
120 bool "Atheros AR71XX/AR724X/AR913X based boards" 120 bool "Atheros AR71XX/AR724X/AR913X based boards"
121 select ARCH_HAS_RESET_CONTROLLER
121 select ARCH_REQUIRE_GPIOLIB 122 select ARCH_REQUIRE_GPIOLIB
122 select BOOT_RAW 123 select BOOT_RAW
123 select CEVT_R4K 124 select CEVT_R4K
diff --git a/arch/mips/boot/dts/qca/ar9132.dtsi b/arch/mips/boot/dts/qca/ar9132.dtsi
index 4759cff814d1..fb7734eadbf0 100644
--- a/arch/mips/boot/dts/qca/ar9132.dtsi
+++ b/arch/mips/boot/dts/qca/ar9132.dtsi
@@ -115,6 +115,14 @@
115 interrupt-controller; 115 interrupt-controller;
116 #interrupt-cells = <1>; 116 #interrupt-cells = <1>;
117 }; 117 };
118
119 rst: reset-controller@1806001c {
120 compatible = "qca,ar9132-reset",
121 "qca,ar7100-reset";
122 reg = <0x1806001c 0x4>;
123
124 #reset-cells = <1>;
125 };
118 }; 126 };
119 127
120 spi@1f000000 { 128 spi@1f000000 {
diff --git a/drivers/clk/shmobile/clk-mstp.c b/drivers/clk/shmobile/clk-mstp.c
index 2d2fe773ac81..b1df7b2f1e97 100644
--- a/drivers/clk/shmobile/clk-mstp.c
+++ b/drivers/clk/shmobile/clk-mstp.c
@@ -2,6 +2,7 @@
2 * R-Car MSTP clocks 2 * R-Car MSTP clocks
3 * 3 *
4 * Copyright (C) 2013 Ideas On Board SPRL 4 * Copyright (C) 2013 Ideas On Board SPRL
5 * Copyright (C) 2015 Glider bvba
5 * 6 *
6 * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com> 7 * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
7 * 8 *
@@ -10,11 +11,16 @@
10 * the Free Software Foundation; version 2 of the License. 11 * the Free Software Foundation; version 2 of the License.
11 */ 12 */
12 13
14#include <linux/clk.h>
13#include <linux/clk-provider.h> 15#include <linux/clk-provider.h>
14#include <linux/clkdev.h> 16#include <linux/clkdev.h>
17#include <linux/clk/shmobile.h>
18#include <linux/device.h>
15#include <linux/io.h> 19#include <linux/io.h>
16#include <linux/of.h> 20#include <linux/of.h>
17#include <linux/of_address.h> 21#include <linux/of_address.h>
22#include <linux/pm_clock.h>
23#include <linux/pm_domain.h>
18#include <linux/spinlock.h> 24#include <linux/spinlock.h>
19 25
20/* 26/*
@@ -236,3 +242,84 @@ static void __init cpg_mstp_clocks_init(struct device_node *np)
236 of_clk_add_provider(np, of_clk_src_onecell_get, &group->data); 242 of_clk_add_provider(np, of_clk_src_onecell_get, &group->data);
237} 243}
238CLK_OF_DECLARE(cpg_mstp_clks, "renesas,cpg-mstp-clocks", cpg_mstp_clocks_init); 244CLK_OF_DECLARE(cpg_mstp_clks, "renesas,cpg-mstp-clocks", cpg_mstp_clocks_init);
245
246
247#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
248int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev)
249{
250 struct device_node *np = dev->of_node;
251 struct of_phandle_args clkspec;
252 struct clk *clk;
253 int i = 0;
254 int error;
255
256 while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
257 &clkspec)) {
258 if (of_device_is_compatible(clkspec.np,
259 "renesas,cpg-mstp-clocks"))
260 goto found;
261
262 of_node_put(clkspec.np);
263 i++;
264 }
265
266 return 0;
267
268found:
269 clk = of_clk_get_from_provider(&clkspec);
270 of_node_put(clkspec.np);
271
272 if (IS_ERR(clk))
273 return PTR_ERR(clk);
274
275 error = pm_clk_create(dev);
276 if (error) {
277 dev_err(dev, "pm_clk_create failed %d\n", error);
278 goto fail_put;
279 }
280
281 error = pm_clk_add_clk(dev, clk);
282 if (error) {
283 dev_err(dev, "pm_clk_add_clk %pC failed %d\n", clk, error);
284 goto fail_destroy;
285 }
286
287 return 0;
288
289fail_destroy:
290 pm_clk_destroy(dev);
291fail_put:
292 clk_put(clk);
293 return error;
294}
295
296void cpg_mstp_detach_dev(struct generic_pm_domain *domain, struct device *dev)
297{
298 if (!list_empty(&dev->power.subsys_data->clock_list))
299 pm_clk_destroy(dev);
300}
301
302void __init cpg_mstp_add_clk_domain(struct device_node *np)
303{
304 struct generic_pm_domain *pd;
305 u32 ncells;
306
307 if (of_property_read_u32(np, "#power-domain-cells", &ncells)) {
308 pr_warn("%s lacks #power-domain-cells\n", np->full_name);
309 return;
310 }
311
312 pd = kzalloc(sizeof(*pd), GFP_KERNEL);
313 if (!pd)
314 return;
315
316 pd->name = np->name;
317
318 pd->flags = GENPD_FLAG_PM_CLK;
319 pm_genpd_init(pd, &simple_qos_governor, false);
320 pd->attach_dev = cpg_mstp_attach_dev;
321 pd->detach_dev = cpg_mstp_detach_dev;
322
323 of_genpd_add_provider_simple(np, pd);
324}
325#endif /* !CONFIG_PM_GENERIC_DOMAINS_OF */
diff --git a/drivers/clk/shmobile/clk-r8a7778.c b/drivers/clk/shmobile/clk-r8a7778.c
index e97e28fcfc13..87c1d2f2fb57 100644
--- a/drivers/clk/shmobile/clk-r8a7778.c
+++ b/drivers/clk/shmobile/clk-r8a7778.c
@@ -124,6 +124,8 @@ static void __init r8a7778_cpg_clocks_init(struct device_node *np)
124 } 124 }
125 125
126 of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); 126 of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data);
127
128 cpg_mstp_add_clk_domain(np);
127} 129}
128 130
129CLK_OF_DECLARE(r8a7778_cpg_clks, "renesas,r8a7778-cpg-clocks", 131CLK_OF_DECLARE(r8a7778_cpg_clks, "renesas,r8a7778-cpg-clocks",
diff --git a/drivers/clk/shmobile/clk-r8a7779.c b/drivers/clk/shmobile/clk-r8a7779.c
index af297963489f..92275c5f2c60 100644
--- a/drivers/clk/shmobile/clk-r8a7779.c
+++ b/drivers/clk/shmobile/clk-r8a7779.c
@@ -168,6 +168,8 @@ static void __init r8a7779_cpg_clocks_init(struct device_node *np)
168 } 168 }
169 169
170 of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); 170 of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data);
171
172 cpg_mstp_add_clk_domain(np);
171} 173}
172CLK_OF_DECLARE(r8a7779_cpg_clks, "renesas,r8a7779-cpg-clocks", 174CLK_OF_DECLARE(r8a7779_cpg_clks, "renesas,r8a7779-cpg-clocks",
173 r8a7779_cpg_clocks_init); 175 r8a7779_cpg_clocks_init);
diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c
index 9233ebf8cc49..745496f7ee9c 100644
--- a/drivers/clk/shmobile/clk-rcar-gen2.c
+++ b/drivers/clk/shmobile/clk-rcar-gen2.c
@@ -415,6 +415,8 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np)
415 } 415 }
416 416
417 of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); 417 of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data);
418
419 cpg_mstp_add_clk_domain(np);
418} 420}
419CLK_OF_DECLARE(rcar_gen2_cpg_clks, "renesas,rcar-gen2-cpg-clocks", 421CLK_OF_DECLARE(rcar_gen2_cpg_clks, "renesas,rcar-gen2-cpg-clocks",
420 rcar_gen2_cpg_clocks_init); 422 rcar_gen2_cpg_clocks_init);
diff --git a/drivers/clk/shmobile/clk-rz.c b/drivers/clk/shmobile/clk-rz.c
index 7e68e8630962..9766e3cb595f 100644
--- a/drivers/clk/shmobile/clk-rz.c
+++ b/drivers/clk/shmobile/clk-rz.c
@@ -10,6 +10,7 @@
10 */ 10 */
11 11
12#include <linux/clk-provider.h> 12#include <linux/clk-provider.h>
13#include <linux/clk/shmobile.h>
13#include <linux/init.h> 14#include <linux/init.h>
14#include <linux/kernel.h> 15#include <linux/kernel.h>
15#include <linux/of.h> 16#include <linux/of.h>
@@ -99,5 +100,7 @@ static void __init rz_cpg_clocks_init(struct device_node *np)
99 } 100 }
100 101
101 of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data); 102 of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data);
103
104 cpg_mstp_add_clk_domain(np);
102} 105}
103CLK_OF_DECLARE(rz_cpg_clks, "renesas,rz-cpg-clocks", rz_cpg_clocks_init); 106CLK_OF_DECLARE(rz_cpg_clks, "renesas,rz-cpg-clocks", rz_cpg_clocks_init);
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index cc8a71c267b8..24e5c664683f 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -247,12 +247,19 @@ config ARM_SPEAR_CPUFREQ
247 help 247 help
248 This adds the CPUFreq driver support for SPEAr SOCs. 248 This adds the CPUFreq driver support for SPEAr SOCs.
249 249
250config ARM_TEGRA_CPUFREQ 250config ARM_TEGRA20_CPUFREQ
251 bool "TEGRA CPUFreq support" 251 bool "Tegra20 CPUFreq support"
252 depends on ARCH_TEGRA 252 depends on ARCH_TEGRA
253 default y 253 default y
254 help 254 help
255 This adds the CPUFreq driver support for TEGRA SOCs. 255 This adds the CPUFreq driver support for Tegra20 SOCs.
256
257config ARM_TEGRA124_CPUFREQ
258 tristate "Tegra124 CPUFreq support"
259 depends on ARCH_TEGRA && CPUFREQ_DT
260 default y
261 help
262 This adds the CPUFreq driver support for Tegra124 SOCs.
256 263
257config ARM_PXA2xx_CPUFREQ 264config ARM_PXA2xx_CPUFREQ
258 tristate "Intel PXA2xx CPUfreq driver" 265 tristate "Intel PXA2xx CPUfreq driver"
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 2169bf792db7..032745de8fcc 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -76,7 +76,8 @@ obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
76obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o 76obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o
77obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o 77obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o
78obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o 78obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o
79obj-$(CONFIG_ARM_TEGRA_CPUFREQ) += tegra-cpufreq.o 79obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o
80obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o
80obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o 81obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
81 82
82################################################################################## 83##################################################################################
diff --git a/drivers/cpufreq/tegra124-cpufreq.c b/drivers/cpufreq/tegra124-cpufreq.c
new file mode 100644
index 000000000000..20bcceb58ccc
--- /dev/null
+++ b/drivers/cpufreq/tegra124-cpufreq.c
@@ -0,0 +1,214 @@
1/*
2 * Tegra 124 cpufreq driver
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
15
16#include <linux/clk.h>
17#include <linux/cpufreq-dt.h>
18#include <linux/err.h>
19#include <linux/init.h>
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/of_device.h>
23#include <linux/of.h>
24#include <linux/platform_device.h>
25#include <linux/pm_opp.h>
26#include <linux/regulator/consumer.h>
27#include <linux/types.h>
28
29struct tegra124_cpufreq_priv {
30 struct regulator *vdd_cpu_reg;
31 struct clk *cpu_clk;
32 struct clk *pllp_clk;
33 struct clk *pllx_clk;
34 struct clk *dfll_clk;
35 struct platform_device *cpufreq_dt_pdev;
36};
37
38static int tegra124_cpu_switch_to_dfll(struct tegra124_cpufreq_priv *priv)
39{
40 struct clk *orig_parent;
41 int ret;
42
43 ret = clk_set_rate(priv->dfll_clk, clk_get_rate(priv->cpu_clk));
44 if (ret)
45 return ret;
46
47 orig_parent = clk_get_parent(priv->cpu_clk);
48 clk_set_parent(priv->cpu_clk, priv->pllp_clk);
49
50 ret = clk_prepare_enable(priv->dfll_clk);
51 if (ret)
52 goto out;
53
54 clk_set_parent(priv->cpu_clk, priv->dfll_clk);
55
56 return 0;
57
58out:
59 clk_set_parent(priv->cpu_clk, orig_parent);
60
61 return ret;
62}
63
64static void tegra124_cpu_switch_to_pllx(struct tegra124_cpufreq_priv *priv)
65{
66 clk_set_parent(priv->cpu_clk, priv->pllp_clk);
67 clk_disable_unprepare(priv->dfll_clk);
68 regulator_sync_voltage(priv->vdd_cpu_reg);
69 clk_set_parent(priv->cpu_clk, priv->pllx_clk);
70}
71
72static struct cpufreq_dt_platform_data cpufreq_dt_pd = {
73 .independent_clocks = false,
74};
75
76static int tegra124_cpufreq_probe(struct platform_device *pdev)
77{
78 struct tegra124_cpufreq_priv *priv;
79 struct device_node *np;
80 struct device *cpu_dev;
81 struct platform_device_info cpufreq_dt_devinfo = {};
82 int ret;
83
84 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
85 if (!priv)
86 return -ENOMEM;
87
88 cpu_dev = get_cpu_device(0);
89 if (!cpu_dev)
90 return -ENODEV;
91
92 np = of_cpu_device_node_get(0);
93 if (!np)
94 return -ENODEV;
95
96 priv->vdd_cpu_reg = regulator_get(cpu_dev, "vdd-cpu");
97 if (IS_ERR(priv->vdd_cpu_reg)) {
98 ret = PTR_ERR(priv->vdd_cpu_reg);
99 goto out_put_np;
100 }
101
102 priv->cpu_clk = of_clk_get_by_name(np, "cpu_g");
103 if (IS_ERR(priv->cpu_clk)) {
104 ret = PTR_ERR(priv->cpu_clk);
105 goto out_put_vdd_cpu_reg;
106 }
107
108 priv->dfll_clk = of_clk_get_by_name(np, "dfll");
109 if (IS_ERR(priv->dfll_clk)) {
110 ret = PTR_ERR(priv->dfll_clk);
111 goto out_put_cpu_clk;
112 }
113
114 priv->pllx_clk = of_clk_get_by_name(np, "pll_x");
115 if (IS_ERR(priv->pllx_clk)) {
116 ret = PTR_ERR(priv->pllx_clk);
117 goto out_put_dfll_clk;
118 }
119
120 priv->pllp_clk = of_clk_get_by_name(np, "pll_p");
121 if (IS_ERR(priv->pllp_clk)) {
122 ret = PTR_ERR(priv->pllp_clk);
123 goto out_put_pllx_clk;
124 }
125
126 ret = tegra124_cpu_switch_to_dfll(priv);
127 if (ret)
128 goto out_put_pllp_clk;
129
130 cpufreq_dt_devinfo.name = "cpufreq-dt";
131 cpufreq_dt_devinfo.parent = &pdev->dev;
132 cpufreq_dt_devinfo.data = &cpufreq_dt_pd;
133 cpufreq_dt_devinfo.size_data = sizeof(cpufreq_dt_pd);
134
135 priv->cpufreq_dt_pdev =
136 platform_device_register_full(&cpufreq_dt_devinfo);
137 if (IS_ERR(priv->cpufreq_dt_pdev)) {
138 ret = PTR_ERR(priv->cpufreq_dt_pdev);
139 goto out_switch_to_pllx;
140 }
141
142 platform_set_drvdata(pdev, priv);
143
144 return 0;
145
146out_switch_to_pllx:
147 tegra124_cpu_switch_to_pllx(priv);
148out_put_pllp_clk:
149 clk_put(priv->pllp_clk);
150out_put_pllx_clk:
151 clk_put(priv->pllx_clk);
152out_put_dfll_clk:
153 clk_put(priv->dfll_clk);
154out_put_cpu_clk:
155 clk_put(priv->cpu_clk);
156out_put_vdd_cpu_reg:
157 regulator_put(priv->vdd_cpu_reg);
158out_put_np:
159 of_node_put(np);
160
161 return ret;
162}
163
164static int tegra124_cpufreq_remove(struct platform_device *pdev)
165{
166 struct tegra124_cpufreq_priv *priv = platform_get_drvdata(pdev);
167
168 platform_device_unregister(priv->cpufreq_dt_pdev);
169 tegra124_cpu_switch_to_pllx(priv);
170
171 clk_put(priv->pllp_clk);
172 clk_put(priv->pllx_clk);
173 clk_put(priv->dfll_clk);
174 clk_put(priv->cpu_clk);
175 regulator_put(priv->vdd_cpu_reg);
176
177 return 0;
178}
179
180static struct platform_driver tegra124_cpufreq_platdrv = {
181 .driver.name = "cpufreq-tegra124",
182 .probe = tegra124_cpufreq_probe,
183 .remove = tegra124_cpufreq_remove,
184};
185
186static int __init tegra_cpufreq_init(void)
187{
188 int ret;
189 struct platform_device *pdev;
190
191 if (!of_machine_is_compatible("nvidia,tegra124"))
192 return -ENODEV;
193
194 /*
195 * Platform driver+device required for handling EPROBE_DEFER with
196 * the regulator and the DFLL clock
197 */
198 ret = platform_driver_register(&tegra124_cpufreq_platdrv);
199 if (ret)
200 return ret;
201
202 pdev = platform_device_register_simple("cpufreq-tegra124", -1, NULL, 0);
203 if (IS_ERR(pdev)) {
204 platform_driver_unregister(&tegra124_cpufreq_platdrv);
205 return PTR_ERR(pdev);
206 }
207
208 return 0;
209}
210module_init(tegra_cpufreq_init);
211
212MODULE_AUTHOR("Tuomas Tynkkynen <ttynkkynen@nvidia.com>");
213MODULE_DESCRIPTION("cpufreq driver for NVIDIA Tegra124");
214MODULE_LICENSE("GPL v2");
diff --git a/drivers/cpufreq/tegra-cpufreq.c b/drivers/cpufreq/tegra20-cpufreq.c
index 8084c7f7e206..8084c7f7e206 100644
--- a/drivers/cpufreq/tegra-cpufreq.c
+++ b/drivers/cpufreq/tegra20-cpufreq.c
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index f1fb1d3ccc56..f491aec95160 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -222,7 +222,7 @@ config TEGRA_IOMMU_SMMU
222 select IOMMU_API 222 select IOMMU_API
223 help 223 help
224 This driver supports the IOMMU hardware (SMMU) found on NVIDIA Tegra 224 This driver supports the IOMMU hardware (SMMU) found on NVIDIA Tegra
225 SoCs (Tegra30 up to Tegra132). 225 SoCs (Tegra30 up to Tegra210).
226 226
227config EXYNOS_IOMMU 227config EXYNOS_IOMMU
228 bool "Exynos IOMMU Support" 228 bool "Exynos IOMMU Support"
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig
index 8406c668ecdc..c6a644b22af4 100644
--- a/drivers/memory/Kconfig
+++ b/drivers/memory/Kconfig
@@ -7,6 +7,14 @@ menuconfig MEMORY
7 7
8if MEMORY 8if MEMORY
9 9
10config ARM_PL172_MPMC
11 tristate "ARM PL172 MPMC driver"
12 depends on ARM_AMBA && OF
13 help
14 This selects the ARM PrimeCell PL172 MultiPort Memory Controller.
15 If you have an embedded system with an AMBA bus and a PL172
16 controller, say Y or M here.
17
10config ATMEL_SDRAMC 18config ATMEL_SDRAMC
11 bool "Atmel (Multi-port DDR-)SDRAM Controller" 19 bool "Atmel (Multi-port DDR-)SDRAM Controller"
12 default y 20 default y
diff --git a/drivers/memory/Makefile b/drivers/memory/Makefile
index b670441e3cdf..1c46af501610 100644
--- a/drivers/memory/Makefile
+++ b/drivers/memory/Makefile
@@ -5,6 +5,7 @@
5ifeq ($(CONFIG_DDR),y) 5ifeq ($(CONFIG_DDR),y)
6obj-$(CONFIG_OF) += of_memory.o 6obj-$(CONFIG_OF) += of_memory.o
7endif 7endif
8obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o
8obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o 9obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o
9obj-$(CONFIG_TI_AEMIF) += ti-aemif.o 10obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
10obj-$(CONFIG_TI_EMIF) += emif.o 11obj-$(CONFIG_TI_EMIF) += emif.o
diff --git a/drivers/memory/pl172.c b/drivers/memory/pl172.c
new file mode 100644
index 000000000000..b2ef6072fbf4
--- /dev/null
+++ b/drivers/memory/pl172.c
@@ -0,0 +1,301 @@
1/*
2 * Memory controller driver for ARM PrimeCell PL172
3 * PrimeCell MultiPort Memory Controller (PL172)
4 *
5 * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
6 *
7 * Based on:
8 * TI AEMIF driver, Copyright (C) 2010 - 2013 Texas Instruments Inc.
9 *
10 * This file is licensed under the terms of the GNU General Public
11 * License version 2. This program is licensed "as is" without any
12 * warranty of any kind, whether express or implied.
13 */
14
15#include <linux/amba/bus.h>
16#include <linux/clk.h>
17#include <linux/device.h>
18#include <linux/err.h>
19#include <linux/init.h>
20#include <linux/io.h>
21#include <linux/kernel.h>
22#include <linux/module.h>
23#include <linux/of.h>
24#include <linux/of_platform.h>
25#include <linux/time.h>
26
27#define MPMC_STATIC_CFG(n) (0x200 + 0x20 * n)
28#define MPMC_STATIC_CFG_MW_8BIT 0x0
29#define MPMC_STATIC_CFG_MW_16BIT 0x1
30#define MPMC_STATIC_CFG_MW_32BIT 0x2
31#define MPMC_STATIC_CFG_PM BIT(3)
32#define MPMC_STATIC_CFG_PC BIT(6)
33#define MPMC_STATIC_CFG_PB BIT(7)
34#define MPMC_STATIC_CFG_EW BIT(8)
35#define MPMC_STATIC_CFG_B BIT(19)
36#define MPMC_STATIC_CFG_P BIT(20)
37#define MPMC_STATIC_WAIT_WEN(n) (0x204 + 0x20 * n)
38#define MPMC_STATIC_WAIT_WEN_MAX 0x0f
39#define MPMC_STATIC_WAIT_OEN(n) (0x208 + 0x20 * n)
40#define MPMC_STATIC_WAIT_OEN_MAX 0x0f
41#define MPMC_STATIC_WAIT_RD(n) (0x20c + 0x20 * n)
42#define MPMC_STATIC_WAIT_RD_MAX 0x1f
43#define MPMC_STATIC_WAIT_PAGE(n) (0x210 + 0x20 * n)
44#define MPMC_STATIC_WAIT_PAGE_MAX 0x1f
45#define MPMC_STATIC_WAIT_WR(n) (0x214 + 0x20 * n)
46#define MPMC_STATIC_WAIT_WR_MAX 0x1f
47#define MPMC_STATIC_WAIT_TURN(n) (0x218 + 0x20 * n)
48#define MPMC_STATIC_WAIT_TURN_MAX 0x0f
49
50/* Maximum number of static chip selects */
51#define PL172_MAX_CS 4
52
53struct pl172_data {
54 void __iomem *base;
55 unsigned long rate;
56 struct clk *clk;
57};
58
59static int pl172_timing_prop(struct amba_device *adev,
60 const struct device_node *np, const char *name,
61 u32 reg_offset, u32 max, int start)
62{
63 struct pl172_data *pl172 = amba_get_drvdata(adev);
64 int cycles;
65 u32 val;
66
67 if (!of_property_read_u32(np, name, &val)) {
68 cycles = DIV_ROUND_UP(val * pl172->rate, NSEC_PER_MSEC) - start;
69 if (cycles < 0) {
70 cycles = 0;
71 } else if (cycles > max) {
72 dev_err(&adev->dev, "%s timing too tight\n", name);
73 return -EINVAL;
74 }
75
76 writel(cycles, pl172->base + reg_offset);
77 }
78
79 dev_dbg(&adev->dev, "%s: %u cycle(s)\n", name, start +
80 readl(pl172->base + reg_offset));
81
82 return 0;
83}
84
85static int pl172_setup_static(struct amba_device *adev,
86 struct device_node *np, u32 cs)
87{
88 struct pl172_data *pl172 = amba_get_drvdata(adev);
89 u32 cfg;
90 int ret;
91
92 /* MPMC static memory configuration */
93 if (!of_property_read_u32(np, "mpmc,memory-width", &cfg)) {
94 if (cfg == 8) {
95 cfg = MPMC_STATIC_CFG_MW_8BIT;
96 } else if (cfg == 16) {
97 cfg = MPMC_STATIC_CFG_MW_16BIT;
98 } else if (cfg == 32) {
99 cfg = MPMC_STATIC_CFG_MW_32BIT;
100 } else {
101 dev_err(&adev->dev, "invalid memory width cs%u\n", cs);
102 return -EINVAL;
103 }
104 } else {
105 dev_err(&adev->dev, "memory-width property required\n");
106 return -EINVAL;
107 }
108
109 if (of_property_read_bool(np, "mpmc,async-page-mode"))
110 cfg |= MPMC_STATIC_CFG_PM;
111
112 if (of_property_read_bool(np, "mpmc,cs-active-high"))
113 cfg |= MPMC_STATIC_CFG_PC;
114
115 if (of_property_read_bool(np, "mpmc,byte-lane-low"))
116 cfg |= MPMC_STATIC_CFG_PB;
117
118 if (of_property_read_bool(np, "mpmc,extended-wait"))
119 cfg |= MPMC_STATIC_CFG_EW;
120
121 if (of_property_read_bool(np, "mpmc,buffer-enable"))
122 cfg |= MPMC_STATIC_CFG_B;
123
124 if (of_property_read_bool(np, "mpmc,write-protect"))
125 cfg |= MPMC_STATIC_CFG_P;
126
127 writel(cfg, pl172->base + MPMC_STATIC_CFG(cs));
128 dev_dbg(&adev->dev, "mpmc static config cs%u: 0x%08x\n", cs, cfg);
129
130 /* MPMC static memory timing */
131 ret = pl172_timing_prop(adev, np, "mpmc,write-enable-delay",
132 MPMC_STATIC_WAIT_WEN(cs),
133 MPMC_STATIC_WAIT_WEN_MAX, 1);
134 if (ret)
135 goto fail;
136
137 ret = pl172_timing_prop(adev, np, "mpmc,output-enable-delay",
138 MPMC_STATIC_WAIT_OEN(cs),
139 MPMC_STATIC_WAIT_OEN_MAX, 0);
140 if (ret)
141 goto fail;
142
143 ret = pl172_timing_prop(adev, np, "mpmc,read-access-delay",
144 MPMC_STATIC_WAIT_RD(cs),
145 MPMC_STATIC_WAIT_RD_MAX, 1);
146 if (ret)
147 goto fail;
148
149 ret = pl172_timing_prop(adev, np, "mpmc,page-mode-read-delay",
150 MPMC_STATIC_WAIT_PAGE(cs),
151 MPMC_STATIC_WAIT_PAGE_MAX, 1);
152 if (ret)
153 goto fail;
154
155 ret = pl172_timing_prop(adev, np, "mpmc,write-access-delay",
156 MPMC_STATIC_WAIT_WR(cs),
157 MPMC_STATIC_WAIT_WR_MAX, 2);
158 if (ret)
159 goto fail;
160
161 ret = pl172_timing_prop(adev, np, "mpmc,turn-round-delay",
162 MPMC_STATIC_WAIT_TURN(cs),
163 MPMC_STATIC_WAIT_TURN_MAX, 1);
164 if (ret)
165 goto fail;
166
167 return 0;
168fail:
169 dev_err(&adev->dev, "failed to configure cs%u\n", cs);
170 return ret;
171}
172
173static int pl172_parse_cs_config(struct amba_device *adev,
174 struct device_node *np)
175{
176 u32 cs;
177
178 if (!of_property_read_u32(np, "mpmc,cs", &cs)) {
179 if (cs >= PL172_MAX_CS) {
180 dev_err(&adev->dev, "cs%u invalid\n", cs);
181 return -EINVAL;
182 }
183
184 return pl172_setup_static(adev, np, cs);
185 }
186
187 dev_err(&adev->dev, "cs property required\n");
188
189 return -EINVAL;
190}
191
192static const char * const pl172_revisions[] = {"r1", "r2", "r2p3", "r2p4"};
193
194static int pl172_probe(struct amba_device *adev, const struct amba_id *id)
195{
196 struct device_node *child_np, *np = adev->dev.of_node;
197 struct device *dev = &adev->dev;
198 static const char *rev = "?";
199 struct pl172_data *pl172;
200 int ret;
201
202 if (amba_part(adev) == 0x172) {
203 if (amba_rev(adev) < ARRAY_SIZE(pl172_revisions))
204 rev = pl172_revisions[amba_rev(adev)];
205 }
206
207 dev_info(dev, "ARM PL%x revision %s\n", amba_part(adev), rev);
208
209 pl172 = devm_kzalloc(dev, sizeof(*pl172), GFP_KERNEL);
210 if (!pl172)
211 return -ENOMEM;
212
213 pl172->clk = devm_clk_get(dev, "mpmcclk");
214 if (IS_ERR(pl172->clk)) {
215 dev_err(dev, "no mpmcclk provided clock\n");
216 return PTR_ERR(pl172->clk);
217 }
218
219 ret = clk_prepare_enable(pl172->clk);
220 if (ret) {
221 dev_err(dev, "unable to mpmcclk enable clock\n");
222 return ret;
223 }
224
225 pl172->rate = clk_get_rate(pl172->clk) / MSEC_PER_SEC;
226 if (!pl172->rate) {
227 dev_err(dev, "unable to get mpmcclk clock rate\n");
228 ret = -EINVAL;
229 goto err_clk_enable;
230 }
231
232 ret = amba_request_regions(adev, NULL);
233 if (ret) {
234 dev_err(dev, "unable to request AMBA regions\n");
235 goto err_clk_enable;
236 }
237
238 pl172->base = devm_ioremap(dev, adev->res.start,
239 resource_size(&adev->res));
240 if (!pl172->base) {
241 dev_err(dev, "ioremap failed\n");
242 ret = -ENOMEM;
243 goto err_no_ioremap;
244 }
245
246 amba_set_drvdata(adev, pl172);
247
248 /*
249 * Loop through each child node, which represent a chip select, and
250 * configure parameters and timing. If successful; populate devices
251 * under that node.
252 */
253 for_each_available_child_of_node(np, child_np) {
254 ret = pl172_parse_cs_config(adev, child_np);
255 if (ret)
256 continue;
257
258 of_platform_populate(child_np, NULL, NULL, dev);
259 }
260
261 return 0;
262
263err_no_ioremap:
264 amba_release_regions(adev);
265err_clk_enable:
266 clk_disable_unprepare(pl172->clk);
267 return ret;
268}
269
270static int pl172_remove(struct amba_device *adev)
271{
272 struct pl172_data *pl172 = amba_get_drvdata(adev);
273
274 clk_disable_unprepare(pl172->clk);
275 amba_release_regions(adev);
276
277 return 0;
278}
279
280static const struct amba_id pl172_ids[] = {
281 {
282 .id = 0x07341172,
283 .mask = 0xffffffff,
284 },
285 { 0, 0 },
286};
287MODULE_DEVICE_TABLE(amba, pl172_ids);
288
289static struct amba_driver pl172_driver = {
290 .drv = {
291 .name = "memory-pl172",
292 },
293 .probe = pl172_probe,
294 .remove = pl172_remove,
295 .id_table = pl172_ids,
296};
297module_amba_driver(pl172_driver);
298
299MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
300MODULE_DESCRIPTION("PL172 Memory Controller Driver");
301MODULE_LICENSE("GPL v2");
diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile
index 6a0b9ac54f05..c2cb671ffc4a 100644
--- a/drivers/memory/tegra/Makefile
+++ b/drivers/memory/tegra/Makefile
@@ -4,6 +4,7 @@ tegra-mc-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30.o
4tegra-mc-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114.o 4tegra-mc-$(CONFIG_ARCH_TEGRA_114_SOC) += tegra114.o
5tegra-mc-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124.o 5tegra-mc-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124.o
6tegra-mc-$(CONFIG_ARCH_TEGRA_132_SOC) += tegra124.o 6tegra-mc-$(CONFIG_ARCH_TEGRA_132_SOC) += tegra124.o
7tegra-mc-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o
7 8
8obj-$(CONFIG_TEGRA_MC) += tegra-mc.o 9obj-$(CONFIG_TEGRA_MC) += tegra-mc.o
9 10
diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
index c71ede67e6c8..a1ae0cc2b86d 100644
--- a/drivers/memory/tegra/mc.c
+++ b/drivers/memory/tegra/mc.c
@@ -42,7 +42,6 @@
42#define MC_ERR_STATUS_ADR_HI_MASK 0x3 42#define MC_ERR_STATUS_ADR_HI_MASK 0x3
43#define MC_ERR_STATUS_SECURITY (1 << 17) 43#define MC_ERR_STATUS_SECURITY (1 << 17)
44#define MC_ERR_STATUS_RW (1 << 16) 44#define MC_ERR_STATUS_RW (1 << 16)
45#define MC_ERR_STATUS_CLIENT_MASK 0x7f
46 45
47#define MC_ERR_ADR 0x0c 46#define MC_ERR_ADR 0x0c
48 47
@@ -67,6 +66,9 @@ static const struct of_device_id tegra_mc_of_match[] = {
67#ifdef CONFIG_ARCH_TEGRA_132_SOC 66#ifdef CONFIG_ARCH_TEGRA_132_SOC
68 { .compatible = "nvidia,tegra132-mc", .data = &tegra132_mc_soc }, 67 { .compatible = "nvidia,tegra132-mc", .data = &tegra132_mc_soc },
69#endif 68#endif
69#ifdef CONFIG_ARCH_TEGRA_210_SOC
70 { .compatible = "nvidia,tegra210-mc", .data = &tegra210_mc_soc },
71#endif
70 { } 72 { }
71}; 73};
72MODULE_DEVICE_TABLE(of, tegra_mc_of_match); 74MODULE_DEVICE_TABLE(of, tegra_mc_of_match);
@@ -283,7 +285,7 @@ static irqreturn_t tegra_mc_irq(int irq, void *data)
283 else 285 else
284 secure = ""; 286 secure = "";
285 287
286 id = value & MC_ERR_STATUS_CLIENT_MASK; 288 id = value & mc->soc->client_id_mask;
287 289
288 for (i = 0; i < mc->soc->num_clients; i++) { 290 for (i = 0; i < mc->soc->num_clients; i++) {
289 if (mc->soc->clients[i].id == id) { 291 if (mc->soc->clients[i].id == id) {
@@ -410,6 +412,8 @@ static int tegra_mc_probe(struct platform_device *pdev)
410 return err; 412 return err;
411 } 413 }
412 414
415 WARN(!mc->soc->client_id_mask, "Missing client ID mask for this SoC\n");
416
413 value = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR | 417 value = MC_INT_DECERR_MTS | MC_INT_SECERR_SEC | MC_INT_DECERR_VPR |
414 MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE | 418 MC_INT_INVALID_APB_ASID_UPDATE | MC_INT_INVALID_SMMU_PAGE |
415 MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM; 419 MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM;
diff --git a/drivers/memory/tegra/mc.h b/drivers/memory/tegra/mc.h
index b7361b0a6696..ddb16676c3af 100644
--- a/drivers/memory/tegra/mc.h
+++ b/drivers/memory/tegra/mc.h
@@ -41,4 +41,8 @@ extern const struct tegra_mc_soc tegra124_mc_soc;
41extern const struct tegra_mc_soc tegra132_mc_soc; 41extern const struct tegra_mc_soc tegra132_mc_soc;
42#endif 42#endif
43 43
44#ifdef CONFIG_ARCH_TEGRA_210_SOC
45extern const struct tegra_mc_soc tegra210_mc_soc;
46#endif
47
44#endif /* MEMORY_TEGRA_MC_H */ 48#endif /* MEMORY_TEGRA_MC_H */
diff --git a/drivers/memory/tegra/tegra114.c b/drivers/memory/tegra/tegra114.c
index 9f579589e800..c8765db07a62 100644
--- a/drivers/memory/tegra/tegra114.c
+++ b/drivers/memory/tegra/tegra114.c
@@ -944,5 +944,6 @@ const struct tegra_mc_soc tegra114_mc_soc = {
944 .num_clients = ARRAY_SIZE(tegra114_mc_clients), 944 .num_clients = ARRAY_SIZE(tegra114_mc_clients),
945 .num_address_bits = 32, 945 .num_address_bits = 32,
946 .atom_size = 32, 946 .atom_size = 32,
947 .client_id_mask = 0x7f,
947 .smmu = &tegra114_smmu_soc, 948 .smmu = &tegra114_smmu_soc,
948}; 949};
diff --git a/drivers/memory/tegra/tegra124-emc.c b/drivers/memory/tegra/tegra124-emc.c
index 8620355776fe..3dac7be39654 100644
--- a/drivers/memory/tegra/tegra124-emc.c
+++ b/drivers/memory/tegra/tegra124-emc.c
@@ -1027,7 +1027,40 @@ static int emc_debug_rate_set(void *data, u64 rate)
1027DEFINE_SIMPLE_ATTRIBUTE(emc_debug_rate_fops, emc_debug_rate_get, 1027DEFINE_SIMPLE_ATTRIBUTE(emc_debug_rate_fops, emc_debug_rate_get,
1028 emc_debug_rate_set, "%lld\n"); 1028 emc_debug_rate_set, "%lld\n");
1029 1029
1030static void emc_debugfs_init(struct device *dev) 1030static int emc_debug_supported_rates_show(struct seq_file *s, void *data)
1031{
1032 struct tegra_emc *emc = s->private;
1033 const char *prefix = "";
1034 unsigned int i;
1035
1036 for (i = 0; i < emc->num_timings; i++) {
1037 struct emc_timing *timing = &emc->timings[i];
1038
1039 seq_printf(s, "%s%lu", prefix, timing->rate);
1040
1041 prefix = " ";
1042 }
1043
1044 seq_puts(s, "\n");
1045
1046 return 0;
1047}
1048
1049static int emc_debug_supported_rates_open(struct inode *inode,
1050 struct file *file)
1051{
1052 return single_open(file, emc_debug_supported_rates_show,
1053 inode->i_private);
1054}
1055
1056static const struct file_operations emc_debug_supported_rates_fops = {
1057 .open = emc_debug_supported_rates_open,
1058 .read = seq_read,
1059 .llseek = seq_lseek,
1060 .release = single_release,
1061};
1062
1063static void emc_debugfs_init(struct device *dev, struct tegra_emc *emc)
1031{ 1064{
1032 struct dentry *root, *file; 1065 struct dentry *root, *file;
1033 struct clk *clk; 1066 struct clk *clk;
@@ -1048,6 +1081,11 @@ static void emc_debugfs_init(struct device *dev)
1048 &emc_debug_rate_fops); 1081 &emc_debug_rate_fops);
1049 if (!file) 1082 if (!file)
1050 dev_err(dev, "failed to create debugfs entry\n"); 1083 dev_err(dev, "failed to create debugfs entry\n");
1084
1085 file = debugfs_create_file("supported_rates", S_IRUGO, root, emc,
1086 &emc_debug_supported_rates_fops);
1087 if (!file)
1088 dev_err(dev, "failed to create debugfs entry\n");
1051} 1089}
1052 1090
1053static int tegra_emc_probe(struct platform_device *pdev) 1091static int tegra_emc_probe(struct platform_device *pdev)
@@ -1119,7 +1157,7 @@ static int tegra_emc_probe(struct platform_device *pdev)
1119 platform_set_drvdata(pdev, emc); 1157 platform_set_drvdata(pdev, emc);
1120 1158
1121 if (IS_ENABLED(CONFIG_DEBUG_FS)) 1159 if (IS_ENABLED(CONFIG_DEBUG_FS))
1122 emc_debugfs_init(&pdev->dev); 1160 emc_debugfs_init(&pdev->dev, emc);
1123 1161
1124 return 0; 1162 return 0;
1125}; 1163};
diff --git a/drivers/memory/tegra/tegra124.c b/drivers/memory/tegra/tegra124.c
index 966e1557e6f4..060fb3d7a23f 100644
--- a/drivers/memory/tegra/tegra124.c
+++ b/drivers/memory/tegra/tegra124.c
@@ -1032,6 +1032,7 @@ const struct tegra_mc_soc tegra124_mc_soc = {
1032 .num_clients = ARRAY_SIZE(tegra124_mc_clients), 1032 .num_clients = ARRAY_SIZE(tegra124_mc_clients),
1033 .num_address_bits = 34, 1033 .num_address_bits = 34,
1034 .atom_size = 32, 1034 .atom_size = 32,
1035 .client_id_mask = 0x7f,
1035 .smmu = &tegra124_smmu_soc, 1036 .smmu = &tegra124_smmu_soc,
1036 .emem_regs = tegra124_mc_emem_regs, 1037 .emem_regs = tegra124_mc_emem_regs,
1037 .num_emem_regs = ARRAY_SIZE(tegra124_mc_emem_regs), 1038 .num_emem_regs = ARRAY_SIZE(tegra124_mc_emem_regs),
@@ -1067,6 +1068,7 @@ const struct tegra_mc_soc tegra132_mc_soc = {
1067 .num_clients = ARRAY_SIZE(tegra124_mc_clients), 1068 .num_clients = ARRAY_SIZE(tegra124_mc_clients),
1068 .num_address_bits = 34, 1069 .num_address_bits = 34,
1069 .atom_size = 32, 1070 .atom_size = 32,
1071 .client_id_mask = 0x7f,
1070 .smmu = &tegra132_smmu_soc, 1072 .smmu = &tegra132_smmu_soc,
1071}; 1073};
1072#endif /* CONFIG_ARCH_TEGRA_132_SOC */ 1074#endif /* CONFIG_ARCH_TEGRA_132_SOC */
diff --git a/drivers/memory/tegra/tegra210.c b/drivers/memory/tegra/tegra210.c
new file mode 100644
index 000000000000..5e144abe4c18
--- /dev/null
+++ b/drivers/memory/tegra/tegra210.c
@@ -0,0 +1,1080 @@
1/*
2 * Copyright (C) 2015 NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/of.h>
10#include <linux/mm.h>
11
12#include <asm/cacheflush.h>
13
14#include <dt-bindings/memory/tegra210-mc.h>
15
16#include "mc.h"
17
18static const struct tegra_mc_client tegra210_mc_clients[] = {
19 {
20 .id = 0x00,
21 .name = "ptcr",
22 .swgroup = TEGRA_SWGROUP_PTC,
23 }, {
24 .id = 0x01,
25 .name = "display0a",
26 .swgroup = TEGRA_SWGROUP_DC,
27 .smmu = {
28 .reg = 0x228,
29 .bit = 1,
30 },
31 .la = {
32 .reg = 0x2e8,
33 .shift = 0,
34 .mask = 0xff,
35 .def = 0xc2,
36 },
37 }, {
38 .id = 0x02,
39 .name = "display0ab",
40 .swgroup = TEGRA_SWGROUP_DCB,
41 .smmu = {
42 .reg = 0x228,
43 .bit = 2,
44 },
45 .la = {
46 .reg = 0x2f4,
47 .shift = 0,
48 .mask = 0xff,
49 .def = 0xc6,
50 },
51 }, {
52 .id = 0x03,
53 .name = "display0b",
54 .swgroup = TEGRA_SWGROUP_DC,
55 .smmu = {
56 .reg = 0x228,
57 .bit = 3,
58 },
59 .la = {
60 .reg = 0x2e8,
61 .shift = 16,
62 .mask = 0xff,
63 .def = 0x50,
64 },
65 }, {
66 .id = 0x04,
67 .name = "display0bb",
68 .swgroup = TEGRA_SWGROUP_DCB,
69 .smmu = {
70 .reg = 0x228,
71 .bit = 4,
72 },
73 .la = {
74 .reg = 0x2f4,
75 .shift = 16,
76 .mask = 0xff,
77 .def = 0x50,
78 },
79 }, {
80 .id = 0x05,
81 .name = "display0c",
82 .swgroup = TEGRA_SWGROUP_DC,
83 .smmu = {
84 .reg = 0x228,
85 .bit = 5,
86 },
87 .la = {
88 .reg = 0x2ec,
89 .shift = 0,
90 .mask = 0xff,
91 .def = 0x50,
92 },
93 }, {
94 .id = 0x06,
95 .name = "display0cb",
96 .swgroup = TEGRA_SWGROUP_DCB,
97 .smmu = {
98 .reg = 0x228,
99 .bit = 6,
100 },
101 .la = {
102 .reg = 0x2f8,
103 .shift = 0,
104 .mask = 0xff,
105 .def = 0x50,
106 },
107 }, {
108 .id = 0x0e,
109 .name = "afir",
110 .swgroup = TEGRA_SWGROUP_AFI,
111 .smmu = {
112 .reg = 0x228,
113 .bit = 14,
114 },
115 .la = {
116 .reg = 0x2e0,
117 .shift = 0,
118 .mask = 0xff,
119 .def = 0x13,
120 },
121 }, {
122 .id = 0x0f,
123 .name = "avpcarm7r",
124 .swgroup = TEGRA_SWGROUP_AVPC,
125 .smmu = {
126 .reg = 0x228,
127 .bit = 15,
128 },
129 .la = {
130 .reg = 0x2e4,
131 .shift = 0,
132 .mask = 0xff,
133 .def = 0x04,
134 },
135 }, {
136 .id = 0x10,
137 .name = "displayhc",
138 .swgroup = TEGRA_SWGROUP_DC,
139 .smmu = {
140 .reg = 0x228,
141 .bit = 16,
142 },
143 .la = {
144 .reg = 0x2f0,
145 .shift = 0,
146 .mask = 0xff,
147 .def = 0x50,
148 },
149 }, {
150 .id = 0x11,
151 .name = "displayhcb",
152 .swgroup = TEGRA_SWGROUP_DCB,
153 .smmu = {
154 .reg = 0x228,
155 .bit = 17,
156 },
157 .la = {
158 .reg = 0x2fc,
159 .shift = 0,
160 .mask = 0xff,
161 .def = 0x50,
162 },
163 }, {
164 .id = 0x15,
165 .name = "hdar",
166 .swgroup = TEGRA_SWGROUP_HDA,
167 .smmu = {
168 .reg = 0x228,
169 .bit = 21,
170 },
171 .la = {
172 .reg = 0x318,
173 .shift = 0,
174 .mask = 0xff,
175 .def = 0x24,
176 },
177 }, {
178 .id = 0x16,
179 .name = "host1xdmar",
180 .swgroup = TEGRA_SWGROUP_HC,
181 .smmu = {
182 .reg = 0x228,
183 .bit = 22,
184 },
185 .la = {
186 .reg = 0x310,
187 .shift = 0,
188 .mask = 0xff,
189 .def = 0x1e,
190 },
191 }, {
192 .id = 0x17,
193 .name = "host1xr",
194 .swgroup = TEGRA_SWGROUP_HC,
195 .smmu = {
196 .reg = 0x228,
197 .bit = 23,
198 },
199 .la = {
200 .reg = 0x310,
201 .shift = 16,
202 .mask = 0xff,
203 .def = 0x50,
204 },
205 }, {
206 .id = 0x1c,
207 .name = "nvencsrd",
208 .swgroup = TEGRA_SWGROUP_NVENC,
209 .smmu = {
210 .reg = 0x228,
211 .bit = 28,
212 },
213 .la = {
214 .reg = 0x328,
215 .shift = 0,
216 .mask = 0xff,
217 .def = 0x23,
218 },
219 }, {
220 .id = 0x1d,
221 .name = "ppcsahbdmar",
222 .swgroup = TEGRA_SWGROUP_PPCS,
223 .smmu = {
224 .reg = 0x228,
225 .bit = 29,
226 },
227 .la = {
228 .reg = 0x344,
229 .shift = 0,
230 .mask = 0xff,
231 .def = 0x49,
232 },
233 }, {
234 .id = 0x1e,
235 .name = "ppcsahbslvr",
236 .swgroup = TEGRA_SWGROUP_PPCS,
237 .smmu = {
238 .reg = 0x228,
239 .bit = 30,
240 },
241 .la = {
242 .reg = 0x344,
243 .shift = 16,
244 .mask = 0xff,
245 .def = 0x1a,
246 },
247 }, {
248 .id = 0x1f,
249 .name = "satar",
250 .swgroup = TEGRA_SWGROUP_SATA,
251 .smmu = {
252 .reg = 0x228,
253 .bit = 31,
254 },
255 .la = {
256 .reg = 0x350,
257 .shift = 0,
258 .mask = 0xff,
259 .def = 0x65,
260 },
261 }, {
262 .id = 0x27,
263 .name = "mpcorer",
264 .swgroup = TEGRA_SWGROUP_MPCORE,
265 .la = {
266 .reg = 0x320,
267 .shift = 0,
268 .mask = 0xff,
269 .def = 0x04,
270 },
271 }, {
272 .id = 0x2b,
273 .name = "nvencswr",
274 .swgroup = TEGRA_SWGROUP_NVENC,
275 .smmu = {
276 .reg = 0x22c,
277 .bit = 11,
278 },
279 .la = {
280 .reg = 0x328,
281 .shift = 16,
282 .mask = 0xff,
283 .def = 0x80,
284 },
285 }, {
286 .id = 0x31,
287 .name = "afiw",
288 .swgroup = TEGRA_SWGROUP_AFI,
289 .smmu = {
290 .reg = 0x22c,
291 .bit = 17,
292 },
293 .la = {
294 .reg = 0x2e0,
295 .shift = 16,
296 .mask = 0xff,
297 .def = 0x80,
298 },
299 }, {
300 .id = 0x32,
301 .name = "avpcarm7w",
302 .swgroup = TEGRA_SWGROUP_AVPC,
303 .smmu = {
304 .reg = 0x22c,
305 .bit = 18,
306 },
307 .la = {
308 .reg = 0x2e4,
309 .shift = 16,
310 .mask = 0xff,
311 .def = 0x80,
312 },
313 }, {
314 .id = 0x35,
315 .name = "hdaw",
316 .swgroup = TEGRA_SWGROUP_HDA,
317 .smmu = {
318 .reg = 0x22c,
319 .bit = 21,
320 },
321 .la = {
322 .reg = 0x318,
323 .shift = 16,
324 .mask = 0xff,
325 .def = 0x80,
326 },
327 }, {
328 .id = 0x36,
329 .name = "host1xw",
330 .swgroup = TEGRA_SWGROUP_HC,
331 .smmu = {
332 .reg = 0x22c,
333 .bit = 22,
334 },
335 .la = {
336 .reg = 0x314,
337 .shift = 0,
338 .mask = 0xff,
339 .def = 0x80,
340 },
341 }, {
342 .id = 0x39,
343 .name = "mpcorew",
344 .swgroup = TEGRA_SWGROUP_MPCORE,
345 .la = {
346 .reg = 0x320,
347 .shift = 16,
348 .mask = 0xff,
349 .def = 0x80,
350 },
351 }, {
352 .id = 0x3b,
353 .name = "ppcsahbdmaw",
354 .swgroup = TEGRA_SWGROUP_PPCS,
355 .smmu = {
356 .reg = 0x22c,
357 .bit = 27,
358 },
359 .la = {
360 .reg = 0x348,
361 .shift = 0,
362 .mask = 0xff,
363 .def = 0x80,
364 },
365 }, {
366 .id = 0x3c,
367 .name = "ppcsahbslvw",
368 .swgroup = TEGRA_SWGROUP_PPCS,
369 .smmu = {
370 .reg = 0x22c,
371 .bit = 28,
372 },
373 .la = {
374 .reg = 0x348,
375 .shift = 16,
376 .mask = 0xff,
377 .def = 0x80,
378 },
379 }, {
380 .id = 0x3d,
381 .name = "sataw",
382 .swgroup = TEGRA_SWGROUP_SATA,
383 .smmu = {
384 .reg = 0x22c,
385 .bit = 29,
386 },
387 .la = {
388 .reg = 0x350,
389 .shift = 16,
390 .mask = 0xff,
391 .def = 0x65,
392 },
393 }, {
394 .id = 0x44,
395 .name = "ispra",
396 .swgroup = TEGRA_SWGROUP_ISP2,
397 .smmu = {
398 .reg = 0x230,
399 .bit = 4,
400 },
401 .la = {
402 .reg = 0x370,
403 .shift = 0,
404 .mask = 0xff,
405 .def = 0x18,
406 },
407 }, {
408 .id = 0x46,
409 .name = "ispwa",
410 .swgroup = TEGRA_SWGROUP_ISP2,
411 .smmu = {
412 .reg = 0x230,
413 .bit = 6,
414 },
415 .la = {
416 .reg = 0x374,
417 .shift = 0,
418 .mask = 0xff,
419 .def = 0x80,
420 },
421 }, {
422 .id = 0x47,
423 .name = "ispwb",
424 .swgroup = TEGRA_SWGROUP_ISP2,
425 .smmu = {
426 .reg = 0x230,
427 .bit = 7,
428 },
429 .la = {
430 .reg = 0x374,
431 .shift = 16,
432 .mask = 0xff,
433 .def = 0x80,
434 },
435 }, {
436 .id = 0x4a,
437 .name = "xusb_hostr",
438 .swgroup = TEGRA_SWGROUP_XUSB_HOST,
439 .smmu = {
440 .reg = 0x230,
441 .bit = 10,
442 },
443 .la = {
444 .reg = 0x37c,
445 .shift = 0,
446 .mask = 0xff,
447 .def = 0x39,
448 },
449 }, {
450 .id = 0x4b,
451 .name = "xusb_hostw",
452 .swgroup = TEGRA_SWGROUP_XUSB_HOST,
453 .smmu = {
454 .reg = 0x230,
455 .bit = 11,
456 },
457 .la = {
458 .reg = 0x37c,
459 .shift = 16,
460 .mask = 0xff,
461 .def = 0x80,
462 },
463 }, {
464 .id = 0x4c,
465 .name = "xusb_devr",
466 .swgroup = TEGRA_SWGROUP_XUSB_DEV,
467 .smmu = {
468 .reg = 0x230,
469 .bit = 12,
470 },
471 .la = {
472 .reg = 0x380,
473 .shift = 0,
474 .mask = 0xff,
475 .def = 0x39,
476 },
477 }, {
478 .id = 0x4d,
479 .name = "xusb_devw",
480 .swgroup = TEGRA_SWGROUP_XUSB_DEV,
481 .smmu = {
482 .reg = 0x230,
483 .bit = 13,
484 },
485 .la = {
486 .reg = 0x380,
487 .shift = 16,
488 .mask = 0xff,
489 .def = 0x80,
490 },
491 }, {
492 .id = 0x4e,
493 .name = "isprab",
494 .swgroup = TEGRA_SWGROUP_ISP2B,
495 .smmu = {
496 .reg = 0x230,
497 .bit = 14,
498 },
499 .la = {
500 .reg = 0x384,
501 .shift = 0,
502 .mask = 0xff,
503 .def = 0x18,
504 },
505 }, {
506 .id = 0x50,
507 .name = "ispwab",
508 .swgroup = TEGRA_SWGROUP_ISP2B,
509 .smmu = {
510 .reg = 0x230,
511 .bit = 16,
512 },
513 .la = {
514 .reg = 0x388,
515 .shift = 0,
516 .mask = 0xff,
517 .def = 0x80,
518 },
519 }, {
520 .id = 0x51,
521 .name = "ispwbb",
522 .swgroup = TEGRA_SWGROUP_ISP2B,
523 .smmu = {
524 .reg = 0x230,
525 .bit = 17,
526 },
527 .la = {
528 .reg = 0x388,
529 .shift = 16,
530 .mask = 0xff,
531 .def = 0x80,
532 },
533 }, {
534 .id = 0x54,
535 .name = "tsecsrd",
536 .swgroup = TEGRA_SWGROUP_TSEC,
537 .smmu = {
538 .reg = 0x230,
539 .bit = 20,
540 },
541 .la = {
542 .reg = 0x390,
543 .shift = 0,
544 .mask = 0xff,
545 .def = 0x9b,
546 },
547 }, {
548 .id = 0x55,
549 .name = "tsecswr",
550 .swgroup = TEGRA_SWGROUP_TSEC,
551 .smmu = {
552 .reg = 0x230,
553 .bit = 21,
554 },
555 .la = {
556 .reg = 0x390,
557 .shift = 16,
558 .mask = 0xff,
559 .def = 0x80,
560 },
561 }, {
562 .id = 0x56,
563 .name = "a9avpscr",
564 .swgroup = TEGRA_SWGROUP_A9AVP,
565 .smmu = {
566 .reg = 0x230,
567 .bit = 22,
568 },
569 .la = {
570 .reg = 0x3a4,
571 .shift = 0,
572 .mask = 0xff,
573 .def = 0x04,
574 },
575 }, {
576 .id = 0x57,
577 .name = "a9avpscw",
578 .swgroup = TEGRA_SWGROUP_A9AVP,
579 .smmu = {
580 .reg = 0x230,
581 .bit = 23,
582 },
583 .la = {
584 .reg = 0x3a4,
585 .shift = 16,
586 .mask = 0xff,
587 .def = 0x80,
588 },
589 }, {
590 .id = 0x58,
591 .name = "gpusrd",
592 .swgroup = TEGRA_SWGROUP_GPU,
593 .smmu = {
594 /* read-only */
595 .reg = 0x230,
596 .bit = 24,
597 },
598 .la = {
599 .reg = 0x3c8,
600 .shift = 0,
601 .mask = 0xff,
602 .def = 0x1a,
603 },
604 }, {
605 .id = 0x59,
606 .name = "gpuswr",
607 .swgroup = TEGRA_SWGROUP_GPU,
608 .smmu = {
609 /* read-only */
610 .reg = 0x230,
611 .bit = 25,
612 },
613 .la = {
614 .reg = 0x3c8,
615 .shift = 16,
616 .mask = 0xff,
617 .def = 0x80,
618 },
619 }, {
620 .id = 0x5a,
621 .name = "displayt",
622 .swgroup = TEGRA_SWGROUP_DC,
623 .smmu = {
624 .reg = 0x230,
625 .bit = 26,
626 },
627 .la = {
628 .reg = 0x2f0,
629 .shift = 16,
630 .mask = 0xff,
631 .def = 0x50,
632 },
633 }, {
634 .id = 0x60,
635 .name = "sdmmcra",
636 .swgroup = TEGRA_SWGROUP_SDMMC1A,
637 .smmu = {
638 .reg = 0x234,
639 .bit = 0,
640 },
641 .la = {
642 .reg = 0x3b8,
643 .shift = 0,
644 .mask = 0xff,
645 .def = 0x49,
646 },
647 }, {
648 .id = 0x61,
649 .name = "sdmmcraa",
650 .swgroup = TEGRA_SWGROUP_SDMMC2A,
651 .smmu = {
652 .reg = 0x234,
653 .bit = 1,
654 },
655 .la = {
656 .reg = 0x3bc,
657 .shift = 0,
658 .mask = 0xff,
659 .def = 0x49,
660 },
661 }, {
662 .id = 0x62,
663 .name = "sdmmcr",
664 .swgroup = TEGRA_SWGROUP_SDMMC3A,
665 .smmu = {
666 .reg = 0x234,
667 .bit = 2,
668 },
669 .la = {
670 .reg = 0x3c0,
671 .shift = 0,
672 .mask = 0xff,
673 .def = 0x49,
674 },
675 }, {
676 .id = 0x63,
677 .swgroup = TEGRA_SWGROUP_SDMMC4A,
678 .name = "sdmmcrab",
679 .smmu = {
680 .reg = 0x234,
681 .bit = 3,
682 },
683 .la = {
684 .reg = 0x3c4,
685 .shift = 0,
686 .mask = 0xff,
687 .def = 0x49,
688 },
689 }, {
690 .id = 0x64,
691 .name = "sdmmcwa",
692 .swgroup = TEGRA_SWGROUP_SDMMC1A,
693 .smmu = {
694 .reg = 0x234,
695 .bit = 4,
696 },
697 .la = {
698 .reg = 0x3b8,
699 .shift = 16,
700 .mask = 0xff,
701 .def = 0x80,
702 },
703 }, {
704 .id = 0x65,
705 .name = "sdmmcwaa",
706 .swgroup = TEGRA_SWGROUP_SDMMC2A,
707 .smmu = {
708 .reg = 0x234,
709 .bit = 5,
710 },
711 .la = {
712 .reg = 0x3bc,
713 .shift = 16,
714 .mask = 0xff,
715 .def = 0x80,
716 },
717 }, {
718 .id = 0x66,
719 .name = "sdmmcw",
720 .swgroup = TEGRA_SWGROUP_SDMMC3A,
721 .smmu = {
722 .reg = 0x234,
723 .bit = 6,
724 },
725 .la = {
726 .reg = 0x3c0,
727 .shift = 16,
728 .mask = 0xff,
729 .def = 0x80,
730 },
731 }, {
732 .id = 0x67,
733 .name = "sdmmcwab",
734 .swgroup = TEGRA_SWGROUP_SDMMC4A,
735 .smmu = {
736 .reg = 0x234,
737 .bit = 7,
738 },
739 .la = {
740 .reg = 0x3c4,
741 .shift = 16,
742 .mask = 0xff,
743 .def = 0x80,
744 },
745 }, {
746 .id = 0x6c,
747 .name = "vicsrd",
748 .swgroup = TEGRA_SWGROUP_VIC,
749 .smmu = {
750 .reg = 0x234,
751 .bit = 12,
752 },
753 .la = {
754 .reg = 0x394,
755 .shift = 0,
756 .mask = 0xff,
757 .def = 0x1a,
758 },
759 }, {
760 .id = 0x6d,
761 .name = "vicswr",
762 .swgroup = TEGRA_SWGROUP_VIC,
763 .smmu = {
764 .reg = 0x234,
765 .bit = 13,
766 },
767 .la = {
768 .reg = 0x394,
769 .shift = 16,
770 .mask = 0xff,
771 .def = 0x80,
772 },
773 }, {
774 .id = 0x72,
775 .name = "viw",
776 .swgroup = TEGRA_SWGROUP_VI,
777 .smmu = {
778 .reg = 0x234,
779 .bit = 18,
780 },
781 .la = {
782 .reg = 0x398,
783 .shift = 0,
784 .mask = 0xff,
785 .def = 0x80,
786 },
787 }, {
788 .id = 0x73,
789 .name = "displayd",
790 .swgroup = TEGRA_SWGROUP_DC,
791 .smmu = {
792 .reg = 0x234,
793 .bit = 19,
794 },
795 .la = {
796 .reg = 0x3c8,
797 .shift = 0,
798 .mask = 0xff,
799 .def = 0x50,
800 },
801 }, {
802 .id = 0x78,
803 .name = "nvdecsrd",
804 .swgroup = TEGRA_SWGROUP_NVDEC,
805 .smmu = {
806 .reg = 0x234,
807 .bit = 24,
808 },
809 .la = {
810 .reg = 0x3d8,
811 .shift = 0,
812 .mask = 0xff,
813 .def = 0x23,
814 },
815 }, {
816 .id = 0x79,
817 .name = "nvdecswr",
818 .swgroup = TEGRA_SWGROUP_NVDEC,
819 .smmu = {
820 .reg = 0x234,
821 .bit = 25,
822 },
823 .la = {
824 .reg = 0x3d8,
825 .shift = 16,
826 .mask = 0xff,
827 .def = 0x80,
828 },
829 }, {
830 .id = 0x7a,
831 .name = "aper",
832 .swgroup = TEGRA_SWGROUP_APE,
833 .smmu = {
834 .reg = 0x234,
835 .bit = 26,
836 },
837 .la = {
838 .reg = 0x3dc,
839 .shift = 0,
840 .mask = 0xff,
841 .def = 0xff,
842 },
843 }, {
844 .id = 0x7b,
845 .name = "apew",
846 .swgroup = TEGRA_SWGROUP_APE,
847 .smmu = {
848 .reg = 0x234,
849 .bit = 27,
850 },
851 .la = {
852 .reg = 0x3dc,
853 .shift = 0,
854 .mask = 0xff,
855 .def = 0x80,
856 },
857 }, {
858 .id = 0x7e,
859 .name = "nvjpgsrd",
860 .swgroup = TEGRA_SWGROUP_NVJPG,
861 .smmu = {
862 .reg = 0x234,
863 .bit = 30,
864 },
865 .la = {
866 .reg = 0x3e4,
867 .shift = 0,
868 .mask = 0xff,
869 .def = 0x23,
870 },
871 }, {
872 .id = 0x7f,
873 .name = "nvjpgswr",
874 .swgroup = TEGRA_SWGROUP_NVJPG,
875 .smmu = {
876 .reg = 0x234,
877 .bit = 31,
878 },
879 .la = {
880 .reg = 0x3e4,
881 .shift = 16,
882 .mask = 0xff,
883 .def = 0x80,
884 },
885 }, {
886 .id = 0x80,
887 .name = "sesrd",
888 .swgroup = TEGRA_SWGROUP_SE,
889 .smmu = {
890 .reg = 0xb98,
891 .bit = 0,
892 },
893 .la = {
894 .reg = 0x3e0,
895 .shift = 0,
896 .mask = 0xff,
897 .def = 0x2e,
898 },
899 }, {
900 .id = 0x81,
901 .name = "seswr",
902 .swgroup = TEGRA_SWGROUP_SE,
903 .smmu = {
904 .reg = 0xb98,
905 .bit = 1,
906 },
907 .la = {
908 .reg = 0xb98,
909 .shift = 16,
910 .mask = 0xff,
911 .def = 0x80,
912 },
913 }, {
914 .id = 0x82,
915 .name = "axiapr",
916 .swgroup = TEGRA_SWGROUP_AXIAP,
917 .smmu = {
918 .reg = 0xb98,
919 .bit = 2,
920 },
921 .la = {
922 .reg = 0x3a0,
923 .shift = 0,
924 .mask = 0xff,
925 .def = 0xff,
926 },
927 }, {
928 .id = 0x83,
929 .name = "axiapw",
930 .swgroup = TEGRA_SWGROUP_AXIAP,
931 .smmu = {
932 .reg = 0xb98,
933 .bit = 3,
934 },
935 .la = {
936 .reg = 0x3a0,
937 .shift = 16,
938 .mask = 0xff,
939 .def = 0x80,
940 },
941 }, {
942 .id = 0x84,
943 .name = "etrr",
944 .swgroup = TEGRA_SWGROUP_ETR,
945 .smmu = {
946 .reg = 0xb98,
947 .bit = 4,
948 },
949 .la = {
950 .reg = 0x3ec,
951 .shift = 0,
952 .mask = 0xff,
953 .def = 0xff,
954 },
955 }, {
956 .id = 0x85,
957 .name = "etrw",
958 .swgroup = TEGRA_SWGROUP_ETR,
959 .smmu = {
960 .reg = 0xb98,
961 .bit = 5,
962 },
963 .la = {
964 .reg = 0x3ec,
965 .shift = 16,
966 .mask = 0xff,
967 .def = 0xff,
968 },
969 }, {
970 .id = 0x86,
971 .name = "tsecsrdb",
972 .swgroup = TEGRA_SWGROUP_TSECB,
973 .smmu = {
974 .reg = 0xb98,
975 .bit = 6,
976 },
977 .la = {
978 .reg = 0x3f0,
979 .shift = 0,
980 .mask = 0xff,
981 .def = 0x9b,
982 },
983 }, {
984 .id = 0x87,
985 .name = "tsecswrb",
986 .swgroup = TEGRA_SWGROUP_TSECB,
987 .smmu = {
988 .reg = 0xb98,
989 .bit = 7,
990 },
991 .la = {
992 .reg = 0x3f0,
993 .shift = 16,
994 .mask = 0xff,
995 .def = 0x80,
996 },
997 }, {
998 .id = 0x88,
999 .name = "gpusrd2",
1000 .swgroup = TEGRA_SWGROUP_GPU,
1001 .smmu = {
1002 /* read-only */
1003 .reg = 0xb98,
1004 .bit = 8,
1005 },
1006 .la = {
1007 .reg = 0x3e8,
1008 .shift = 0,
1009 .mask = 0xff,
1010 .def = 0x1a,
1011 },
1012 }, {
1013 .id = 0x89,
1014 .name = "gpuswr2",
1015 .swgroup = TEGRA_SWGROUP_GPU,
1016 .smmu = {
1017 /* read-only */
1018 .reg = 0xb98,
1019 .bit = 9,
1020 },
1021 .la = {
1022 .reg = 0x3e8,
1023 .shift = 16,
1024 .mask = 0xff,
1025 .def = 0x80,
1026 },
1027 },
1028};
1029
1030static const struct tegra_smmu_swgroup tegra210_swgroups[] = {
1031 { .name = "dc", .swgroup = TEGRA_SWGROUP_DC, .reg = 0x240 },
1032 { .name = "dcb", .swgroup = TEGRA_SWGROUP_DCB, .reg = 0x244 },
1033 { .name = "afi", .swgroup = TEGRA_SWGROUP_AFI, .reg = 0x238 },
1034 { .name = "avpc", .swgroup = TEGRA_SWGROUP_AVPC, .reg = 0x23c },
1035 { .name = "hda", .swgroup = TEGRA_SWGROUP_HDA, .reg = 0x254 },
1036 { .name = "hc", .swgroup = TEGRA_SWGROUP_HC, .reg = 0x250 },
1037 { .name = "nvenc", .swgroup = TEGRA_SWGROUP_NVENC, .reg = 0x264 },
1038 { .name = "ppcs", .swgroup = TEGRA_SWGROUP_PPCS, .reg = 0x270 },
1039 { .name = "sata", .swgroup = TEGRA_SWGROUP_SATA, .reg = 0x274 },
1040 { .name = "isp2", .swgroup = TEGRA_SWGROUP_ISP2, .reg = 0x258 },
1041 { .name = "xusb_host", .swgroup = TEGRA_SWGROUP_XUSB_HOST, .reg = 0x288 },
1042 { .name = "xusb_dev", .swgroup = TEGRA_SWGROUP_XUSB_DEV, .reg = 0x28c },
1043 { .name = "isp2b", .swgroup = TEGRA_SWGROUP_ISP2B, .reg = 0xaa4 },
1044 { .name = "tsec", .swgroup = TEGRA_SWGROUP_TSEC, .reg = 0x294 },
1045 { .name = "a9avp", .swgroup = TEGRA_SWGROUP_A9AVP, .reg = 0x290 },
1046 { .name = "gpu", .swgroup = TEGRA_SWGROUP_GPU, .reg = 0xaac },
1047 { .name = "sdmmc1a", .swgroup = TEGRA_SWGROUP_SDMMC1A, .reg = 0xa94 },
1048 { .name = "sdmmc2a", .swgroup = TEGRA_SWGROUP_SDMMC2A, .reg = 0xa98 },
1049 { .name = "sdmmc3a", .swgroup = TEGRA_SWGROUP_SDMMC3A, .reg = 0xa9c },
1050 { .name = "sdmmc4a", .swgroup = TEGRA_SWGROUP_SDMMC4A, .reg = 0xaa0 },
1051 { .name = "vic", .swgroup = TEGRA_SWGROUP_VIC, .reg = 0x284 },
1052 { .name = "vi", .swgroup = TEGRA_SWGROUP_VI, .reg = 0x280 },
1053 { .name = "nvdec", .swgroup = TEGRA_SWGROUP_NVDEC, .reg = 0xab4 },
1054 { .name = "ape", .swgroup = TEGRA_SWGROUP_APE, .reg = 0xab8 },
1055 { .name = "nvjpg", .swgroup = TEGRA_SWGROUP_NVJPG, .reg = 0xac0 },
1056 { .name = "se", .swgroup = TEGRA_SWGROUP_SE, .reg = 0xabc },
1057 { .name = "axiap", .swgroup = TEGRA_SWGROUP_AXIAP, .reg = 0xacc },
1058 { .name = "etr", .swgroup = TEGRA_SWGROUP_ETR, .reg = 0xad0 },
1059 { .name = "tsecb", .swgroup = TEGRA_SWGROUP_TSECB, .reg = 0xad4 },
1060};
1061
1062static const struct tegra_smmu_soc tegra210_smmu_soc = {
1063 .clients = tegra210_mc_clients,
1064 .num_clients = ARRAY_SIZE(tegra210_mc_clients),
1065 .swgroups = tegra210_swgroups,
1066 .num_swgroups = ARRAY_SIZE(tegra210_swgroups),
1067 .supports_round_robin_arbitration = true,
1068 .supports_request_limit = true,
1069 .num_tlb_lines = 32,
1070 .num_asids = 128,
1071};
1072
1073const struct tegra_mc_soc tegra210_mc_soc = {
1074 .clients = tegra210_mc_clients,
1075 .num_clients = ARRAY_SIZE(tegra210_mc_clients),
1076 .num_address_bits = 34,
1077 .atom_size = 64,
1078 .client_id_mask = 0xff,
1079 .smmu = &tegra210_smmu_soc,
1080};
diff --git a/drivers/memory/tegra/tegra30.c b/drivers/memory/tegra/tegra30.c
index 1abcd8f6f3ba..52e16c7b34f8 100644
--- a/drivers/memory/tegra/tegra30.c
+++ b/drivers/memory/tegra/tegra30.c
@@ -966,5 +966,6 @@ const struct tegra_mc_soc tegra30_mc_soc = {
966 .num_clients = ARRAY_SIZE(tegra30_mc_clients), 966 .num_clients = ARRAY_SIZE(tegra30_mc_clients),
967 .num_address_bits = 32, 967 .num_address_bits = 32,
968 .atom_size = 16, 968 .atom_size = 16,
969 .client_id_mask = 0x7f,
969 .smmu = &tegra30_smmu_soc, 970 .smmu = &tegra30_smmu_soc,
970}; 971};
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 157d421f755b..85d5904e5480 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -1,5 +1,8 @@
1obj-$(CONFIG_RESET_CONTROLLER) += core.o 1obj-$(CONFIG_RESET_CONTROLLER) += core.o
2obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o
2obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o 3obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
3obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o 4obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
4obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o 5obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
5obj-$(CONFIG_ARCH_STI) += sti/ 6obj-$(CONFIG_ARCH_STI) += sti/
7obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o
8obj-$(CONFIG_ATH79) += reset-ath79.o
diff --git a/drivers/reset/reset-ath79.c b/drivers/reset/reset-ath79.c
new file mode 100644
index 000000000000..d2d290413113
--- /dev/null
+++ b/drivers/reset/reset-ath79.c
@@ -0,0 +1,128 @@
1/*
2 * Copyright (C) 2015 Alban Bedel <albeu@free.fr>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/module.h>
16#include <linux/platform_device.h>
17#include <linux/reset-controller.h>
18
19struct ath79_reset {
20 struct reset_controller_dev rcdev;
21 void __iomem *base;
22 spinlock_t lock;
23};
24
25static int ath79_reset_update(struct reset_controller_dev *rcdev,
26 unsigned long id, bool assert)
27{
28 struct ath79_reset *ath79_reset =
29 container_of(rcdev, struct ath79_reset, rcdev);
30 unsigned long flags;
31 u32 val;
32
33 spin_lock_irqsave(&ath79_reset->lock, flags);
34 val = readl(ath79_reset->base);
35 if (assert)
36 val |= BIT(id);
37 else
38 val &= ~BIT(id);
39 writel(val, ath79_reset->base);
40 spin_unlock_irqrestore(&ath79_reset->lock, flags);
41
42 return 0;
43}
44
45static int ath79_reset_assert(struct reset_controller_dev *rcdev,
46 unsigned long id)
47{
48 return ath79_reset_update(rcdev, id, true);
49}
50
51static int ath79_reset_deassert(struct reset_controller_dev *rcdev,
52 unsigned long id)
53{
54 return ath79_reset_update(rcdev, id, false);
55}
56
57static int ath79_reset_status(struct reset_controller_dev *rcdev,
58 unsigned long id)
59{
60 struct ath79_reset *ath79_reset =
61 container_of(rcdev, struct ath79_reset, rcdev);
62 u32 val;
63
64 val = readl(ath79_reset->base);
65
66 return !!(val & BIT(id));
67}
68
69static struct reset_control_ops ath79_reset_ops = {
70 .assert = ath79_reset_assert,
71 .deassert = ath79_reset_deassert,
72 .status = ath79_reset_status,
73};
74
75static int ath79_reset_probe(struct platform_device *pdev)
76{
77 struct ath79_reset *ath79_reset;
78 struct resource *res;
79
80 ath79_reset = devm_kzalloc(&pdev->dev,
81 sizeof(*ath79_reset), GFP_KERNEL);
82 if (!ath79_reset)
83 return -ENOMEM;
84
85 platform_set_drvdata(pdev, ath79_reset);
86
87 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
88 ath79_reset->base = devm_ioremap_resource(&pdev->dev, res);
89 if (IS_ERR(ath79_reset->base))
90 return PTR_ERR(ath79_reset->base);
91
92 ath79_reset->rcdev.ops = &ath79_reset_ops;
93 ath79_reset->rcdev.owner = THIS_MODULE;
94 ath79_reset->rcdev.of_node = pdev->dev.of_node;
95 ath79_reset->rcdev.of_reset_n_cells = 1;
96 ath79_reset->rcdev.nr_resets = 32;
97
98 return reset_controller_register(&ath79_reset->rcdev);
99}
100
101static int ath79_reset_remove(struct platform_device *pdev)
102{
103 struct ath79_reset *ath79_reset = platform_get_drvdata(pdev);
104
105 reset_controller_unregister(&ath79_reset->rcdev);
106
107 return 0;
108}
109
110static const struct of_device_id ath79_reset_dt_ids[] = {
111 { .compatible = "qca,ar7100-reset", },
112 { },
113};
114MODULE_DEVICE_TABLE(of, ath79_reset_dt_ids);
115
116static struct platform_driver ath79_reset_driver = {
117 .probe = ath79_reset_probe,
118 .remove = ath79_reset_remove,
119 .driver = {
120 .name = "ath79-reset",
121 .of_match_table = ath79_reset_dt_ids,
122 },
123};
124module_platform_driver(ath79_reset_driver);
125
126MODULE_AUTHOR("Alban Bedel <albeu@free.fr>");
127MODULE_DESCRIPTION("AR71xx Reset Controller Driver");
128MODULE_LICENSE("GPL");
diff --git a/drivers/reset/reset-lpc18xx.c b/drivers/reset/reset-lpc18xx.c
new file mode 100644
index 000000000000..70922e9ac27f
--- /dev/null
+++ b/drivers/reset/reset-lpc18xx.c
@@ -0,0 +1,258 @@
1/*
2 * Reset driver for NXP LPC18xx/43xx Reset Generation Unit (RGU).
3 *
4 * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 */
11
12#include <linux/clk.h>
13#include <linux/delay.h>
14#include <linux/err.h>
15#include <linux/io.h>
16#include <linux/module.h>
17#include <linux/of.h>
18#include <linux/platform_device.h>
19#include <linux/reboot.h>
20#include <linux/reset-controller.h>
21#include <linux/spinlock.h>
22
23/* LPC18xx RGU registers */
24#define LPC18XX_RGU_CTRL0 0x100
25#define LPC18XX_RGU_CTRL1 0x104
26#define LPC18XX_RGU_ACTIVE_STATUS0 0x150
27#define LPC18XX_RGU_ACTIVE_STATUS1 0x154
28
29#define LPC18XX_RGU_RESETS_PER_REG 32
30
31/* Internal reset outputs */
32#define LPC18XX_RGU_CORE_RST 0
33#define LPC43XX_RGU_M0SUB_RST 12
34#define LPC43XX_RGU_M0APP_RST 56
35
36struct lpc18xx_rgu_data {
37 struct reset_controller_dev rcdev;
38 struct clk *clk_delay;
39 struct clk *clk_reg;
40 void __iomem *base;
41 spinlock_t lock;
42 u32 delay_us;
43};
44
45#define to_rgu_data(p) container_of(p, struct lpc18xx_rgu_data, rcdev)
46
47static void __iomem *rgu_base;
48
49static int lpc18xx_rgu_restart(struct notifier_block *this, unsigned long mode,
50 void *cmd)
51{
52 writel(BIT(LPC18XX_RGU_CORE_RST), rgu_base + LPC18XX_RGU_CTRL0);
53 mdelay(2000);
54
55 pr_emerg("%s: unable to restart system\n", __func__);
56
57 return NOTIFY_DONE;
58}
59
60static struct notifier_block lpc18xx_rgu_restart_nb = {
61 .notifier_call = lpc18xx_rgu_restart,
62 .priority = 192,
63};
64
65/*
66 * The LPC18xx RGU has mostly self-deasserting resets except for the
67 * two reset lines going to the internal Cortex-M0 cores.
68 *
69 * To prevent the M0 core resets from accidentally getting deasserted
70 * status register must be check and bits in control register set to
71 * preserve the state.
72 */
73static int lpc18xx_rgu_setclear_reset(struct reset_controller_dev *rcdev,
74 unsigned long id, bool set)
75{
76 struct lpc18xx_rgu_data *rc = to_rgu_data(rcdev);
77 u32 stat_offset = LPC18XX_RGU_ACTIVE_STATUS0;
78 u32 ctrl_offset = LPC18XX_RGU_CTRL0;
79 unsigned long flags;
80 u32 stat, rst_bit;
81
82 stat_offset += (id / LPC18XX_RGU_RESETS_PER_REG) * sizeof(u32);
83 ctrl_offset += (id / LPC18XX_RGU_RESETS_PER_REG) * sizeof(u32);
84 rst_bit = 1 << (id % LPC18XX_RGU_RESETS_PER_REG);
85
86 spin_lock_irqsave(&rc->lock, flags);
87 stat = ~readl(rc->base + stat_offset);
88 if (set)
89 writel(stat | rst_bit, rc->base + ctrl_offset);
90 else
91 writel(stat & ~rst_bit, rc->base + ctrl_offset);
92 spin_unlock_irqrestore(&rc->lock, flags);
93
94 return 0;
95}
96
97static int lpc18xx_rgu_assert(struct reset_controller_dev *rcdev,
98 unsigned long id)
99{
100 return lpc18xx_rgu_setclear_reset(rcdev, id, true);
101}
102
103static int lpc18xx_rgu_deassert(struct reset_controller_dev *rcdev,
104 unsigned long id)
105{
106 return lpc18xx_rgu_setclear_reset(rcdev, id, false);
107}
108
109/* Only M0 cores require explicit reset deassert */
110static int lpc18xx_rgu_reset(struct reset_controller_dev *rcdev,
111 unsigned long id)
112{
113 struct lpc18xx_rgu_data *rc = to_rgu_data(rcdev);
114
115 lpc18xx_rgu_assert(rcdev, id);
116 udelay(rc->delay_us);
117
118 switch (id) {
119 case LPC43XX_RGU_M0SUB_RST:
120 case LPC43XX_RGU_M0APP_RST:
121 lpc18xx_rgu_setclear_reset(rcdev, id, false);
122 }
123
124 return 0;
125}
126
127static int lpc18xx_rgu_status(struct reset_controller_dev *rcdev,
128 unsigned long id)
129{
130 struct lpc18xx_rgu_data *rc = to_rgu_data(rcdev);
131 u32 bit, offset = LPC18XX_RGU_ACTIVE_STATUS0;
132
133 offset += (id / LPC18XX_RGU_RESETS_PER_REG) * sizeof(u32);
134 bit = 1 << (id % LPC18XX_RGU_RESETS_PER_REG);
135
136 return !(readl(rc->base + offset) & bit);
137}
138
139static struct reset_control_ops lpc18xx_rgu_ops = {
140 .reset = lpc18xx_rgu_reset,
141 .assert = lpc18xx_rgu_assert,
142 .deassert = lpc18xx_rgu_deassert,
143 .status = lpc18xx_rgu_status,
144};
145
146static int lpc18xx_rgu_probe(struct platform_device *pdev)
147{
148 struct lpc18xx_rgu_data *rc;
149 struct resource *res;
150 u32 fcclk, firc;
151 int ret;
152
153 rc = devm_kzalloc(&pdev->dev, sizeof(*rc), GFP_KERNEL);
154 if (!rc)
155 return -ENOMEM;
156
157 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
158 rc->base = devm_ioremap_resource(&pdev->dev, res);
159 if (IS_ERR(rc->base))
160 return PTR_ERR(rc->base);
161
162 rc->clk_reg = devm_clk_get(&pdev->dev, "reg");
163 if (IS_ERR(rc->clk_reg)) {
164 dev_err(&pdev->dev, "reg clock not found\n");
165 return PTR_ERR(rc->clk_reg);
166 }
167
168 rc->clk_delay = devm_clk_get(&pdev->dev, "delay");
169 if (IS_ERR(rc->clk_delay)) {
170 dev_err(&pdev->dev, "delay clock not found\n");
171 return PTR_ERR(rc->clk_delay);
172 }
173
174 ret = clk_prepare_enable(rc->clk_reg);
175 if (ret) {
176 dev_err(&pdev->dev, "unable to enable reg clock\n");
177 return ret;
178 }
179
180 ret = clk_prepare_enable(rc->clk_delay);
181 if (ret) {
182 dev_err(&pdev->dev, "unable to enable delay clock\n");
183 goto dis_clk_reg;
184 }
185
186 fcclk = clk_get_rate(rc->clk_reg) / USEC_PER_SEC;
187 firc = clk_get_rate(rc->clk_delay) / USEC_PER_SEC;
188 if (fcclk == 0 || firc == 0)
189 rc->delay_us = 2;
190 else
191 rc->delay_us = DIV_ROUND_UP(fcclk, firc * firc);
192
193 spin_lock_init(&rc->lock);
194
195 rc->rcdev.owner = THIS_MODULE;
196 rc->rcdev.nr_resets = 64;
197 rc->rcdev.ops = &lpc18xx_rgu_ops;
198 rc->rcdev.of_node = pdev->dev.of_node;
199
200 platform_set_drvdata(pdev, rc);
201
202 ret = reset_controller_register(&rc->rcdev);
203 if (ret) {
204 dev_err(&pdev->dev, "unable to register device\n");
205 goto dis_clks;
206 }
207
208 rgu_base = rc->base;
209 ret = register_restart_handler(&lpc18xx_rgu_restart_nb);
210 if (ret)
211 dev_warn(&pdev->dev, "failed to register restart handler\n");
212
213 return 0;
214
215dis_clks:
216 clk_disable_unprepare(rc->clk_delay);
217dis_clk_reg:
218 clk_disable_unprepare(rc->clk_reg);
219
220 return ret;
221}
222
223static int lpc18xx_rgu_remove(struct platform_device *pdev)
224{
225 struct lpc18xx_rgu_data *rc = platform_get_drvdata(pdev);
226 int ret;
227
228 ret = unregister_restart_handler(&lpc18xx_rgu_restart_nb);
229 if (ret)
230 dev_warn(&pdev->dev, "failed to unregister restart handler\n");
231
232 reset_controller_unregister(&rc->rcdev);
233
234 clk_disable_unprepare(rc->clk_delay);
235 clk_disable_unprepare(rc->clk_reg);
236
237 return 0;
238}
239
240static const struct of_device_id lpc18xx_rgu_match[] = {
241 { .compatible = "nxp,lpc1850-rgu" },
242 { }
243};
244MODULE_DEVICE_TABLE(of, lpc18xx_rgu_match);
245
246static struct platform_driver lpc18xx_rgu_driver = {
247 .probe = lpc18xx_rgu_probe,
248 .remove = lpc18xx_rgu_remove,
249 .driver = {
250 .name = "lpc18xx-reset",
251 .of_match_table = lpc18xx_rgu_match,
252 },
253};
254module_platform_driver(lpc18xx_rgu_driver);
255
256MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
257MODULE_DESCRIPTION("Reset driver for LPC18xx/43xx RGU");
258MODULE_LICENSE("GPL v2");
diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
index 0a8def35ea2e..1a6c5d66c83b 100644
--- a/drivers/reset/reset-socfpga.c
+++ b/drivers/reset/reset-socfpga.c
@@ -24,11 +24,11 @@
24#include <linux/types.h> 24#include <linux/types.h>
25 25
26#define NR_BANKS 4 26#define NR_BANKS 4
27#define OFFSET_MODRST 0x10
28 27
29struct socfpga_reset_data { 28struct socfpga_reset_data {
30 spinlock_t lock; 29 spinlock_t lock;
31 void __iomem *membase; 30 void __iomem *membase;
31 u32 modrst_offset;
32 struct reset_controller_dev rcdev; 32 struct reset_controller_dev rcdev;
33}; 33};
34 34
@@ -45,8 +45,8 @@ static int socfpga_reset_assert(struct reset_controller_dev *rcdev,
45 45
46 spin_lock_irqsave(&data->lock, flags); 46 spin_lock_irqsave(&data->lock, flags);
47 47
48 reg = readl(data->membase + OFFSET_MODRST + (bank * NR_BANKS)); 48 reg = readl(data->membase + data->modrst_offset + (bank * NR_BANKS));
49 writel(reg | BIT(offset), data->membase + OFFSET_MODRST + 49 writel(reg | BIT(offset), data->membase + data->modrst_offset +
50 (bank * NR_BANKS)); 50 (bank * NR_BANKS));
51 spin_unlock_irqrestore(&data->lock, flags); 51 spin_unlock_irqrestore(&data->lock, flags);
52 52
@@ -67,8 +67,8 @@ static int socfpga_reset_deassert(struct reset_controller_dev *rcdev,
67 67
68 spin_lock_irqsave(&data->lock, flags); 68 spin_lock_irqsave(&data->lock, flags);
69 69
70 reg = readl(data->membase + OFFSET_MODRST + (bank * NR_BANKS)); 70 reg = readl(data->membase + data->modrst_offset + (bank * NR_BANKS));
71 writel(reg & ~BIT(offset), data->membase + OFFSET_MODRST + 71 writel(reg & ~BIT(offset), data->membase + data->modrst_offset +
72 (bank * NR_BANKS)); 72 (bank * NR_BANKS));
73 73
74 spin_unlock_irqrestore(&data->lock, flags); 74 spin_unlock_irqrestore(&data->lock, flags);
@@ -85,7 +85,7 @@ static int socfpga_reset_status(struct reset_controller_dev *rcdev,
85 int offset = id % BITS_PER_LONG; 85 int offset = id % BITS_PER_LONG;
86 u32 reg; 86 u32 reg;
87 87
88 reg = readl(data->membase + OFFSET_MODRST + (bank * NR_BANKS)); 88 reg = readl(data->membase + data->modrst_offset + (bank * NR_BANKS));
89 89
90 return !(reg & BIT(offset)); 90 return !(reg & BIT(offset));
91} 91}
@@ -100,6 +100,8 @@ static int socfpga_reset_probe(struct platform_device *pdev)
100{ 100{
101 struct socfpga_reset_data *data; 101 struct socfpga_reset_data *data;
102 struct resource *res; 102 struct resource *res;
103 struct device *dev = &pdev->dev;
104 struct device_node *np = dev->of_node;
103 105
104 /* 106 /*
105 * The binding was mainlined without the required property. 107 * The binding was mainlined without the required property.
@@ -120,6 +122,11 @@ static int socfpga_reset_probe(struct platform_device *pdev)
120 if (IS_ERR(data->membase)) 122 if (IS_ERR(data->membase))
121 return PTR_ERR(data->membase); 123 return PTR_ERR(data->membase);
122 124
125 if (of_property_read_u32(np, "altr,modrst-offset", &data->modrst_offset)) {
126 dev_warn(dev, "missing altr,modrst-offset property, assuming 0x10!\n");
127 data->modrst_offset = 0x10;
128 }
129
123 spin_lock_init(&data->lock); 130 spin_lock_init(&data->lock);
124 131
125 data->rcdev.owner = THIS_MODULE; 132 data->rcdev.owner = THIS_MODULE;
diff --git a/drivers/reset/reset-zynq.c b/drivers/reset/reset-zynq.c
new file mode 100644
index 000000000000..89318a5d5bd7
--- /dev/null
+++ b/drivers/reset/reset-zynq.c
@@ -0,0 +1,155 @@
1/*
2 * Copyright (c) 2015, National Instruments Corp.
3 *
4 * Xilinx Zynq Reset controller driver
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <linux/err.h>
17#include <linux/io.h>
18#include <linux/module.h>
19#include <linux/mfd/syscon.h>
20#include <linux/of.h>
21#include <linux/platform_device.h>
22#include <linux/reset-controller.h>
23#include <linux/regmap.h>
24#include <linux/types.h>
25
26struct zynq_reset_data {
27 struct regmap *slcr;
28 struct reset_controller_dev rcdev;
29 u32 offset;
30};
31
32#define to_zynq_reset_data(p) \
33 container_of((p), struct zynq_reset_data, rcdev)
34
35static int zynq_reset_assert(struct reset_controller_dev *rcdev,
36 unsigned long id)
37{
38 struct zynq_reset_data *priv = to_zynq_reset_data(rcdev);
39
40 int bank = id / BITS_PER_LONG;
41 int offset = id % BITS_PER_LONG;
42
43 pr_debug("%s: %s reset bank %u offset %u\n", KBUILD_MODNAME, __func__,
44 bank, offset);
45
46 return regmap_update_bits(priv->slcr,
47 priv->offset + (bank * 4),
48 BIT(offset),
49 BIT(offset));
50}
51
52static int zynq_reset_deassert(struct reset_controller_dev *rcdev,
53 unsigned long id)
54{
55 struct zynq_reset_data *priv = to_zynq_reset_data(rcdev);
56
57 int bank = id / BITS_PER_LONG;
58 int offset = id % BITS_PER_LONG;
59
60 pr_debug("%s: %s reset bank %u offset %u\n", KBUILD_MODNAME, __func__,
61 bank, offset);
62
63 return regmap_update_bits(priv->slcr,
64 priv->offset + (bank * 4),
65 BIT(offset),
66 ~BIT(offset));
67}
68
69static int zynq_reset_status(struct reset_controller_dev *rcdev,
70 unsigned long id)
71{
72 struct zynq_reset_data *priv = to_zynq_reset_data(rcdev);
73
74 int bank = id / BITS_PER_LONG;
75 int offset = id % BITS_PER_LONG;
76 int ret;
77 u32 reg;
78
79 pr_debug("%s: %s reset bank %u offset %u\n", KBUILD_MODNAME, __func__,
80 bank, offset);
81
82 ret = regmap_read(priv->slcr, priv->offset + (bank * 4), &reg);
83 if (ret)
84 return ret;
85
86 return !!(reg & BIT(offset));
87}
88
89static struct reset_control_ops zynq_reset_ops = {
90 .assert = zynq_reset_assert,
91 .deassert = zynq_reset_deassert,
92 .status = zynq_reset_status,
93};
94
95static int zynq_reset_probe(struct platform_device *pdev)
96{
97 struct resource *res;
98 struct zynq_reset_data *priv;
99
100 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
101 if (!priv)
102 return -ENOMEM;
103 platform_set_drvdata(pdev, priv);
104
105 priv->slcr = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
106 "syscon");
107 if (IS_ERR(priv->slcr)) {
108 dev_err(&pdev->dev, "unable to get zynq-slcr regmap");
109 return PTR_ERR(priv->slcr);
110 }
111
112 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
113 if (!res) {
114 dev_err(&pdev->dev, "missing IO resource\n");
115 return -ENODEV;
116 }
117
118 priv->offset = res->start;
119
120 priv->rcdev.owner = THIS_MODULE;
121 priv->rcdev.nr_resets = resource_size(res) / 4 * BITS_PER_LONG;
122 priv->rcdev.ops = &zynq_reset_ops;
123 priv->rcdev.of_node = pdev->dev.of_node;
124 reset_controller_register(&priv->rcdev);
125
126 return 0;
127}
128
129static int zynq_reset_remove(struct platform_device *pdev)
130{
131 struct zynq_reset_data *priv = platform_get_drvdata(pdev);
132
133 reset_controller_unregister(&priv->rcdev);
134
135 return 0;
136}
137
138static const struct of_device_id zynq_reset_dt_ids[] = {
139 { .compatible = "xlnx,zynq-reset", },
140 { /* sentinel */ },
141};
142
143static struct platform_driver zynq_reset_driver = {
144 .probe = zynq_reset_probe,
145 .remove = zynq_reset_remove,
146 .driver = {
147 .name = KBUILD_MODNAME,
148 .of_match_table = zynq_reset_dt_ids,
149 },
150};
151module_platform_driver(zynq_reset_driver);
152
153MODULE_LICENSE("GPL v2");
154MODULE_AUTHOR("Moritz Fischer <moritz.fischer@ettus.com>");
155MODULE_DESCRIPTION("Zynq Reset Controller Driver");
diff --git a/drivers/reset/sti/reset-stih407.c b/drivers/reset/sti/reset-stih407.c
index d83db5d72d08..827eb3dae47d 100644
--- a/drivers/reset/sti/reset-stih407.c
+++ b/drivers/reset/sti/reset-stih407.c
@@ -11,7 +11,7 @@
11#include <linux/of.h> 11#include <linux/of.h>
12#include <linux/of_platform.h> 12#include <linux/of_platform.h>
13#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <dt-bindings/reset-controller/stih407-resets.h> 14#include <dt-bindings/reset/stih407-resets.h>
15#include "reset-syscfg.h" 15#include "reset-syscfg.h"
16 16
17/* STiH407 Peripheral powerdown definitions. */ 17/* STiH407 Peripheral powerdown definitions. */
@@ -126,7 +126,7 @@ static const struct syscfg_reset_controller_data stih407_picophyreset_controller
126 .channels = stih407_picophyresets, 126 .channels = stih407_picophyresets,
127}; 127};
128 128
129static struct of_device_id stih407_reset_match[] = { 129static const struct of_device_id stih407_reset_match[] = {
130 { 130 {
131 .compatible = "st,stih407-powerdown", 131 .compatible = "st,stih407-powerdown",
132 .data = &stih407_powerdown_controller, 132 .data = &stih407_powerdown_controller,
diff --git a/drivers/reset/sti/reset-stih415.c b/drivers/reset/sti/reset-stih415.c
index 8dad603d863c..6f220cdbef46 100644
--- a/drivers/reset/sti/reset-stih415.c
+++ b/drivers/reset/sti/reset-stih415.c
@@ -13,7 +13,7 @@
13#include <linux/of_platform.h> 13#include <linux/of_platform.h>
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15 15
16#include <dt-bindings/reset-controller/stih415-resets.h> 16#include <dt-bindings/reset/stih415-resets.h>
17 17
18#include "reset-syscfg.h" 18#include "reset-syscfg.h"
19 19
@@ -89,7 +89,7 @@ static struct syscfg_reset_controller_data stih415_softreset_controller = {
89 .channels = stih415_softresets, 89 .channels = stih415_softresets,
90}; 90};
91 91
92static struct of_device_id stih415_reset_match[] = { 92static const struct of_device_id stih415_reset_match[] = {
93 { .compatible = "st,stih415-powerdown", 93 { .compatible = "st,stih415-powerdown",
94 .data = &stih415_powerdown_controller, }, 94 .data = &stih415_powerdown_controller, },
95 { .compatible = "st,stih415-softreset", 95 { .compatible = "st,stih415-softreset",
diff --git a/drivers/reset/sti/reset-stih416.c b/drivers/reset/sti/reset-stih416.c
index 79aed70a26c0..c581d606ef0f 100644
--- a/drivers/reset/sti/reset-stih416.c
+++ b/drivers/reset/sti/reset-stih416.c
@@ -13,7 +13,7 @@
13#include <linux/of_platform.h> 13#include <linux/of_platform.h>
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15 15
16#include <dt-bindings/reset-controller/stih416-resets.h> 16#include <dt-bindings/reset/stih416-resets.h>
17 17
18#include "reset-syscfg.h" 18#include "reset-syscfg.h"
19 19
@@ -120,7 +120,7 @@ static struct syscfg_reset_controller_data stih416_softreset_controller = {
120 .channels = stih416_softresets, 120 .channels = stih416_softresets,
121}; 121};
122 122
123static struct of_device_id stih416_reset_match[] = { 123static const struct of_device_id stih416_reset_match[] = {
124 { .compatible = "st,stih416-powerdown", 124 { .compatible = "st,stih416-powerdown",
125 .data = &stih416_powerdown_controller, }, 125 .data = &stih416_powerdown_controller, },
126 { .compatible = "st,stih416-softreset", 126 { .compatible = "st,stih416-softreset",
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 7dc7c0d8a2c1..0b12d777d3c4 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -2,6 +2,7 @@
2# Makefile for the Linux Kernel SOC specific device drivers. 2# Makefile for the Linux Kernel SOC specific device drivers.
3# 3#
4 4
5obj-$(CONFIG_MACH_DOVE) += dove/
5obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ 6obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
6obj-$(CONFIG_ARCH_QCOM) += qcom/ 7obj-$(CONFIG_ARCH_QCOM) += qcom/
7obj-$(CONFIG_ARCH_SUNXI) += sunxi/ 8obj-$(CONFIG_ARCH_SUNXI) += sunxi/
diff --git a/drivers/soc/dove/Makefile b/drivers/soc/dove/Makefile
new file mode 100644
index 000000000000..2db8e65513a3
--- /dev/null
+++ b/drivers/soc/dove/Makefile
@@ -0,0 +1 @@
obj-y += pmu.o
diff --git a/drivers/soc/dove/pmu.c b/drivers/soc/dove/pmu.c
new file mode 100644
index 000000000000..6792aae9e2e5
--- /dev/null
+++ b/drivers/soc/dove/pmu.c
@@ -0,0 +1,412 @@
1/*
2 * Marvell Dove PMU support
3 */
4#include <linux/io.h>
5#include <linux/irq.h>
6#include <linux/irqdomain.h>
7#include <linux/of.h>
8#include <linux/of_irq.h>
9#include <linux/of_address.h>
10#include <linux/platform_device.h>
11#include <linux/pm_domain.h>
12#include <linux/reset.h>
13#include <linux/reset-controller.h>
14#include <linux/sched.h>
15#include <linux/slab.h>
16#include <linux/soc/dove/pmu.h>
17#include <linux/spinlock.h>
18
19#define NR_PMU_IRQS 7
20
21#define PMC_SW_RST 0x30
22#define PMC_IRQ_CAUSE 0x50
23#define PMC_IRQ_MASK 0x54
24
25#define PMU_PWR 0x10
26#define PMU_ISO 0x58
27
28struct pmu_data {
29 spinlock_t lock;
30 struct device_node *of_node;
31 void __iomem *pmc_base;
32 void __iomem *pmu_base;
33 struct irq_chip_generic *irq_gc;
34 struct irq_domain *irq_domain;
35#ifdef CONFIG_RESET_CONTROLLER
36 struct reset_controller_dev reset;
37#endif
38};
39
40/*
41 * The PMU contains a register to reset various subsystems within the
42 * SoC. Export this as a reset controller.
43 */
44#ifdef CONFIG_RESET_CONTROLLER
45#define rcdev_to_pmu(rcdev) container_of(rcdev, struct pmu_data, reset)
46
47static int pmu_reset_reset(struct reset_controller_dev *rc, unsigned long id)
48{
49 struct pmu_data *pmu = rcdev_to_pmu(rc);
50 unsigned long flags;
51 u32 val;
52
53 spin_lock_irqsave(&pmu->lock, flags);
54 val = readl_relaxed(pmu->pmc_base + PMC_SW_RST);
55 writel_relaxed(val & ~BIT(id), pmu->pmc_base + PMC_SW_RST);
56 writel_relaxed(val | BIT(id), pmu->pmc_base + PMC_SW_RST);
57 spin_unlock_irqrestore(&pmu->lock, flags);
58
59 return 0;
60}
61
62static int pmu_reset_assert(struct reset_controller_dev *rc, unsigned long id)
63{
64 struct pmu_data *pmu = rcdev_to_pmu(rc);
65 unsigned long flags;
66 u32 val = ~BIT(id);
67
68 spin_lock_irqsave(&pmu->lock, flags);
69 val &= readl_relaxed(pmu->pmc_base + PMC_SW_RST);
70 writel_relaxed(val, pmu->pmc_base + PMC_SW_RST);
71 spin_unlock_irqrestore(&pmu->lock, flags);
72
73 return 0;
74}
75
76static int pmu_reset_deassert(struct reset_controller_dev *rc, unsigned long id)
77{
78 struct pmu_data *pmu = rcdev_to_pmu(rc);
79 unsigned long flags;
80 u32 val = BIT(id);
81
82 spin_lock_irqsave(&pmu->lock, flags);
83 val |= readl_relaxed(pmu->pmc_base + PMC_SW_RST);
84 writel_relaxed(val, pmu->pmc_base + PMC_SW_RST);
85 spin_unlock_irqrestore(&pmu->lock, flags);
86
87 return 0;
88}
89
90static struct reset_control_ops pmu_reset_ops = {
91 .reset = pmu_reset_reset,
92 .assert = pmu_reset_assert,
93 .deassert = pmu_reset_deassert,
94};
95
96static struct reset_controller_dev pmu_reset __initdata = {
97 .ops = &pmu_reset_ops,
98 .owner = THIS_MODULE,
99 .nr_resets = 32,
100};
101
102static void __init pmu_reset_init(struct pmu_data *pmu)
103{
104 int ret;
105
106 pmu->reset = pmu_reset;
107 pmu->reset.of_node = pmu->of_node;
108
109 ret = reset_controller_register(&pmu->reset);
110 if (ret)
111 pr_err("pmu: %s failed: %d\n", "reset_controller_register", ret);
112}
113#else
114static void __init pmu_reset_init(struct pmu_data *pmu)
115{
116}
117#endif
118
119struct pmu_domain {
120 struct pmu_data *pmu;
121 u32 pwr_mask;
122 u32 rst_mask;
123 u32 iso_mask;
124 struct generic_pm_domain base;
125};
126
127#define to_pmu_domain(dom) container_of(dom, struct pmu_domain, base)
128
129/*
130 * This deals with the "old" Marvell sequence of bringing a power domain
131 * down/up, which is: apply power, release reset, disable isolators.
132 *
133 * Later devices apparantly use a different sequence: power up, disable
134 * isolators, assert repair signal, enable SRMA clock, enable AXI clock,
135 * enable module clock, deassert reset.
136 *
137 * Note: reading the assembly, it seems that the IO accessors have an
138 * unfortunate side-effect - they cause memory already read into registers
139 * for the if () to be re-read for the bit-set or bit-clear operation.
140 * The code is written to avoid this.
141 */
142static int pmu_domain_power_off(struct generic_pm_domain *domain)
143{
144 struct pmu_domain *pmu_dom = to_pmu_domain(domain);
145 struct pmu_data *pmu = pmu_dom->pmu;
146 unsigned long flags;
147 unsigned int val;
148 void __iomem *pmu_base = pmu->pmu_base;
149 void __iomem *pmc_base = pmu->pmc_base;
150
151 spin_lock_irqsave(&pmu->lock, flags);
152
153 /* Enable isolators */
154 if (pmu_dom->iso_mask) {
155 val = ~pmu_dom->iso_mask;
156 val &= readl_relaxed(pmu_base + PMU_ISO);
157 writel_relaxed(val, pmu_base + PMU_ISO);
158 }
159
160 /* Reset unit */
161 if (pmu_dom->rst_mask) {
162 val = ~pmu_dom->rst_mask;
163 val &= readl_relaxed(pmc_base + PMC_SW_RST);
164 writel_relaxed(val, pmc_base + PMC_SW_RST);
165 }
166
167 /* Power down */
168 val = readl_relaxed(pmu_base + PMU_PWR) | pmu_dom->pwr_mask;
169 writel_relaxed(val, pmu_base + PMU_PWR);
170
171 spin_unlock_irqrestore(&pmu->lock, flags);
172
173 return 0;
174}
175
176static int pmu_domain_power_on(struct generic_pm_domain *domain)
177{
178 struct pmu_domain *pmu_dom = to_pmu_domain(domain);
179 struct pmu_data *pmu = pmu_dom->pmu;
180 unsigned long flags;
181 unsigned int val;
182 void __iomem *pmu_base = pmu->pmu_base;
183 void __iomem *pmc_base = pmu->pmc_base;
184
185 spin_lock_irqsave(&pmu->lock, flags);
186
187 /* Power on */
188 val = ~pmu_dom->pwr_mask & readl_relaxed(pmu_base + PMU_PWR);
189 writel_relaxed(val, pmu_base + PMU_PWR);
190
191 /* Release reset */
192 if (pmu_dom->rst_mask) {
193 val = pmu_dom->rst_mask;
194 val |= readl_relaxed(pmc_base + PMC_SW_RST);
195 writel_relaxed(val, pmc_base + PMC_SW_RST);
196 }
197
198 /* Disable isolators */
199 if (pmu_dom->iso_mask) {
200 val = pmu_dom->iso_mask;
201 val |= readl_relaxed(pmu_base + PMU_ISO);
202 writel_relaxed(val, pmu_base + PMU_ISO);
203 }
204
205 spin_unlock_irqrestore(&pmu->lock, flags);
206
207 return 0;
208}
209
210static void __pmu_domain_register(struct pmu_domain *domain,
211 struct device_node *np)
212{
213 unsigned int val = readl_relaxed(domain->pmu->pmu_base + PMU_PWR);
214
215 domain->base.power_off = pmu_domain_power_off;
216 domain->base.power_on = pmu_domain_power_on;
217
218 pm_genpd_init(&domain->base, NULL, !(val & domain->pwr_mask));
219
220 if (np)
221 of_genpd_add_provider_simple(np, &domain->base);
222}
223
224/* PMU IRQ controller */
225static void pmu_irq_handler(unsigned int irq, struct irq_desc *desc)
226{
227 struct pmu_data *pmu = irq_get_handler_data(irq);
228 struct irq_chip_generic *gc = pmu->irq_gc;
229 struct irq_domain *domain = pmu->irq_domain;
230 void __iomem *base = gc->reg_base;
231 u32 stat = readl_relaxed(base + PMC_IRQ_CAUSE) & gc->mask_cache;
232 u32 done = ~0;
233
234 if (stat == 0) {
235 handle_bad_irq(irq, desc);
236 return;
237 }
238
239 while (stat) {
240 u32 hwirq = fls(stat) - 1;
241
242 stat &= ~(1 << hwirq);
243 done &= ~(1 << hwirq);
244
245 generic_handle_irq(irq_find_mapping(domain, hwirq));
246 }
247
248 /*
249 * The PMU mask register is not RW0C: it is RW. This means that
250 * the bits take whatever value is written to them; if you write
251 * a '1', you will set the interrupt.
252 *
253 * Unfortunately this means there is NO race free way to clear
254 * these interrupts.
255 *
256 * So, let's structure the code so that the window is as small as
257 * possible.
258 */
259 irq_gc_lock(gc);
260 done &= readl_relaxed(base + PMC_IRQ_CAUSE);
261 writel_relaxed(done, base + PMC_IRQ_CAUSE);
262 irq_gc_unlock(gc);
263}
264
265static int __init dove_init_pmu_irq(struct pmu_data *pmu, int irq)
266{
267 const char *name = "pmu_irq";
268 struct irq_chip_generic *gc;
269 struct irq_domain *domain;
270 int ret;
271
272 /* mask and clear all interrupts */
273 writel(0, pmu->pmc_base + PMC_IRQ_MASK);
274 writel(0, pmu->pmc_base + PMC_IRQ_CAUSE);
275
276 domain = irq_domain_add_linear(pmu->of_node, NR_PMU_IRQS,
277 &irq_generic_chip_ops, NULL);
278 if (!domain) {
279 pr_err("%s: unable to add irq domain\n", name);
280 return -ENOMEM;
281 }
282
283 ret = irq_alloc_domain_generic_chips(domain, NR_PMU_IRQS, 1, name,
284 handle_level_irq,
285 IRQ_NOREQUEST | IRQ_NOPROBE, 0,
286 IRQ_GC_INIT_MASK_CACHE);
287 if (ret) {
288 pr_err("%s: unable to alloc irq domain gc: %d\n", name, ret);
289 irq_domain_remove(domain);
290 return ret;
291 }
292
293 gc = irq_get_domain_generic_chip(domain, 0);
294 gc->reg_base = pmu->pmc_base;
295 gc->chip_types[0].regs.mask = PMC_IRQ_MASK;
296 gc->chip_types[0].chip.irq_mask = irq_gc_mask_clr_bit;
297 gc->chip_types[0].chip.irq_unmask = irq_gc_mask_set_bit;
298
299 pmu->irq_domain = domain;
300 pmu->irq_gc = gc;
301
302 irq_set_handler_data(irq, pmu);
303 irq_set_chained_handler(irq, pmu_irq_handler);
304
305 return 0;
306}
307
308/*
309 * pmu: power-manager@d0000 {
310 * compatible = "marvell,dove-pmu";
311 * reg = <0xd0000 0x8000> <0xd8000 0x8000>;
312 * interrupts = <33>;
313 * interrupt-controller;
314 * #reset-cells = 1;
315 * vpu_domain: vpu-domain {
316 * #power-domain-cells = <0>;
317 * marvell,pmu_pwr_mask = <0x00000008>;
318 * marvell,pmu_iso_mask = <0x00000001>;
319 * resets = <&pmu 16>;
320 * };
321 * gpu_domain: gpu-domain {
322 * #power-domain-cells = <0>;
323 * marvell,pmu_pwr_mask = <0x00000004>;
324 * marvell,pmu_iso_mask = <0x00000002>;
325 * resets = <&pmu 18>;
326 * };
327 * };
328 */
329int __init dove_init_pmu(void)
330{
331 struct device_node *np_pmu, *domains_node, *np;
332 struct pmu_data *pmu;
333 int ret, parent_irq;
334
335 /* Lookup the PMU node */
336 np_pmu = of_find_compatible_node(NULL, NULL, "marvell,dove-pmu");
337 if (!np_pmu)
338 return 0;
339
340 domains_node = of_get_child_by_name(np_pmu, "domains");
341 if (!domains_node) {
342 pr_err("%s: failed to find domains sub-node\n", np_pmu->name);
343 return 0;
344 }
345
346 pmu = kzalloc(sizeof(*pmu), GFP_KERNEL);
347 if (!pmu)
348 return -ENOMEM;
349
350 spin_lock_init(&pmu->lock);
351 pmu->of_node = np_pmu;
352 pmu->pmc_base = of_iomap(pmu->of_node, 0);
353 pmu->pmu_base = of_iomap(pmu->of_node, 1);
354 if (!pmu->pmc_base || !pmu->pmu_base) {
355 pr_err("%s: failed to map PMU\n", np_pmu->name);
356 iounmap(pmu->pmu_base);
357 iounmap(pmu->pmc_base);
358 kfree(pmu);
359 return -ENOMEM;
360 }
361
362 pmu_reset_init(pmu);
363
364 for_each_available_child_of_node(domains_node, np) {
365 struct of_phandle_args args;
366 struct pmu_domain *domain;
367
368 domain = kzalloc(sizeof(*domain), GFP_KERNEL);
369 if (!domain)
370 break;
371
372 domain->pmu = pmu;
373 domain->base.name = kstrdup(np->name, GFP_KERNEL);
374 if (!domain->base.name) {
375 kfree(domain);
376 break;
377 }
378
379 of_property_read_u32(np, "marvell,pmu_pwr_mask",
380 &domain->pwr_mask);
381 of_property_read_u32(np, "marvell,pmu_iso_mask",
382 &domain->iso_mask);
383
384 /*
385 * We parse the reset controller property directly here
386 * to ensure that we can operate when the reset controller
387 * support is not configured into the kernel.
388 */
389 ret = of_parse_phandle_with_args(np, "resets", "#reset-cells",
390 0, &args);
391 if (ret == 0) {
392 if (args.np == pmu->of_node)
393 domain->rst_mask = BIT(args.args[0]);
394 of_node_put(args.np);
395 }
396
397 __pmu_domain_register(domain, np);
398 }
399 pm_genpd_poweroff_unused();
400
401 /* Loss of the interrupt controller is not a fatal error. */
402 parent_irq = irq_of_parse_and_map(pmu->of_node, 0);
403 if (!parent_irq) {
404 pr_err("%s: no interrupt specified\n", np_pmu->name);
405 } else {
406 ret = dove_init_pmu_irq(pmu, parent_irq);
407 if (ret)
408 pr_err("dove_init_pmu_irq() failed: %d\n", ret);
409 }
410
411 return 0;
412}
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 5eea374c8fa6..ba47b70f4d85 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -13,7 +13,38 @@ config QCOM_GSBI
13config QCOM_PM 13config QCOM_PM
14 bool "Qualcomm Power Management" 14 bool "Qualcomm Power Management"
15 depends on ARCH_QCOM && !ARM64 15 depends on ARCH_QCOM && !ARM64
16 select QCOM_SCM
16 help 17 help
17 QCOM Platform specific power driver to manage cores and L2 low power 18 QCOM Platform specific power driver to manage cores and L2 low power
18 modes. It interface with various system drivers to put the cores in 19 modes. It interface with various system drivers to put the cores in
19 low power modes. 20 low power modes.
21
22config QCOM_SMD
23 tristate "Qualcomm Shared Memory Driver (SMD)"
24 depends on QCOM_SMEM
25 help
26 Say y here to enable support for the Qualcomm Shared Memory Driver
27 providing communication channels to remote processors in Qualcomm
28 platforms.
29
30config QCOM_SMD_RPM
31 tristate "Qualcomm Resource Power Manager (RPM) over SMD"
32 depends on QCOM_SMD && OF
33 help
34 If you say yes to this option, support will be included for the
35 Resource Power Manager system found in the Qualcomm 8974 based
36 devices.
37
38 This is required to access many regulators, clocks and bus
39 frequencies controlled by the RPM on these devices.
40
41 Say M here if you want to include support for the Qualcomm RPM as a
42 module. This will build a module called "qcom-smd-rpm".
43
44config QCOM_SMEM
45 tristate "Qualcomm Shared Memory Manager (SMEM)"
46 depends on ARCH_QCOM
47 help
48 Say y here to enable support for the Qualcomm Shared Memory Manager.
49 The driver provides an interface to items in a heap shared among all
50 processors in a Qualcomm platform.
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 931d385386c5..10a93d168e0e 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -1,2 +1,5 @@
1obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o 1obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
2obj-$(CONFIG_QCOM_PM) += spm.o 2obj-$(CONFIG_QCOM_PM) += spm.o
3obj-$(CONFIG_QCOM_SMD) += smd.o
4obj-$(CONFIG_QCOM_SMD_RPM) += smd-rpm.o
5obj-$(CONFIG_QCOM_SMEM) += smem.o
diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
new file mode 100644
index 000000000000..1392ccf14a20
--- /dev/null
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -0,0 +1,244 @@
1/*
2 * Copyright (c) 2015, Sony Mobile Communications AB.
3 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 and
7 * only version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/module.h>
16#include <linux/platform_device.h>
17#include <linux/of_platform.h>
18#include <linux/io.h>
19#include <linux/interrupt.h>
20
21#include <linux/soc/qcom/smd.h>
22#include <linux/soc/qcom/smd-rpm.h>
23
24#define RPM_REQUEST_TIMEOUT (5 * HZ)
25
26/**
27 * struct qcom_smd_rpm - state of the rpm device driver
28 * @rpm_channel: reference to the smd channel
29 * @ack: completion for acks
30 * @lock: mutual exclusion around the send/complete pair
31 * @ack_status: result of the rpm request
32 */
33struct qcom_smd_rpm {
34 struct qcom_smd_channel *rpm_channel;
35
36 struct completion ack;
37 struct mutex lock;
38 int ack_status;
39};
40
41/**
42 * struct qcom_rpm_header - header for all rpm requests and responses
43 * @service_type: identifier of the service
44 * @length: length of the payload
45 */
46struct qcom_rpm_header {
47 u32 service_type;
48 u32 length;
49};
50
51/**
52 * struct qcom_rpm_request - request message to the rpm
53 * @msg_id: identifier of the outgoing message
54 * @flags: active/sleep state flags
55 * @type: resource type
56 * @id: resource id
57 * @data_len: length of the payload following this header
58 */
59struct qcom_rpm_request {
60 u32 msg_id;
61 u32 flags;
62 u32 type;
63 u32 id;
64 u32 data_len;
65};
66
67/**
68 * struct qcom_rpm_message - response message from the rpm
69 * @msg_type: indicator of the type of message
70 * @length: the size of this message, including the message header
71 * @msg_id: message id
72 * @message: textual message from the rpm
73 *
74 * Multiple of these messages can be stacked in an rpm message.
75 */
76struct qcom_rpm_message {
77 u32 msg_type;
78 u32 length;
79 union {
80 u32 msg_id;
81 u8 message[0];
82 };
83};
84
85#define RPM_SERVICE_TYPE_REQUEST 0x00716572 /* "req\0" */
86
87#define RPM_MSG_TYPE_ERR 0x00727265 /* "err\0" */
88#define RPM_MSG_TYPE_MSG_ID 0x2367736d /* "msg#" */
89
90/**
91 * qcom_rpm_smd_write - write @buf to @type:@id
92 * @rpm: rpm handle
93 * @type: resource type
94 * @id: resource identifier
95 * @buf: the data to be written
96 * @count: number of bytes in @buf
97 */
98int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm,
99 int state,
100 u32 type, u32 id,
101 void *buf,
102 size_t count)
103{
104 static unsigned msg_id = 1;
105 int left;
106 int ret;
107
108 struct {
109 struct qcom_rpm_header hdr;
110 struct qcom_rpm_request req;
111 u8 payload[count];
112 } pkt;
113
114 /* SMD packets to the RPM may not exceed 256 bytes */
115 if (WARN_ON(sizeof(pkt) >= 256))
116 return -EINVAL;
117
118 mutex_lock(&rpm->lock);
119
120 pkt.hdr.service_type = RPM_SERVICE_TYPE_REQUEST;
121 pkt.hdr.length = sizeof(struct qcom_rpm_request) + count;
122
123 pkt.req.msg_id = msg_id++;
124 pkt.req.flags = BIT(state);
125 pkt.req.type = type;
126 pkt.req.id = id;
127 pkt.req.data_len = count;
128 memcpy(pkt.payload, buf, count);
129
130 ret = qcom_smd_send(rpm->rpm_channel, &pkt, sizeof(pkt));
131 if (ret)
132 goto out;
133
134 left = wait_for_completion_timeout(&rpm->ack, RPM_REQUEST_TIMEOUT);
135 if (!left)
136 ret = -ETIMEDOUT;
137 else
138 ret = rpm->ack_status;
139
140out:
141 mutex_unlock(&rpm->lock);
142 return ret;
143}
144EXPORT_SYMBOL(qcom_rpm_smd_write);
145
146static int qcom_smd_rpm_callback(struct qcom_smd_device *qsdev,
147 const void *data,
148 size_t count)
149{
150 const struct qcom_rpm_header *hdr = data;
151 const struct qcom_rpm_message *msg;
152 struct qcom_smd_rpm *rpm = dev_get_drvdata(&qsdev->dev);
153 const u8 *buf = data + sizeof(struct qcom_rpm_header);
154 const u8 *end = buf + hdr->length;
155 char msgbuf[32];
156 int status = 0;
157 u32 len;
158
159 if (hdr->service_type != RPM_SERVICE_TYPE_REQUEST ||
160 hdr->length < sizeof(struct qcom_rpm_message)) {
161 dev_err(&qsdev->dev, "invalid request\n");
162 return 0;
163 }
164
165 while (buf < end) {
166 msg = (struct qcom_rpm_message *)buf;
167 switch (msg->msg_type) {
168 case RPM_MSG_TYPE_MSG_ID:
169 break;
170 case RPM_MSG_TYPE_ERR:
171 len = min_t(u32, ALIGN(msg->length, 4), sizeof(msgbuf));
172 memcpy_fromio(msgbuf, msg->message, len);
173 msgbuf[len - 1] = 0;
174
175 if (!strcmp(msgbuf, "resource does not exist"))
176 status = -ENXIO;
177 else
178 status = -EINVAL;
179 break;
180 }
181
182 buf = PTR_ALIGN(buf + 2 * sizeof(u32) + msg->length, 4);
183 }
184
185 rpm->ack_status = status;
186 complete(&rpm->ack);
187 return 0;
188}
189
190static int qcom_smd_rpm_probe(struct qcom_smd_device *sdev)
191{
192 struct qcom_smd_rpm *rpm;
193
194 rpm = devm_kzalloc(&sdev->dev, sizeof(*rpm), GFP_KERNEL);
195 if (!rpm)
196 return -ENOMEM;
197
198 mutex_init(&rpm->lock);
199 init_completion(&rpm->ack);
200
201 rpm->rpm_channel = sdev->channel;
202
203 dev_set_drvdata(&sdev->dev, rpm);
204
205 return of_platform_populate(sdev->dev.of_node, NULL, NULL, &sdev->dev);
206}
207
208static void qcom_smd_rpm_remove(struct qcom_smd_device *sdev)
209{
210 of_platform_depopulate(&sdev->dev);
211}
212
213static const struct of_device_id qcom_smd_rpm_of_match[] = {
214 { .compatible = "qcom,rpm-msm8974" },
215 {}
216};
217MODULE_DEVICE_TABLE(of, qcom_smd_rpm_of_match);
218
219static struct qcom_smd_driver qcom_smd_rpm_driver = {
220 .probe = qcom_smd_rpm_probe,
221 .remove = qcom_smd_rpm_remove,
222 .callback = qcom_smd_rpm_callback,
223 .driver = {
224 .name = "qcom_smd_rpm",
225 .owner = THIS_MODULE,
226 .of_match_table = qcom_smd_rpm_of_match,
227 },
228};
229
230static int __init qcom_smd_rpm_init(void)
231{
232 return qcom_smd_driver_register(&qcom_smd_rpm_driver);
233}
234arch_initcall(qcom_smd_rpm_init);
235
236static void __exit qcom_smd_rpm_exit(void)
237{
238 qcom_smd_driver_unregister(&qcom_smd_rpm_driver);
239}
240module_exit(qcom_smd_rpm_exit);
241
242MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
243MODULE_DESCRIPTION("Qualcomm SMD backed RPM driver");
244MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/smd.c b/drivers/soc/qcom/smd.c
new file mode 100644
index 000000000000..327adcf117c1
--- /dev/null
+++ b/drivers/soc/qcom/smd.c
@@ -0,0 +1,1319 @@
1/*
2 * Copyright (c) 2015, Sony Mobile Communications AB.
3 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 and
7 * only version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/interrupt.h>
16#include <linux/io.h>
17#include <linux/mfd/syscon.h>
18#include <linux/module.h>
19#include <linux/of_irq.h>
20#include <linux/of_platform.h>
21#include <linux/platform_device.h>
22#include <linux/regmap.h>
23#include <linux/sched.h>
24#include <linux/slab.h>
25#include <linux/soc/qcom/smd.h>
26#include <linux/soc/qcom/smem.h>
27#include <linux/wait.h>
28
29/*
30 * The Qualcomm Shared Memory communication solution provides point-to-point
31 * channels for clients to send and receive streaming or packet based data.
32 *
33 * Each channel consists of a control item (channel info) and a ring buffer
34 * pair. The channel info carry information related to channel state, flow
35 * control and the offsets within the ring buffer.
36 *
37 * All allocated channels are listed in an allocation table, identifying the
38 * pair of items by name, type and remote processor.
39 *
40 * Upon creating a new channel the remote processor allocates channel info and
41 * ring buffer items from the smem heap and populate the allocation table. An
42 * interrupt is sent to the other end of the channel and a scan for new
43 * channels should be done. A channel never goes away, it will only change
44 * state.
45 *
46 * The remote processor signals it intent for bring up the communication
47 * channel by setting the state of its end of the channel to "opening" and
48 * sends out an interrupt. We detect this change and register a smd device to
49 * consume the channel. Upon finding a consumer we finish the handshake and the
50 * channel is up.
51 *
52 * Upon closing a channel, the remote processor will update the state of its
53 * end of the channel and signal us, we will then unregister any attached
54 * device and close our end of the channel.
55 *
56 * Devices attached to a channel can use the qcom_smd_send function to push
57 * data to the channel, this is done by copying the data into the tx ring
58 * buffer, updating the pointers in the channel info and signaling the remote
59 * processor.
60 *
61 * The remote processor does the equivalent when it transfer data and upon
62 * receiving the interrupt we check the channel info for new data and delivers
63 * this to the attached device. If the device is not ready to receive the data
64 * we leave it in the ring buffer for now.
65 */
66
67struct smd_channel_info;
68struct smd_channel_info_word;
69
70#define SMD_ALLOC_TBL_COUNT 2
71#define SMD_ALLOC_TBL_SIZE 64
72
73/*
74 * This lists the various smem heap items relevant for the allocation table and
75 * smd channel entries.
76 */
77static const struct {
78 unsigned alloc_tbl_id;
79 unsigned info_base_id;
80 unsigned fifo_base_id;
81} smem_items[SMD_ALLOC_TBL_COUNT] = {
82 {
83 .alloc_tbl_id = 13,
84 .info_base_id = 14,
85 .fifo_base_id = 338
86 },
87 {
88 .alloc_tbl_id = 14,
89 .info_base_id = 266,
90 .fifo_base_id = 202,
91 },
92};
93
94/**
95 * struct qcom_smd_edge - representing a remote processor
96 * @smd: handle to qcom_smd
97 * @of_node: of_node handle for information related to this edge
98 * @edge_id: identifier of this edge
99 * @irq: interrupt for signals on this edge
100 * @ipc_regmap: regmap handle holding the outgoing ipc register
101 * @ipc_offset: offset within @ipc_regmap of the register for ipc
102 * @ipc_bit: bit in the register at @ipc_offset of @ipc_regmap
103 * @channels: list of all channels detected on this edge
104 * @channels_lock: guard for modifications of @channels
105 * @allocated: array of bitmaps representing already allocated channels
106 * @need_rescan: flag that the @work needs to scan smem for new channels
107 * @smem_available: last available amount of smem triggering a channel scan
108 * @work: work item for edge house keeping
109 */
110struct qcom_smd_edge {
111 struct qcom_smd *smd;
112 struct device_node *of_node;
113 unsigned edge_id;
114
115 int irq;
116
117 struct regmap *ipc_regmap;
118 int ipc_offset;
119 int ipc_bit;
120
121 struct list_head channels;
122 spinlock_t channels_lock;
123
124 DECLARE_BITMAP(allocated[SMD_ALLOC_TBL_COUNT], SMD_ALLOC_TBL_SIZE);
125
126 bool need_rescan;
127 unsigned smem_available;
128
129 struct work_struct work;
130};
131
132/*
133 * SMD channel states.
134 */
135enum smd_channel_state {
136 SMD_CHANNEL_CLOSED,
137 SMD_CHANNEL_OPENING,
138 SMD_CHANNEL_OPENED,
139 SMD_CHANNEL_FLUSHING,
140 SMD_CHANNEL_CLOSING,
141 SMD_CHANNEL_RESET,
142 SMD_CHANNEL_RESET_OPENING
143};
144
145/**
146 * struct qcom_smd_channel - smd channel struct
147 * @edge: qcom_smd_edge this channel is living on
148 * @qsdev: reference to a associated smd client device
149 * @name: name of the channel
150 * @state: local state of the channel
151 * @remote_state: remote state of the channel
152 * @tx_info: byte aligned outgoing channel info
153 * @rx_info: byte aligned incoming channel info
154 * @tx_info_word: word aligned outgoing channel info
155 * @rx_info_word: word aligned incoming channel info
156 * @tx_lock: lock to make writes to the channel mutually exclusive
157 * @fblockread_event: wakeup event tied to tx fBLOCKREADINTR
158 * @tx_fifo: pointer to the outgoing ring buffer
159 * @rx_fifo: pointer to the incoming ring buffer
160 * @fifo_size: size of each ring buffer
161 * @bounce_buffer: bounce buffer for reading wrapped packets
162 * @cb: callback function registered for this channel
163 * @recv_lock: guard for rx info modifications and cb pointer
164 * @pkt_size: size of the currently handled packet
165 * @list: lite entry for @channels in qcom_smd_edge
166 */
167struct qcom_smd_channel {
168 struct qcom_smd_edge *edge;
169
170 struct qcom_smd_device *qsdev;
171
172 char *name;
173 enum smd_channel_state state;
174 enum smd_channel_state remote_state;
175
176 struct smd_channel_info *tx_info;
177 struct smd_channel_info *rx_info;
178
179 struct smd_channel_info_word *tx_info_word;
180 struct smd_channel_info_word *rx_info_word;
181
182 struct mutex tx_lock;
183 wait_queue_head_t fblockread_event;
184
185 void *tx_fifo;
186 void *rx_fifo;
187 int fifo_size;
188
189 void *bounce_buffer;
190 int (*cb)(struct qcom_smd_device *, const void *, size_t);
191
192 spinlock_t recv_lock;
193
194 int pkt_size;
195
196 struct list_head list;
197};
198
199/**
200 * struct qcom_smd - smd struct
201 * @dev: device struct
202 * @num_edges: number of entries in @edges
203 * @edges: array of edges to be handled
204 */
205struct qcom_smd {
206 struct device *dev;
207
208 unsigned num_edges;
209 struct qcom_smd_edge edges[0];
210};
211
212/*
213 * Format of the smd_info smem items, for byte aligned channels.
214 */
215struct smd_channel_info {
216 u32 state;
217 u8 fDSR;
218 u8 fCTS;
219 u8 fCD;
220 u8 fRI;
221 u8 fHEAD;
222 u8 fTAIL;
223 u8 fSTATE;
224 u8 fBLOCKREADINTR;
225 u32 tail;
226 u32 head;
227};
228
229/*
230 * Format of the smd_info smem items, for word aligned channels.
231 */
232struct smd_channel_info_word {
233 u32 state;
234 u32 fDSR;
235 u32 fCTS;
236 u32 fCD;
237 u32 fRI;
238 u32 fHEAD;
239 u32 fTAIL;
240 u32 fSTATE;
241 u32 fBLOCKREADINTR;
242 u32 tail;
243 u32 head;
244};
245
246#define GET_RX_CHANNEL_INFO(channel, param) \
247 (channel->rx_info_word ? \
248 channel->rx_info_word->param : \
249 channel->rx_info->param)
250
251#define SET_RX_CHANNEL_INFO(channel, param, value) \
252 (channel->rx_info_word ? \
253 (channel->rx_info_word->param = value) : \
254 (channel->rx_info->param = value))
255
256#define GET_TX_CHANNEL_INFO(channel, param) \
257 (channel->tx_info_word ? \
258 channel->tx_info_word->param : \
259 channel->tx_info->param)
260
261#define SET_TX_CHANNEL_INFO(channel, param, value) \
262 (channel->tx_info_word ? \
263 (channel->tx_info_word->param = value) : \
264 (channel->tx_info->param = value))
265
266/**
267 * struct qcom_smd_alloc_entry - channel allocation entry
268 * @name: channel name
269 * @cid: channel index
270 * @flags: channel flags and edge id
271 * @ref_count: reference count of the channel
272 */
273struct qcom_smd_alloc_entry {
274 u8 name[20];
275 u32 cid;
276 u32 flags;
277 u32 ref_count;
278} __packed;
279
280#define SMD_CHANNEL_FLAGS_EDGE_MASK 0xff
281#define SMD_CHANNEL_FLAGS_STREAM BIT(8)
282#define SMD_CHANNEL_FLAGS_PACKET BIT(9)
283
284/*
285 * Each smd packet contains a 20 byte header, with the first 4 being the length
286 * of the packet.
287 */
288#define SMD_PACKET_HEADER_LEN 20
289
290/*
291 * Signal the remote processor associated with 'channel'.
292 */
293static void qcom_smd_signal_channel(struct qcom_smd_channel *channel)
294{
295 struct qcom_smd_edge *edge = channel->edge;
296
297 regmap_write(edge->ipc_regmap, edge->ipc_offset, BIT(edge->ipc_bit));
298}
299
300/*
301 * Initialize the tx channel info
302 */
303static void qcom_smd_channel_reset(struct qcom_smd_channel *channel)
304{
305 SET_TX_CHANNEL_INFO(channel, state, SMD_CHANNEL_CLOSED);
306 SET_TX_CHANNEL_INFO(channel, fDSR, 0);
307 SET_TX_CHANNEL_INFO(channel, fCTS, 0);
308 SET_TX_CHANNEL_INFO(channel, fCD, 0);
309 SET_TX_CHANNEL_INFO(channel, fRI, 0);
310 SET_TX_CHANNEL_INFO(channel, fHEAD, 0);
311 SET_TX_CHANNEL_INFO(channel, fTAIL, 0);
312 SET_TX_CHANNEL_INFO(channel, fSTATE, 1);
313 SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 0);
314 SET_TX_CHANNEL_INFO(channel, head, 0);
315 SET_TX_CHANNEL_INFO(channel, tail, 0);
316
317 qcom_smd_signal_channel(channel);
318
319 channel->state = SMD_CHANNEL_CLOSED;
320 channel->pkt_size = 0;
321}
322
323/*
324 * Calculate the amount of data available in the rx fifo
325 */
326static size_t qcom_smd_channel_get_rx_avail(struct qcom_smd_channel *channel)
327{
328 unsigned head;
329 unsigned tail;
330
331 head = GET_RX_CHANNEL_INFO(channel, head);
332 tail = GET_RX_CHANNEL_INFO(channel, tail);
333
334 return (head - tail) & (channel->fifo_size - 1);
335}
336
337/*
338 * Set tx channel state and inform the remote processor
339 */
340static void qcom_smd_channel_set_state(struct qcom_smd_channel *channel,
341 int state)
342{
343 struct qcom_smd_edge *edge = channel->edge;
344 bool is_open = state == SMD_CHANNEL_OPENED;
345
346 if (channel->state == state)
347 return;
348
349 dev_dbg(edge->smd->dev, "set_state(%s, %d)\n", channel->name, state);
350
351 SET_TX_CHANNEL_INFO(channel, fDSR, is_open);
352 SET_TX_CHANNEL_INFO(channel, fCTS, is_open);
353 SET_TX_CHANNEL_INFO(channel, fCD, is_open);
354
355 SET_TX_CHANNEL_INFO(channel, state, state);
356 SET_TX_CHANNEL_INFO(channel, fSTATE, 1);
357
358 channel->state = state;
359 qcom_smd_signal_channel(channel);
360}
361
362/*
363 * Copy count bytes of data using 32bit accesses, if that's required.
364 */
365static void smd_copy_to_fifo(void __iomem *_dst,
366 const void *_src,
367 size_t count,
368 bool word_aligned)
369{
370 u32 *dst = (u32 *)_dst;
371 u32 *src = (u32 *)_src;
372
373 if (word_aligned) {
374 count /= sizeof(u32);
375 while (count--)
376 writel_relaxed(*src++, dst++);
377 } else {
378 memcpy_toio(_dst, _src, count);
379 }
380}
381
382/*
383 * Copy count bytes of data using 32bit accesses, if that is required.
384 */
385static void smd_copy_from_fifo(void *_dst,
386 const void __iomem *_src,
387 size_t count,
388 bool word_aligned)
389{
390 u32 *dst = (u32 *)_dst;
391 u32 *src = (u32 *)_src;
392
393 if (word_aligned) {
394 count /= sizeof(u32);
395 while (count--)
396 *dst++ = readl_relaxed(src++);
397 } else {
398 memcpy_fromio(_dst, _src, count);
399 }
400}
401
402/*
403 * Read count bytes of data from the rx fifo into buf, but don't advance the
404 * tail.
405 */
406static size_t qcom_smd_channel_peek(struct qcom_smd_channel *channel,
407 void *buf, size_t count)
408{
409 bool word_aligned;
410 unsigned tail;
411 size_t len;
412
413 word_aligned = channel->rx_info_word != NULL;
414 tail = GET_RX_CHANNEL_INFO(channel, tail);
415
416 len = min_t(size_t, count, channel->fifo_size - tail);
417 if (len) {
418 smd_copy_from_fifo(buf,
419 channel->rx_fifo + tail,
420 len,
421 word_aligned);
422 }
423
424 if (len != count) {
425 smd_copy_from_fifo(buf + len,
426 channel->rx_fifo,
427 count - len,
428 word_aligned);
429 }
430
431 return count;
432}
433
434/*
435 * Advance the rx tail by count bytes.
436 */
437static void qcom_smd_channel_advance(struct qcom_smd_channel *channel,
438 size_t count)
439{
440 unsigned tail;
441
442 tail = GET_RX_CHANNEL_INFO(channel, tail);
443 tail += count;
444 tail &= (channel->fifo_size - 1);
445 SET_RX_CHANNEL_INFO(channel, tail, tail);
446}
447
448/*
449 * Read out a single packet from the rx fifo and deliver it to the device
450 */
451static int qcom_smd_channel_recv_single(struct qcom_smd_channel *channel)
452{
453 struct qcom_smd_device *qsdev = channel->qsdev;
454 unsigned tail;
455 size_t len;
456 void *ptr;
457 int ret;
458
459 if (!channel->cb)
460 return 0;
461
462 tail = GET_RX_CHANNEL_INFO(channel, tail);
463
464 /* Use bounce buffer if the data wraps */
465 if (tail + channel->pkt_size >= channel->fifo_size) {
466 ptr = channel->bounce_buffer;
467 len = qcom_smd_channel_peek(channel, ptr, channel->pkt_size);
468 } else {
469 ptr = channel->rx_fifo + tail;
470 len = channel->pkt_size;
471 }
472
473 ret = channel->cb(qsdev, ptr, len);
474 if (ret < 0)
475 return ret;
476
477 /* Only forward the tail if the client consumed the data */
478 qcom_smd_channel_advance(channel, len);
479
480 channel->pkt_size = 0;
481
482 return 0;
483}
484
485/*
486 * Per channel interrupt handling
487 */
488static bool qcom_smd_channel_intr(struct qcom_smd_channel *channel)
489{
490 bool need_state_scan = false;
491 int remote_state;
492 u32 pktlen;
493 int avail;
494 int ret;
495
496 /* Handle state changes */
497 remote_state = GET_RX_CHANNEL_INFO(channel, state);
498 if (remote_state != channel->remote_state) {
499 channel->remote_state = remote_state;
500 need_state_scan = true;
501 }
502 /* Indicate that we have seen any state change */
503 SET_RX_CHANNEL_INFO(channel, fSTATE, 0);
504
505 /* Signal waiting qcom_smd_send() about the interrupt */
506 if (!GET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR))
507 wake_up_interruptible(&channel->fblockread_event);
508
509 /* Don't consume any data until we've opened the channel */
510 if (channel->state != SMD_CHANNEL_OPENED)
511 goto out;
512
513 /* Indicate that we've seen the new data */
514 SET_RX_CHANNEL_INFO(channel, fHEAD, 0);
515
516 /* Consume data */
517 for (;;) {
518 avail = qcom_smd_channel_get_rx_avail(channel);
519
520 if (!channel->pkt_size && avail >= SMD_PACKET_HEADER_LEN) {
521 qcom_smd_channel_peek(channel, &pktlen, sizeof(pktlen));
522 qcom_smd_channel_advance(channel, SMD_PACKET_HEADER_LEN);
523 channel->pkt_size = pktlen;
524 } else if (channel->pkt_size && avail >= channel->pkt_size) {
525 ret = qcom_smd_channel_recv_single(channel);
526 if (ret)
527 break;
528 } else {
529 break;
530 }
531 }
532
533 /* Indicate that we have seen and updated tail */
534 SET_RX_CHANNEL_INFO(channel, fTAIL, 1);
535
536 /* Signal the remote that we've consumed the data (if requested) */
537 if (!GET_RX_CHANNEL_INFO(channel, fBLOCKREADINTR)) {
538 /* Ensure ordering of channel info updates */
539 wmb();
540
541 qcom_smd_signal_channel(channel);
542 }
543
544out:
545 return need_state_scan;
546}
547
548/*
549 * The edge interrupts are triggered by the remote processor on state changes,
550 * channel info updates or when new channels are created.
551 */
552static irqreturn_t qcom_smd_edge_intr(int irq, void *data)
553{
554 struct qcom_smd_edge *edge = data;
555 struct qcom_smd_channel *channel;
556 unsigned available;
557 bool kick_worker = false;
558
559 /*
560 * Handle state changes or data on each of the channels on this edge
561 */
562 spin_lock(&edge->channels_lock);
563 list_for_each_entry(channel, &edge->channels, list) {
564 spin_lock(&channel->recv_lock);
565 kick_worker |= qcom_smd_channel_intr(channel);
566 spin_unlock(&channel->recv_lock);
567 }
568 spin_unlock(&edge->channels_lock);
569
570 /*
571 * Creating a new channel requires allocating an smem entry, so we only
572 * have to scan if the amount of available space in smem have changed
573 * since last scan.
574 */
575 available = qcom_smem_get_free_space(edge->edge_id);
576 if (available != edge->smem_available) {
577 edge->smem_available = available;
578 edge->need_rescan = true;
579 kick_worker = true;
580 }
581
582 if (kick_worker)
583 schedule_work(&edge->work);
584
585 return IRQ_HANDLED;
586}
587
588/*
589 * Delivers any outstanding packets in the rx fifo, can be used after probe of
590 * the clients to deliver any packets that wasn't delivered before the client
591 * was setup.
592 */
593static void qcom_smd_channel_resume(struct qcom_smd_channel *channel)
594{
595 unsigned long flags;
596
597 spin_lock_irqsave(&channel->recv_lock, flags);
598 qcom_smd_channel_intr(channel);
599 spin_unlock_irqrestore(&channel->recv_lock, flags);
600}
601
602/*
603 * Calculate how much space is available in the tx fifo.
604 */
605static size_t qcom_smd_get_tx_avail(struct qcom_smd_channel *channel)
606{
607 unsigned head;
608 unsigned tail;
609 unsigned mask = channel->fifo_size - 1;
610
611 head = GET_TX_CHANNEL_INFO(channel, head);
612 tail = GET_TX_CHANNEL_INFO(channel, tail);
613
614 return mask - ((head - tail) & mask);
615}
616
617/*
618 * Write count bytes of data into channel, possibly wrapping in the ring buffer
619 */
620static int qcom_smd_write_fifo(struct qcom_smd_channel *channel,
621 const void *data,
622 size_t count)
623{
624 bool word_aligned;
625 unsigned head;
626 size_t len;
627
628 word_aligned = channel->tx_info_word != NULL;
629 head = GET_TX_CHANNEL_INFO(channel, head);
630
631 len = min_t(size_t, count, channel->fifo_size - head);
632 if (len) {
633 smd_copy_to_fifo(channel->tx_fifo + head,
634 data,
635 len,
636 word_aligned);
637 }
638
639 if (len != count) {
640 smd_copy_to_fifo(channel->tx_fifo,
641 data + len,
642 count - len,
643 word_aligned);
644 }
645
646 head += count;
647 head &= (channel->fifo_size - 1);
648 SET_TX_CHANNEL_INFO(channel, head, head);
649
650 return count;
651}
652
653/**
654 * qcom_smd_send - write data to smd channel
655 * @channel: channel handle
656 * @data: buffer of data to write
657 * @len: number of bytes to write
658 *
659 * This is a blocking write of len bytes into the channel's tx ring buffer and
660 * signal the remote end. It will sleep until there is enough space available
661 * in the tx buffer, utilizing the fBLOCKREADINTR signaling mechanism to avoid
662 * polling.
663 */
664int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len)
665{
666 u32 hdr[5] = {len,};
667 int tlen = sizeof(hdr) + len;
668 int ret;
669
670 /* Word aligned channels only accept word size aligned data */
671 if (channel->rx_info_word != NULL && len % 4)
672 return -EINVAL;
673
674 ret = mutex_lock_interruptible(&channel->tx_lock);
675 if (ret)
676 return ret;
677
678 while (qcom_smd_get_tx_avail(channel) < tlen) {
679 if (channel->state != SMD_CHANNEL_OPENED) {
680 ret = -EPIPE;
681 goto out;
682 }
683
684 SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 1);
685
686 ret = wait_event_interruptible(channel->fblockread_event,
687 qcom_smd_get_tx_avail(channel) >= tlen ||
688 channel->state != SMD_CHANNEL_OPENED);
689 if (ret)
690 goto out;
691
692 SET_TX_CHANNEL_INFO(channel, fBLOCKREADINTR, 0);
693 }
694
695 SET_TX_CHANNEL_INFO(channel, fTAIL, 0);
696
697 qcom_smd_write_fifo(channel, hdr, sizeof(hdr));
698 qcom_smd_write_fifo(channel, data, len);
699
700 SET_TX_CHANNEL_INFO(channel, fHEAD, 1);
701
702 /* Ensure ordering of channel info updates */
703 wmb();
704
705 qcom_smd_signal_channel(channel);
706
707out:
708 mutex_unlock(&channel->tx_lock);
709
710 return ret;
711}
712EXPORT_SYMBOL(qcom_smd_send);
713
714static struct qcom_smd_device *to_smd_device(struct device *dev)
715{
716 return container_of(dev, struct qcom_smd_device, dev);
717}
718
719static struct qcom_smd_driver *to_smd_driver(struct device *dev)
720{
721 struct qcom_smd_device *qsdev = to_smd_device(dev);
722
723 return container_of(qsdev->dev.driver, struct qcom_smd_driver, driver);
724}
725
726static int qcom_smd_dev_match(struct device *dev, struct device_driver *drv)
727{
728 return of_driver_match_device(dev, drv);
729}
730
731/*
732 * Probe the smd client.
733 *
734 * The remote side have indicated that it want the channel to be opened, so
735 * complete the state handshake and probe our client driver.
736 */
737static int qcom_smd_dev_probe(struct device *dev)
738{
739 struct qcom_smd_device *qsdev = to_smd_device(dev);
740 struct qcom_smd_driver *qsdrv = to_smd_driver(dev);
741 struct qcom_smd_channel *channel = qsdev->channel;
742 size_t bb_size;
743 int ret;
744
745 /*
746 * Packets are maximum 4k, but reduce if the fifo is smaller
747 */
748 bb_size = min(channel->fifo_size, SZ_4K);
749 channel->bounce_buffer = kmalloc(bb_size, GFP_KERNEL);
750 if (!channel->bounce_buffer)
751 return -ENOMEM;
752
753 channel->cb = qsdrv->callback;
754
755 qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENING);
756
757 qcom_smd_channel_set_state(channel, SMD_CHANNEL_OPENED);
758
759 ret = qsdrv->probe(qsdev);
760 if (ret)
761 goto err;
762
763 qcom_smd_channel_resume(channel);
764
765 return 0;
766
767err:
768 dev_err(&qsdev->dev, "probe failed\n");
769
770 channel->cb = NULL;
771 kfree(channel->bounce_buffer);
772 channel->bounce_buffer = NULL;
773
774 qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSED);
775 return ret;
776}
777
778/*
779 * Remove the smd client.
780 *
781 * The channel is going away, for some reason, so remove the smd client and
782 * reset the channel state.
783 */
784static int qcom_smd_dev_remove(struct device *dev)
785{
786 struct qcom_smd_device *qsdev = to_smd_device(dev);
787 struct qcom_smd_driver *qsdrv = to_smd_driver(dev);
788 struct qcom_smd_channel *channel = qsdev->channel;
789 unsigned long flags;
790
791 qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSING);
792
793 /*
794 * Make sure we don't race with the code receiving data.
795 */
796 spin_lock_irqsave(&channel->recv_lock, flags);
797 channel->cb = NULL;
798 spin_unlock_irqrestore(&channel->recv_lock, flags);
799
800 /* Wake up any sleepers in qcom_smd_send() */
801 wake_up_interruptible(&channel->fblockread_event);
802
803 /*
804 * We expect that the client might block in remove() waiting for any
805 * outstanding calls to qcom_smd_send() to wake up and finish.
806 */
807 if (qsdrv->remove)
808 qsdrv->remove(qsdev);
809
810 /*
811 * The client is now gone, cleanup and reset the channel state.
812 */
813 channel->qsdev = NULL;
814 kfree(channel->bounce_buffer);
815 channel->bounce_buffer = NULL;
816
817 qcom_smd_channel_set_state(channel, SMD_CHANNEL_CLOSED);
818
819 qcom_smd_channel_reset(channel);
820
821 return 0;
822}
823
824static struct bus_type qcom_smd_bus = {
825 .name = "qcom_smd",
826 .match = qcom_smd_dev_match,
827 .probe = qcom_smd_dev_probe,
828 .remove = qcom_smd_dev_remove,
829};
830
831/*
832 * Release function for the qcom_smd_device object.
833 */
834static void qcom_smd_release_device(struct device *dev)
835{
836 struct qcom_smd_device *qsdev = to_smd_device(dev);
837
838 kfree(qsdev);
839}
840
841/*
842 * Finds the device_node for the smd child interested in this channel.
843 */
844static struct device_node *qcom_smd_match_channel(struct device_node *edge_node,
845 const char *channel)
846{
847 struct device_node *child;
848 const char *name;
849 const char *key;
850 int ret;
851
852 for_each_available_child_of_node(edge_node, child) {
853 key = "qcom,smd-channels";
854 ret = of_property_read_string(child, key, &name);
855 if (ret) {
856 of_node_put(child);
857 continue;
858 }
859
860 if (strcmp(name, channel) == 0)
861 return child;
862 }
863
864 return NULL;
865}
866
867/*
868 * Create a smd client device for channel that is being opened.
869 */
870static int qcom_smd_create_device(struct qcom_smd_channel *channel)
871{
872 struct qcom_smd_device *qsdev;
873 struct qcom_smd_edge *edge = channel->edge;
874 struct device_node *node;
875 struct qcom_smd *smd = edge->smd;
876 int ret;
877
878 if (channel->qsdev)
879 return -EEXIST;
880
881 node = qcom_smd_match_channel(edge->of_node, channel->name);
882 if (!node) {
883 dev_dbg(smd->dev, "no match for '%s'\n", channel->name);
884 return -ENXIO;
885 }
886
887 dev_dbg(smd->dev, "registering '%s'\n", channel->name);
888
889 qsdev = kzalloc(sizeof(*qsdev), GFP_KERNEL);
890 if (!qsdev)
891 return -ENOMEM;
892
893 dev_set_name(&qsdev->dev, "%s.%s", edge->of_node->name, node->name);
894 qsdev->dev.parent = smd->dev;
895 qsdev->dev.bus = &qcom_smd_bus;
896 qsdev->dev.release = qcom_smd_release_device;
897 qsdev->dev.of_node = node;
898
899 qsdev->channel = channel;
900
901 channel->qsdev = qsdev;
902
903 ret = device_register(&qsdev->dev);
904 if (ret) {
905 dev_err(smd->dev, "device_register failed: %d\n", ret);
906 put_device(&qsdev->dev);
907 }
908
909 return ret;
910}
911
912/*
913 * Destroy a smd client device for a channel that's going away.
914 */
915static void qcom_smd_destroy_device(struct qcom_smd_channel *channel)
916{
917 struct device *dev;
918
919 BUG_ON(!channel->qsdev);
920
921 dev = &channel->qsdev->dev;
922
923 device_unregister(dev);
924 of_node_put(dev->of_node);
925 put_device(dev);
926}
927
928/**
929 * qcom_smd_driver_register - register a smd driver
930 * @qsdrv: qcom_smd_driver struct
931 */
932int qcom_smd_driver_register(struct qcom_smd_driver *qsdrv)
933{
934 qsdrv->driver.bus = &qcom_smd_bus;
935 return driver_register(&qsdrv->driver);
936}
937EXPORT_SYMBOL(qcom_smd_driver_register);
938
939/**
940 * qcom_smd_driver_unregister - unregister a smd driver
941 * @qsdrv: qcom_smd_driver struct
942 */
943void qcom_smd_driver_unregister(struct qcom_smd_driver *qsdrv)
944{
945 driver_unregister(&qsdrv->driver);
946}
947EXPORT_SYMBOL(qcom_smd_driver_unregister);
948
949/*
950 * Allocate the qcom_smd_channel object for a newly found smd channel,
951 * retrieving and validating the smem items involved.
952 */
953static struct qcom_smd_channel *qcom_smd_create_channel(struct qcom_smd_edge *edge,
954 unsigned smem_info_item,
955 unsigned smem_fifo_item,
956 char *name)
957{
958 struct qcom_smd_channel *channel;
959 struct qcom_smd *smd = edge->smd;
960 size_t fifo_size;
961 size_t info_size;
962 void *fifo_base;
963 void *info;
964 int ret;
965
966 channel = devm_kzalloc(smd->dev, sizeof(*channel), GFP_KERNEL);
967 if (!channel)
968 return ERR_PTR(-ENOMEM);
969
970 channel->edge = edge;
971 channel->name = devm_kstrdup(smd->dev, name, GFP_KERNEL);
972 if (!channel->name)
973 return ERR_PTR(-ENOMEM);
974
975 mutex_init(&channel->tx_lock);
976 spin_lock_init(&channel->recv_lock);
977 init_waitqueue_head(&channel->fblockread_event);
978
979 ret = qcom_smem_get(edge->edge_id, smem_info_item, (void **)&info, &info_size);
980 if (ret)
981 goto free_name_and_channel;
982
983 /*
984 * Use the size of the item to figure out which channel info struct to
985 * use.
986 */
987 if (info_size == 2 * sizeof(struct smd_channel_info_word)) {
988 channel->tx_info_word = info;
989 channel->rx_info_word = info + sizeof(struct smd_channel_info_word);
990 } else if (info_size == 2 * sizeof(struct smd_channel_info)) {
991 channel->tx_info = info;
992 channel->rx_info = info + sizeof(struct smd_channel_info);
993 } else {
994 dev_err(smd->dev,
995 "channel info of size %zu not supported\n", info_size);
996 ret = -EINVAL;
997 goto free_name_and_channel;
998 }
999
1000 ret = qcom_smem_get(edge->edge_id, smem_fifo_item, &fifo_base, &fifo_size);
1001 if (ret)
1002 goto free_name_and_channel;
1003
1004 /* The channel consist of a rx and tx fifo of equal size */
1005 fifo_size /= 2;
1006
1007 dev_dbg(smd->dev, "new channel '%s' info-size: %zu fifo-size: %zu\n",
1008 name, info_size, fifo_size);
1009
1010 channel->tx_fifo = fifo_base;
1011 channel->rx_fifo = fifo_base + fifo_size;
1012 channel->fifo_size = fifo_size;
1013
1014 qcom_smd_channel_reset(channel);
1015
1016 return channel;
1017
1018free_name_and_channel:
1019 devm_kfree(smd->dev, channel->name);
1020 devm_kfree(smd->dev, channel);
1021
1022 return ERR_PTR(ret);
1023}
1024
1025/*
1026 * Scans the allocation table for any newly allocated channels, calls
1027 * qcom_smd_create_channel() to create representations of these and add
1028 * them to the edge's list of channels.
1029 */
1030static void qcom_discover_channels(struct qcom_smd_edge *edge)
1031{
1032 struct qcom_smd_alloc_entry *alloc_tbl;
1033 struct qcom_smd_alloc_entry *entry;
1034 struct qcom_smd_channel *channel;
1035 struct qcom_smd *smd = edge->smd;
1036 unsigned long flags;
1037 unsigned fifo_id;
1038 unsigned info_id;
1039 int ret;
1040 int tbl;
1041 int i;
1042
1043 for (tbl = 0; tbl < SMD_ALLOC_TBL_COUNT; tbl++) {
1044 ret = qcom_smem_get(edge->edge_id,
1045 smem_items[tbl].alloc_tbl_id,
1046 (void **)&alloc_tbl,
1047 NULL);
1048 if (ret < 0)
1049 continue;
1050
1051 for (i = 0; i < SMD_ALLOC_TBL_SIZE; i++) {
1052 entry = &alloc_tbl[i];
1053 if (test_bit(i, edge->allocated[tbl]))
1054 continue;
1055
1056 if (entry->ref_count == 0)
1057 continue;
1058
1059 if (!entry->name[0])
1060 continue;
1061
1062 if (!(entry->flags & SMD_CHANNEL_FLAGS_PACKET))
1063 continue;
1064
1065 if ((entry->flags & SMD_CHANNEL_FLAGS_EDGE_MASK) != edge->edge_id)
1066 continue;
1067
1068 info_id = smem_items[tbl].info_base_id + entry->cid;
1069 fifo_id = smem_items[tbl].fifo_base_id + entry->cid;
1070
1071 channel = qcom_smd_create_channel(edge, info_id, fifo_id, entry->name);
1072 if (IS_ERR(channel))
1073 continue;
1074
1075 spin_lock_irqsave(&edge->channels_lock, flags);
1076 list_add(&channel->list, &edge->channels);
1077 spin_unlock_irqrestore(&edge->channels_lock, flags);
1078
1079 dev_dbg(smd->dev, "new channel found: '%s'\n", channel->name);
1080 set_bit(i, edge->allocated[tbl]);
1081 }
1082 }
1083
1084 schedule_work(&edge->work);
1085}
1086
1087/*
1088 * This per edge worker scans smem for any new channels and register these. It
1089 * then scans all registered channels for state changes that should be handled
1090 * by creating or destroying smd client devices for the registered channels.
1091 *
1092 * LOCKING: edge->channels_lock is not needed to be held during the traversal
1093 * of the channels list as it's done synchronously with the only writer.
1094 */
1095static void qcom_channel_state_worker(struct work_struct *work)
1096{
1097 struct qcom_smd_channel *channel;
1098 struct qcom_smd_edge *edge = container_of(work,
1099 struct qcom_smd_edge,
1100 work);
1101 unsigned remote_state;
1102
1103 /*
1104 * Rescan smem if we have reason to belive that there are new channels.
1105 */
1106 if (edge->need_rescan) {
1107 edge->need_rescan = false;
1108 qcom_discover_channels(edge);
1109 }
1110
1111 /*
1112 * Register a device for any closed channel where the remote processor
1113 * is showing interest in opening the channel.
1114 */
1115 list_for_each_entry(channel, &edge->channels, list) {
1116 if (channel->state != SMD_CHANNEL_CLOSED)
1117 continue;
1118
1119 remote_state = GET_RX_CHANNEL_INFO(channel, state);
1120 if (remote_state != SMD_CHANNEL_OPENING &&
1121 remote_state != SMD_CHANNEL_OPENED)
1122 continue;
1123
1124 qcom_smd_create_device(channel);
1125 }
1126
1127 /*
1128 * Unregister the device for any channel that is opened where the
1129 * remote processor is closing the channel.
1130 */
1131 list_for_each_entry(channel, &edge->channels, list) {
1132 if (channel->state != SMD_CHANNEL_OPENING &&
1133 channel->state != SMD_CHANNEL_OPENED)
1134 continue;
1135
1136 remote_state = GET_RX_CHANNEL_INFO(channel, state);
1137 if (remote_state == SMD_CHANNEL_OPENING ||
1138 remote_state == SMD_CHANNEL_OPENED)
1139 continue;
1140
1141 qcom_smd_destroy_device(channel);
1142 }
1143}
1144
1145/*
1146 * Parses an of_node describing an edge.
1147 */
1148static int qcom_smd_parse_edge(struct device *dev,
1149 struct device_node *node,
1150 struct qcom_smd_edge *edge)
1151{
1152 struct device_node *syscon_np;
1153 const char *key;
1154 int irq;
1155 int ret;
1156
1157 INIT_LIST_HEAD(&edge->channels);
1158 spin_lock_init(&edge->channels_lock);
1159
1160 INIT_WORK(&edge->work, qcom_channel_state_worker);
1161
1162 edge->of_node = of_node_get(node);
1163
1164 irq = irq_of_parse_and_map(node, 0);
1165 if (irq < 0) {
1166 dev_err(dev, "required smd interrupt missing\n");
1167 return -EINVAL;
1168 }
1169
1170 ret = devm_request_irq(dev, irq,
1171 qcom_smd_edge_intr, IRQF_TRIGGER_RISING,
1172 node->name, edge);
1173 if (ret) {
1174 dev_err(dev, "failed to request smd irq\n");
1175 return ret;
1176 }
1177
1178 edge->irq = irq;
1179
1180 key = "qcom,smd-edge";
1181 ret = of_property_read_u32(node, key, &edge->edge_id);
1182 if (ret) {
1183 dev_err(dev, "edge missing %s property\n", key);
1184 return -EINVAL;
1185 }
1186
1187 syscon_np = of_parse_phandle(node, "qcom,ipc", 0);
1188 if (!syscon_np) {
1189 dev_err(dev, "no qcom,ipc node\n");
1190 return -ENODEV;
1191 }
1192
1193 edge->ipc_regmap = syscon_node_to_regmap(syscon_np);
1194 if (IS_ERR(edge->ipc_regmap))
1195 return PTR_ERR(edge->ipc_regmap);
1196
1197 key = "qcom,ipc";
1198 ret = of_property_read_u32_index(node, key, 1, &edge->ipc_offset);
1199 if (ret < 0) {
1200 dev_err(dev, "no offset in %s\n", key);
1201 return -EINVAL;
1202 }
1203
1204 ret = of_property_read_u32_index(node, key, 2, &edge->ipc_bit);
1205 if (ret < 0) {
1206 dev_err(dev, "no bit in %s\n", key);
1207 return -EINVAL;
1208 }
1209
1210 return 0;
1211}
1212
1213static int qcom_smd_probe(struct platform_device *pdev)
1214{
1215 struct qcom_smd_edge *edge;
1216 struct device_node *node;
1217 struct qcom_smd *smd;
1218 size_t array_size;
1219 int num_edges;
1220 int ret;
1221 int i = 0;
1222
1223 /* Wait for smem */
1224 ret = qcom_smem_get(QCOM_SMEM_HOST_ANY, smem_items[0].alloc_tbl_id, NULL, NULL);
1225 if (ret == -EPROBE_DEFER)
1226 return ret;
1227
1228 num_edges = of_get_available_child_count(pdev->dev.of_node);
1229 array_size = sizeof(*smd) + num_edges * sizeof(struct qcom_smd_edge);
1230 smd = devm_kzalloc(&pdev->dev, array_size, GFP_KERNEL);
1231 if (!smd)
1232 return -ENOMEM;
1233 smd->dev = &pdev->dev;
1234
1235 smd->num_edges = num_edges;
1236 for_each_available_child_of_node(pdev->dev.of_node, node) {
1237 edge = &smd->edges[i++];
1238 edge->smd = smd;
1239
1240 ret = qcom_smd_parse_edge(&pdev->dev, node, edge);
1241 if (ret)
1242 continue;
1243
1244 edge->need_rescan = true;
1245 schedule_work(&edge->work);
1246 }
1247
1248 platform_set_drvdata(pdev, smd);
1249
1250 return 0;
1251}
1252
1253/*
1254 * Shut down all smd clients by making sure that each edge stops processing
1255 * events and scanning for new channels, then call destroy on the devices.
1256 */
1257static int qcom_smd_remove(struct platform_device *pdev)
1258{
1259 struct qcom_smd_channel *channel;
1260 struct qcom_smd_edge *edge;
1261 struct qcom_smd *smd = platform_get_drvdata(pdev);
1262 int i;
1263
1264 for (i = 0; i < smd->num_edges; i++) {
1265 edge = &smd->edges[i];
1266
1267 disable_irq(edge->irq);
1268 cancel_work_sync(&edge->work);
1269
1270 list_for_each_entry(channel, &edge->channels, list) {
1271 if (!channel->qsdev)
1272 continue;
1273
1274 qcom_smd_destroy_device(channel);
1275 }
1276 }
1277
1278 return 0;
1279}
1280
1281static const struct of_device_id qcom_smd_of_match[] = {
1282 { .compatible = "qcom,smd" },
1283 {}
1284};
1285MODULE_DEVICE_TABLE(of, qcom_smd_of_match);
1286
1287static struct platform_driver qcom_smd_driver = {
1288 .probe = qcom_smd_probe,
1289 .remove = qcom_smd_remove,
1290 .driver = {
1291 .name = "qcom-smd",
1292 .of_match_table = qcom_smd_of_match,
1293 },
1294};
1295
1296static int __init qcom_smd_init(void)
1297{
1298 int ret;
1299
1300 ret = bus_register(&qcom_smd_bus);
1301 if (ret) {
1302 pr_err("failed to register smd bus: %d\n", ret);
1303 return ret;
1304 }
1305
1306 return platform_driver_register(&qcom_smd_driver);
1307}
1308postcore_initcall(qcom_smd_init);
1309
1310static void __exit qcom_smd_exit(void)
1311{
1312 platform_driver_unregister(&qcom_smd_driver);
1313 bus_unregister(&qcom_smd_bus);
1314}
1315module_exit(qcom_smd_exit);
1316
1317MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
1318MODULE_DESCRIPTION("Qualcomm Shared Memory Driver");
1319MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
new file mode 100644
index 000000000000..7c2c324c4b10
--- /dev/null
+++ b/drivers/soc/qcom/smem.c
@@ -0,0 +1,775 @@
1/*
2 * Copyright (c) 2015, Sony Mobile Communications AB.
3 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 and
7 * only version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/hwspinlock.h>
16#include <linux/io.h>
17#include <linux/module.h>
18#include <linux/of.h>
19#include <linux/of_address.h>
20#include <linux/platform_device.h>
21#include <linux/slab.h>
22#include <linux/soc/qcom/smem.h>
23
24/*
25 * The Qualcomm shared memory system is a allocate only heap structure that
26 * consists of one of more memory areas that can be accessed by the processors
27 * in the SoC.
28 *
29 * All systems contains a global heap, accessible by all processors in the SoC,
30 * with a table of contents data structure (@smem_header) at the beginning of
31 * the main shared memory block.
32 *
33 * The global header contains meta data for allocations as well as a fixed list
34 * of 512 entries (@smem_global_entry) that can be initialized to reference
35 * parts of the shared memory space.
36 *
37 *
38 * In addition to this global heap a set of "private" heaps can be set up at
39 * boot time with access restrictions so that only certain processor pairs can
40 * access the data.
41 *
42 * These partitions are referenced from an optional partition table
43 * (@smem_ptable), that is found 4kB from the end of the main smem region. The
44 * partition table entries (@smem_ptable_entry) lists the involved processors
45 * (or hosts) and their location in the main shared memory region.
46 *
47 * Each partition starts with a header (@smem_partition_header) that identifies
48 * the partition and holds properties for the two internal memory regions. The
49 * two regions are cached and non-cached memory respectively. Each region
50 * contain a link list of allocation headers (@smem_private_entry) followed by
51 * their data.
52 *
53 * Items in the non-cached region are allocated from the start of the partition
54 * while items in the cached region are allocated from the end. The free area
55 * is hence the region between the cached and non-cached offsets.
56 *
57 *
58 * To synchronize allocations in the shared memory heaps a remote spinlock must
59 * be held - currently lock number 3 of the sfpb or tcsr is used for this on all
60 * platforms.
61 *
62 */
63
64/*
65 * Item 3 of the global heap contains an array of versions for the various
66 * software components in the SoC. We verify that the boot loader version is
67 * what the expected version (SMEM_EXPECTED_VERSION) as a sanity check.
68 */
69#define SMEM_ITEM_VERSION 3
70#define SMEM_MASTER_SBL_VERSION_INDEX 7
71#define SMEM_EXPECTED_VERSION 11
72
73/*
74 * The first 8 items are only to be allocated by the boot loader while
75 * initializing the heap.
76 */
77#define SMEM_ITEM_LAST_FIXED 8
78
79/* Highest accepted item number, for both global and private heaps */
80#define SMEM_ITEM_COUNT 512
81
82/* Processor/host identifier for the application processor */
83#define SMEM_HOST_APPS 0
84
85/* Max number of processors/hosts in a system */
86#define SMEM_HOST_COUNT 9
87
88/**
89 * struct smem_proc_comm - proc_comm communication struct (legacy)
90 * @command: current command to be executed
91 * @status: status of the currently requested command
92 * @params: parameters to the command
93 */
94struct smem_proc_comm {
95 u32 command;
96 u32 status;
97 u32 params[2];
98};
99
100/**
101 * struct smem_global_entry - entry to reference smem items on the heap
102 * @allocated: boolean to indicate if this entry is used
103 * @offset: offset to the allocated space
104 * @size: size of the allocated space, 8 byte aligned
105 * @aux_base: base address for the memory region used by this unit, or 0 for
106 * the default region. bits 0,1 are reserved
107 */
108struct smem_global_entry {
109 u32 allocated;
110 u32 offset;
111 u32 size;
112 u32 aux_base; /* bits 1:0 reserved */
113};
114#define AUX_BASE_MASK 0xfffffffc
115
116/**
117 * struct smem_header - header found in beginning of primary smem region
118 * @proc_comm: proc_comm communication interface (legacy)
119 * @version: array of versions for the various subsystems
120 * @initialized: boolean to indicate that smem is initialized
121 * @free_offset: index of the first unallocated byte in smem
122 * @available: number of bytes available for allocation
123 * @reserved: reserved field, must be 0
124 * toc: array of references to items
125 */
126struct smem_header {
127 struct smem_proc_comm proc_comm[4];
128 u32 version[32];
129 u32 initialized;
130 u32 free_offset;
131 u32 available;
132 u32 reserved;
133 struct smem_global_entry toc[SMEM_ITEM_COUNT];
134};
135
136/**
137 * struct smem_ptable_entry - one entry in the @smem_ptable list
138 * @offset: offset, within the main shared memory region, of the partition
139 * @size: size of the partition
140 * @flags: flags for the partition (currently unused)
141 * @host0: first processor/host with access to this partition
142 * @host1: second processor/host with access to this partition
143 * @reserved: reserved entries for later use
144 */
145struct smem_ptable_entry {
146 u32 offset;
147 u32 size;
148 u32 flags;
149 u16 host0;
150 u16 host1;
151 u32 reserved[8];
152};
153
154/**
155 * struct smem_ptable - partition table for the private partitions
156 * @magic: magic number, must be SMEM_PTABLE_MAGIC
157 * @version: version of the partition table
158 * @num_entries: number of partitions in the table
159 * @reserved: for now reserved entries
160 * @entry: list of @smem_ptable_entry for the @num_entries partitions
161 */
162struct smem_ptable {
163 u32 magic;
164 u32 version;
165 u32 num_entries;
166 u32 reserved[5];
167 struct smem_ptable_entry entry[];
168};
169#define SMEM_PTABLE_MAGIC 0x434f5424 /* "$TOC" */
170
171/**
172 * struct smem_partition_header - header of the partitions
173 * @magic: magic number, must be SMEM_PART_MAGIC
174 * @host0: first processor/host with access to this partition
175 * @host1: second processor/host with access to this partition
176 * @size: size of the partition
177 * @offset_free_uncached: offset to the first free byte of uncached memory in
178 * this partition
179 * @offset_free_cached: offset to the first free byte of cached memory in this
180 * partition
181 * @reserved: for now reserved entries
182 */
183struct smem_partition_header {
184 u32 magic;
185 u16 host0;
186 u16 host1;
187 u32 size;
188 u32 offset_free_uncached;
189 u32 offset_free_cached;
190 u32 reserved[3];
191};
192#define SMEM_PART_MAGIC 0x54525024 /* "$PRT" */
193
194/**
195 * struct smem_private_entry - header of each item in the private partition
196 * @canary: magic number, must be SMEM_PRIVATE_CANARY
197 * @item: identifying number of the smem item
198 * @size: size of the data, including padding bytes
199 * @padding_data: number of bytes of padding of data
200 * @padding_hdr: number of bytes of padding between the header and the data
201 * @reserved: for now reserved entry
202 */
203struct smem_private_entry {
204 u16 canary;
205 u16 item;
206 u32 size; /* includes padding bytes */
207 u16 padding_data;
208 u16 padding_hdr;
209 u32 reserved;
210};
211#define SMEM_PRIVATE_CANARY 0xa5a5
212
213/**
214 * struct smem_region - representation of a chunk of memory used for smem
215 * @aux_base: identifier of aux_mem base
216 * @virt_base: virtual base address of memory with this aux_mem identifier
217 * @size: size of the memory region
218 */
219struct smem_region {
220 u32 aux_base;
221 void __iomem *virt_base;
222 size_t size;
223};
224
225/**
226 * struct qcom_smem - device data for the smem device
227 * @dev: device pointer
228 * @hwlock: reference to a hwspinlock
229 * @partitions: list of pointers to partitions affecting the current
230 * processor/host
231 * @num_regions: number of @regions
232 * @regions: list of the memory regions defining the shared memory
233 */
234struct qcom_smem {
235 struct device *dev;
236
237 struct hwspinlock *hwlock;
238
239 struct smem_partition_header *partitions[SMEM_HOST_COUNT];
240
241 unsigned num_regions;
242 struct smem_region regions[0];
243};
244
245/* Pointer to the one and only smem handle */
246static struct qcom_smem *__smem;
247
248/* Timeout (ms) for the trylock of remote spinlocks */
249#define HWSPINLOCK_TIMEOUT 1000
250
251static int qcom_smem_alloc_private(struct qcom_smem *smem,
252 unsigned host,
253 unsigned item,
254 size_t size)
255{
256 struct smem_partition_header *phdr;
257 struct smem_private_entry *hdr;
258 size_t alloc_size;
259 void *p;
260
261 /* We're not going to find it if there's no matching partition */
262 if (host >= SMEM_HOST_COUNT || !smem->partitions[host])
263 return -ENOENT;
264
265 phdr = smem->partitions[host];
266
267 p = (void *)phdr + sizeof(*phdr);
268 while (p < (void *)phdr + phdr->offset_free_uncached) {
269 hdr = p;
270
271 if (hdr->canary != SMEM_PRIVATE_CANARY) {
272 dev_err(smem->dev,
273 "Found invalid canary in host %d partition\n",
274 host);
275 return -EINVAL;
276 }
277
278 if (hdr->item == item)
279 return -EEXIST;
280
281 p += sizeof(*hdr) + hdr->padding_hdr + hdr->size;
282 }
283
284 /* Check that we don't grow into the cached region */
285 alloc_size = sizeof(*hdr) + ALIGN(size, 8);
286 if (p + alloc_size >= (void *)phdr + phdr->offset_free_cached) {
287 dev_err(smem->dev, "Out of memory\n");
288 return -ENOSPC;
289 }
290
291 hdr = p;
292 hdr->canary = SMEM_PRIVATE_CANARY;
293 hdr->item = item;
294 hdr->size = ALIGN(size, 8);
295 hdr->padding_data = hdr->size - size;
296 hdr->padding_hdr = 0;
297
298 /*
299 * Ensure the header is written before we advance the free offset, so
300 * that remote processors that does not take the remote spinlock still
301 * gets a consistent view of the linked list.
302 */
303 wmb();
304 phdr->offset_free_uncached += alloc_size;
305
306 return 0;
307}
308
309static int qcom_smem_alloc_global(struct qcom_smem *smem,
310 unsigned item,
311 size_t size)
312{
313 struct smem_header *header;
314 struct smem_global_entry *entry;
315
316 if (WARN_ON(item >= SMEM_ITEM_COUNT))
317 return -EINVAL;
318
319 header = smem->regions[0].virt_base;
320 entry = &header->toc[item];
321 if (entry->allocated)
322 return -EEXIST;
323
324 size = ALIGN(size, 8);
325 if (WARN_ON(size > header->available))
326 return -ENOMEM;
327
328 entry->offset = header->free_offset;
329 entry->size = size;
330
331 /*
332 * Ensure the header is consistent before we mark the item allocated,
333 * so that remote processors will get a consistent view of the item
334 * even though they do not take the spinlock on read.
335 */
336 wmb();
337 entry->allocated = 1;
338
339 header->free_offset += size;
340 header->available -= size;
341
342 return 0;
343}
344
345/**
346 * qcom_smem_alloc() - allocate space for a smem item
347 * @host: remote processor id, or -1
348 * @item: smem item handle
349 * @size: number of bytes to be allocated
350 *
351 * Allocate space for a given smem item of size @size, given that the item is
352 * not yet allocated.
353 */
354int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
355{
356 unsigned long flags;
357 int ret;
358
359 if (!__smem)
360 return -EPROBE_DEFER;
361
362 if (item < SMEM_ITEM_LAST_FIXED) {
363 dev_err(__smem->dev,
364 "Rejecting allocation of static entry %d\n", item);
365 return -EINVAL;
366 }
367
368 ret = hwspin_lock_timeout_irqsave(__smem->hwlock,
369 HWSPINLOCK_TIMEOUT,
370 &flags);
371 if (ret)
372 return ret;
373
374 ret = qcom_smem_alloc_private(__smem, host, item, size);
375 if (ret == -ENOENT)
376 ret = qcom_smem_alloc_global(__smem, item, size);
377
378 hwspin_unlock_irqrestore(__smem->hwlock, &flags);
379
380 return ret;
381}
382EXPORT_SYMBOL(qcom_smem_alloc);
383
384static int qcom_smem_get_global(struct qcom_smem *smem,
385 unsigned item,
386 void **ptr,
387 size_t *size)
388{
389 struct smem_header *header;
390 struct smem_region *area;
391 struct smem_global_entry *entry;
392 u32 aux_base;
393 unsigned i;
394
395 if (WARN_ON(item >= SMEM_ITEM_COUNT))
396 return -EINVAL;
397
398 header = smem->regions[0].virt_base;
399 entry = &header->toc[item];
400 if (!entry->allocated)
401 return -ENXIO;
402
403 if (ptr != NULL) {
404 aux_base = entry->aux_base & AUX_BASE_MASK;
405
406 for (i = 0; i < smem->num_regions; i++) {
407 area = &smem->regions[i];
408
409 if (area->aux_base == aux_base || !aux_base) {
410 *ptr = area->virt_base + entry->offset;
411 break;
412 }
413 }
414 }
415 if (size != NULL)
416 *size = entry->size;
417
418 return 0;
419}
420
421static int qcom_smem_get_private(struct qcom_smem *smem,
422 unsigned host,
423 unsigned item,
424 void **ptr,
425 size_t *size)
426{
427 struct smem_partition_header *phdr;
428 struct smem_private_entry *hdr;
429 void *p;
430
431 /* We're not going to find it if there's no matching partition */
432 if (host >= SMEM_HOST_COUNT || !smem->partitions[host])
433 return -ENOENT;
434
435 phdr = smem->partitions[host];
436
437 p = (void *)phdr + sizeof(*phdr);
438 while (p < (void *)phdr + phdr->offset_free_uncached) {
439 hdr = p;
440
441 if (hdr->canary != SMEM_PRIVATE_CANARY) {
442 dev_err(smem->dev,
443 "Found invalid canary in host %d partition\n",
444 host);
445 return -EINVAL;
446 }
447
448 if (hdr->item == item) {
449 if (ptr != NULL)
450 *ptr = p + sizeof(*hdr) + hdr->padding_hdr;
451
452 if (size != NULL)
453 *size = hdr->size - hdr->padding_data;
454
455 return 0;
456 }
457
458 p += sizeof(*hdr) + hdr->padding_hdr + hdr->size;
459 }
460
461 return -ENOENT;
462}
463
464/**
465 * qcom_smem_get() - resolve ptr of size of a smem item
466 * @host: the remote processor, or -1
467 * @item: smem item handle
468 * @ptr: pointer to be filled out with address of the item
469 * @size: pointer to be filled out with size of the item
470 *
471 * Looks up pointer and size of a smem item.
472 */
473int qcom_smem_get(unsigned host, unsigned item, void **ptr, size_t *size)
474{
475 unsigned long flags;
476 int ret;
477
478 if (!__smem)
479 return -EPROBE_DEFER;
480
481 ret = hwspin_lock_timeout_irqsave(__smem->hwlock,
482 HWSPINLOCK_TIMEOUT,
483 &flags);
484 if (ret)
485 return ret;
486
487 ret = qcom_smem_get_private(__smem, host, item, ptr, size);
488 if (ret == -ENOENT)
489 ret = qcom_smem_get_global(__smem, item, ptr, size);
490
491 hwspin_unlock_irqrestore(__smem->hwlock, &flags);
492 return ret;
493
494}
495EXPORT_SYMBOL(qcom_smem_get);
496
497/**
498 * qcom_smem_get_free_space() - retrieve amount of free space in a partition
499 * @host: the remote processor identifying a partition, or -1
500 *
501 * To be used by smem clients as a quick way to determine if any new
502 * allocations has been made.
503 */
504int qcom_smem_get_free_space(unsigned host)
505{
506 struct smem_partition_header *phdr;
507 struct smem_header *header;
508 unsigned ret;
509
510 if (!__smem)
511 return -EPROBE_DEFER;
512
513 if (host < SMEM_HOST_COUNT && __smem->partitions[host]) {
514 phdr = __smem->partitions[host];
515 ret = phdr->offset_free_cached - phdr->offset_free_uncached;
516 } else {
517 header = __smem->regions[0].virt_base;
518 ret = header->available;
519 }
520
521 return ret;
522}
523EXPORT_SYMBOL(qcom_smem_get_free_space);
524
525static int qcom_smem_get_sbl_version(struct qcom_smem *smem)
526{
527 unsigned *versions;
528 size_t size;
529 int ret;
530
531 ret = qcom_smem_get_global(smem, SMEM_ITEM_VERSION,
532 (void **)&versions, &size);
533 if (ret < 0) {
534 dev_err(smem->dev, "Unable to read the version item\n");
535 return -ENOENT;
536 }
537
538 if (size < sizeof(unsigned) * SMEM_MASTER_SBL_VERSION_INDEX) {
539 dev_err(smem->dev, "Version item is too small\n");
540 return -EINVAL;
541 }
542
543 return versions[SMEM_MASTER_SBL_VERSION_INDEX];
544}
545
546static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
547 unsigned local_host)
548{
549 struct smem_partition_header *header;
550 struct smem_ptable_entry *entry;
551 struct smem_ptable *ptable;
552 unsigned remote_host;
553 int i;
554
555 ptable = smem->regions[0].virt_base + smem->regions[0].size - SZ_4K;
556 if (ptable->magic != SMEM_PTABLE_MAGIC)
557 return 0;
558
559 if (ptable->version != 1) {
560 dev_err(smem->dev,
561 "Unsupported partition header version %d\n",
562 ptable->version);
563 return -EINVAL;
564 }
565
566 for (i = 0; i < ptable->num_entries; i++) {
567 entry = &ptable->entry[i];
568
569 if (entry->host0 != local_host && entry->host1 != local_host)
570 continue;
571
572 if (!entry->offset)
573 continue;
574
575 if (!entry->size)
576 continue;
577
578 if (entry->host0 == local_host)
579 remote_host = entry->host1;
580 else
581 remote_host = entry->host0;
582
583 if (remote_host >= SMEM_HOST_COUNT) {
584 dev_err(smem->dev,
585 "Invalid remote host %d\n",
586 remote_host);
587 return -EINVAL;
588 }
589
590 if (smem->partitions[remote_host]) {
591 dev_err(smem->dev,
592 "Already found a partition for host %d\n",
593 remote_host);
594 return -EINVAL;
595 }
596
597 header = smem->regions[0].virt_base + entry->offset;
598
599 if (header->magic != SMEM_PART_MAGIC) {
600 dev_err(smem->dev,
601 "Partition %d has invalid magic\n", i);
602 return -EINVAL;
603 }
604
605 if (header->host0 != local_host && header->host1 != local_host) {
606 dev_err(smem->dev,
607 "Partition %d hosts are invalid\n", i);
608 return -EINVAL;
609 }
610
611 if (header->host0 != remote_host && header->host1 != remote_host) {
612 dev_err(smem->dev,
613 "Partition %d hosts are invalid\n", i);
614 return -EINVAL;
615 }
616
617 if (header->size != entry->size) {
618 dev_err(smem->dev,
619 "Partition %d has invalid size\n", i);
620 return -EINVAL;
621 }
622
623 if (header->offset_free_uncached > header->size) {
624 dev_err(smem->dev,
625 "Partition %d has invalid free pointer\n", i);
626 return -EINVAL;
627 }
628
629 smem->partitions[remote_host] = header;
630 }
631
632 return 0;
633}
634
635static int qcom_smem_count_mem_regions(struct platform_device *pdev)
636{
637 struct resource *res;
638 int num_regions = 0;
639 int i;
640
641 for (i = 0; i < pdev->num_resources; i++) {
642 res = &pdev->resource[i];
643
644 if (resource_type(res) == IORESOURCE_MEM)
645 num_regions++;
646 }
647
648 return num_regions;
649}
650
651static int qcom_smem_probe(struct platform_device *pdev)
652{
653 struct smem_header *header;
654 struct device_node *np;
655 struct qcom_smem *smem;
656 struct resource *res;
657 struct resource r;
658 size_t array_size;
659 int num_regions = 0;
660 int hwlock_id;
661 u32 version;
662 int ret;
663 int i;
664
665 num_regions = qcom_smem_count_mem_regions(pdev) + 1;
666
667 array_size = num_regions * sizeof(struct smem_region);
668 smem = devm_kzalloc(&pdev->dev, sizeof(*smem) + array_size, GFP_KERNEL);
669 if (!smem)
670 return -ENOMEM;
671
672 smem->dev = &pdev->dev;
673 smem->num_regions = num_regions;
674
675 np = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
676 if (!np) {
677 dev_err(&pdev->dev, "No memory-region specified\n");
678 return -EINVAL;
679 }
680
681 ret = of_address_to_resource(np, 0, &r);
682 of_node_put(np);
683 if (ret)
684 return ret;
685
686 smem->regions[0].aux_base = (u32)r.start;
687 smem->regions[0].size = resource_size(&r);
688 smem->regions[0].virt_base = devm_ioremap_nocache(&pdev->dev,
689 r.start,
690 resource_size(&r));
691 if (!smem->regions[0].virt_base)
692 return -ENOMEM;
693
694 for (i = 1; i < num_regions; i++) {
695 res = platform_get_resource(pdev, IORESOURCE_MEM, i - 1);
696
697 smem->regions[i].aux_base = (u32)res->start;
698 smem->regions[i].size = resource_size(res);
699 smem->regions[i].virt_base = devm_ioremap_nocache(&pdev->dev,
700 res->start,
701 resource_size(res));
702 if (!smem->regions[i].virt_base)
703 return -ENOMEM;
704 }
705
706 header = smem->regions[0].virt_base;
707 if (header->initialized != 1 || header->reserved) {
708 dev_err(&pdev->dev, "SMEM is not initialized by SBL\n");
709 return -EINVAL;
710 }
711
712 version = qcom_smem_get_sbl_version(smem);
713 if (version >> 16 != SMEM_EXPECTED_VERSION) {
714 dev_err(&pdev->dev, "Unsupported SMEM version 0x%x\n", version);
715 return -EINVAL;
716 }
717
718 ret = qcom_smem_enumerate_partitions(smem, SMEM_HOST_APPS);
719 if (ret < 0)
720 return ret;
721
722 hwlock_id = of_hwspin_lock_get_id(pdev->dev.of_node, 0);
723 if (hwlock_id < 0) {
724 dev_err(&pdev->dev, "failed to retrieve hwlock\n");
725 return hwlock_id;
726 }
727
728 smem->hwlock = hwspin_lock_request_specific(hwlock_id);
729 if (!smem->hwlock)
730 return -ENXIO;
731
732 __smem = smem;
733
734 return 0;
735}
736
737static int qcom_smem_remove(struct platform_device *pdev)
738{
739 __smem = NULL;
740 hwspin_lock_free(__smem->hwlock);
741
742 return 0;
743}
744
745static const struct of_device_id qcom_smem_of_match[] = {
746 { .compatible = "qcom,smem" },
747 {}
748};
749MODULE_DEVICE_TABLE(of, qcom_smem_of_match);
750
751static struct platform_driver qcom_smem_driver = {
752 .probe = qcom_smem_probe,
753 .remove = qcom_smem_remove,
754 .driver = {
755 .name = "qcom-smem",
756 .of_match_table = qcom_smem_of_match,
757 .suppress_bind_attrs = true,
758 },
759};
760
761static int __init qcom_smem_init(void)
762{
763 return platform_driver_register(&qcom_smem_driver);
764}
765arch_initcall(qcom_smem_init);
766
767static void __exit qcom_smem_exit(void)
768{
769 platform_driver_unregister(&qcom_smem_driver);
770}
771module_exit(qcom_smem_exit)
772
773MODULE_AUTHOR("Bjorn Andersson <bjorn.andersson@sonymobile.com>");
774MODULE_DESCRIPTION("Qualcomm Shared Memory Manager");
775MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/tegra/Makefile b/drivers/soc/tegra/Makefile
index cdaad9d53a05..ae857ff7d53d 100644
--- a/drivers/soc/tegra/Makefile
+++ b/drivers/soc/tegra/Makefile
@@ -1,4 +1,4 @@
1obj-$(CONFIG_ARCH_TEGRA) += fuse/ 1obj-y += fuse/
2 2
3obj-$(CONFIG_ARCH_TEGRA) += common.o 3obj-y += common.o
4obj-$(CONFIG_ARCH_TEGRA) += pmc.o 4obj-y += pmc.o
diff --git a/drivers/soc/tegra/common.c b/drivers/soc/tegra/common.c
index a71cb74f3674..cd8f41351add 100644
--- a/drivers/soc/tegra/common.c
+++ b/drivers/soc/tegra/common.c
@@ -15,6 +15,8 @@ static const struct of_device_id tegra_machine_match[] = {
15 { .compatible = "nvidia,tegra30", }, 15 { .compatible = "nvidia,tegra30", },
16 { .compatible = "nvidia,tegra114", }, 16 { .compatible = "nvidia,tegra114", },
17 { .compatible = "nvidia,tegra124", }, 17 { .compatible = "nvidia,tegra124", },
18 { .compatible = "nvidia,tegra132", },
19 { .compatible = "nvidia,tegra210", },
18 { } 20 { }
19}; 21};
20 22
diff --git a/drivers/soc/tegra/fuse/Makefile b/drivers/soc/tegra/fuse/Makefile
index 3af357da91f3..21bc27580178 100644
--- a/drivers/soc/tegra/fuse/Makefile
+++ b/drivers/soc/tegra/fuse/Makefile
@@ -6,3 +6,5 @@ obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += speedo-tegra20.o
6obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += speedo-tegra30.o 6obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += speedo-tegra30.o
7obj-$(CONFIG_ARCH_TEGRA_114_SOC) += speedo-tegra114.o 7obj-$(CONFIG_ARCH_TEGRA_114_SOC) += speedo-tegra114.o
8obj-$(CONFIG_ARCH_TEGRA_124_SOC) += speedo-tegra124.o 8obj-$(CONFIG_ARCH_TEGRA_124_SOC) += speedo-tegra124.o
9obj-$(CONFIG_ARCH_TEGRA_132_SOC) += speedo-tegra124.o
10obj-$(CONFIG_ARCH_TEGRA_210_SOC) += speedo-tegra210.o
diff --git a/drivers/soc/tegra/fuse/fuse-tegra.c b/drivers/soc/tegra/fuse/fuse-tegra.c
index c0d660f1aaac..de2c1bfe28b5 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra.c
@@ -15,9 +15,10 @@
15 * 15 *
16 */ 16 */
17 17
18#include <linux/clk.h>
18#include <linux/device.h> 19#include <linux/device.h>
19#include <linux/kobject.h> 20#include <linux/kobject.h>
20#include <linux/kernel.h> 21#include <linux/module.h>
21#include <linux/platform_device.h> 22#include <linux/platform_device.h>
22#include <linux/of.h> 23#include <linux/of.h>
23#include <linux/of_address.h> 24#include <linux/of_address.h>
@@ -28,8 +29,6 @@
28 29
29#include "fuse.h" 30#include "fuse.h"
30 31
31static u32 (*fuse_readl)(const unsigned int offset);
32static int fuse_size;
33struct tegra_sku_info tegra_sku_info; 32struct tegra_sku_info tegra_sku_info;
34EXPORT_SYMBOL(tegra_sku_info); 33EXPORT_SYMBOL(tegra_sku_info);
35 34
@@ -42,11 +41,11 @@ static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
42 [TEGRA_REVISION_A04] = "A04", 41 [TEGRA_REVISION_A04] = "A04",
43}; 42};
44 43
45static u8 fuse_readb(const unsigned int offset) 44static u8 fuse_readb(struct tegra_fuse *fuse, unsigned int offset)
46{ 45{
47 u32 val; 46 u32 val;
48 47
49 val = fuse_readl(round_down(offset, 4)); 48 val = fuse->read(fuse, round_down(offset, 4));
50 val >>= (offset % 4) * 8; 49 val >>= (offset % 4) * 8;
51 val &= 0xff; 50 val &= 0xff;
52 51
@@ -54,19 +53,21 @@ static u8 fuse_readb(const unsigned int offset)
54} 53}
55 54
56static ssize_t fuse_read(struct file *fd, struct kobject *kobj, 55static ssize_t fuse_read(struct file *fd, struct kobject *kobj,
57 struct bin_attribute *attr, char *buf, 56 struct bin_attribute *attr, char *buf,
58 loff_t pos, size_t size) 57 loff_t pos, size_t size)
59{ 58{
59 struct device *dev = kobj_to_dev(kobj);
60 struct tegra_fuse *fuse = dev_get_drvdata(dev);
60 int i; 61 int i;
61 62
62 if (pos < 0 || pos >= fuse_size) 63 if (pos < 0 || pos >= attr->size)
63 return 0; 64 return 0;
64 65
65 if (size > fuse_size - pos) 66 if (size > attr->size - pos)
66 size = fuse_size - pos; 67 size = attr->size - pos;
67 68
68 for (i = 0; i < size; i++) 69 for (i = 0; i < size; i++)
69 buf[i] = fuse_readb(pos + i); 70 buf[i] = fuse_readb(fuse, pos + i);
70 71
71 return i; 72 return i;
72} 73}
@@ -76,89 +77,239 @@ static struct bin_attribute fuse_bin_attr = {
76 .read = fuse_read, 77 .read = fuse_read,
77}; 78};
78 79
80static int tegra_fuse_create_sysfs(struct device *dev, unsigned int size,
81 const struct tegra_fuse_info *info)
82{
83 fuse_bin_attr.size = size;
84
85 return device_create_bin_file(dev, &fuse_bin_attr);
86}
87
79static const struct of_device_id car_match[] __initconst = { 88static const struct of_device_id car_match[] __initconst = {
80 { .compatible = "nvidia,tegra20-car", }, 89 { .compatible = "nvidia,tegra20-car", },
81 { .compatible = "nvidia,tegra30-car", }, 90 { .compatible = "nvidia,tegra30-car", },
82 { .compatible = "nvidia,tegra114-car", }, 91 { .compatible = "nvidia,tegra114-car", },
83 { .compatible = "nvidia,tegra124-car", }, 92 { .compatible = "nvidia,tegra124-car", },
84 { .compatible = "nvidia,tegra132-car", }, 93 { .compatible = "nvidia,tegra132-car", },
94 { .compatible = "nvidia,tegra210-car", },
85 {}, 95 {},
86}; 96};
87 97
88static void tegra_enable_fuse_clk(void __iomem *base) 98static struct tegra_fuse *fuse = &(struct tegra_fuse) {
99 .base = NULL,
100 .soc = NULL,
101};
102
103static const struct of_device_id tegra_fuse_match[] = {
104#ifdef CONFIG_ARCH_TEGRA_210_SOC
105 { .compatible = "nvidia,tegra210-efuse", .data = &tegra210_fuse_soc },
106#endif
107#ifdef CONFIG_ARCH_TEGRA_132_SOC
108 { .compatible = "nvidia,tegra132-efuse", .data = &tegra124_fuse_soc },
109#endif
110#ifdef CONFIG_ARCH_TEGRA_124_SOC
111 { .compatible = "nvidia,tegra124-efuse", .data = &tegra124_fuse_soc },
112#endif
113#ifdef CONFIG_ARCH_TEGRA_114_SOC
114 { .compatible = "nvidia,tegra114-efuse", .data = &tegra114_fuse_soc },
115#endif
116#ifdef CONFIG_ARCH_TEGRA_3x_SOC
117 { .compatible = "nvidia,tegra30-efuse", .data = &tegra30_fuse_soc },
118#endif
119#ifdef CONFIG_ARCH_TEGRA_2x_SOC
120 { .compatible = "nvidia,tegra20-efuse", .data = &tegra20_fuse_soc },
121#endif
122 { /* sentinel */ }
123};
124
125static int tegra_fuse_probe(struct platform_device *pdev)
89{ 126{
90 u32 reg; 127 void __iomem *base = fuse->base;
128 struct resource *res;
129 int err;
130
131 /* take over the memory region from the early initialization */
132 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
133 fuse->base = devm_ioremap_resource(&pdev->dev, res);
134 if (IS_ERR(fuse->base))
135 return PTR_ERR(fuse->base);
136
137 fuse->clk = devm_clk_get(&pdev->dev, "fuse");
138 if (IS_ERR(fuse->clk)) {
139 dev_err(&pdev->dev, "failed to get FUSE clock: %ld",
140 PTR_ERR(fuse->clk));
141 return PTR_ERR(fuse->clk);
142 }
91 143
92 reg = readl_relaxed(base + 0x48); 144 platform_set_drvdata(pdev, fuse);
93 reg |= 1 << 28; 145 fuse->dev = &pdev->dev;
94 writel(reg, base + 0x48);
95 146
96 /* 147 if (fuse->soc->probe) {
97 * Enable FUSE clock. This needs to be hardcoded because the clock 148 err = fuse->soc->probe(fuse);
98 * subsystem is not active during early boot. 149 if (err < 0)
99 */ 150 return err;
100 reg = readl(base + 0x14); 151 }
101 reg |= 1 << 7; 152
102 writel(reg, base + 0x14); 153 if (tegra_fuse_create_sysfs(&pdev->dev, fuse->soc->info->size,
154 fuse->soc->info))
155 return -ENODEV;
156
157 /* release the early I/O memory mapping */
158 iounmap(base);
159
160 return 0;
161}
162
163static struct platform_driver tegra_fuse_driver = {
164 .driver = {
165 .name = "tegra-fuse",
166 .of_match_table = tegra_fuse_match,
167 .suppress_bind_attrs = true,
168 },
169 .probe = tegra_fuse_probe,
170};
171module_platform_driver(tegra_fuse_driver);
172
173bool __init tegra_fuse_read_spare(unsigned int spare)
174{
175 unsigned int offset = fuse->soc->info->spare + spare * 4;
176
177 return fuse->read_early(fuse, offset) & 1;
178}
179
180u32 __init tegra_fuse_read_early(unsigned int offset)
181{
182 return fuse->read_early(fuse, offset);
103} 183}
104 184
105int tegra_fuse_readl(unsigned long offset, u32 *value) 185int tegra_fuse_readl(unsigned long offset, u32 *value)
106{ 186{
107 if (!fuse_readl) 187 if (!fuse->read)
108 return -EPROBE_DEFER; 188 return -EPROBE_DEFER;
109 189
110 *value = fuse_readl(offset); 190 *value = fuse->read(fuse, offset);
111 191
112 return 0; 192 return 0;
113} 193}
114EXPORT_SYMBOL(tegra_fuse_readl); 194EXPORT_SYMBOL(tegra_fuse_readl);
115 195
116int tegra_fuse_create_sysfs(struct device *dev, int size, 196static void tegra_enable_fuse_clk(void __iomem *base)
117 u32 (*readl)(const unsigned int offset))
118{ 197{
119 if (fuse_size) 198 u32 reg;
120 return -ENODEV;
121
122 fuse_bin_attr.size = size;
123 fuse_bin_attr.read = fuse_read;
124 199
125 fuse_size = size; 200 reg = readl_relaxed(base + 0x48);
126 fuse_readl = readl; 201 reg |= 1 << 28;
202 writel(reg, base + 0x48);
127 203
128 return device_create_bin_file(dev, &fuse_bin_attr); 204 /*
205 * Enable FUSE clock. This needs to be hardcoded because the clock
206 * subsystem is not active during early boot.
207 */
208 reg = readl(base + 0x14);
209 reg |= 1 << 7;
210 writel(reg, base + 0x14);
129} 211}
130 212
131static int __init tegra_init_fuse(void) 213static int __init tegra_init_fuse(void)
132{ 214{
215 const struct of_device_id *match;
133 struct device_node *np; 216 struct device_node *np;
134 void __iomem *car_base; 217 struct resource regs;
135
136 if (!soc_is_tegra())
137 return 0;
138 218
139 tegra_init_apbmisc(); 219 tegra_init_apbmisc();
140 220
141 np = of_find_matching_node(NULL, car_match); 221 np = of_find_matching_node_and_match(NULL, tegra_fuse_match, &match);
142 car_base = of_iomap(np, 0); 222 if (!np) {
143 if (car_base) { 223 /*
144 tegra_enable_fuse_clk(car_base); 224 * Fall back to legacy initialization for 32-bit ARM only. All
145 iounmap(car_base); 225 * 64-bit ARM device tree files for Tegra are required to have
226 * a FUSE node.
227 *
228 * This is for backwards-compatibility with old device trees
229 * that didn't contain a FUSE node.
230 */
231 if (IS_ENABLED(CONFIG_ARM) && soc_is_tegra()) {
232 u8 chip = tegra_get_chip_id();
233
234 regs.start = 0x7000f800;
235 regs.end = 0x7000fbff;
236 regs.flags = IORESOURCE_MEM;
237
238 switch (chip) {
239#ifdef CONFIG_ARCH_TEGRA_2x_SOC
240 case TEGRA20:
241 fuse->soc = &tegra20_fuse_soc;
242 break;
243#endif
244
245#ifdef CONFIG_ARCH_TEGRA_3x_SOC
246 case TEGRA30:
247 fuse->soc = &tegra30_fuse_soc;
248 break;
249#endif
250
251#ifdef CONFIG_ARCH_TEGRA_114_SOC
252 case TEGRA114:
253 fuse->soc = &tegra114_fuse_soc;
254 break;
255#endif
256
257#ifdef CONFIG_ARCH_TEGRA_124_SOC
258 case TEGRA124:
259 fuse->soc = &tegra124_fuse_soc;
260 break;
261#endif
262
263 default:
264 pr_warn("Unsupported SoC: %02x\n", chip);
265 break;
266 }
267 } else {
268 /*
269 * At this point we're not running on Tegra, so play
270 * nice with multi-platform kernels.
271 */
272 return 0;
273 }
146 } else { 274 } else {
147 pr_err("Could not enable fuse clk. ioremap tegra car failed.\n"); 275 /*
276 * Extract information from the device tree if we've found a
277 * matching node.
278 */
279 if (of_address_to_resource(np, 0, &regs) < 0) {
280 pr_err("failed to get FUSE register\n");
281 return -ENXIO;
282 }
283
284 fuse->soc = match->data;
285 }
286
287 np = of_find_matching_node(NULL, car_match);
288 if (np) {
289 void __iomem *base = of_iomap(np, 0);
290 if (base) {
291 tegra_enable_fuse_clk(base);
292 iounmap(base);
293 } else {
294 pr_err("failed to map clock registers\n");
295 return -ENXIO;
296 }
297 }
298
299 fuse->base = ioremap_nocache(regs.start, resource_size(&regs));
300 if (!fuse->base) {
301 pr_err("failed to map FUSE registers\n");
148 return -ENXIO; 302 return -ENXIO;
149 } 303 }
150 304
151 if (tegra_get_chip_id() == TEGRA20) 305 fuse->soc->init(fuse);
152 tegra20_init_fuse_early();
153 else
154 tegra30_init_fuse_early();
155 306
156 pr_info("Tegra Revision: %s SKU: %d CPU Process: %d Core Process: %d\n", 307 pr_info("Tegra Revision: %s SKU: %d CPU Process: %d SoC Process: %d\n",
157 tegra_revision_name[tegra_sku_info.revision], 308 tegra_revision_name[tegra_sku_info.revision],
158 tegra_sku_info.sku_id, tegra_sku_info.cpu_process_id, 309 tegra_sku_info.sku_id, tegra_sku_info.cpu_process_id,
159 tegra_sku_info.core_process_id); 310 tegra_sku_info.soc_process_id);
160 pr_debug("Tegra CPU Speedo ID %d, Soc Speedo ID %d\n", 311 pr_debug("Tegra CPU Speedo ID %d, SoC Speedo ID %d\n",
161 tegra_sku_info.cpu_speedo_id, tegra_sku_info.soc_speedo_id); 312 tegra_sku_info.cpu_speedo_id, tegra_sku_info.soc_speedo_id);
162 313
163 return 0; 314 return 0;
164} 315}
diff --git a/drivers/soc/tegra/fuse/fuse-tegra20.c b/drivers/soc/tegra/fuse/fuse-tegra20.c
index 6acc2c44ee2c..294413a969a0 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra20.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra20.c
@@ -34,159 +34,107 @@
34#include "fuse.h" 34#include "fuse.h"
35 35
36#define FUSE_BEGIN 0x100 36#define FUSE_BEGIN 0x100
37#define FUSE_SIZE 0x1f8
38#define FUSE_UID_LOW 0x08 37#define FUSE_UID_LOW 0x08
39#define FUSE_UID_HIGH 0x0c 38#define FUSE_UID_HIGH 0x0c
40 39
41static phys_addr_t fuse_phys; 40static u32 tegra20_fuse_read_early(struct tegra_fuse *fuse, unsigned int offset)
42static struct clk *fuse_clk; 41{
43static void __iomem __initdata *fuse_base; 42 return readl_relaxed(fuse->base + FUSE_BEGIN + offset);
44 43}
45static DEFINE_MUTEX(apb_dma_lock);
46static DECLARE_COMPLETION(apb_dma_wait);
47static struct dma_chan *apb_dma_chan;
48static struct dma_slave_config dma_sconfig;
49static u32 *apb_buffer;
50static dma_addr_t apb_buffer_phys;
51 44
52static void apb_dma_complete(void *args) 45static void apb_dma_complete(void *args)
53{ 46{
54 complete(&apb_dma_wait); 47 struct tegra_fuse *fuse = args;
48
49 complete(&fuse->apbdma.wait);
55} 50}
56 51
57static u32 tegra20_fuse_readl(const unsigned int offset) 52static u32 tegra20_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
58{ 53{
59 int ret; 54 unsigned long flags = DMA_PREP_INTERRUPT | DMA_CTRL_ACK;
60 u32 val = 0;
61 struct dma_async_tx_descriptor *dma_desc; 55 struct dma_async_tx_descriptor *dma_desc;
62 unsigned long time_left; 56 unsigned long time_left;
57 u32 value = 0;
58 int err;
59
60 mutex_lock(&fuse->apbdma.lock);
63 61
64 mutex_lock(&apb_dma_lock); 62 fuse->apbdma.config.src_addr = fuse->apbdma.phys + FUSE_BEGIN + offset;
65 63
66 dma_sconfig.src_addr = fuse_phys + FUSE_BEGIN + offset; 64 err = dmaengine_slave_config(fuse->apbdma.chan, &fuse->apbdma.config);
67 ret = dmaengine_slave_config(apb_dma_chan, &dma_sconfig); 65 if (err)
68 if (ret)
69 goto out; 66 goto out;
70 67
71 dma_desc = dmaengine_prep_slave_single(apb_dma_chan, apb_buffer_phys, 68 dma_desc = dmaengine_prep_slave_single(fuse->apbdma.chan,
72 sizeof(u32), DMA_DEV_TO_MEM, 69 fuse->apbdma.phys,
73 DMA_PREP_INTERRUPT | DMA_CTRL_ACK); 70 sizeof(u32), DMA_DEV_TO_MEM,
71 flags);
74 if (!dma_desc) 72 if (!dma_desc)
75 goto out; 73 goto out;
76 74
77 dma_desc->callback = apb_dma_complete; 75 dma_desc->callback = apb_dma_complete;
78 dma_desc->callback_param = NULL; 76 dma_desc->callback_param = fuse;
79 77
80 reinit_completion(&apb_dma_wait); 78 reinit_completion(&fuse->apbdma.wait);
81 79
82 clk_prepare_enable(fuse_clk); 80 clk_prepare_enable(fuse->clk);
83 81
84 dmaengine_submit(dma_desc); 82 dmaengine_submit(dma_desc);
85 dma_async_issue_pending(apb_dma_chan); 83 dma_async_issue_pending(fuse->apbdma.chan);
86 time_left = wait_for_completion_timeout(&apb_dma_wait, 84 time_left = wait_for_completion_timeout(&fuse->apbdma.wait,
87 msecs_to_jiffies(50)); 85 msecs_to_jiffies(50));
88 86
89 if (WARN(time_left == 0, "apb read dma timed out")) 87 if (WARN(time_left == 0, "apb read dma timed out"))
90 dmaengine_terminate_all(apb_dma_chan); 88 dmaengine_terminate_all(fuse->apbdma.chan);
91 else 89 else
92 val = *apb_buffer; 90 value = *fuse->apbdma.virt;
93 91
94 clk_disable_unprepare(fuse_clk); 92 clk_disable_unprepare(fuse->clk);
95out:
96 mutex_unlock(&apb_dma_lock);
97 93
98 return val; 94out:
95 mutex_unlock(&fuse->apbdma.lock);
96 return value;
99} 97}
100 98
101static const struct of_device_id tegra20_fuse_of_match[] = { 99static int tegra20_fuse_probe(struct tegra_fuse *fuse)
102 { .compatible = "nvidia,tegra20-efuse" },
103 {},
104};
105
106static int apb_dma_init(void)
107{ 100{
108 dma_cap_mask_t mask; 101 dma_cap_mask_t mask;
109 102
110 dma_cap_zero(mask); 103 dma_cap_zero(mask);
111 dma_cap_set(DMA_SLAVE, mask); 104 dma_cap_set(DMA_SLAVE, mask);
112 apb_dma_chan = dma_request_channel(mask, NULL, NULL); 105
113 if (!apb_dma_chan) 106 fuse->apbdma.chan = dma_request_channel(mask, NULL, NULL);
107 if (!fuse->apbdma.chan)
114 return -EPROBE_DEFER; 108 return -EPROBE_DEFER;
115 109
116 apb_buffer = dma_alloc_coherent(NULL, sizeof(u32), &apb_buffer_phys, 110 fuse->apbdma.virt = dma_alloc_coherent(fuse->dev, sizeof(u32),
117 GFP_KERNEL); 111 &fuse->apbdma.phys,
118 if (!apb_buffer) { 112 GFP_KERNEL);
119 dma_release_channel(apb_dma_chan); 113 if (!fuse->apbdma.virt) {
114 dma_release_channel(fuse->apbdma.chan);
120 return -ENOMEM; 115 return -ENOMEM;
121 } 116 }
122 117
123 dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 118 fuse->apbdma.config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
124 dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; 119 fuse->apbdma.config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
125 dma_sconfig.src_maxburst = 1; 120 fuse->apbdma.config.src_maxburst = 1;
126 dma_sconfig.dst_maxburst = 1; 121 fuse->apbdma.config.dst_maxburst = 1;
127 122
128 return 0; 123 init_completion(&fuse->apbdma.wait);
129} 124 mutex_init(&fuse->apbdma.lock);
130 125 fuse->read = tegra20_fuse_read;
131static int tegra20_fuse_probe(struct platform_device *pdev)
132{
133 struct resource *res;
134 int err;
135
136 fuse_clk = devm_clk_get(&pdev->dev, NULL);
137 if (IS_ERR(fuse_clk)) {
138 dev_err(&pdev->dev, "missing clock");
139 return PTR_ERR(fuse_clk);
140 }
141
142 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
143 if (!res)
144 return -EINVAL;
145 fuse_phys = res->start;
146
147 err = apb_dma_init();
148 if (err)
149 return err;
150
151 if (tegra_fuse_create_sysfs(&pdev->dev, FUSE_SIZE, tegra20_fuse_readl))
152 return -ENODEV;
153
154 dev_dbg(&pdev->dev, "loaded\n");
155 126
156 return 0; 127 return 0;
157} 128}
158 129
159static struct platform_driver tegra20_fuse_driver = { 130static const struct tegra_fuse_info tegra20_fuse_info = {
160 .probe = tegra20_fuse_probe, 131 .read = tegra20_fuse_read,
161 .driver = { 132 .size = 0x1f8,
162 .name = "tegra20_fuse", 133 .spare = 0x100,
163 .of_match_table = tegra20_fuse_of_match,
164 }
165}; 134};
166 135
167static int __init tegra20_fuse_init(void)
168{
169 return platform_driver_register(&tegra20_fuse_driver);
170}
171postcore_initcall(tegra20_fuse_init);
172
173/* Early boot code. This code is called before the devices are created */ 136/* Early boot code. This code is called before the devices are created */
174 137
175u32 __init tegra20_fuse_early(const unsigned int offset)
176{
177 return readl_relaxed(fuse_base + FUSE_BEGIN + offset);
178}
179
180bool __init tegra20_spare_fuse_early(int spare_bit)
181{
182 u32 offset = spare_bit * 4;
183 bool value;
184
185 value = tegra20_fuse_early(offset + 0x100);
186
187 return value;
188}
189
190static void __init tegra20_fuse_add_randomness(void) 138static void __init tegra20_fuse_add_randomness(void)
191{ 139{
192 u32 randomness[7]; 140 u32 randomness[7];
@@ -195,22 +143,27 @@ static void __init tegra20_fuse_add_randomness(void)
195 randomness[1] = tegra_read_straps(); 143 randomness[1] = tegra_read_straps();
196 randomness[2] = tegra_read_chipid(); 144 randomness[2] = tegra_read_chipid();
197 randomness[3] = tegra_sku_info.cpu_process_id << 16; 145 randomness[3] = tegra_sku_info.cpu_process_id << 16;
198 randomness[3] |= tegra_sku_info.core_process_id; 146 randomness[3] |= tegra_sku_info.soc_process_id;
199 randomness[4] = tegra_sku_info.cpu_speedo_id << 16; 147 randomness[4] = tegra_sku_info.cpu_speedo_id << 16;
200 randomness[4] |= tegra_sku_info.soc_speedo_id; 148 randomness[4] |= tegra_sku_info.soc_speedo_id;
201 randomness[5] = tegra20_fuse_early(FUSE_UID_LOW); 149 randomness[5] = tegra_fuse_read_early(FUSE_UID_LOW);
202 randomness[6] = tegra20_fuse_early(FUSE_UID_HIGH); 150 randomness[6] = tegra_fuse_read_early(FUSE_UID_HIGH);
203 151
204 add_device_randomness(randomness, sizeof(randomness)); 152 add_device_randomness(randomness, sizeof(randomness));
205} 153}
206 154
207void __init tegra20_init_fuse_early(void) 155static void __init tegra20_fuse_init(struct tegra_fuse *fuse)
208{ 156{
209 fuse_base = ioremap(TEGRA_FUSE_BASE, TEGRA_FUSE_SIZE); 157 fuse->read_early = tegra20_fuse_read_early;
210 158
211 tegra_init_revision(); 159 tegra_init_revision();
212 tegra20_init_speedo_data(&tegra_sku_info); 160 fuse->soc->speedo_init(&tegra_sku_info);
213 tegra20_fuse_add_randomness(); 161 tegra20_fuse_add_randomness();
214
215 iounmap(fuse_base);
216} 162}
163
164const struct tegra_fuse_soc tegra20_fuse_soc = {
165 .init = tegra20_fuse_init,
166 .speedo_init = tegra20_init_speedo_data,
167 .probe = tegra20_fuse_probe,
168 .info = &tegra20_fuse_info,
169};
diff --git a/drivers/soc/tegra/fuse/fuse-tegra30.c b/drivers/soc/tegra/fuse/fuse-tegra30.c
index 4d2f71bf65c5..882607bcaa6c 100644
--- a/drivers/soc/tegra/fuse/fuse-tegra30.c
+++ b/drivers/soc/tegra/fuse/fuse-tegra30.c
@@ -42,113 +42,33 @@
42 42
43#define FUSE_HAS_REVISION_INFO BIT(0) 43#define FUSE_HAS_REVISION_INFO BIT(0)
44 44
45enum speedo_idx { 45#if defined(CONFIG_ARCH_TEGRA_3x_SOC) || \
46 SPEEDO_TEGRA30 = 0, 46 defined(CONFIG_ARCH_TEGRA_114_SOC) || \
47 SPEEDO_TEGRA114, 47 defined(CONFIG_ARCH_TEGRA_124_SOC) || \
48 SPEEDO_TEGRA124, 48 defined(CONFIG_ARCH_TEGRA_132_SOC) || \
49}; 49 defined(CONFIG_ARCH_TEGRA_210_SOC)
50 50static u32 tegra30_fuse_read_early(struct tegra_fuse *fuse, unsigned int offset)
51struct tegra_fuse_info {
52 int size;
53 int spare_bit;
54 enum speedo_idx speedo_idx;
55};
56
57static void __iomem *fuse_base;
58static struct clk *fuse_clk;
59static const struct tegra_fuse_info *fuse_info;
60
61u32 tegra30_fuse_readl(const unsigned int offset)
62{ 51{
63 u32 val; 52 return readl_relaxed(fuse->base + FUSE_BEGIN + offset);
64
65 /*
66 * early in the boot, the fuse clock will be enabled by
67 * tegra_init_fuse()
68 */
69
70 if (fuse_clk)
71 clk_prepare_enable(fuse_clk);
72
73 val = readl_relaxed(fuse_base + FUSE_BEGIN + offset);
74
75 if (fuse_clk)
76 clk_disable_unprepare(fuse_clk);
77
78 return val;
79} 53}
80 54
81static const struct tegra_fuse_info tegra30_info = { 55static u32 tegra30_fuse_read(struct tegra_fuse *fuse, unsigned int offset)
82 .size = 0x2a4,
83 .spare_bit = 0x144,
84 .speedo_idx = SPEEDO_TEGRA30,
85};
86
87static const struct tegra_fuse_info tegra114_info = {
88 .size = 0x2a0,
89 .speedo_idx = SPEEDO_TEGRA114,
90};
91
92static const struct tegra_fuse_info tegra124_info = {
93 .size = 0x300,
94 .speedo_idx = SPEEDO_TEGRA124,
95};
96
97static const struct of_device_id tegra30_fuse_of_match[] = {
98 { .compatible = "nvidia,tegra30-efuse", .data = &tegra30_info },
99 { .compatible = "nvidia,tegra114-efuse", .data = &tegra114_info },
100 { .compatible = "nvidia,tegra124-efuse", .data = &tegra124_info },
101 {},
102};
103
104static int tegra30_fuse_probe(struct platform_device *pdev)
105{ 56{
106 const struct of_device_id *of_dev_id; 57 u32 value;
107 58 int err;
108 of_dev_id = of_match_device(tegra30_fuse_of_match, &pdev->dev);
109 if (!of_dev_id)
110 return -ENODEV;
111 59
112 fuse_clk = devm_clk_get(&pdev->dev, NULL); 60 err = clk_prepare_enable(fuse->clk);
113 if (IS_ERR(fuse_clk)) { 61 if (err < 0) {
114 dev_err(&pdev->dev, "missing clock"); 62 dev_err(fuse->dev, "failed to enable FUSE clock: %d\n", err);
115 return PTR_ERR(fuse_clk); 63 return 0;
116 } 64 }
117 65
118 platform_set_drvdata(pdev, NULL); 66 value = readl_relaxed(fuse->base + FUSE_BEGIN + offset);
119
120 if (tegra_fuse_create_sysfs(&pdev->dev, fuse_info->size,
121 tegra30_fuse_readl))
122 return -ENODEV;
123 67
124 dev_dbg(&pdev->dev, "loaded\n"); 68 clk_disable_unprepare(fuse->clk);
125 69
126 return 0; 70 return value;
127}
128
129static struct platform_driver tegra30_fuse_driver = {
130 .probe = tegra30_fuse_probe,
131 .driver = {
132 .name = "tegra_fuse",
133 .of_match_table = tegra30_fuse_of_match,
134 }
135};
136
137static int __init tegra30_fuse_init(void)
138{
139 return platform_driver_register(&tegra30_fuse_driver);
140} 71}
141postcore_initcall(tegra30_fuse_init);
142
143/* Early boot code. This code is called before the devices are created */
144
145typedef void (*speedo_f)(struct tegra_sku_info *sku_info);
146
147static speedo_f __initdata speedo_tbl[] = {
148 [SPEEDO_TEGRA30] = tegra30_init_speedo_data,
149 [SPEEDO_TEGRA114] = tegra114_init_speedo_data,
150 [SPEEDO_TEGRA124] = tegra124_init_speedo_data,
151};
152 72
153static void __init tegra30_fuse_add_randomness(void) 73static void __init tegra30_fuse_add_randomness(void)
154{ 74{
@@ -158,67 +78,83 @@ static void __init tegra30_fuse_add_randomness(void)
158 randomness[1] = tegra_read_straps(); 78 randomness[1] = tegra_read_straps();
159 randomness[2] = tegra_read_chipid(); 79 randomness[2] = tegra_read_chipid();
160 randomness[3] = tegra_sku_info.cpu_process_id << 16; 80 randomness[3] = tegra_sku_info.cpu_process_id << 16;
161 randomness[3] |= tegra_sku_info.core_process_id; 81 randomness[3] |= tegra_sku_info.soc_process_id;
162 randomness[4] = tegra_sku_info.cpu_speedo_id << 16; 82 randomness[4] = tegra_sku_info.cpu_speedo_id << 16;
163 randomness[4] |= tegra_sku_info.soc_speedo_id; 83 randomness[4] |= tegra_sku_info.soc_speedo_id;
164 randomness[5] = tegra30_fuse_readl(FUSE_VENDOR_CODE); 84 randomness[5] = tegra_fuse_read_early(FUSE_VENDOR_CODE);
165 randomness[6] = tegra30_fuse_readl(FUSE_FAB_CODE); 85 randomness[6] = tegra_fuse_read_early(FUSE_FAB_CODE);
166 randomness[7] = tegra30_fuse_readl(FUSE_LOT_CODE_0); 86 randomness[7] = tegra_fuse_read_early(FUSE_LOT_CODE_0);
167 randomness[8] = tegra30_fuse_readl(FUSE_LOT_CODE_1); 87 randomness[8] = tegra_fuse_read_early(FUSE_LOT_CODE_1);
168 randomness[9] = tegra30_fuse_readl(FUSE_WAFER_ID); 88 randomness[9] = tegra_fuse_read_early(FUSE_WAFER_ID);
169 randomness[10] = tegra30_fuse_readl(FUSE_X_COORDINATE); 89 randomness[10] = tegra_fuse_read_early(FUSE_X_COORDINATE);
170 randomness[11] = tegra30_fuse_readl(FUSE_Y_COORDINATE); 90 randomness[11] = tegra_fuse_read_early(FUSE_Y_COORDINATE);
171 91
172 add_device_randomness(randomness, sizeof(randomness)); 92 add_device_randomness(randomness, sizeof(randomness));
173} 93}
174 94
175static void __init legacy_fuse_init(void) 95static void __init tegra30_fuse_init(struct tegra_fuse *fuse)
176{ 96{
177 switch (tegra_get_chip_id()) { 97 fuse->read_early = tegra30_fuse_read_early;
178 case TEGRA30: 98 fuse->read = tegra30_fuse_read;
179 fuse_info = &tegra30_info;
180 break;
181 case TEGRA114:
182 fuse_info = &tegra114_info;
183 break;
184 case TEGRA124:
185 case TEGRA132:
186 fuse_info = &tegra124_info;
187 break;
188 default:
189 return;
190 }
191 99
192 fuse_base = ioremap(TEGRA_FUSE_BASE, TEGRA_FUSE_SIZE); 100 tegra_init_revision();
101 fuse->soc->speedo_init(&tegra_sku_info);
102 tegra30_fuse_add_randomness();
193} 103}
104#endif
194 105
195bool __init tegra30_spare_fuse(int spare_bit) 106#ifdef CONFIG_ARCH_TEGRA_3x_SOC
196{ 107static const struct tegra_fuse_info tegra30_fuse_info = {
197 u32 offset = fuse_info->spare_bit + spare_bit * 4; 108 .read = tegra30_fuse_read,
109 .size = 0x2a4,
110 .spare = 0x144,
111};
198 112
199 return tegra30_fuse_readl(offset) & 1; 113const struct tegra_fuse_soc tegra30_fuse_soc = {
200} 114 .init = tegra30_fuse_init,
115 .speedo_init = tegra30_init_speedo_data,
116 .info = &tegra30_fuse_info,
117};
118#endif
201 119
202void __init tegra30_init_fuse_early(void) 120#ifdef CONFIG_ARCH_TEGRA_114_SOC
203{ 121static const struct tegra_fuse_info tegra114_fuse_info = {
204 struct device_node *np; 122 .read = tegra30_fuse_read,
205 const struct of_device_id *of_match; 123 .size = 0x2a0,
206 124 .spare = 0x180,
207 np = of_find_matching_node_and_match(NULL, tegra30_fuse_of_match, 125};
208 &of_match);
209 if (np) {
210 fuse_base = of_iomap(np, 0);
211 fuse_info = (struct tegra_fuse_info *)of_match->data;
212 } else
213 legacy_fuse_init();
214
215 if (!fuse_base) {
216 pr_warn("fuse DT node missing and unknown chip id: 0x%02x\n",
217 tegra_get_chip_id());
218 return;
219 }
220 126
221 tegra_init_revision(); 127const struct tegra_fuse_soc tegra114_fuse_soc = {
222 speedo_tbl[fuse_info->speedo_idx](&tegra_sku_info); 128 .init = tegra30_fuse_init,
223 tegra30_fuse_add_randomness(); 129 .speedo_init = tegra114_init_speedo_data,
224} 130 .info = &tegra114_fuse_info,
131};
132#endif
133
134#if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
135static const struct tegra_fuse_info tegra124_fuse_info = {
136 .read = tegra30_fuse_read,
137 .size = 0x300,
138 .spare = 0x200,
139};
140
141const struct tegra_fuse_soc tegra124_fuse_soc = {
142 .init = tegra30_fuse_init,
143 .speedo_init = tegra124_init_speedo_data,
144 .info = &tegra124_fuse_info,
145};
146#endif
147
148#if defined(CONFIG_ARCH_TEGRA_210_SOC)
149static const struct tegra_fuse_info tegra210_fuse_info = {
150 .read = tegra30_fuse_read,
151 .size = 0x300,
152 .spare = 0x280,
153};
154
155const struct tegra_fuse_soc tegra210_fuse_soc = {
156 .init = tegra30_fuse_init,
157 .speedo_init = tegra210_init_speedo_data,
158 .info = &tegra210_fuse_info,
159};
160#endif
diff --git a/drivers/soc/tegra/fuse/fuse.h b/drivers/soc/tegra/fuse/fuse.h
index 3a398bf3572c..10c2076d5089 100644
--- a/drivers/soc/tegra/fuse/fuse.h
+++ b/drivers/soc/tegra/fuse/fuse.h
@@ -19,53 +19,90 @@
19#ifndef __DRIVERS_MISC_TEGRA_FUSE_H 19#ifndef __DRIVERS_MISC_TEGRA_FUSE_H
20#define __DRIVERS_MISC_TEGRA_FUSE_H 20#define __DRIVERS_MISC_TEGRA_FUSE_H
21 21
22#define TEGRA_FUSE_BASE 0x7000f800 22#include <linux/dmaengine.h>
23#define TEGRA_FUSE_SIZE 0x400 23#include <linux/types.h>
24 24
25int tegra_fuse_create_sysfs(struct device *dev, int size, 25struct tegra_fuse;
26 u32 (*readl)(const unsigned int offset)); 26
27struct tegra_fuse_info {
28 u32 (*read)(struct tegra_fuse *fuse, unsigned int offset);
29 unsigned int size;
30 unsigned int spare;
31};
32
33struct tegra_fuse_soc {
34 void (*init)(struct tegra_fuse *fuse);
35 void (*speedo_init)(struct tegra_sku_info *info);
36 int (*probe)(struct tegra_fuse *fuse);
37
38 const struct tegra_fuse_info *info;
39};
40
41struct tegra_fuse {
42 struct device *dev;
43 void __iomem *base;
44 phys_addr_t phys;
45 struct clk *clk;
46
47 u32 (*read_early)(struct tegra_fuse *fuse, unsigned int offset);
48 u32 (*read)(struct tegra_fuse *fuse, unsigned int offset);
49 const struct tegra_fuse_soc *soc;
50
51 /* APBDMA on Tegra20 */
52 struct {
53 struct mutex lock;
54 struct completion wait;
55 struct dma_chan *chan;
56 struct dma_slave_config config;
57 dma_addr_t phys;
58 u32 *virt;
59 } apbdma;
60};
27 61
28bool tegra30_spare_fuse(int bit);
29u32 tegra30_fuse_readl(const unsigned int offset);
30void tegra30_init_fuse_early(void);
31void tegra_init_revision(void); 62void tegra_init_revision(void);
32void tegra_init_apbmisc(void); 63void tegra_init_apbmisc(void);
33 64
65bool __init tegra_fuse_read_spare(unsigned int spare);
66u32 __init tegra_fuse_read_early(unsigned int offset);
67
34#ifdef CONFIG_ARCH_TEGRA_2x_SOC 68#ifdef CONFIG_ARCH_TEGRA_2x_SOC
35void tegra20_init_speedo_data(struct tegra_sku_info *sku_info); 69void tegra20_init_speedo_data(struct tegra_sku_info *sku_info);
36bool tegra20_spare_fuse_early(int spare_bit);
37void tegra20_init_fuse_early(void);
38u32 tegra20_fuse_early(const unsigned int offset);
39#else
40static inline void tegra20_init_speedo_data(struct tegra_sku_info *sku_info) {}
41static inline bool tegra20_spare_fuse_early(int spare_bit)
42{
43 return false;
44}
45static inline void tegra20_init_fuse_early(void) {}
46static inline u32 tegra20_fuse_early(const unsigned int offset)
47{
48 return 0;
49}
50#endif 70#endif
51 71
52
53#ifdef CONFIG_ARCH_TEGRA_3x_SOC 72#ifdef CONFIG_ARCH_TEGRA_3x_SOC
54void tegra30_init_speedo_data(struct tegra_sku_info *sku_info); 73void tegra30_init_speedo_data(struct tegra_sku_info *sku_info);
55#else
56static inline void tegra30_init_speedo_data(struct tegra_sku_info *sku_info) {}
57#endif 74#endif
58 75
59#ifdef CONFIG_ARCH_TEGRA_114_SOC 76#ifdef CONFIG_ARCH_TEGRA_114_SOC
60void tegra114_init_speedo_data(struct tegra_sku_info *sku_info); 77void tegra114_init_speedo_data(struct tegra_sku_info *sku_info);
61#else
62static inline void tegra114_init_speedo_data(struct tegra_sku_info *sku_info) {}
63#endif 78#endif
64 79
65#ifdef CONFIG_ARCH_TEGRA_124_SOC 80#if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
66void tegra124_init_speedo_data(struct tegra_sku_info *sku_info); 81void tegra124_init_speedo_data(struct tegra_sku_info *sku_info);
67#else 82#endif
68static inline void tegra124_init_speedo_data(struct tegra_sku_info *sku_info) {} 83
84#ifdef CONFIG_ARCH_TEGRA_210_SOC
85void tegra210_init_speedo_data(struct tegra_sku_info *sku_info);
86#endif
87
88#ifdef CONFIG_ARCH_TEGRA_2x_SOC
89extern const struct tegra_fuse_soc tegra20_fuse_soc;
90#endif
91
92#ifdef CONFIG_ARCH_TEGRA_3x_SOC
93extern const struct tegra_fuse_soc tegra30_fuse_soc;
94#endif
95
96#ifdef CONFIG_ARCH_TEGRA_114_SOC
97extern const struct tegra_fuse_soc tegra114_fuse_soc;
98#endif
99
100#if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC)
101extern const struct tegra_fuse_soc tegra124_fuse_soc;
102#endif
103
104#ifdef CONFIG_ARCH_TEGRA_210_SOC
105extern const struct tegra_fuse_soc tegra210_fuse_soc;
69#endif 106#endif
70 107
71#endif 108#endif
diff --git a/drivers/soc/tegra/fuse/speedo-tegra114.c b/drivers/soc/tegra/fuse/speedo-tegra114.c
index 2a6ca036f09f..1ba41ebbb23d 100644
--- a/drivers/soc/tegra/fuse/speedo-tegra114.c
+++ b/drivers/soc/tegra/fuse/speedo-tegra114.c
@@ -22,7 +22,7 @@
22 22
23#include "fuse.h" 23#include "fuse.h"
24 24
25#define CORE_PROCESS_CORNERS 2 25#define SOC_PROCESS_CORNERS 2
26#define CPU_PROCESS_CORNERS 2 26#define CPU_PROCESS_CORNERS 2
27 27
28enum { 28enum {
@@ -31,7 +31,7 @@ enum {
31 THRESHOLD_INDEX_COUNT, 31 THRESHOLD_INDEX_COUNT,
32}; 32};
33 33
34static const u32 __initconst core_process_speedos[][CORE_PROCESS_CORNERS] = { 34static const u32 __initconst soc_process_speedos[][SOC_PROCESS_CORNERS] = {
35 {1123, UINT_MAX}, 35 {1123, UINT_MAX},
36 {0, UINT_MAX}, 36 {0, UINT_MAX},
37}; 37};
@@ -74,8 +74,8 @@ static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info,
74 } 74 }
75 75
76 if (rev == TEGRA_REVISION_A01) { 76 if (rev == TEGRA_REVISION_A01) {
77 tmp = tegra30_fuse_readl(0x270) << 1; 77 tmp = tegra_fuse_read_early(0x270) << 1;
78 tmp |= tegra30_fuse_readl(0x26c); 78 tmp |= tegra_fuse_read_early(0x26c);
79 if (!tmp) 79 if (!tmp)
80 sku_info->cpu_speedo_id = 0; 80 sku_info->cpu_speedo_id = 0;
81 } 81 }
@@ -84,27 +84,27 @@ static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info,
84void __init tegra114_init_speedo_data(struct tegra_sku_info *sku_info) 84void __init tegra114_init_speedo_data(struct tegra_sku_info *sku_info)
85{ 85{
86 u32 cpu_speedo_val; 86 u32 cpu_speedo_val;
87 u32 core_speedo_val; 87 u32 soc_speedo_val;
88 int threshold; 88 int threshold;
89 int i; 89 int i;
90 90
91 BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != 91 BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
92 THRESHOLD_INDEX_COUNT); 92 THRESHOLD_INDEX_COUNT);
93 BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != 93 BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) !=
94 THRESHOLD_INDEX_COUNT); 94 THRESHOLD_INDEX_COUNT);
95 95
96 rev_sku_to_speedo_ids(sku_info, &threshold); 96 rev_sku_to_speedo_ids(sku_info, &threshold);
97 97
98 cpu_speedo_val = tegra30_fuse_readl(0x12c) + 1024; 98 cpu_speedo_val = tegra_fuse_read_early(0x12c) + 1024;
99 core_speedo_val = tegra30_fuse_readl(0x134); 99 soc_speedo_val = tegra_fuse_read_early(0x134);
100 100
101 for (i = 0; i < CPU_PROCESS_CORNERS; i++) 101 for (i = 0; i < CPU_PROCESS_CORNERS; i++)
102 if (cpu_speedo_val < cpu_process_speedos[threshold][i]) 102 if (cpu_speedo_val < cpu_process_speedos[threshold][i])
103 break; 103 break;
104 sku_info->cpu_process_id = i; 104 sku_info->cpu_process_id = i;
105 105
106 for (i = 0; i < CORE_PROCESS_CORNERS; i++) 106 for (i = 0; i < SOC_PROCESS_CORNERS; i++)
107 if (core_speedo_val < core_process_speedos[threshold][i]) 107 if (soc_speedo_val < soc_process_speedos[threshold][i])
108 break; 108 break;
109 sku_info->core_process_id = i; 109 sku_info->soc_process_id = i;
110} 110}
diff --git a/drivers/soc/tegra/fuse/speedo-tegra124.c b/drivers/soc/tegra/fuse/speedo-tegra124.c
index 46362387d974..a63a134101ab 100644
--- a/drivers/soc/tegra/fuse/speedo-tegra124.c
+++ b/drivers/soc/tegra/fuse/speedo-tegra124.c
@@ -24,7 +24,7 @@
24 24
25#define CPU_PROCESS_CORNERS 2 25#define CPU_PROCESS_CORNERS 2
26#define GPU_PROCESS_CORNERS 2 26#define GPU_PROCESS_CORNERS 2
27#define CORE_PROCESS_CORNERS 2 27#define SOC_PROCESS_CORNERS 2
28 28
29#define FUSE_CPU_SPEEDO_0 0x14 29#define FUSE_CPU_SPEEDO_0 0x14
30#define FUSE_CPU_SPEEDO_1 0x2c 30#define FUSE_CPU_SPEEDO_1 0x2c
@@ -53,7 +53,7 @@ static const u32 __initconst gpu_process_speedos[][GPU_PROCESS_CORNERS] = {
53 {0, UINT_MAX}, 53 {0, UINT_MAX},
54}; 54};
55 55
56static const u32 __initconst core_process_speedos[][CORE_PROCESS_CORNERS] = { 56static const u32 __initconst soc_process_speedos[][SOC_PROCESS_CORNERS] = {
57 {2101, UINT_MAX}, 57 {2101, UINT_MAX},
58 {0, UINT_MAX}, 58 {0, UINT_MAX},
59}; 59};
@@ -119,19 +119,19 @@ void __init tegra124_init_speedo_data(struct tegra_sku_info *sku_info)
119 THRESHOLD_INDEX_COUNT); 119 THRESHOLD_INDEX_COUNT);
120 BUILD_BUG_ON(ARRAY_SIZE(gpu_process_speedos) != 120 BUILD_BUG_ON(ARRAY_SIZE(gpu_process_speedos) !=
121 THRESHOLD_INDEX_COUNT); 121 THRESHOLD_INDEX_COUNT);
122 BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != 122 BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) !=
123 THRESHOLD_INDEX_COUNT); 123 THRESHOLD_INDEX_COUNT);
124 124
125 cpu_speedo_0_value = tegra30_fuse_readl(FUSE_CPU_SPEEDO_0); 125 cpu_speedo_0_value = tegra_fuse_read_early(FUSE_CPU_SPEEDO_0);
126 126
127 /* GPU Speedo is stored in CPU_SPEEDO_2 */ 127 /* GPU Speedo is stored in CPU_SPEEDO_2 */
128 sku_info->gpu_speedo_value = tegra30_fuse_readl(FUSE_CPU_SPEEDO_2); 128 sku_info->gpu_speedo_value = tegra_fuse_read_early(FUSE_CPU_SPEEDO_2);
129 129
130 soc_speedo_0_value = tegra30_fuse_readl(FUSE_SOC_SPEEDO_0); 130 soc_speedo_0_value = tegra_fuse_read_early(FUSE_SOC_SPEEDO_0);
131 131
132 cpu_iddq_value = tegra30_fuse_readl(FUSE_CPU_IDDQ); 132 cpu_iddq_value = tegra_fuse_read_early(FUSE_CPU_IDDQ);
133 soc_iddq_value = tegra30_fuse_readl(FUSE_SOC_IDDQ); 133 soc_iddq_value = tegra_fuse_read_early(FUSE_SOC_IDDQ);
134 gpu_iddq_value = tegra30_fuse_readl(FUSE_GPU_IDDQ); 134 gpu_iddq_value = tegra_fuse_read_early(FUSE_GPU_IDDQ);
135 135
136 sku_info->cpu_speedo_value = cpu_speedo_0_value; 136 sku_info->cpu_speedo_value = cpu_speedo_0_value;
137 137
@@ -143,7 +143,7 @@ void __init tegra124_init_speedo_data(struct tegra_sku_info *sku_info)
143 143
144 rev_sku_to_speedo_ids(sku_info, &threshold); 144 rev_sku_to_speedo_ids(sku_info, &threshold);
145 145
146 sku_info->cpu_iddq_value = tegra30_fuse_readl(FUSE_CPU_IDDQ); 146 sku_info->cpu_iddq_value = tegra_fuse_read_early(FUSE_CPU_IDDQ);
147 147
148 for (i = 0; i < GPU_PROCESS_CORNERS; i++) 148 for (i = 0; i < GPU_PROCESS_CORNERS; i++)
149 if (sku_info->gpu_speedo_value < 149 if (sku_info->gpu_speedo_value <
@@ -157,11 +157,11 @@ void __init tegra124_init_speedo_data(struct tegra_sku_info *sku_info)
157 break; 157 break;
158 sku_info->cpu_process_id = i; 158 sku_info->cpu_process_id = i;
159 159
160 for (i = 0; i < CORE_PROCESS_CORNERS; i++) 160 for (i = 0; i < SOC_PROCESS_CORNERS; i++)
161 if (soc_speedo_0_value < 161 if (soc_speedo_0_value <
162 core_process_speedos[threshold][i]) 162 soc_process_speedos[threshold][i])
163 break; 163 break;
164 sku_info->core_process_id = i; 164 sku_info->soc_process_id = i;
165 165
166 pr_debug("Tegra GPU Speedo ID=%d, Speedo Value=%d\n", 166 pr_debug("Tegra GPU Speedo ID=%d, Speedo Value=%d\n",
167 sku_info->gpu_speedo_id, sku_info->gpu_speedo_value); 167 sku_info->gpu_speedo_id, sku_info->gpu_speedo_value);
diff --git a/drivers/soc/tegra/fuse/speedo-tegra20.c b/drivers/soc/tegra/fuse/speedo-tegra20.c
index eff1b63f330d..5f7818bf6072 100644
--- a/drivers/soc/tegra/fuse/speedo-tegra20.c
+++ b/drivers/soc/tegra/fuse/speedo-tegra20.c
@@ -28,11 +28,11 @@
28#define CPU_SPEEDO_REDUND_MSBIT 39 28#define CPU_SPEEDO_REDUND_MSBIT 39
29#define CPU_SPEEDO_REDUND_OFFS (CPU_SPEEDO_REDUND_MSBIT - CPU_SPEEDO_MSBIT) 29#define CPU_SPEEDO_REDUND_OFFS (CPU_SPEEDO_REDUND_MSBIT - CPU_SPEEDO_MSBIT)
30 30
31#define CORE_SPEEDO_LSBIT 40 31#define SOC_SPEEDO_LSBIT 40
32#define CORE_SPEEDO_MSBIT 47 32#define SOC_SPEEDO_MSBIT 47
33#define CORE_SPEEDO_REDUND_LSBIT 48 33#define SOC_SPEEDO_REDUND_LSBIT 48
34#define CORE_SPEEDO_REDUND_MSBIT 55 34#define SOC_SPEEDO_REDUND_MSBIT 55
35#define CORE_SPEEDO_REDUND_OFFS (CORE_SPEEDO_REDUND_MSBIT - CORE_SPEEDO_MSBIT) 35#define SOC_SPEEDO_REDUND_OFFS (SOC_SPEEDO_REDUND_MSBIT - SOC_SPEEDO_MSBIT)
36 36
37#define SPEEDO_MULT 4 37#define SPEEDO_MULT 4
38 38
@@ -56,7 +56,7 @@ static const u32 __initconst cpu_process_speedos[][PROCESS_CORNERS_NUM] = {
56 {316, 331, 383, UINT_MAX}, 56 {316, 331, 383, UINT_MAX},
57}; 57};
58 58
59static const u32 __initconst core_process_speedos[][PROCESS_CORNERS_NUM] = { 59static const u32 __initconst soc_process_speedos[][PROCESS_CORNERS_NUM] = {
60 {165, 195, 224, UINT_MAX}, 60 {165, 195, 224, UINT_MAX},
61 {165, 195, 224, UINT_MAX}, 61 {165, 195, 224, UINT_MAX},
62 {165, 195, 224, UINT_MAX}, 62 {165, 195, 224, UINT_MAX},
@@ -69,7 +69,7 @@ void __init tegra20_init_speedo_data(struct tegra_sku_info *sku_info)
69 int i; 69 int i;
70 70
71 BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != SPEEDO_ID_COUNT); 71 BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != SPEEDO_ID_COUNT);
72 BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != SPEEDO_ID_COUNT); 72 BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) != SPEEDO_ID_COUNT);
73 73
74 if (SPEEDO_ID_SELECT_0(sku_info->revision)) 74 if (SPEEDO_ID_SELECT_0(sku_info->revision))
75 sku_info->soc_speedo_id = SPEEDO_ID_0; 75 sku_info->soc_speedo_id = SPEEDO_ID_0;
@@ -80,8 +80,8 @@ void __init tegra20_init_speedo_data(struct tegra_sku_info *sku_info)
80 80
81 val = 0; 81 val = 0;
82 for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) { 82 for (i = CPU_SPEEDO_MSBIT; i >= CPU_SPEEDO_LSBIT; i--) {
83 reg = tegra20_spare_fuse_early(i) | 83 reg = tegra_fuse_read_spare(i) |
84 tegra20_spare_fuse_early(i + CPU_SPEEDO_REDUND_OFFS); 84 tegra_fuse_read_spare(i + CPU_SPEEDO_REDUND_OFFS);
85 val = (val << 1) | (reg & 0x1); 85 val = (val << 1) | (reg & 0x1);
86 } 86 }
87 val = val * SPEEDO_MULT; 87 val = val * SPEEDO_MULT;
@@ -94,17 +94,17 @@ void __init tegra20_init_speedo_data(struct tegra_sku_info *sku_info)
94 sku_info->cpu_process_id = i; 94 sku_info->cpu_process_id = i;
95 95
96 val = 0; 96 val = 0;
97 for (i = CORE_SPEEDO_MSBIT; i >= CORE_SPEEDO_LSBIT; i--) { 97 for (i = SOC_SPEEDO_MSBIT; i >= SOC_SPEEDO_LSBIT; i--) {
98 reg = tegra20_spare_fuse_early(i) | 98 reg = tegra_fuse_read_spare(i) |
99 tegra20_spare_fuse_early(i + CORE_SPEEDO_REDUND_OFFS); 99 tegra_fuse_read_spare(i + SOC_SPEEDO_REDUND_OFFS);
100 val = (val << 1) | (reg & 0x1); 100 val = (val << 1) | (reg & 0x1);
101 } 101 }
102 val = val * SPEEDO_MULT; 102 val = val * SPEEDO_MULT;
103 pr_debug("Core speedo value %u\n", val); 103 pr_debug("Core speedo value %u\n", val);
104 104
105 for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) { 105 for (i = 0; i < (PROCESS_CORNERS_NUM - 1); i++) {
106 if (val <= core_process_speedos[sku_info->soc_speedo_id][i]) 106 if (val <= soc_process_speedos[sku_info->soc_speedo_id][i])
107 break; 107 break;
108 } 108 }
109 sku_info->core_process_id = i; 109 sku_info->soc_process_id = i;
110} 110}
diff --git a/drivers/soc/tegra/fuse/speedo-tegra210.c b/drivers/soc/tegra/fuse/speedo-tegra210.c
new file mode 100644
index 000000000000..5373f4c16b54
--- /dev/null
+++ b/drivers/soc/tegra/fuse/speedo-tegra210.c
@@ -0,0 +1,184 @@
1/*
2 * Copyright (c) 2013-2015, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include <linux/device.h>
18#include <linux/kernel.h>
19#include <linux/bug.h>
20
21#include <soc/tegra/fuse.h>
22
23#include "fuse.h"
24
25#define CPU_PROCESS_CORNERS 2
26#define GPU_PROCESS_CORNERS 2
27#define SOC_PROCESS_CORNERS 3
28
29#define FUSE_CPU_SPEEDO_0 0x014
30#define FUSE_CPU_SPEEDO_1 0x02c
31#define FUSE_CPU_SPEEDO_2 0x030
32#define FUSE_SOC_SPEEDO_0 0x034
33#define FUSE_SOC_SPEEDO_1 0x038
34#define FUSE_SOC_SPEEDO_2 0x03c
35#define FUSE_CPU_IDDQ 0x018
36#define FUSE_SOC_IDDQ 0x040
37#define FUSE_GPU_IDDQ 0x128
38#define FUSE_FT_REV 0x028
39
40enum {
41 THRESHOLD_INDEX_0,
42 THRESHOLD_INDEX_1,
43 THRESHOLD_INDEX_COUNT,
44};
45
46static const u32 __initconst cpu_process_speedos[][CPU_PROCESS_CORNERS] = {
47 { 2119, UINT_MAX },
48 { 2119, UINT_MAX },
49};
50
51static const u32 __initconst gpu_process_speedos[][GPU_PROCESS_CORNERS] = {
52 { UINT_MAX, UINT_MAX },
53 { UINT_MAX, UINT_MAX },
54};
55
56static const u32 __initconst soc_process_speedos[][SOC_PROCESS_CORNERS] = {
57 { 1950, 2100, UINT_MAX },
58 { 1950, 2100, UINT_MAX },
59};
60
61static u8 __init get_speedo_revision(void)
62{
63 return tegra_fuse_read_spare(4) << 2 |
64 tegra_fuse_read_spare(3) << 1 |
65 tegra_fuse_read_spare(2) << 0;
66}
67
68static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info,
69 u8 speedo_rev, int *threshold)
70{
71 int sku = sku_info->sku_id;
72
73 /* Assign to default */
74 sku_info->cpu_speedo_id = 0;
75 sku_info->soc_speedo_id = 0;
76 sku_info->gpu_speedo_id = 0;
77 *threshold = THRESHOLD_INDEX_0;
78
79 switch (sku) {
80 case 0x00: /* Engineering SKU */
81 case 0x01: /* Engineering SKU */
82 case 0x07:
83 case 0x17:
84 case 0x27:
85 if (speedo_rev >= 2)
86 sku_info->gpu_speedo_id = 1;
87 break;
88
89 case 0x13:
90 if (speedo_rev >= 2)
91 sku_info->gpu_speedo_id = 1;
92
93 sku_info->cpu_speedo_id = 1;
94 break;
95
96 default:
97 pr_err("Tegra210: unknown SKU %#04x\n", sku);
98 /* Using the default for the error case */
99 break;
100 }
101}
102
103static int get_process_id(int value, const u32 *speedos, unsigned int num)
104{
105 unsigned int i;
106
107 for (i = 0; i < num; i++)
108 if (value < speedos[num])
109 return i;
110
111 return -EINVAL;
112}
113
114void __init tegra210_init_speedo_data(struct tegra_sku_info *sku_info)
115{
116 int cpu_speedo[3], soc_speedo[3], cpu_iddq, gpu_iddq, soc_iddq;
117 unsigned int index;
118 u8 speedo_revision;
119
120 BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
121 THRESHOLD_INDEX_COUNT);
122 BUILD_BUG_ON(ARRAY_SIZE(gpu_process_speedos) !=
123 THRESHOLD_INDEX_COUNT);
124 BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) !=
125 THRESHOLD_INDEX_COUNT);
126
127 /* Read speedo/IDDQ fuses */
128 cpu_speedo[0] = tegra_fuse_read_early(FUSE_CPU_SPEEDO_0);
129 cpu_speedo[1] = tegra_fuse_read_early(FUSE_CPU_SPEEDO_1);
130 cpu_speedo[2] = tegra_fuse_read_early(FUSE_CPU_SPEEDO_2);
131
132 soc_speedo[0] = tegra_fuse_read_early(FUSE_SOC_SPEEDO_0);
133 soc_speedo[1] = tegra_fuse_read_early(FUSE_SOC_SPEEDO_1);
134 soc_speedo[2] = tegra_fuse_read_early(FUSE_CPU_SPEEDO_2);
135
136 cpu_iddq = tegra_fuse_read_early(FUSE_CPU_IDDQ) * 4;
137 soc_iddq = tegra_fuse_read_early(FUSE_SOC_IDDQ) * 4;
138 gpu_iddq = tegra_fuse_read_early(FUSE_GPU_IDDQ) * 5;
139
140 /*
141 * Determine CPU, GPU and SoC speedo values depending on speedo fusing
142 * revision. Note that GPU speedo value is fused in CPU_SPEEDO_2.
143 */
144 speedo_revision = get_speedo_revision();
145 pr_info("Speedo Revision %u\n", speedo_revision);
146
147 if (speedo_revision >= 3) {
148 sku_info->cpu_speedo_value = cpu_speedo[0];
149 sku_info->gpu_speedo_value = cpu_speedo[2];
150 sku_info->soc_speedo_value = soc_speedo[0];
151 } else if (speedo_revision == 2) {
152 sku_info->cpu_speedo_value = (-1938 + (1095 * cpu_speedo[0] / 100)) / 10;
153 sku_info->gpu_speedo_value = (-1662 + (1082 * cpu_speedo[2] / 100)) / 10;
154 sku_info->soc_speedo_value = ( -705 + (1037 * soc_speedo[0] / 100)) / 10;
155 } else {
156 sku_info->cpu_speedo_value = 2100;
157 sku_info->gpu_speedo_value = cpu_speedo[2] - 75;
158 sku_info->soc_speedo_value = 1900;
159 }
160
161 if ((sku_info->cpu_speedo_value <= 0) ||
162 (sku_info->gpu_speedo_value <= 0) ||
163 (sku_info->soc_speedo_value <= 0)) {
164 WARN(1, "speedo value not fused\n");
165 return;
166 }
167
168 rev_sku_to_speedo_ids(sku_info, speedo_revision, &index);
169
170 sku_info->gpu_process_id = get_process_id(sku_info->gpu_speedo_value,
171 gpu_process_speedos[index],
172 GPU_PROCESS_CORNERS);
173
174 sku_info->cpu_process_id = get_process_id(sku_info->cpu_speedo_value,
175 cpu_process_speedos[index],
176 CPU_PROCESS_CORNERS);
177
178 sku_info->soc_process_id = get_process_id(sku_info->soc_speedo_value,
179 soc_process_speedos[index],
180 SOC_PROCESS_CORNERS);
181
182 pr_debug("Tegra GPU Speedo ID=%d, Speedo Value=%d\n",
183 sku_info->gpu_speedo_id, sku_info->gpu_speedo_value);
184}
diff --git a/drivers/soc/tegra/fuse/speedo-tegra30.c b/drivers/soc/tegra/fuse/speedo-tegra30.c
index b17f0dcdfebe..9b010b3ef009 100644
--- a/drivers/soc/tegra/fuse/speedo-tegra30.c
+++ b/drivers/soc/tegra/fuse/speedo-tegra30.c
@@ -22,7 +22,7 @@
22 22
23#include "fuse.h" 23#include "fuse.h"
24 24
25#define CORE_PROCESS_CORNERS 1 25#define SOC_PROCESS_CORNERS 1
26#define CPU_PROCESS_CORNERS 6 26#define CPU_PROCESS_CORNERS 6
27 27
28#define FUSE_SPEEDO_CALIB_0 0x14 28#define FUSE_SPEEDO_CALIB_0 0x14
@@ -54,7 +54,7 @@ enum {
54 THRESHOLD_INDEX_COUNT, 54 THRESHOLD_INDEX_COUNT,
55}; 55};
56 56
57static const u32 __initconst core_process_speedos[][CORE_PROCESS_CORNERS] = { 57static const u32 __initconst soc_process_speedos[][SOC_PROCESS_CORNERS] = {
58 {180}, 58 {180},
59 {170}, 59 {170},
60 {195}, 60 {195},
@@ -93,25 +93,25 @@ static void __init fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
93 int bit_minus1; 93 int bit_minus1;
94 int bit_minus2; 94 int bit_minus2;
95 95
96 reg = tegra30_fuse_readl(FUSE_SPEEDO_CALIB_0); 96 reg = tegra_fuse_read_early(FUSE_SPEEDO_CALIB_0);
97 97
98 *speedo_lp = (reg & 0xFFFF) * 4; 98 *speedo_lp = (reg & 0xFFFF) * 4;
99 *speedo_g = ((reg >> 16) & 0xFFFF) * 4; 99 *speedo_g = ((reg >> 16) & 0xFFFF) * 4;
100 100
101 ate_ver = tegra30_fuse_readl(FUSE_TEST_PROG_VER); 101 ate_ver = tegra_fuse_read_early(FUSE_TEST_PROG_VER);
102 pr_debug("Tegra ATE prog ver %d.%d\n", ate_ver/10, ate_ver%10); 102 pr_debug("Tegra ATE prog ver %d.%d\n", ate_ver/10, ate_ver%10);
103 103
104 if (ate_ver >= 26) { 104 if (ate_ver >= 26) {
105 bit_minus1 = tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS1); 105 bit_minus1 = tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS1);
106 bit_minus1 |= tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS1_R); 106 bit_minus1 |= tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS1_R);
107 bit_minus2 = tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS2); 107 bit_minus2 = tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS2);
108 bit_minus2 |= tegra30_spare_fuse(LP_SPEEDO_BIT_MINUS2_R); 108 bit_minus2 |= tegra_fuse_read_spare(LP_SPEEDO_BIT_MINUS2_R);
109 *speedo_lp |= (bit_minus1 << 1) | bit_minus2; 109 *speedo_lp |= (bit_minus1 << 1) | bit_minus2;
110 110
111 bit_minus1 = tegra30_spare_fuse(G_SPEEDO_BIT_MINUS1); 111 bit_minus1 = tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS1);
112 bit_minus1 |= tegra30_spare_fuse(G_SPEEDO_BIT_MINUS1_R); 112 bit_minus1 |= tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS1_R);
113 bit_minus2 = tegra30_spare_fuse(G_SPEEDO_BIT_MINUS2); 113 bit_minus2 = tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS2);
114 bit_minus2 |= tegra30_spare_fuse(G_SPEEDO_BIT_MINUS2_R); 114 bit_minus2 |= tegra_fuse_read_spare(G_SPEEDO_BIT_MINUS2_R);
115 *speedo_g |= (bit_minus1 << 1) | bit_minus2; 115 *speedo_g |= (bit_minus1 << 1) | bit_minus2;
116 } else { 116 } else {
117 *speedo_lp |= 0x3; 117 *speedo_lp |= 0x3;
@@ -121,7 +121,7 @@ static void __init fuse_speedo_calib(u32 *speedo_g, u32 *speedo_lp)
121 121
122static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info) 122static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info)
123{ 123{
124 int package_id = tegra30_fuse_readl(FUSE_PACKAGE_INFO) & 0x0F; 124 int package_id = tegra_fuse_read_early(FUSE_PACKAGE_INFO) & 0x0F;
125 125
126 switch (sku_info->revision) { 126 switch (sku_info->revision) {
127 case TEGRA_REVISION_A01: 127 case TEGRA_REVISION_A01:
@@ -246,19 +246,19 @@ static void __init rev_sku_to_speedo_ids(struct tegra_sku_info *sku_info)
246void __init tegra30_init_speedo_data(struct tegra_sku_info *sku_info) 246void __init tegra30_init_speedo_data(struct tegra_sku_info *sku_info)
247{ 247{
248 u32 cpu_speedo_val; 248 u32 cpu_speedo_val;
249 u32 core_speedo_val; 249 u32 soc_speedo_val;
250 int i; 250 int i;
251 251
252 BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) != 252 BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
253 THRESHOLD_INDEX_COUNT); 253 THRESHOLD_INDEX_COUNT);
254 BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) != 254 BUILD_BUG_ON(ARRAY_SIZE(soc_process_speedos) !=
255 THRESHOLD_INDEX_COUNT); 255 THRESHOLD_INDEX_COUNT);
256 256
257 257
258 rev_sku_to_speedo_ids(sku_info); 258 rev_sku_to_speedo_ids(sku_info);
259 fuse_speedo_calib(&cpu_speedo_val, &core_speedo_val); 259 fuse_speedo_calib(&cpu_speedo_val, &soc_speedo_val);
260 pr_debug("Tegra CPU speedo value %u\n", cpu_speedo_val); 260 pr_debug("Tegra CPU speedo value %u\n", cpu_speedo_val);
261 pr_debug("Tegra Core speedo value %u\n", core_speedo_val); 261 pr_debug("Tegra Core speedo value %u\n", soc_speedo_val);
262 262
263 for (i = 0; i < CPU_PROCESS_CORNERS; i++) { 263 for (i = 0; i < CPU_PROCESS_CORNERS; i++) {
264 if (cpu_speedo_val < cpu_process_speedos[threshold_index][i]) 264 if (cpu_speedo_val < cpu_process_speedos[threshold_index][i])
@@ -273,16 +273,16 @@ void __init tegra30_init_speedo_data(struct tegra_sku_info *sku_info)
273 sku_info->cpu_speedo_id = 1; 273 sku_info->cpu_speedo_id = 1;
274 } 274 }
275 275
276 for (i = 0; i < CORE_PROCESS_CORNERS; i++) { 276 for (i = 0; i < SOC_PROCESS_CORNERS; i++) {
277 if (core_speedo_val < core_process_speedos[threshold_index][i]) 277 if (soc_speedo_val < soc_process_speedos[threshold_index][i])
278 break; 278 break;
279 } 279 }
280 sku_info->core_process_id = i - 1; 280 sku_info->soc_process_id = i - 1;
281 281
282 if (sku_info->core_process_id == -1) { 282 if (sku_info->soc_process_id == -1) {
283 pr_warn("Tegra CORE speedo value %3d out of range", 283 pr_warn("Tegra SoC speedo value %3d out of range",
284 core_speedo_val); 284 soc_speedo_val);
285 sku_info->core_process_id = 0; 285 sku_info->soc_process_id = 0;
286 sku_info->soc_speedo_id = 1; 286 sku_info->soc_speedo_id = 1;
287 } 287 }
288} 288}
diff --git a/drivers/soc/tegra/fuse/tegra-apbmisc.c b/drivers/soc/tegra/fuse/tegra-apbmisc.c
index 73fad05d8f2c..5b18f6ffa45c 100644
--- a/drivers/soc/tegra/fuse/tegra-apbmisc.c
+++ b/drivers/soc/tegra/fuse/tegra-apbmisc.c
@@ -21,11 +21,10 @@
21#include <linux/io.h> 21#include <linux/io.h>
22 22
23#include <soc/tegra/fuse.h> 23#include <soc/tegra/fuse.h>
24#include <soc/tegra/common.h>
24 25
25#include "fuse.h" 26#include "fuse.h"
26 27
27#define APBMISC_BASE 0x70000800
28#define APBMISC_SIZE 0x64
29#define FUSE_SKU_INFO 0x10 28#define FUSE_SKU_INFO 0x10
30 29
31#define PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT 4 30#define PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT 4
@@ -95,8 +94,8 @@ void __init tegra_init_revision(void)
95 rev = TEGRA_REVISION_A02; 94 rev = TEGRA_REVISION_A02;
96 break; 95 break;
97 case 3: 96 case 3:
98 if (chip_id == TEGRA20 && (tegra20_spare_fuse_early(18) || 97 if (chip_id == TEGRA20 && (tegra_fuse_read_spare(18) ||
99 tegra20_spare_fuse_early(19))) 98 tegra_fuse_read_spare(19)))
100 rev = TEGRA_REVISION_A03p; 99 rev = TEGRA_REVISION_A03p;
101 else 100 else
102 rev = TEGRA_REVISION_A03; 101 rev = TEGRA_REVISION_A03;
@@ -110,27 +109,74 @@ void __init tegra_init_revision(void)
110 109
111 tegra_sku_info.revision = rev; 110 tegra_sku_info.revision = rev;
112 111
113 if (chip_id == TEGRA20) 112 tegra_sku_info.sku_id = tegra_fuse_read_early(FUSE_SKU_INFO);
114 tegra_sku_info.sku_id = tegra20_fuse_early(FUSE_SKU_INFO);
115 else
116 tegra_sku_info.sku_id = tegra30_fuse_readl(FUSE_SKU_INFO);
117} 113}
118 114
119void __init tegra_init_apbmisc(void) 115void __init tegra_init_apbmisc(void)
120{ 116{
117 struct resource apbmisc, straps;
121 struct device_node *np; 118 struct device_node *np;
122 119
123 np = of_find_matching_node(NULL, apbmisc_match); 120 np = of_find_matching_node(NULL, apbmisc_match);
124 apbmisc_base = of_iomap(np, 0); 121 if (!np) {
125 if (!apbmisc_base) { 122 /*
126 pr_warn("ioremap tegra apbmisc failed. using %08x instead\n", 123 * Fall back to legacy initialization for 32-bit ARM only. All
127 APBMISC_BASE); 124 * 64-bit ARM device tree files for Tegra are required to have
128 apbmisc_base = ioremap(APBMISC_BASE, APBMISC_SIZE); 125 * an APBMISC node.
126 *
127 * This is for backwards-compatibility with old device trees
128 * that didn't contain an APBMISC node.
129 */
130 if (IS_ENABLED(CONFIG_ARM) && soc_is_tegra()) {
131 /* APBMISC registers (chip revision, ...) */
132 apbmisc.start = 0x70000800;
133 apbmisc.end = 0x70000863;
134 apbmisc.flags = IORESOURCE_MEM;
135
136 /* strapping options */
137 if (tegra_get_chip_id() == TEGRA124) {
138 straps.start = 0x7000e864;
139 straps.end = 0x7000e867;
140 } else {
141 straps.start = 0x70000008;
142 straps.end = 0x7000000b;
143 }
144
145 straps.flags = IORESOURCE_MEM;
146
147 pr_warn("Using APBMISC region %pR\n", &apbmisc);
148 pr_warn("Using strapping options registers %pR\n",
149 &straps);
150 } else {
151 /*
152 * At this point we're not running on Tegra, so play
153 * nice with multi-platform kernels.
154 */
155 return;
156 }
157 } else {
158 /*
159 * Extract information from the device tree if we've found a
160 * matching node.
161 */
162 if (of_address_to_resource(np, 0, &apbmisc) < 0) {
163 pr_err("failed to get APBMISC registers\n");
164 return;
165 }
166
167 if (of_address_to_resource(np, 1, &straps) < 0) {
168 pr_err("failed to get strapping options registers\n");
169 return;
170 }
129 } 171 }
130 172
131 strapping_base = of_iomap(np, 1); 173 apbmisc_base = ioremap_nocache(apbmisc.start, resource_size(&apbmisc));
174 if (!apbmisc_base)
175 pr_err("failed to map APBMISC registers\n");
176
177 strapping_base = ioremap_nocache(straps.start, resource_size(&straps));
132 if (!strapping_base) 178 if (!strapping_base)
133 pr_err("ioremap tegra strapping_base failed\n"); 179 pr_err("failed to map strapping options registers\n");
134 180
135 long_ram_code = of_property_read_bool(np, "nvidia,long-ram-code"); 181 long_ram_code = of_property_read_bool(np, "nvidia,long-ram-code");
136} 182}
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 75d0457a77b7..bc34cf7482fb 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -17,6 +17,8 @@
17 * 17 *
18 */ 18 */
19 19
20#define pr_fmt(fmt) "tegra-pmc: " fmt
21
20#include <linux/kernel.h> 22#include <linux/kernel.h>
21#include <linux/clk.h> 23#include <linux/clk.h>
22#include <linux/clk/tegra.h> 24#include <linux/clk/tegra.h>
@@ -457,7 +459,6 @@ static int tegra_io_rail_prepare(int id, unsigned long *request,
457 unsigned long *status, unsigned int *bit) 459 unsigned long *status, unsigned int *bit)
458{ 460{
459 unsigned long rate, value; 461 unsigned long rate, value;
460 struct clk *clk;
461 462
462 *bit = id % 32; 463 *bit = id % 32;
463 464
@@ -476,12 +477,7 @@ static int tegra_io_rail_prepare(int id, unsigned long *request,
476 *request = IO_DPD2_REQ; 477 *request = IO_DPD2_REQ;
477 } 478 }
478 479
479 clk = clk_get_sys(NULL, "pclk"); 480 rate = clk_get_rate(pmc->clk);
480 if (IS_ERR(clk))
481 return PTR_ERR(clk);
482
483 rate = clk_get_rate(clk);
484 clk_put(clk);
485 481
486 tegra_pmc_writel(DPD_SAMPLE_ENABLE, DPD_SAMPLE); 482 tegra_pmc_writel(DPD_SAMPLE_ENABLE, DPD_SAMPLE);
487 483
@@ -535,8 +531,10 @@ int tegra_io_rail_power_on(int id)
535 tegra_pmc_writel(value, request); 531 tegra_pmc_writel(value, request);
536 532
537 err = tegra_io_rail_poll(status, mask, 0, 250); 533 err = tegra_io_rail_poll(status, mask, 0, 250);
538 if (err < 0) 534 if (err < 0) {
535 pr_info("tegra_io_rail_poll() failed: %d\n", err);
539 return err; 536 return err;
537 }
540 538
541 tegra_io_rail_unprepare(); 539 tegra_io_rail_unprepare();
542 540
@@ -551,8 +549,10 @@ int tegra_io_rail_power_off(int id)
551 int err; 549 int err;
552 550
553 err = tegra_io_rail_prepare(id, &request, &status, &bit); 551 err = tegra_io_rail_prepare(id, &request, &status, &bit);
554 if (err < 0) 552 if (err < 0) {
553 pr_info("tegra_io_rail_prepare() failed: %d\n", err);
555 return err; 554 return err;
555 }
556 556
557 mask = 1 << bit; 557 mask = 1 << bit;
558 558
@@ -736,12 +736,12 @@ void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
736 u32 value, checksum; 736 u32 value, checksum;
737 737
738 if (!pmc->soc->has_tsense_reset) 738 if (!pmc->soc->has_tsense_reset)
739 goto out; 739 return;
740 740
741 np = of_find_node_by_name(pmc->dev->of_node, "i2c-thermtrip"); 741 np = of_find_node_by_name(pmc->dev->of_node, "i2c-thermtrip");
742 if (!np) { 742 if (!np) {
743 dev_warn(dev, "i2c-thermtrip node not found, %s.\n", disabled); 743 dev_warn(dev, "i2c-thermtrip node not found, %s.\n", disabled);
744 goto out; 744 return;
745 } 745 }
746 746
747 if (of_property_read_u32(np, "nvidia,i2c-controller-id", &ctrl_id)) { 747 if (of_property_read_u32(np, "nvidia,i2c-controller-id", &ctrl_id)) {
@@ -801,7 +801,6 @@ void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc)
801 801
802out: 802out:
803 of_node_put(np); 803 of_node_put(np);
804 return;
805} 804}
806 805
807static int tegra_pmc_probe(struct platform_device *pdev) 806static int tegra_pmc_probe(struct platform_device *pdev)
@@ -1002,7 +1001,56 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = {
1002 .has_gpu_clamps = true, 1001 .has_gpu_clamps = true,
1003}; 1002};
1004 1003
1004static const char * const tegra210_powergates[] = {
1005 [TEGRA_POWERGATE_CPU] = "crail",
1006 [TEGRA_POWERGATE_3D] = "3d",
1007 [TEGRA_POWERGATE_VENC] = "venc",
1008 [TEGRA_POWERGATE_PCIE] = "pcie",
1009 [TEGRA_POWERGATE_L2] = "l2",
1010 [TEGRA_POWERGATE_MPE] = "mpe",
1011 [TEGRA_POWERGATE_HEG] = "heg",
1012 [TEGRA_POWERGATE_SATA] = "sata",
1013 [TEGRA_POWERGATE_CPU1] = "cpu1",
1014 [TEGRA_POWERGATE_CPU2] = "cpu2",
1015 [TEGRA_POWERGATE_CPU3] = "cpu3",
1016 [TEGRA_POWERGATE_CELP] = "celp",
1017 [TEGRA_POWERGATE_CPU0] = "cpu0",
1018 [TEGRA_POWERGATE_C0NC] = "c0nc",
1019 [TEGRA_POWERGATE_C1NC] = "c1nc",
1020 [TEGRA_POWERGATE_SOR] = "sor",
1021 [TEGRA_POWERGATE_DIS] = "dis",
1022 [TEGRA_POWERGATE_DISB] = "disb",
1023 [TEGRA_POWERGATE_XUSBA] = "xusba",
1024 [TEGRA_POWERGATE_XUSBB] = "xusbb",
1025 [TEGRA_POWERGATE_XUSBC] = "xusbc",
1026 [TEGRA_POWERGATE_VIC] = "vic",
1027 [TEGRA_POWERGATE_IRAM] = "iram",
1028 [TEGRA_POWERGATE_NVDEC] = "nvdec",
1029 [TEGRA_POWERGATE_NVJPG] = "nvjpg",
1030 [TEGRA_POWERGATE_AUD] = "aud",
1031 [TEGRA_POWERGATE_DFD] = "dfd",
1032 [TEGRA_POWERGATE_VE2] = "ve2",
1033};
1034
1035static const u8 tegra210_cpu_powergates[] = {
1036 TEGRA_POWERGATE_CPU0,
1037 TEGRA_POWERGATE_CPU1,
1038 TEGRA_POWERGATE_CPU2,
1039 TEGRA_POWERGATE_CPU3,
1040};
1041
1042static const struct tegra_pmc_soc tegra210_pmc_soc = {
1043 .num_powergates = ARRAY_SIZE(tegra210_powergates),
1044 .powergates = tegra210_powergates,
1045 .num_cpu_powergates = ARRAY_SIZE(tegra210_cpu_powergates),
1046 .cpu_powergates = tegra210_cpu_powergates,
1047 .has_tsense_reset = true,
1048 .has_gpu_clamps = true,
1049};
1050
1005static const struct of_device_id tegra_pmc_match[] = { 1051static const struct of_device_id tegra_pmc_match[] = {
1052 { .compatible = "nvidia,tegra210-pmc", .data = &tegra210_pmc_soc },
1053 { .compatible = "nvidia,tegra132-pmc", .data = &tegra124_pmc_soc },
1006 { .compatible = "nvidia,tegra124-pmc", .data = &tegra124_pmc_soc }, 1054 { .compatible = "nvidia,tegra124-pmc", .data = &tegra124_pmc_soc },
1007 { .compatible = "nvidia,tegra114-pmc", .data = &tegra114_pmc_soc }, 1055 { .compatible = "nvidia,tegra114-pmc", .data = &tegra114_pmc_soc },
1008 { .compatible = "nvidia,tegra30-pmc", .data = &tegra30_pmc_soc }, 1056 { .compatible = "nvidia,tegra30-pmc", .data = &tegra30_pmc_soc },
@@ -1035,25 +1083,44 @@ static int __init tegra_pmc_early_init(void)
1035 bool invert; 1083 bool invert;
1036 u32 value; 1084 u32 value;
1037 1085
1038 if (!soc_is_tegra())
1039 return 0;
1040
1041 np = of_find_matching_node_and_match(NULL, tegra_pmc_match, &match); 1086 np = of_find_matching_node_and_match(NULL, tegra_pmc_match, &match);
1042 if (!np) { 1087 if (!np) {
1043 pr_warn("PMC device node not found, disabling powergating\n"); 1088 /*
1044 1089 * Fall back to legacy initialization for 32-bit ARM only. All
1045 regs.start = 0x7000e400; 1090 * 64-bit ARM device tree files for Tegra are required to have
1046 regs.end = 0x7000e7ff; 1091 * a PMC node.
1047 regs.flags = IORESOURCE_MEM; 1092 *
1048 1093 * This is for backwards-compatibility with old device trees
1049 pr_warn("Using memory region %pR\n", &regs); 1094 * that didn't contain a PMC node. Note that in this case the
1095 * SoC data can't be matched and therefore powergating is
1096 * disabled.
1097 */
1098 if (IS_ENABLED(CONFIG_ARM) && soc_is_tegra()) {
1099 pr_warn("DT node not found, powergating disabled\n");
1100
1101 regs.start = 0x7000e400;
1102 regs.end = 0x7000e7ff;
1103 regs.flags = IORESOURCE_MEM;
1104
1105 pr_warn("Using memory region %pR\n", &regs);
1106 } else {
1107 /*
1108 * At this point we're not running on Tegra, so play
1109 * nice with multi-platform kernels.
1110 */
1111 return 0;
1112 }
1050 } else { 1113 } else {
1051 pmc->soc = match->data; 1114 /*
1052 } 1115 * Extract information from the device tree if we've found a
1116 * matching node.
1117 */
1118 if (of_address_to_resource(np, 0, &regs) < 0) {
1119 pr_err("failed to get PMC registers\n");
1120 return -ENXIO;
1121 }
1053 1122
1054 if (of_address_to_resource(np, 0, &regs) < 0) { 1123 pmc->soc = match->data;
1055 pr_err("failed to get PMC registers\n");
1056 return -ENXIO;
1057 } 1124 }
1058 1125
1059 pmc->base = ioremap_nocache(regs.start, resource_size(&regs)); 1126 pmc->base = ioremap_nocache(regs.start, resource_size(&regs));
@@ -1064,6 +1131,10 @@ static int __init tegra_pmc_early_init(void)
1064 1131
1065 mutex_init(&pmc->powergates_lock); 1132 mutex_init(&pmc->powergates_lock);
1066 1133
1134 /*
1135 * Invert the interrupt polarity if a PMC device tree node exists and
1136 * contains the nvidia,invert-interrupt property.
1137 */
1067 invert = of_property_read_bool(np, "nvidia,invert-interrupt"); 1138 invert = of_property_read_bool(np, "nvidia,invert-interrupt");
1068 1139
1069 value = tegra_pmc_readl(PMC_CNTRL); 1140 value = tegra_pmc_readl(PMC_CNTRL);
diff --git a/include/dt-bindings/memory/tegra210-mc.h b/include/dt-bindings/memory/tegra210-mc.h
new file mode 100644
index 000000000000..d1731bc14dbc
--- /dev/null
+++ b/include/dt-bindings/memory/tegra210-mc.h
@@ -0,0 +1,36 @@
1#ifndef DT_BINDINGS_MEMORY_TEGRA210_MC_H
2#define DT_BINDINGS_MEMORY_TEGRA210_MC_H
3
4#define TEGRA_SWGROUP_PTC 0
5#define TEGRA_SWGROUP_DC 1
6#define TEGRA_SWGROUP_DCB 2
7#define TEGRA_SWGROUP_AFI 3
8#define TEGRA_SWGROUP_AVPC 4
9#define TEGRA_SWGROUP_HDA 5
10#define TEGRA_SWGROUP_HC 6
11#define TEGRA_SWGROUP_NVENC 7
12#define TEGRA_SWGROUP_PPCS 8
13#define TEGRA_SWGROUP_SATA 9
14#define TEGRA_SWGROUP_MPCORE 10
15#define TEGRA_SWGROUP_ISP2 11
16#define TEGRA_SWGROUP_XUSB_HOST 12
17#define TEGRA_SWGROUP_XUSB_DEV 13
18#define TEGRA_SWGROUP_ISP2B 14
19#define TEGRA_SWGROUP_TSEC 15
20#define TEGRA_SWGROUP_A9AVP 16
21#define TEGRA_SWGROUP_GPU 17
22#define TEGRA_SWGROUP_SDMMC1A 18
23#define TEGRA_SWGROUP_SDMMC2A 19
24#define TEGRA_SWGROUP_SDMMC3A 20
25#define TEGRA_SWGROUP_SDMMC4A 21
26#define TEGRA_SWGROUP_VIC 22
27#define TEGRA_SWGROUP_VI 23
28#define TEGRA_SWGROUP_NVDEC 24
29#define TEGRA_SWGROUP_APE 25
30#define TEGRA_SWGROUP_NVJPG 26
31#define TEGRA_SWGROUP_SE 27
32#define TEGRA_SWGROUP_AXIAP 28
33#define TEGRA_SWGROUP_ETR 29
34#define TEGRA_SWGROUP_TSECB 30
35
36#endif
diff --git a/include/dt-bindings/reset-controller/stih407-resets.h b/include/dt-bindings/reset/stih407-resets.h
index 02d4328fe479..02d4328fe479 100644
--- a/include/dt-bindings/reset-controller/stih407-resets.h
+++ b/include/dt-bindings/reset/stih407-resets.h
diff --git a/include/dt-bindings/reset-controller/stih415-resets.h b/include/dt-bindings/reset/stih415-resets.h
index c2329fe29cf6..c2329fe29cf6 100644
--- a/include/dt-bindings/reset-controller/stih415-resets.h
+++ b/include/dt-bindings/reset/stih415-resets.h
diff --git a/include/dt-bindings/reset-controller/stih416-resets.h b/include/dt-bindings/reset/stih416-resets.h
index fcf9af1ac0b2..fcf9af1ac0b2 100644
--- a/include/dt-bindings/reset-controller/stih416-resets.h
+++ b/include/dt-bindings/reset/stih416-resets.h
diff --git a/include/linux/clk/shmobile.h b/include/linux/clk/shmobile.h
index 63a8159c4e64..cb19cc1865ca 100644
--- a/include/linux/clk/shmobile.h
+++ b/include/linux/clk/shmobile.h
@@ -16,8 +16,20 @@
16 16
17#include <linux/types.h> 17#include <linux/types.h>
18 18
19struct device;
20struct device_node;
21struct generic_pm_domain;
22
19void r8a7778_clocks_init(u32 mode); 23void r8a7778_clocks_init(u32 mode);
20void r8a7779_clocks_init(u32 mode); 24void r8a7779_clocks_init(u32 mode);
21void rcar_gen2_clocks_init(u32 mode); 25void rcar_gen2_clocks_init(u32 mode);
22 26
27#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
28void cpg_mstp_add_clk_domain(struct device_node *np);
29int cpg_mstp_attach_dev(struct generic_pm_domain *domain, struct device *dev);
30void cpg_mstp_detach_dev(struct generic_pm_domain *domain, struct device *dev);
31#else
32static inline void cpg_mstp_add_clk_domain(struct device_node *np) {}
33#endif
34
23#endif 35#endif
diff --git a/include/linux/soc/dove/pmu.h b/include/linux/soc/dove/pmu.h
new file mode 100644
index 000000000000..9c99f84bcc0e
--- /dev/null
+++ b/include/linux/soc/dove/pmu.h
@@ -0,0 +1,6 @@
1#ifndef LINUX_SOC_DOVE_PMU_H
2#define LINUX_SOC_DOVE_PMU_H
3
4int dove_init_pmu(void);
5
6#endif
diff --git a/include/linux/soc/qcom/smd-rpm.h b/include/linux/soc/qcom/smd-rpm.h
new file mode 100644
index 000000000000..2a53dcaeeeed
--- /dev/null
+++ b/include/linux/soc/qcom/smd-rpm.h
@@ -0,0 +1,35 @@
1#ifndef __QCOM_SMD_RPM_H__
2#define __QCOM_SMD_RPM_H__
3
4struct qcom_smd_rpm;
5
6#define QCOM_SMD_RPM_ACTIVE_STATE 0
7#define QCOM_SMD_RPM_SLEEP_STATE 1
8
9/*
10 * Constants used for addressing resources in the RPM.
11 */
12#define QCOM_SMD_RPM_BOOST 0x61747362
13#define QCOM_SMD_RPM_BUS_CLK 0x316b6c63
14#define QCOM_SMD_RPM_BUS_MASTER 0x73616d62
15#define QCOM_SMD_RPM_BUS_SLAVE 0x766c7362
16#define QCOM_SMD_RPM_CLK_BUF_A 0x616B6C63
17#define QCOM_SMD_RPM_LDOA 0x616f646c
18#define QCOM_SMD_RPM_LDOB 0x626F646C
19#define QCOM_SMD_RPM_MEM_CLK 0x326b6c63
20#define QCOM_SMD_RPM_MISC_CLK 0x306b6c63
21#define QCOM_SMD_RPM_NCPA 0x6170636E
22#define QCOM_SMD_RPM_NCPB 0x6270636E
23#define QCOM_SMD_RPM_OCMEM_PWR 0x706d636f
24#define QCOM_SMD_RPM_QPIC_CLK 0x63697071
25#define QCOM_SMD_RPM_SMPA 0x61706d73
26#define QCOM_SMD_RPM_SMPB 0x62706d73
27#define QCOM_SMD_RPM_SPDM 0x63707362
28#define QCOM_SMD_RPM_VSA 0x00617376
29
30int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm,
31 int state,
32 u32 resource_type, u32 resource_id,
33 void *buf, size_t count);
34
35#endif
diff --git a/include/linux/soc/qcom/smd.h b/include/linux/soc/qcom/smd.h
new file mode 100644
index 000000000000..d7e50aa6a4ac
--- /dev/null
+++ b/include/linux/soc/qcom/smd.h
@@ -0,0 +1,46 @@
1#ifndef __QCOM_SMD_H__
2#define __QCOM_SMD_H__
3
4#include <linux/device.h>
5#include <linux/mod_devicetable.h>
6
7struct qcom_smd;
8struct qcom_smd_channel;
9struct qcom_smd_lookup;
10
11/**
12 * struct qcom_smd_device - smd device struct
13 * @dev: the device struct
14 * @channel: handle to the smd channel for this device
15 */
16struct qcom_smd_device {
17 struct device dev;
18 struct qcom_smd_channel *channel;
19};
20
21/**
22 * struct qcom_smd_driver - smd driver struct
23 * @driver: underlying device driver
24 * @probe: invoked when the smd channel is found
25 * @remove: invoked when the smd channel is closed
26 * @callback: invoked when an inbound message is received on the channel,
27 * should return 0 on success or -EBUSY if the data cannot be
28 * consumed at this time
29 */
30struct qcom_smd_driver {
31 struct device_driver driver;
32 int (*probe)(struct qcom_smd_device *dev);
33 void (*remove)(struct qcom_smd_device *dev);
34 int (*callback)(struct qcom_smd_device *, const void *, size_t);
35};
36
37int qcom_smd_driver_register(struct qcom_smd_driver *drv);
38void qcom_smd_driver_unregister(struct qcom_smd_driver *drv);
39
40#define module_qcom_smd_driver(__smd_driver) \
41 module_driver(__smd_driver, qcom_smd_driver_register, \
42 qcom_smd_driver_unregister)
43
44int qcom_smd_send(struct qcom_smd_channel *channel, const void *data, int len);
45
46#endif
diff --git a/include/linux/soc/qcom/smem.h b/include/linux/soc/qcom/smem.h
new file mode 100644
index 000000000000..bc9630d3aced
--- /dev/null
+++ b/include/linux/soc/qcom/smem.h
@@ -0,0 +1,11 @@
1#ifndef __QCOM_SMEM_H__
2#define __QCOM_SMEM_H__
3
4#define QCOM_SMEM_HOST_ANY -1
5
6int qcom_smem_alloc(unsigned host, unsigned item, size_t size);
7int qcom_smem_get(unsigned host, unsigned item, void **ptr, size_t *size);
8
9int qcom_smem_get_free_space(unsigned host);
10
11#endif
diff --git a/include/soc/tegra/fuse.h b/include/soc/tegra/fuse.h
index b019e3465f11..961b821b6a46 100644
--- a/include/soc/tegra/fuse.h
+++ b/include/soc/tegra/fuse.h
@@ -22,6 +22,7 @@
22#define TEGRA114 0x35 22#define TEGRA114 0x35
23#define TEGRA124 0x40 23#define TEGRA124 0x40
24#define TEGRA132 0x13 24#define TEGRA132 0x13
25#define TEGRA210 0x21
25 26
26#define TEGRA_FUSE_SKU_CALIB_0 0xf0 27#define TEGRA_FUSE_SKU_CALIB_0 0xf0
27#define TEGRA30_FUSE_SATA_CALIB 0x124 28#define TEGRA30_FUSE_SATA_CALIB 0x124
@@ -47,10 +48,11 @@ struct tegra_sku_info {
47 int cpu_speedo_id; 48 int cpu_speedo_id;
48 int cpu_speedo_value; 49 int cpu_speedo_value;
49 int cpu_iddq_value; 50 int cpu_iddq_value;
50 int core_process_id; 51 int soc_process_id;
51 int soc_speedo_id; 52 int soc_speedo_id;
52 int gpu_speedo_id; 53 int soc_speedo_value;
53 int gpu_process_id; 54 int gpu_process_id;
55 int gpu_speedo_id;
54 int gpu_speedo_value; 56 int gpu_speedo_value;
55 enum tegra_revision revision; 57 enum tegra_revision revision;
56}; 58};
diff --git a/include/soc/tegra/mc.h b/include/soc/tegra/mc.h
index 1ab2813273cd..370f2909ec19 100644
--- a/include/soc/tegra/mc.h
+++ b/include/soc/tegra/mc.h
@@ -102,6 +102,8 @@ struct tegra_mc_soc {
102 unsigned int num_address_bits; 102 unsigned int num_address_bits;
103 unsigned int atom_size; 103 unsigned int atom_size;
104 104
105 u8 client_id_mask;
106
105 const struct tegra_smmu_soc *smmu; 107 const struct tegra_smmu_soc *smmu;
106}; 108};
107 109
diff --git a/include/soc/tegra/pmc.h b/include/soc/tegra/pmc.h
index f5c0de43a5fa..d18efe402ff1 100644
--- a/include/soc/tegra/pmc.h
+++ b/include/soc/tegra/pmc.h
@@ -67,6 +67,11 @@ int tegra_pmc_cpu_remove_clamping(int cpuid);
67#define TEGRA_POWERGATE_XUSBC 22 67#define TEGRA_POWERGATE_XUSBC 22
68#define TEGRA_POWERGATE_VIC 23 68#define TEGRA_POWERGATE_VIC 23
69#define TEGRA_POWERGATE_IRAM 24 69#define TEGRA_POWERGATE_IRAM 24
70#define TEGRA_POWERGATE_NVDEC 25
71#define TEGRA_POWERGATE_NVJPG 26
72#define TEGRA_POWERGATE_AUD 27
73#define TEGRA_POWERGATE_DFD 28
74#define TEGRA_POWERGATE_VE2 29
70 75
71#define TEGRA_POWERGATE_3D0 TEGRA_POWERGATE_3D 76#define TEGRA_POWERGATE_3D0 TEGRA_POWERGATE_3D
72 77