aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Gross <andy.gross@linaro.org>2018-09-30 13:44:33 -0400
committerAndy Gross <andy.gross@linaro.org>2018-09-30 13:44:33 -0400
commit579fde69dc1467a033ff44ced75ff368b9d3d072 (patch)
tree590e07ada6c72f4d8e1acbd6ddb8ca4a1c9f50fe
parentbbd4b28bb8f65fc7347202f32ac82901201ac02f (diff)
parentbb85ce5122487b2b1de1b48b557c5fdf9828dc6e (diff)
Merge branch 'drivers-for-4.20' into drivers-for-4.20-final
-rw-r--r--Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt19
-rw-r--r--Documentation/devicetree/bindings/firmware/qcom,scm.txt33
-rw-r--r--MAINTAINERS8
-rw-r--r--drivers/edac/Kconfig14
-rw-r--r--drivers/edac/Makefile1
-rw-r--r--drivers/edac/qcom_edac.c414
-rw-r--r--drivers/firmware/qcom_scm.c74
-rw-r--r--drivers/soc/qcom/Kconfig21
-rw-r--r--drivers/soc/qcom/apr.c6
-rw-r--r--drivers/soc/qcom/llcc-slice.c74
-rw-r--r--drivers/soc/qcom/rmtfs_mem.c5
-rw-r--r--drivers/soc/qcom/rpmh-rsc.c2
-rw-r--r--drivers/soc/qcom/smem.c174
-rw-r--r--drivers/soc/qcom/spm.c3
-rw-r--r--drivers/soc/qcom/wcnss_ctrl.c2
-rw-r--r--include/linux/soc/qcom/llcc-qcom.h30
16 files changed, 704 insertions, 176 deletions
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
index 5e85749262ae..eaee06b2d8f2 100644
--- a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
@@ -16,11 +16,26 @@ Properties:
16- reg: 16- reg:
17 Usage: required 17 Usage: required
18 Value Type: <prop-encoded-array> 18 Value Type: <prop-encoded-array>
19 Definition: Start address and the the size of the register region. 19 Definition: The first element specifies the llcc base start address and
20 the size of the register region. The second element specifies
21 the llcc broadcast base address and size of the register region.
22
23- reg-names:
24 Usage: required
25 Value Type: <stringlist>
26 Definition: Register region names. Must be "llcc_base", "llcc_broadcast_base".
27
28- interrupts:
29 Usage: required
30 Definition: The interrupt is associated with the llcc edac device.
31 It's used for llcc cache single and double bit error detection
32 and reporting.
20 33
21Example: 34Example:
22 35
23 cache-controller@1100000 { 36 cache-controller@1100000 {
24 compatible = "qcom,sdm845-llcc"; 37 compatible = "qcom,sdm845-llcc";
25 reg = <0x1100000 0x250000>; 38 reg = <0x1100000 0x200000>, <0x1300000 0x50000> ;
39 reg-names = "llcc_base", "llcc_broadcast_base";
40 interrupts = <GIC_SPI 582 IRQ_TYPE_LEVEL_HIGH>;
26 }; 41 };
diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.txt b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
index fcf6979c0b6d..41f133a4e2fa 100644
--- a/Documentation/devicetree/bindings/firmware/qcom,scm.txt
+++ b/Documentation/devicetree/bindings/firmware/qcom,scm.txt
@@ -7,16 +7,23 @@ assorted actions.
7 7
8Required properties: 8Required properties:
9- compatible: must contain one of the following: 9- compatible: must contain one of the following:
10 * "qcom,scm-apq8064" for APQ8064 platforms 10 * "qcom,scm-apq8064"
11 * "qcom,scm-msm8660" for MSM8660 platforms 11 * "qcom,scm-apq8084"
12 * "qcom,scm-msm8690" for MSM8690 platforms 12 * "qcom,scm-msm8660"
13 * "qcom,scm-msm8996" for MSM8996 platforms 13 * "qcom,scm-msm8916"
14 * "qcom,scm-ipq4019" for IPQ4019 platforms 14 * "qcom,scm-msm8960"
15 * "qcom,scm" for later processors (MSM8916, APQ8084, MSM8974, etc) 15 * "qcom,scm-msm8974"
16- clocks: One to three clocks may be required based on compatible. 16 * "qcom,scm-msm8996"
17 * No clock required for "qcom,scm-msm8996", "qcom,scm-ipq4019" 17 * "qcom,scm-msm8998"
18 * Only core clock required for "qcom,scm-apq8064", "qcom,scm-msm8660", and "qcom,scm-msm8960" 18 * "qcom,scm-ipq4019"
19 * Core, iface, and bus clocks required for "qcom,scm" 19 * "qcom,scm-sdm845"
20 and:
21 * "qcom,scm"
22- clocks: Specifies clocks needed by the SCM interface, if any:
23 * core clock required for "qcom,scm-apq8064", "qcom,scm-msm8660" and
24 "qcom,scm-msm8960"
25 * core, iface and bus clocks required for "qcom,scm-apq8084",
26 "qcom,scm-msm8916" and "qcom,scm-msm8974"
20- clock-names: Must contain "core" for the core clock, "iface" for the interface 27- clock-names: Must contain "core" for the core clock, "iface" for the interface
21 clock and "bus" for the bus clock per the requirements of the compatible. 28 clock and "bus" for the bus clock per the requirements of the compatible.
22- qcom,dload-mode: phandle to the TCSR hardware block and offset of the 29- qcom,dload-mode: phandle to the TCSR hardware block and offset of the
@@ -26,8 +33,10 @@ Example for MSM8916:
26 33
27 firmware { 34 firmware {
28 scm { 35 scm {
29 compatible = "qcom,scm"; 36 compatible = "qcom,msm8916", "qcom,scm";
30 clocks = <&gcc GCC_CRYPTO_CLK> , <&gcc GCC_CRYPTO_AXI_CLK>, <&gcc GCC_CRYPTO_AHB_CLK>; 37 clocks = <&gcc GCC_CRYPTO_CLK> ,
38 <&gcc GCC_CRYPTO_AXI_CLK>,
39 <&gcc GCC_CRYPTO_AHB_CLK>;
31 clock-names = "core", "bus", "iface"; 40 clock-names = "core", "bus", "iface";
32 }; 41 };
33 }; 42 };
diff --git a/MAINTAINERS b/MAINTAINERS
index a5b256b25905..f7d7213ca293 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5346,6 +5346,14 @@ L: linux-edac@vger.kernel.org
5346S: Maintained 5346S: Maintained
5347F: drivers/edac/ti_edac.c 5347F: drivers/edac/ti_edac.c
5348 5348
5349EDAC-QCOM
5350M: Channagoud Kadabi <ckadabi@codeaurora.org>
5351M: Venkata Narendra Kumar Gutta <vnkgutta@codeaurora.org>
5352L: linux-arm-msm@vger.kernel.org
5353L: linux-edac@vger.kernel.org
5354S: Maintained
5355F: drivers/edac/qcom_edac.c
5356
5349EDIROL UA-101/UA-1000 DRIVER 5357EDIROL UA-101/UA-1000 DRIVER
5350M: Clemens Ladisch <clemens@ladisch.de> 5358M: Clemens Ladisch <clemens@ladisch.de>
5351L: alsa-devel@alsa-project.org (moderated for non-subscribers) 5359L: alsa-devel@alsa-project.org (moderated for non-subscribers)
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 57304b2e989f..df9467eef32a 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -460,4 +460,18 @@ config EDAC_TI
460 Support for error detection and correction on the 460 Support for error detection and correction on the
461 TI SoCs. 461 TI SoCs.
462 462
463config EDAC_QCOM
464 tristate "QCOM EDAC Controller"
465 depends on ARCH_QCOM && QCOM_LLCC
466 help
467 Support for error detection and correction on the
468 Qualcomm Technologies, Inc. SoCs.
469
470 This driver reports Single Bit Errors (SBEs) and Double Bit Errors (DBEs).
471 As of now, it supports error reporting for Last Level Cache Controller (LLCC)
472 of Tag RAM and Data RAM.
473
474 For debugging issues having to do with stability and overall system
475 health, you should probably say 'Y' here.
476
463endif # EDAC 477endif # EDAC
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile
index 02b43a7d8c3e..716096d08ea0 100644
--- a/drivers/edac/Makefile
+++ b/drivers/edac/Makefile
@@ -77,3 +77,4 @@ obj-$(CONFIG_EDAC_ALTERA) += altera_edac.o
77obj-$(CONFIG_EDAC_SYNOPSYS) += synopsys_edac.o 77obj-$(CONFIG_EDAC_SYNOPSYS) += synopsys_edac.o
78obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o 78obj-$(CONFIG_EDAC_XGENE) += xgene_edac.o
79obj-$(CONFIG_EDAC_TI) += ti_edac.o 79obj-$(CONFIG_EDAC_TI) += ti_edac.o
80obj-$(CONFIG_EDAC_QCOM) += qcom_edac.o
diff --git a/drivers/edac/qcom_edac.c b/drivers/edac/qcom_edac.c
new file mode 100644
index 000000000000..82bd775124f2
--- /dev/null
+++ b/drivers/edac/qcom_edac.c
@@ -0,0 +1,414 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
4 */
5
6#include <linux/edac.h>
7#include <linux/interrupt.h>
8#include <linux/kernel.h>
9#include <linux/of.h>
10#include <linux/platform_device.h>
11#include <linux/regmap.h>
12#include <linux/soc/qcom/llcc-qcom.h>
13
14#include "edac_mc.h"
15#include "edac_device.h"
16
17#define EDAC_LLCC "qcom_llcc"
18
19#define LLCC_ERP_PANIC_ON_UE 1
20
21#define TRP_SYN_REG_CNT 6
22#define DRP_SYN_REG_CNT 8
23
24#define LLCC_COMMON_STATUS0 0x0003000c
25#define LLCC_LB_CNT_MASK GENMASK(31, 28)
26#define LLCC_LB_CNT_SHIFT 28
27
28/* Single & double bit syndrome register offsets */
29#define TRP_ECC_SB_ERR_SYN0 0x0002304c
30#define TRP_ECC_DB_ERR_SYN0 0x00020370
31#define DRP_ECC_SB_ERR_SYN0 0x0004204c
32#define DRP_ECC_DB_ERR_SYN0 0x00042070
33
34/* Error register offsets */
35#define TRP_ECC_ERROR_STATUS1 0x00020348
36#define TRP_ECC_ERROR_STATUS0 0x00020344
37#define DRP_ECC_ERROR_STATUS1 0x00042048
38#define DRP_ECC_ERROR_STATUS0 0x00042044
39
40/* TRP, DRP interrupt register offsets */
41#define DRP_INTERRUPT_STATUS 0x00041000
42#define TRP_INTERRUPT_0_STATUS 0x00020480
43#define DRP_INTERRUPT_CLEAR 0x00041008
44#define DRP_ECC_ERROR_CNTR_CLEAR 0x00040004
45#define TRP_INTERRUPT_0_CLEAR 0x00020484
46#define TRP_ECC_ERROR_CNTR_CLEAR 0x00020440
47
48/* Mask and shift macros */
49#define ECC_DB_ERR_COUNT_MASK GENMASK(4, 0)
50#define ECC_DB_ERR_WAYS_MASK GENMASK(31, 16)
51#define ECC_DB_ERR_WAYS_SHIFT BIT(4)
52
53#define ECC_SB_ERR_COUNT_MASK GENMASK(23, 16)
54#define ECC_SB_ERR_COUNT_SHIFT BIT(4)
55#define ECC_SB_ERR_WAYS_MASK GENMASK(15, 0)
56
57#define SB_ECC_ERROR BIT(0)
58#define DB_ECC_ERROR BIT(1)
59
60#define DRP_TRP_INT_CLEAR GENMASK(1, 0)
61#define DRP_TRP_CNT_CLEAR GENMASK(1, 0)
62
63/* Config registers offsets*/
64#define DRP_ECC_ERROR_CFG 0x00040000
65
66/* Tag RAM, Data RAM interrupt register offsets */
67#define CMN_INTERRUPT_0_ENABLE 0x0003001c
68#define CMN_INTERRUPT_2_ENABLE 0x0003003c
69#define TRP_INTERRUPT_0_ENABLE 0x00020488
70#define DRP_INTERRUPT_ENABLE 0x0004100c
71
72#define SB_ERROR_THRESHOLD 0x1
73#define SB_ERROR_THRESHOLD_SHIFT 24
74#define SB_DB_TRP_INTERRUPT_ENABLE 0x3
75#define TRP0_INTERRUPT_ENABLE 0x1
76#define DRP0_INTERRUPT_ENABLE BIT(6)
77#define SB_DB_DRP_INTERRUPT_ENABLE 0x3
78
79enum {
80 LLCC_DRAM_CE = 0,
81 LLCC_DRAM_UE,
82 LLCC_TRAM_CE,
83 LLCC_TRAM_UE,
84};
85
86static const struct llcc_edac_reg_data edac_reg_data[] = {
87 [LLCC_DRAM_CE] = {
88 .name = "DRAM Single-bit",
89 .synd_reg = DRP_ECC_SB_ERR_SYN0,
90 .count_status_reg = DRP_ECC_ERROR_STATUS1,
91 .ways_status_reg = DRP_ECC_ERROR_STATUS0,
92 .reg_cnt = DRP_SYN_REG_CNT,
93 .count_mask = ECC_SB_ERR_COUNT_MASK,
94 .ways_mask = ECC_SB_ERR_WAYS_MASK,
95 .count_shift = ECC_SB_ERR_COUNT_SHIFT,
96 },
97 [LLCC_DRAM_UE] = {
98 .name = "DRAM Double-bit",
99 .synd_reg = DRP_ECC_DB_ERR_SYN0,
100 .count_status_reg = DRP_ECC_ERROR_STATUS1,
101 .ways_status_reg = DRP_ECC_ERROR_STATUS0,
102 .reg_cnt = DRP_SYN_REG_CNT,
103 .count_mask = ECC_DB_ERR_COUNT_MASK,
104 .ways_mask = ECC_DB_ERR_WAYS_MASK,
105 .ways_shift = ECC_DB_ERR_WAYS_SHIFT,
106 },
107 [LLCC_TRAM_CE] = {
108 .name = "TRAM Single-bit",
109 .synd_reg = TRP_ECC_SB_ERR_SYN0,
110 .count_status_reg = TRP_ECC_ERROR_STATUS1,
111 .ways_status_reg = TRP_ECC_ERROR_STATUS0,
112 .reg_cnt = TRP_SYN_REG_CNT,
113 .count_mask = ECC_SB_ERR_COUNT_MASK,
114 .ways_mask = ECC_SB_ERR_WAYS_MASK,
115 .count_shift = ECC_SB_ERR_COUNT_SHIFT,
116 },
117 [LLCC_TRAM_UE] = {
118 .name = "TRAM Double-bit",
119 .synd_reg = TRP_ECC_DB_ERR_SYN0,
120 .count_status_reg = TRP_ECC_ERROR_STATUS1,
121 .ways_status_reg = TRP_ECC_ERROR_STATUS0,
122 .reg_cnt = TRP_SYN_REG_CNT,
123 .count_mask = ECC_DB_ERR_COUNT_MASK,
124 .ways_mask = ECC_DB_ERR_WAYS_MASK,
125 .ways_shift = ECC_DB_ERR_WAYS_SHIFT,
126 },
127};
128
129static int qcom_llcc_core_setup(struct regmap *llcc_bcast_regmap)
130{
131 u32 sb_err_threshold;
132 int ret;
133
134 /*
135 * Configure interrupt enable registers such that Tag, Data RAM related
136 * interrupts are propagated to interrupt controller for servicing
137 */
138 ret = regmap_update_bits(llcc_bcast_regmap, CMN_INTERRUPT_2_ENABLE,
139 TRP0_INTERRUPT_ENABLE,
140 TRP0_INTERRUPT_ENABLE);
141 if (ret)
142 return ret;
143
144 ret = regmap_update_bits(llcc_bcast_regmap, TRP_INTERRUPT_0_ENABLE,
145 SB_DB_TRP_INTERRUPT_ENABLE,
146 SB_DB_TRP_INTERRUPT_ENABLE);
147 if (ret)
148 return ret;
149
150 sb_err_threshold = (SB_ERROR_THRESHOLD << SB_ERROR_THRESHOLD_SHIFT);
151 ret = regmap_write(llcc_bcast_regmap, DRP_ECC_ERROR_CFG,
152 sb_err_threshold);
153 if (ret)
154 return ret;
155
156 ret = regmap_update_bits(llcc_bcast_regmap, CMN_INTERRUPT_2_ENABLE,
157 DRP0_INTERRUPT_ENABLE,
158 DRP0_INTERRUPT_ENABLE);
159 if (ret)
160 return ret;
161
162 ret = regmap_write(llcc_bcast_regmap, DRP_INTERRUPT_ENABLE,
163 SB_DB_DRP_INTERRUPT_ENABLE);
164 return ret;
165}
166
167/* Clear the error interrupt and counter registers */
168static int
169qcom_llcc_clear_error_status(int err_type, struct llcc_drv_data *drv)
170{
171 int ret = 0;
172
173 switch (err_type) {
174 case LLCC_DRAM_CE:
175 case LLCC_DRAM_UE:
176 ret = regmap_write(drv->bcast_regmap, DRP_INTERRUPT_CLEAR,
177 DRP_TRP_INT_CLEAR);
178 if (ret)
179 return ret;
180
181 ret = regmap_write(drv->bcast_regmap, DRP_ECC_ERROR_CNTR_CLEAR,
182 DRP_TRP_CNT_CLEAR);
183 if (ret)
184 return ret;
185 break;
186 case LLCC_TRAM_CE:
187 case LLCC_TRAM_UE:
188 ret = regmap_write(drv->bcast_regmap, TRP_INTERRUPT_0_CLEAR,
189 DRP_TRP_INT_CLEAR);
190 if (ret)
191 return ret;
192
193 ret = regmap_write(drv->bcast_regmap, TRP_ECC_ERROR_CNTR_CLEAR,
194 DRP_TRP_CNT_CLEAR);
195 if (ret)
196 return ret;
197 break;
198 default:
199 ret = -EINVAL;
200 edac_printk(KERN_CRIT, EDAC_LLCC, "Unexpected error type: %d\n",
201 err_type);
202 }
203 return ret;
204}
205
206/* Dump Syndrome registers data for Tag RAM, Data RAM bit errors*/
207static int
208dump_syn_reg_values(struct llcc_drv_data *drv, u32 bank, int err_type)
209{
210 struct llcc_edac_reg_data reg_data = edac_reg_data[err_type];
211 int err_cnt, err_ways, ret, i;
212 u32 synd_reg, synd_val;
213
214 for (i = 0; i < reg_data.reg_cnt; i++) {
215 synd_reg = reg_data.synd_reg + (i * 4);
216 ret = regmap_read(drv->regmap, drv->offsets[bank] + synd_reg,
217 &synd_val);
218 if (ret)
219 goto clear;
220
221 edac_printk(KERN_CRIT, EDAC_LLCC, "%s: ECC_SYN%d: 0x%8x\n",
222 reg_data.name, i, synd_val);
223 }
224
225 ret = regmap_read(drv->regmap,
226 drv->offsets[bank] + reg_data.count_status_reg,
227 &err_cnt);
228 if (ret)
229 goto clear;
230
231 err_cnt &= reg_data.count_mask;
232 err_cnt >>= reg_data.count_shift;
233 edac_printk(KERN_CRIT, EDAC_LLCC, "%s: Error count: 0x%4x\n",
234 reg_data.name, err_cnt);
235
236 ret = regmap_read(drv->regmap,
237 drv->offsets[bank] + reg_data.ways_status_reg,
238 &err_ways);
239 if (ret)
240 goto clear;
241
242 err_ways &= reg_data.ways_mask;
243 err_ways >>= reg_data.ways_shift;
244
245 edac_printk(KERN_CRIT, EDAC_LLCC, "%s: Error ways: 0x%4x\n",
246 reg_data.name, err_ways);
247
248clear:
249 return qcom_llcc_clear_error_status(err_type, drv);
250}
251
252static int
253dump_syn_reg(struct edac_device_ctl_info *edev_ctl, int err_type, u32 bank)
254{
255 struct llcc_drv_data *drv = edev_ctl->pvt_info;
256 int ret;
257
258 ret = dump_syn_reg_values(drv, bank, err_type);
259 if (ret)
260 return ret;
261
262 switch (err_type) {
263 case LLCC_DRAM_CE:
264 edac_device_handle_ce(edev_ctl, 0, bank,
265 "LLCC Data RAM correctable Error");
266 break;
267 case LLCC_DRAM_UE:
268 edac_device_handle_ue(edev_ctl, 0, bank,
269 "LLCC Data RAM uncorrectable Error");
270 break;
271 case LLCC_TRAM_CE:
272 edac_device_handle_ce(edev_ctl, 0, bank,
273 "LLCC Tag RAM correctable Error");
274 break;
275 case LLCC_TRAM_UE:
276 edac_device_handle_ue(edev_ctl, 0, bank,
277 "LLCC Tag RAM uncorrectable Error");
278 break;
279 default:
280 ret = -EINVAL;
281 edac_printk(KERN_CRIT, EDAC_LLCC, "Unexpected error type: %d\n",
282 err_type);
283 }
284
285 return ret;
286}
287
288static irqreturn_t
289llcc_ecc_irq_handler(int irq, void *edev_ctl)
290{
291 struct edac_device_ctl_info *edac_dev_ctl = edev_ctl;
292 struct llcc_drv_data *drv = edac_dev_ctl->pvt_info;
293 irqreturn_t irq_rc = IRQ_NONE;
294 u32 drp_error, trp_error, i;
295 bool irq_handled;
296 int ret;
297
298 /* Iterate over the banks and look for Tag RAM or Data RAM errors */
299 for (i = 0; i < drv->num_banks; i++) {
300 ret = regmap_read(drv->regmap,
301 drv->offsets[i] + DRP_INTERRUPT_STATUS,
302 &drp_error);
303
304 if (!ret && (drp_error & SB_ECC_ERROR)) {
305 edac_printk(KERN_CRIT, EDAC_LLCC,
306 "Single Bit Error detected in Data RAM\n");
307 ret = dump_syn_reg(edev_ctl, LLCC_DRAM_CE, i);
308 } else if (!ret && (drp_error & DB_ECC_ERROR)) {
309 edac_printk(KERN_CRIT, EDAC_LLCC,
310 "Double Bit Error detected in Data RAM\n");
311 ret = dump_syn_reg(edev_ctl, LLCC_DRAM_UE, i);
312 }
313 if (!ret)
314 irq_handled = true;
315
316 ret = regmap_read(drv->regmap,
317 drv->offsets[i] + TRP_INTERRUPT_0_STATUS,
318 &trp_error);
319
320 if (!ret && (trp_error & SB_ECC_ERROR)) {
321 edac_printk(KERN_CRIT, EDAC_LLCC,
322 "Single Bit Error detected in Tag RAM\n");
323 ret = dump_syn_reg(edev_ctl, LLCC_TRAM_CE, i);
324 } else if (!ret && (trp_error & DB_ECC_ERROR)) {
325 edac_printk(KERN_CRIT, EDAC_LLCC,
326 "Double Bit Error detected in Tag RAM\n");
327 ret = dump_syn_reg(edev_ctl, LLCC_TRAM_UE, i);
328 }
329 if (!ret)
330 irq_handled = true;
331 }
332
333 if (irq_handled)
334 irq_rc = IRQ_HANDLED;
335
336 return irq_rc;
337}
338
339static int qcom_llcc_edac_probe(struct platform_device *pdev)
340{
341 struct llcc_drv_data *llcc_driv_data = pdev->dev.platform_data;
342 struct edac_device_ctl_info *edev_ctl;
343 struct device *dev = &pdev->dev;
344 int ecc_irq;
345 int rc;
346
347 rc = qcom_llcc_core_setup(llcc_driv_data->bcast_regmap);
348 if (rc)
349 return rc;
350
351 /* Allocate edac control info */
352 edev_ctl = edac_device_alloc_ctl_info(0, "qcom-llcc", 1, "bank",
353 llcc_driv_data->num_banks, 1,
354 NULL, 0,
355 edac_device_alloc_index());
356
357 if (!edev_ctl)
358 return -ENOMEM;
359
360 edev_ctl->dev = dev;
361 edev_ctl->mod_name = dev_name(dev);
362 edev_ctl->dev_name = dev_name(dev);
363 edev_ctl->ctl_name = "llcc";
364 edev_ctl->panic_on_ue = LLCC_ERP_PANIC_ON_UE;
365 edev_ctl->pvt_info = llcc_driv_data;
366
367 rc = edac_device_add_device(edev_ctl);
368 if (rc)
369 goto out_mem;
370
371 platform_set_drvdata(pdev, edev_ctl);
372
373 /* Request for ecc irq */
374 ecc_irq = llcc_driv_data->ecc_irq;
375 if (ecc_irq < 0) {
376 rc = -ENODEV;
377 goto out_dev;
378 }
379 rc = devm_request_irq(dev, ecc_irq, llcc_ecc_irq_handler,
380 IRQF_TRIGGER_HIGH, "llcc_ecc", edev_ctl);
381 if (rc)
382 goto out_dev;
383
384 return rc;
385
386out_dev:
387 edac_device_del_device(edev_ctl->dev);
388out_mem:
389 edac_device_free_ctl_info(edev_ctl);
390
391 return rc;
392}
393
394static int qcom_llcc_edac_remove(struct platform_device *pdev)
395{
396 struct edac_device_ctl_info *edev_ctl = dev_get_drvdata(&pdev->dev);
397
398 edac_device_del_device(edev_ctl->dev);
399 edac_device_free_ctl_info(edev_ctl);
400
401 return 0;
402}
403
404static struct platform_driver qcom_llcc_edac_driver = {
405 .probe = qcom_llcc_edac_probe,
406 .remove = qcom_llcc_edac_remove,
407 .driver = {
408 .name = "qcom_llcc_edac",
409 },
410};
411module_platform_driver(qcom_llcc_edac_driver);
412
413MODULE_DESCRIPTION("QCOM EDAC driver");
414MODULE_LICENSE("GPL v2");
diff --git a/drivers/firmware/qcom_scm.c b/drivers/firmware/qcom_scm.c
index e778af766fae..af4eee86919d 100644
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -525,34 +525,44 @@ static int qcom_scm_probe(struct platform_device *pdev)
525 return ret; 525 return ret;
526 526
527 clks = (unsigned long)of_device_get_match_data(&pdev->dev); 527 clks = (unsigned long)of_device_get_match_data(&pdev->dev);
528 if (clks & SCM_HAS_CORE_CLK) { 528
529 scm->core_clk = devm_clk_get(&pdev->dev, "core"); 529 scm->core_clk = devm_clk_get(&pdev->dev, "core");
530 if (IS_ERR(scm->core_clk)) { 530 if (IS_ERR(scm->core_clk)) {
531 if (PTR_ERR(scm->core_clk) != -EPROBE_DEFER) 531 if (PTR_ERR(scm->core_clk) == -EPROBE_DEFER)
532 dev_err(&pdev->dev, 532 return PTR_ERR(scm->core_clk);
533 "failed to acquire core clk\n"); 533
534 if (clks & SCM_HAS_CORE_CLK) {
535 dev_err(&pdev->dev, "failed to acquire core clk\n");
534 return PTR_ERR(scm->core_clk); 536 return PTR_ERR(scm->core_clk);
535 } 537 }
538
539 scm->core_clk = NULL;
536 } 540 }
537 541
538 if (clks & SCM_HAS_IFACE_CLK) { 542 scm->iface_clk = devm_clk_get(&pdev->dev, "iface");
539 scm->iface_clk = devm_clk_get(&pdev->dev, "iface"); 543 if (IS_ERR(scm->iface_clk)) {
540 if (IS_ERR(scm->iface_clk)) { 544 if (PTR_ERR(scm->iface_clk) == -EPROBE_DEFER)
541 if (PTR_ERR(scm->iface_clk) != -EPROBE_DEFER) 545 return PTR_ERR(scm->iface_clk);
542 dev_err(&pdev->dev, 546
543 "failed to acquire iface clk\n"); 547 if (clks & SCM_HAS_IFACE_CLK) {
548 dev_err(&pdev->dev, "failed to acquire iface clk\n");
544 return PTR_ERR(scm->iface_clk); 549 return PTR_ERR(scm->iface_clk);
545 } 550 }
551
552 scm->iface_clk = NULL;
546 } 553 }
547 554
548 if (clks & SCM_HAS_BUS_CLK) { 555 scm->bus_clk = devm_clk_get(&pdev->dev, "bus");
549 scm->bus_clk = devm_clk_get(&pdev->dev, "bus"); 556 if (IS_ERR(scm->bus_clk)) {
550 if (IS_ERR(scm->bus_clk)) { 557 if (PTR_ERR(scm->bus_clk) == -EPROBE_DEFER)
551 if (PTR_ERR(scm->bus_clk) != -EPROBE_DEFER) 558 return PTR_ERR(scm->bus_clk);
552 dev_err(&pdev->dev, 559
553 "failed to acquire bus clk\n"); 560 if (clks & SCM_HAS_BUS_CLK) {
561 dev_err(&pdev->dev, "failed to acquire bus clk\n");
554 return PTR_ERR(scm->bus_clk); 562 return PTR_ERR(scm->bus_clk);
555 } 563 }
564
565 scm->bus_clk = NULL;
556 } 566 }
557 567
558 scm->reset.ops = &qcom_scm_pas_reset_ops; 568 scm->reset.ops = &qcom_scm_pas_reset_ops;
@@ -594,23 +604,23 @@ static const struct of_device_id qcom_scm_dt_match[] = {
594 { .compatible = "qcom,scm-apq8064", 604 { .compatible = "qcom,scm-apq8064",
595 /* FIXME: This should have .data = (void *) SCM_HAS_CORE_CLK */ 605 /* FIXME: This should have .data = (void *) SCM_HAS_CORE_CLK */
596 }, 606 },
597 { .compatible = "qcom,scm-msm8660", 607 { .compatible = "qcom,scm-apq8084", .data = (void *)(SCM_HAS_CORE_CLK |
598 .data = (void *) SCM_HAS_CORE_CLK, 608 SCM_HAS_IFACE_CLK |
599 }, 609 SCM_HAS_BUS_CLK)
600 { .compatible = "qcom,scm-msm8960",
601 .data = (void *) SCM_HAS_CORE_CLK,
602 },
603 { .compatible = "qcom,scm-msm8996",
604 .data = NULL, /* no clocks */
605 }, 610 },
606 { .compatible = "qcom,scm-ipq4019", 611 { .compatible = "qcom,scm-ipq4019" },
607 .data = NULL, /* no clocks */ 612 { .compatible = "qcom,scm-msm8660", .data = (void *) SCM_HAS_CORE_CLK },
613 { .compatible = "qcom,scm-msm8960", .data = (void *) SCM_HAS_CORE_CLK },
614 { .compatible = "qcom,scm-msm8916", .data = (void *)(SCM_HAS_CORE_CLK |
615 SCM_HAS_IFACE_CLK |
616 SCM_HAS_BUS_CLK)
608 }, 617 },
609 { .compatible = "qcom,scm", 618 { .compatible = "qcom,scm-msm8974", .data = (void *)(SCM_HAS_CORE_CLK |
610 .data = (void *)(SCM_HAS_CORE_CLK 619 SCM_HAS_IFACE_CLK |
611 | SCM_HAS_IFACE_CLK 620 SCM_HAS_BUS_CLK)
612 | SCM_HAS_BUS_CLK),
613 }, 621 },
622 { .compatible = "qcom,scm-msm8996" },
623 { .compatible = "qcom,scm" },
614 {} 624 {}
615}; 625};
616 626
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index ba79b609aca2..684cb51694d1 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -33,7 +33,7 @@ config QCOM_GLINK_SSR
33 33
34config QCOM_GSBI 34config QCOM_GSBI
35 tristate "QCOM General Serial Bus Interface" 35 tristate "QCOM General Serial Bus Interface"
36 depends on ARCH_QCOM 36 depends on ARCH_QCOM || COMPILE_TEST
37 select MFD_SYSCON 37 select MFD_SYSCON
38 help 38 help
39 Say y here to enable GSBI support. The GSBI provides control 39 Say y here to enable GSBI support. The GSBI provides control
@@ -42,7 +42,7 @@ config QCOM_GSBI
42 42
43config QCOM_LLCC 43config QCOM_LLCC
44 tristate "Qualcomm Technologies, Inc. LLCC driver" 44 tristate "Qualcomm Technologies, Inc. LLCC driver"
45 depends on ARCH_QCOM 45 depends on ARCH_QCOM || COMPILE_TEST
46 help 46 help
47 Qualcomm Technologies, Inc. platform specific 47 Qualcomm Technologies, Inc. platform specific
48 Last Level Cache Controller(LLCC) driver. This provides interfaces 48 Last Level Cache Controller(LLCC) driver. This provides interfaces
@@ -73,7 +73,8 @@ config QCOM_PM
73 73
74config QCOM_QMI_HELPERS 74config QCOM_QMI_HELPERS
75 tristate 75 tristate
76 depends on ARCH_QCOM && NET 76 depends on ARCH_QCOM || COMPILE_TEST
77 depends on NET
77 help 78 help
78 Helper library for handling QMI encoded messages. QMI encoded 79 Helper library for handling QMI encoded messages. QMI encoded
79 messages are used in communication between the majority of QRTR 80 messages are used in communication between the majority of QRTR
@@ -94,7 +95,7 @@ config QCOM_RMTFS_MEM
94 95
95config QCOM_RPMH 96config QCOM_RPMH
96 bool "Qualcomm RPM-Hardened (RPMH) Communication" 97 bool "Qualcomm RPM-Hardened (RPMH) Communication"
97 depends on ARCH_QCOM && ARM64 && OF || COMPILE_TEST 98 depends on ARCH_QCOM && ARM64 || COMPILE_TEST
98 help 99 help
99 Support for communication with the hardened-RPM blocks in 100 Support for communication with the hardened-RPM blocks in
100 Qualcomm Technologies Inc (QTI) SoCs. RPMH communication uses an 101 Qualcomm Technologies Inc (QTI) SoCs. RPMH communication uses an
@@ -104,7 +105,7 @@ config QCOM_RPMH
104 105
105config QCOM_SMEM 106config QCOM_SMEM
106 tristate "Qualcomm Shared Memory Manager (SMEM)" 107 tristate "Qualcomm Shared Memory Manager (SMEM)"
107 depends on ARCH_QCOM 108 depends on ARCH_QCOM || COMPILE_TEST
108 depends on HWSPINLOCK 109 depends on HWSPINLOCK
109 help 110 help
110 Say y here to enable support for the Qualcomm Shared Memory Manager. 111 Say y here to enable support for the Qualcomm Shared Memory Manager.
@@ -113,8 +114,8 @@ config QCOM_SMEM
113 114
114config QCOM_SMD_RPM 115config QCOM_SMD_RPM
115 tristate "Qualcomm Resource Power Manager (RPM) over SMD" 116 tristate "Qualcomm Resource Power Manager (RPM) over SMD"
116 depends on ARCH_QCOM 117 depends on ARCH_QCOM || COMPILE_TEST
117 depends on RPMSG && OF 118 depends on RPMSG
118 help 119 help
119 If you say yes to this option, support will be included for the 120 If you say yes to this option, support will be included for the
120 Resource Power Manager system found in the Qualcomm 8974 based 121 Resource Power Manager system found in the Qualcomm 8974 based
@@ -134,6 +135,7 @@ config QCOM_SMP2P
134 depends on MAILBOX 135 depends on MAILBOX
135 depends on QCOM_SMEM 136 depends on QCOM_SMEM
136 select QCOM_SMEM_STATE 137 select QCOM_SMEM_STATE
138 select IRQ_DOMAIN
137 help 139 help
138 Say yes here to support the Qualcomm Shared Memory Point to Point 140 Say yes here to support the Qualcomm Shared Memory Point to Point
139 protocol. 141 protocol.
@@ -142,13 +144,14 @@ config QCOM_SMSM
142 tristate "Qualcomm Shared Memory State Machine" 144 tristate "Qualcomm Shared Memory State Machine"
143 depends on QCOM_SMEM 145 depends on QCOM_SMEM
144 select QCOM_SMEM_STATE 146 select QCOM_SMEM_STATE
147 select IRQ_DOMAIN
145 help 148 help
146 Say yes here to support the Qualcomm Shared Memory State Machine. 149 Say yes here to support the Qualcomm Shared Memory State Machine.
147 The state machine is represented by bits in shared memory. 150 The state machine is represented by bits in shared memory.
148 151
149config QCOM_WCNSS_CTRL 152config QCOM_WCNSS_CTRL
150 tristate "Qualcomm WCNSS control driver" 153 tristate "Qualcomm WCNSS control driver"
151 depends on ARCH_QCOM 154 depends on ARCH_QCOM || COMPILE_TEST
152 depends on RPMSG 155 depends on RPMSG
153 help 156 help
154 Client driver for the WCNSS_CTRL SMD channel, used to download nv 157 Client driver for the WCNSS_CTRL SMD channel, used to download nv
@@ -156,7 +159,7 @@ config QCOM_WCNSS_CTRL
156 159
157config QCOM_APR 160config QCOM_APR
158 tristate "Qualcomm APR Bus (Asynchronous Packet Router)" 161 tristate "Qualcomm APR Bus (Asynchronous Packet Router)"
159 depends on ARCH_QCOM 162 depends on ARCH_QCOM || COMPILE_TEST
160 depends on RPMSG 163 depends on RPMSG
161 help 164 help
162 Enable APR IPC protocol support between 165 Enable APR IPC protocol support between
diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c
index 57af8a537332..716762d59c1f 100644
--- a/drivers/soc/qcom/apr.c
+++ b/drivers/soc/qcom/apr.c
@@ -87,7 +87,7 @@ static int apr_callback(struct rpmsg_device *rpdev, void *buf,
87 } 87 }
88 88
89 if (hdr->pkt_size < APR_HDR_SIZE || hdr->pkt_size != len) { 89 if (hdr->pkt_size < APR_HDR_SIZE || hdr->pkt_size != len) {
90 dev_err(apr->dev, "APR: Wrong paket size\n"); 90 dev_err(apr->dev, "APR: Wrong packet size\n");
91 return -EINVAL; 91 return -EINVAL;
92 } 92 }
93 93
@@ -219,9 +219,9 @@ static int apr_add_device(struct device *dev, struct device_node *np,
219 adev->domain_id = id->domain_id; 219 adev->domain_id = id->domain_id;
220 adev->version = id->svc_version; 220 adev->version = id->svc_version;
221 if (np) 221 if (np)
222 strncpy(adev->name, np->name, APR_NAME_SIZE); 222 strscpy(adev->name, np->name, APR_NAME_SIZE);
223 else 223 else
224 strncpy(adev->name, id->name, APR_NAME_SIZE); 224 strscpy(adev->name, id->name, APR_NAME_SIZE);
225 225
226 dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, 226 dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name,
227 id->domain_id, id->svc_id); 227 id->domain_id, id->svc_id);
diff --git a/drivers/soc/qcom/llcc-slice.c b/drivers/soc/qcom/llcc-slice.c
index 54063a31132f..192ca761b2cb 100644
--- a/drivers/soc/qcom/llcc-slice.c
+++ b/drivers/soc/qcom/llcc-slice.c
@@ -13,6 +13,7 @@
13#include <linux/mutex.h> 13#include <linux/mutex.h>
14#include <linux/of_device.h> 14#include <linux/of_device.h>
15#include <linux/regmap.h> 15#include <linux/regmap.h>
16#include <linux/sizes.h>
16#include <linux/slab.h> 17#include <linux/slab.h>
17#include <linux/soc/qcom/llcc-qcom.h> 18#include <linux/soc/qcom/llcc-qcom.h>
18 19
@@ -106,22 +107,24 @@ static int llcc_update_act_ctrl(u32 sid,
106 u32 slice_status; 107 u32 slice_status;
107 int ret; 108 int ret;
108 109
109 act_ctrl_reg = drv_data->bcast_off + LLCC_TRP_ACT_CTRLn(sid); 110 act_ctrl_reg = LLCC_TRP_ACT_CTRLn(sid);
110 status_reg = drv_data->bcast_off + LLCC_TRP_STATUSn(sid); 111 status_reg = LLCC_TRP_STATUSn(sid);
111 112
112 /* Set the ACTIVE trigger */ 113 /* Set the ACTIVE trigger */
113 act_ctrl_reg_val |= ACT_CTRL_ACT_TRIG; 114 act_ctrl_reg_val |= ACT_CTRL_ACT_TRIG;
114 ret = regmap_write(drv_data->regmap, act_ctrl_reg, act_ctrl_reg_val); 115 ret = regmap_write(drv_data->bcast_regmap, act_ctrl_reg,
116 act_ctrl_reg_val);
115 if (ret) 117 if (ret)
116 return ret; 118 return ret;
117 119
118 /* Clear the ACTIVE trigger */ 120 /* Clear the ACTIVE trigger */
119 act_ctrl_reg_val &= ~ACT_CTRL_ACT_TRIG; 121 act_ctrl_reg_val &= ~ACT_CTRL_ACT_TRIG;
120 ret = regmap_write(drv_data->regmap, act_ctrl_reg, act_ctrl_reg_val); 122 ret = regmap_write(drv_data->bcast_regmap, act_ctrl_reg,
123 act_ctrl_reg_val);
121 if (ret) 124 if (ret)
122 return ret; 125 return ret;
123 126
124 ret = regmap_read_poll_timeout(drv_data->regmap, status_reg, 127 ret = regmap_read_poll_timeout(drv_data->bcast_regmap, status_reg,
125 slice_status, !(slice_status & status), 128 slice_status, !(slice_status & status),
126 0, LLCC_STATUS_READ_DELAY); 129 0, LLCC_STATUS_READ_DELAY);
127 return ret; 130 return ret;
@@ -223,19 +226,16 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev)
223 u32 attr0_val; 226 u32 attr0_val;
224 u32 max_cap_cacheline; 227 u32 max_cap_cacheline;
225 u32 sz; 228 u32 sz;
226 int ret; 229 int ret = 0;
227 const struct llcc_slice_config *llcc_table; 230 const struct llcc_slice_config *llcc_table;
228 struct llcc_slice_desc desc; 231 struct llcc_slice_desc desc;
229 u32 bcast_off = drv_data->bcast_off;
230 232
231 sz = drv_data->cfg_size; 233 sz = drv_data->cfg_size;
232 llcc_table = drv_data->cfg; 234 llcc_table = drv_data->cfg;
233 235
234 for (i = 0; i < sz; i++) { 236 for (i = 0; i < sz; i++) {
235 attr1_cfg = bcast_off + 237 attr1_cfg = LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id);
236 LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id); 238 attr0_cfg = LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id);
237 attr0_cfg = bcast_off +
238 LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id);
239 239
240 attr1_val = llcc_table[i].cache_mode; 240 attr1_val = llcc_table[i].cache_mode;
241 attr1_val |= llcc_table[i].probe_target_ways << 241 attr1_val |= llcc_table[i].probe_target_ways <<
@@ -260,10 +260,12 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev)
260 attr0_val = llcc_table[i].res_ways & ATTR0_RES_WAYS_MASK; 260 attr0_val = llcc_table[i].res_ways & ATTR0_RES_WAYS_MASK;
261 attr0_val |= llcc_table[i].bonus_ways << ATTR0_BONUS_WAYS_SHIFT; 261 attr0_val |= llcc_table[i].bonus_ways << ATTR0_BONUS_WAYS_SHIFT;
262 262
263 ret = regmap_write(drv_data->regmap, attr1_cfg, attr1_val); 263 ret = regmap_write(drv_data->bcast_regmap, attr1_cfg,
264 attr1_val);
264 if (ret) 265 if (ret)
265 return ret; 266 return ret;
266 ret = regmap_write(drv_data->regmap, attr0_cfg, attr0_val); 267 ret = regmap_write(drv_data->bcast_regmap, attr0_cfg,
268 attr0_val);
267 if (ret) 269 if (ret)
268 return ret; 270 return ret;
269 if (llcc_table[i].activate_on_init) { 271 if (llcc_table[i].activate_on_init) {
@@ -279,24 +281,37 @@ int qcom_llcc_probe(struct platform_device *pdev,
279{ 281{
280 u32 num_banks; 282 u32 num_banks;
281 struct device *dev = &pdev->dev; 283 struct device *dev = &pdev->dev;
282 struct resource *res; 284 struct resource *llcc_banks_res, *llcc_bcast_res;
283 void __iomem *base; 285 void __iomem *llcc_banks_base, *llcc_bcast_base;
284 int ret, i; 286 int ret, i;
287 struct platform_device *llcc_edac;
285 288
286 drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL); 289 drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
287 if (!drv_data) 290 if (!drv_data)
288 return -ENOMEM; 291 return -ENOMEM;
289 292
290 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 293 llcc_banks_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
291 base = devm_ioremap_resource(&pdev->dev, res); 294 "llcc_base");
292 if (IS_ERR(base)) 295 llcc_banks_base = devm_ioremap_resource(&pdev->dev, llcc_banks_res);
293 return PTR_ERR(base); 296 if (IS_ERR(llcc_banks_base))
297 return PTR_ERR(llcc_banks_base);
294 298
295 drv_data->regmap = devm_regmap_init_mmio(dev, base, 299 drv_data->regmap = devm_regmap_init_mmio(dev, llcc_banks_base,
296 &llcc_regmap_config); 300 &llcc_regmap_config);
297 if (IS_ERR(drv_data->regmap)) 301 if (IS_ERR(drv_data->regmap))
298 return PTR_ERR(drv_data->regmap); 302 return PTR_ERR(drv_data->regmap);
299 303
304 llcc_bcast_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
305 "llcc_broadcast_base");
306 llcc_bcast_base = devm_ioremap_resource(&pdev->dev, llcc_bcast_res);
307 if (IS_ERR(llcc_bcast_base))
308 return PTR_ERR(llcc_bcast_base);
309
310 drv_data->bcast_regmap = devm_regmap_init_mmio(dev, llcc_bcast_base,
311 &llcc_regmap_config);
312 if (IS_ERR(drv_data->bcast_regmap))
313 return PTR_ERR(drv_data->bcast_regmap);
314
300 ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0, 315 ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0,
301 &num_banks); 316 &num_banks);
302 if (ret) 317 if (ret)
@@ -318,8 +333,6 @@ int qcom_llcc_probe(struct platform_device *pdev,
318 for (i = 0; i < num_banks; i++) 333 for (i = 0; i < num_banks; i++)
319 drv_data->offsets[i] = i * BANK_OFFSET_STRIDE; 334 drv_data->offsets[i] = i * BANK_OFFSET_STRIDE;
320 335
321 drv_data->bcast_off = num_banks * BANK_OFFSET_STRIDE;
322
323 drv_data->bitmap = devm_kcalloc(dev, 336 drv_data->bitmap = devm_kcalloc(dev,
324 BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long), 337 BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long),
325 GFP_KERNEL); 338 GFP_KERNEL);
@@ -331,7 +344,20 @@ int qcom_llcc_probe(struct platform_device *pdev,
331 mutex_init(&drv_data->lock); 344 mutex_init(&drv_data->lock);
332 platform_set_drvdata(pdev, drv_data); 345 platform_set_drvdata(pdev, drv_data);
333 346
334 return qcom_llcc_cfg_program(pdev); 347 ret = qcom_llcc_cfg_program(pdev);
348 if (ret)
349 return ret;
350
351 drv_data->ecc_irq = platform_get_irq(pdev, 0);
352 if (drv_data->ecc_irq >= 0) {
353 llcc_edac = platform_device_register_data(&pdev->dev,
354 "qcom_llcc_edac", -1, drv_data,
355 sizeof(*drv_data));
356 if (IS_ERR(llcc_edac))
357 dev_err(dev, "Failed to register llcc edac driver\n");
358 }
359
360 return ret;
335} 361}
336EXPORT_SYMBOL_GPL(qcom_llcc_probe); 362EXPORT_SYMBOL_GPL(qcom_llcc_probe);
337 363
diff --git a/drivers/soc/qcom/rmtfs_mem.c b/drivers/soc/qcom/rmtfs_mem.c
index 8a3678c2e83c..97bb5989aa21 100644
--- a/drivers/soc/qcom/rmtfs_mem.c
+++ b/drivers/soc/qcom/rmtfs_mem.c
@@ -212,6 +212,11 @@ static int qcom_rmtfs_mem_probe(struct platform_device *pdev)
212 dev_err(&pdev->dev, "failed to parse qcom,vmid\n"); 212 dev_err(&pdev->dev, "failed to parse qcom,vmid\n");
213 goto remove_cdev; 213 goto remove_cdev;
214 } else if (!ret) { 214 } else if (!ret) {
215 if (!qcom_scm_is_available()) {
216 ret = -EPROBE_DEFER;
217 goto remove_cdev;
218 }
219
215 perms[0].vmid = QCOM_SCM_VMID_HLOS; 220 perms[0].vmid = QCOM_SCM_VMID_HLOS;
216 perms[0].perm = QCOM_SCM_PERM_RW; 221 perms[0].perm = QCOM_SCM_PERM_RW;
217 perms[1].vmid = vmid; 222 perms[1].vmid = vmid;
diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index ee75da66d64b..75bd9a83aef0 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -121,6 +121,7 @@ static int tcs_invalidate(struct rsc_drv *drv, int type)
121 return -EAGAIN; 121 return -EAGAIN;
122 } 122 }
123 write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, m, 0); 123 write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, m, 0);
124 write_tcs_reg_sync(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, m, 0);
124 } 125 }
125 bitmap_zero(tcs->slots, MAX_TCS_SLOTS); 126 bitmap_zero(tcs->slots, MAX_TCS_SLOTS);
126 spin_unlock(&tcs->lock); 127 spin_unlock(&tcs->lock);
@@ -239,6 +240,7 @@ static irqreturn_t tcs_tx_done(int irq, void *p)
239skip: 240skip:
240 /* Reclaim the TCS */ 241 /* Reclaim the TCS */
241 write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, i, 0); 242 write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, i, 0);
243 write_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, i, 0);
242 write_tcs_reg(drv, RSC_DRV_IRQ_CLEAR, 0, BIT(i)); 244 write_tcs_reg(drv, RSC_DRV_IRQ_CLEAR, 0, BIT(i));
243 spin_lock(&drv->lock); 245 spin_lock(&drv->lock);
244 clear_bit(i, drv->tcs_in_use); 246 clear_bit(i, drv->tcs_in_use);
diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c
index bf4bd71ab53f..f80d040601fd 100644
--- a/drivers/soc/qcom/smem.c
+++ b/drivers/soc/qcom/smem.c
@@ -18,6 +18,7 @@
18#include <linux/of.h> 18#include <linux/of.h>
19#include <linux/of_address.h> 19#include <linux/of_address.h>
20#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/sizes.h>
21#include <linux/slab.h> 22#include <linux/slab.h>
22#include <linux/soc/qcom/smem.h> 23#include <linux/soc/qcom/smem.h>
23 24
@@ -277,7 +278,7 @@ struct qcom_smem {
277 u32 item_count; 278 u32 item_count;
278 279
279 unsigned num_regions; 280 unsigned num_regions;
280 struct smem_region regions[0]; 281 struct smem_region regions[];
281}; 282};
282 283
283static void * 284static void *
@@ -489,7 +490,7 @@ static void *qcom_smem_get_global(struct qcom_smem *smem,
489 size_t *size) 490 size_t *size)
490{ 491{
491 struct smem_header *header; 492 struct smem_header *header;
492 struct smem_region *area; 493 struct smem_region *region;
493 struct smem_global_entry *entry; 494 struct smem_global_entry *entry;
494 u32 aux_base; 495 u32 aux_base;
495 unsigned i; 496 unsigned i;
@@ -502,12 +503,12 @@ static void *qcom_smem_get_global(struct qcom_smem *smem,
502 aux_base = le32_to_cpu(entry->aux_base) & AUX_BASE_MASK; 503 aux_base = le32_to_cpu(entry->aux_base) & AUX_BASE_MASK;
503 504
504 for (i = 0; i < smem->num_regions; i++) { 505 for (i = 0; i < smem->num_regions; i++) {
505 area = &smem->regions[i]; 506 region = &smem->regions[i];
506 507
507 if (area->aux_base == aux_base || !aux_base) { 508 if (region->aux_base == aux_base || !aux_base) {
508 if (size != NULL) 509 if (size != NULL)
509 *size = le32_to_cpu(entry->size); 510 *size = le32_to_cpu(entry->size);
510 return area->virt_base + le32_to_cpu(entry->offset); 511 return region->virt_base + le32_to_cpu(entry->offset);
511 } 512 }
512 } 513 }
513 514
@@ -722,12 +723,59 @@ static u32 qcom_smem_get_item_count(struct qcom_smem *smem)
722 return le16_to_cpu(info->num_items); 723 return le16_to_cpu(info->num_items);
723} 724}
724 725
726/*
727 * Validate the partition header for a partition whose partition
728 * table entry is supplied. Returns a pointer to its header if
729 * valid, or a null pointer otherwise.
730 */
731static struct smem_partition_header *
732qcom_smem_partition_header(struct qcom_smem *smem,
733 struct smem_ptable_entry *entry, u16 host0, u16 host1)
734{
735 struct smem_partition_header *header;
736 u32 size;
737
738 header = smem->regions[0].virt_base + le32_to_cpu(entry->offset);
739
740 if (memcmp(header->magic, SMEM_PART_MAGIC, sizeof(header->magic))) {
741 dev_err(smem->dev, "bad partition magic %02x %02x %02x %02x\n",
742 header->magic[0], header->magic[1],
743 header->magic[2], header->magic[3]);
744 return NULL;
745 }
746
747 if (host0 != le16_to_cpu(header->host0)) {
748 dev_err(smem->dev, "bad host0 (%hu != %hu)\n",
749 host0, le16_to_cpu(header->host0));
750 return NULL;
751 }
752 if (host1 != le16_to_cpu(header->host1)) {
753 dev_err(smem->dev, "bad host1 (%hu != %hu)\n",
754 host1, le16_to_cpu(header->host1));
755 return NULL;
756 }
757
758 size = le32_to_cpu(header->size);
759 if (size != le32_to_cpu(entry->size)) {
760 dev_err(smem->dev, "bad partition size (%u != %u)\n",
761 size, le32_to_cpu(entry->size));
762 return NULL;
763 }
764
765 if (le32_to_cpu(header->offset_free_uncached) > size) {
766 dev_err(smem->dev, "bad partition free uncached (%u > %u)\n",
767 le32_to_cpu(header->offset_free_uncached), size);
768 return NULL;
769 }
770
771 return header;
772}
773
725static int qcom_smem_set_global_partition(struct qcom_smem *smem) 774static int qcom_smem_set_global_partition(struct qcom_smem *smem)
726{ 775{
727 struct smem_partition_header *header; 776 struct smem_partition_header *header;
728 struct smem_ptable_entry *entry; 777 struct smem_ptable_entry *entry;
729 struct smem_ptable *ptable; 778 struct smem_ptable *ptable;
730 u32 host0, host1, size;
731 bool found = false; 779 bool found = false;
732 int i; 780 int i;
733 781
@@ -742,10 +790,15 @@ static int qcom_smem_set_global_partition(struct qcom_smem *smem)
742 790
743 for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) { 791 for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) {
744 entry = &ptable->entry[i]; 792 entry = &ptable->entry[i];
745 host0 = le16_to_cpu(entry->host0); 793 if (!le32_to_cpu(entry->offset))
746 host1 = le16_to_cpu(entry->host1); 794 continue;
795 if (!le32_to_cpu(entry->size))
796 continue;
797
798 if (le16_to_cpu(entry->host0) != SMEM_GLOBAL_HOST)
799 continue;
747 800
748 if (host0 == SMEM_GLOBAL_HOST && host0 == host1) { 801 if (le16_to_cpu(entry->host1) == SMEM_GLOBAL_HOST) {
749 found = true; 802 found = true;
750 break; 803 break;
751 } 804 }
@@ -756,36 +809,10 @@ static int qcom_smem_set_global_partition(struct qcom_smem *smem)
756 return -EINVAL; 809 return -EINVAL;
757 } 810 }
758 811
759 if (!le32_to_cpu(entry->offset) || !le32_to_cpu(entry->size)) { 812 header = qcom_smem_partition_header(smem, entry,
760 dev_err(smem->dev, "Invalid entry for global partition\n"); 813 SMEM_GLOBAL_HOST, SMEM_GLOBAL_HOST);
814 if (!header)
761 return -EINVAL; 815 return -EINVAL;
762 }
763
764 header = smem->regions[0].virt_base + le32_to_cpu(entry->offset);
765 host0 = le16_to_cpu(header->host0);
766 host1 = le16_to_cpu(header->host1);
767
768 if (memcmp(header->magic, SMEM_PART_MAGIC, sizeof(header->magic))) {
769 dev_err(smem->dev, "Global partition has invalid magic\n");
770 return -EINVAL;
771 }
772
773 if (host0 != SMEM_GLOBAL_HOST && host1 != SMEM_GLOBAL_HOST) {
774 dev_err(smem->dev, "Global partition hosts are invalid\n");
775 return -EINVAL;
776 }
777
778 if (le32_to_cpu(header->size) != le32_to_cpu(entry->size)) {
779 dev_err(smem->dev, "Global partition has invalid size\n");
780 return -EINVAL;
781 }
782
783 size = le32_to_cpu(header->offset_free_uncached);
784 if (size > le32_to_cpu(header->size)) {
785 dev_err(smem->dev,
786 "Global partition has invalid free pointer\n");
787 return -EINVAL;
788 }
789 816
790 smem->global_partition = header; 817 smem->global_partition = header;
791 smem->global_cacheline = le32_to_cpu(entry->cacheline); 818 smem->global_cacheline = le32_to_cpu(entry->cacheline);
@@ -793,14 +820,14 @@ static int qcom_smem_set_global_partition(struct qcom_smem *smem)
793 return 0; 820 return 0;
794} 821}
795 822
796static int qcom_smem_enumerate_partitions(struct qcom_smem *smem, 823static int
797 unsigned int local_host) 824qcom_smem_enumerate_partitions(struct qcom_smem *smem, u16 local_host)
798{ 825{
799 struct smem_partition_header *header; 826 struct smem_partition_header *header;
800 struct smem_ptable_entry *entry; 827 struct smem_ptable_entry *entry;
801 struct smem_ptable *ptable; 828 struct smem_ptable *ptable;
802 unsigned int remote_host; 829 unsigned int remote_host;
803 u32 host0, host1; 830 u16 host0, host1;
804 int i; 831 int i;
805 832
806 ptable = qcom_smem_get_ptable(smem); 833 ptable = qcom_smem_get_ptable(smem);
@@ -809,71 +836,33 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem,
809 836
810 for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) { 837 for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) {
811 entry = &ptable->entry[i]; 838 entry = &ptable->entry[i];
812 host0 = le16_to_cpu(entry->host0);
813 host1 = le16_to_cpu(entry->host1);
814
815 if (host0 != local_host && host1 != local_host)
816 continue;
817
818 if (!le32_to_cpu(entry->offset)) 839 if (!le32_to_cpu(entry->offset))
819 continue; 840 continue;
820
821 if (!le32_to_cpu(entry->size)) 841 if (!le32_to_cpu(entry->size))
822 continue; 842 continue;
823 843
844 host0 = le16_to_cpu(entry->host0);
845 host1 = le16_to_cpu(entry->host1);
824 if (host0 == local_host) 846 if (host0 == local_host)
825 remote_host = host1; 847 remote_host = host1;
826 else 848 else if (host1 == local_host)
827 remote_host = host0; 849 remote_host = host0;
850 else
851 continue;
828 852
829 if (remote_host >= SMEM_HOST_COUNT) { 853 if (remote_host >= SMEM_HOST_COUNT) {
830 dev_err(smem->dev, 854 dev_err(smem->dev, "bad host %hu\n", remote_host);
831 "Invalid remote host %d\n",
832 remote_host);
833 return -EINVAL; 855 return -EINVAL;
834 } 856 }
835 857
836 if (smem->partitions[remote_host]) { 858 if (smem->partitions[remote_host]) {
837 dev_err(smem->dev, 859 dev_err(smem->dev, "duplicate host %hu\n", remote_host);
838 "Already found a partition for host %d\n",
839 remote_host);
840 return -EINVAL;
841 }
842
843 header = smem->regions[0].virt_base + le32_to_cpu(entry->offset);
844 host0 = le16_to_cpu(header->host0);
845 host1 = le16_to_cpu(header->host1);
846
847 if (memcmp(header->magic, SMEM_PART_MAGIC,
848 sizeof(header->magic))) {
849 dev_err(smem->dev,
850 "Partition %d has invalid magic\n", i);
851 return -EINVAL; 860 return -EINVAL;
852 } 861 }
853 862
854 if (host0 != local_host && host1 != local_host) { 863 header = qcom_smem_partition_header(smem, entry, host0, host1);
855 dev_err(smem->dev, 864 if (!header)
856 "Partition %d hosts are invalid\n", i);
857 return -EINVAL; 865 return -EINVAL;
858 }
859
860 if (host0 != remote_host && host1 != remote_host) {
861 dev_err(smem->dev,
862 "Partition %d hosts are invalid\n", i);
863 return -EINVAL;
864 }
865
866 if (le32_to_cpu(header->size) != le32_to_cpu(entry->size)) {
867 dev_err(smem->dev,
868 "Partition %d has invalid size\n", i);
869 return -EINVAL;
870 }
871
872 if (le32_to_cpu(header->offset_free_uncached) > le32_to_cpu(header->size)) {
873 dev_err(smem->dev,
874 "Partition %d has invalid free pointer\n", i);
875 return -EINVAL;
876 }
877 866
878 smem->partitions[remote_host] = header; 867 smem->partitions[remote_host] = header;
879 smem->cacheline[remote_host] = le32_to_cpu(entry->cacheline); 868 smem->cacheline[remote_host] = le32_to_cpu(entry->cacheline);
@@ -887,6 +876,7 @@ static int qcom_smem_map_memory(struct qcom_smem *smem, struct device *dev,
887{ 876{
888 struct device_node *np; 877 struct device_node *np;
889 struct resource r; 878 struct resource r;
879 resource_size_t size;
890 int ret; 880 int ret;
891 881
892 np = of_parse_phandle(dev->of_node, name, 0); 882 np = of_parse_phandle(dev->of_node, name, 0);
@@ -899,12 +889,13 @@ static int qcom_smem_map_memory(struct qcom_smem *smem, struct device *dev,
899 of_node_put(np); 889 of_node_put(np);
900 if (ret) 890 if (ret)
901 return ret; 891 return ret;
892 size = resource_size(&r);
902 893
903 smem->regions[i].aux_base = (u32)r.start; 894 smem->regions[i].virt_base = devm_ioremap_wc(dev, r.start, size);
904 smem->regions[i].size = resource_size(&r);
905 smem->regions[i].virt_base = devm_ioremap_wc(dev, r.start, resource_size(&r));
906 if (!smem->regions[i].virt_base) 895 if (!smem->regions[i].virt_base)
907 return -ENOMEM; 896 return -ENOMEM;
897 smem->regions[i].aux_base = (u32)r.start;
898 smem->regions[i].size = size;
908 899
909 return 0; 900 return 0;
910} 901}
@@ -962,6 +953,7 @@ static int qcom_smem_probe(struct platform_device *pdev)
962 return -EINVAL; 953 return -EINVAL;
963 } 954 }
964 955
956 BUILD_BUG_ON(SMEM_HOST_APPS >= SMEM_HOST_COUNT);
965 ret = qcom_smem_enumerate_partitions(smem, SMEM_HOST_APPS); 957 ret = qcom_smem_enumerate_partitions(smem, SMEM_HOST_APPS);
966 if (ret < 0 && ret != -ENOENT) 958 if (ret < 0 && ret != -ENOENT)
967 return ret; 959 return ret;
diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c
index f9d7a85b2822..53807e839664 100644
--- a/drivers/soc/qcom/spm.c
+++ b/drivers/soc/qcom/spm.c
@@ -219,6 +219,9 @@ static int __init qcom_cpuidle_init(struct device_node *cpu_node, int cpu)
219 cpumask_t mask; 219 cpumask_t mask;
220 bool use_scm_power_down = false; 220 bool use_scm_power_down = false;
221 221
222 if (!qcom_scm_is_available())
223 return -EPROBE_DEFER;
224
222 for (i = 0; ; i++) { 225 for (i = 0; ; i++) {
223 state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); 226 state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i);
224 if (!state_node) 227 if (!state_node)
diff --git a/drivers/soc/qcom/wcnss_ctrl.c b/drivers/soc/qcom/wcnss_ctrl.c
index df3ccb30bc2d..373400dd816d 100644
--- a/drivers/soc/qcom/wcnss_ctrl.c
+++ b/drivers/soc/qcom/wcnss_ctrl.c
@@ -281,7 +281,7 @@ struct rpmsg_endpoint *qcom_wcnss_open_channel(void *wcnss, const char *name, rp
281 struct rpmsg_channel_info chinfo; 281 struct rpmsg_channel_info chinfo;
282 struct wcnss_ctrl *_wcnss = wcnss; 282 struct wcnss_ctrl *_wcnss = wcnss;
283 283
284 strncpy(chinfo.name, name, sizeof(chinfo.name)); 284 strscpy(chinfo.name, name, sizeof(chinfo.name));
285 chinfo.src = RPMSG_ADDR_ANY; 285 chinfo.src = RPMSG_ADDR_ANY;
286 chinfo.dst = RPMSG_ADDR_ANY; 286 chinfo.dst = RPMSG_ADDR_ANY;
287 287
diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h
index 7e3b9c605ab2..69c285b1c990 100644
--- a/include/linux/soc/qcom/llcc-qcom.h
+++ b/include/linux/soc/qcom/llcc-qcom.h
@@ -70,25 +70,51 @@ struct llcc_slice_config {
70/** 70/**
71 * llcc_drv_data - Data associated with the llcc driver 71 * llcc_drv_data - Data associated with the llcc driver
72 * @regmap: regmap associated with the llcc device 72 * @regmap: regmap associated with the llcc device
73 * @bcast_regmap: regmap associated with llcc broadcast offset
73 * @cfg: pointer to the data structure for slice configuration 74 * @cfg: pointer to the data structure for slice configuration
74 * @lock: mutex associated with each slice 75 * @lock: mutex associated with each slice
75 * @cfg_size: size of the config data table 76 * @cfg_size: size of the config data table
76 * @max_slices: max slices as read from device tree 77 * @max_slices: max slices as read from device tree
77 * @bcast_off: Offset of the broadcast bank
78 * @num_banks: Number of llcc banks 78 * @num_banks: Number of llcc banks
79 * @bitmap: Bit map to track the active slice ids 79 * @bitmap: Bit map to track the active slice ids
80 * @offsets: Pointer to the bank offsets array 80 * @offsets: Pointer to the bank offsets array
81 * @ecc_irq: interrupt for llcc cache error detection and reporting
81 */ 82 */
82struct llcc_drv_data { 83struct llcc_drv_data {
83 struct regmap *regmap; 84 struct regmap *regmap;
85 struct regmap *bcast_regmap;
84 const struct llcc_slice_config *cfg; 86 const struct llcc_slice_config *cfg;
85 struct mutex lock; 87 struct mutex lock;
86 u32 cfg_size; 88 u32 cfg_size;
87 u32 max_slices; 89 u32 max_slices;
88 u32 bcast_off;
89 u32 num_banks; 90 u32 num_banks;
90 unsigned long *bitmap; 91 unsigned long *bitmap;
91 u32 *offsets; 92 u32 *offsets;
93 int ecc_irq;
94};
95
96/**
97 * llcc_edac_reg_data - llcc edac registers data for each error type
98 * @name: Name of the error
99 * @synd_reg: Syndrome register address
100 * @count_status_reg: Status register address to read the error count
101 * @ways_status_reg: Status register address to read the error ways
102 * @reg_cnt: Number of registers
103 * @count_mask: Mask value to get the error count
104 * @ways_mask: Mask value to get the error ways
105 * @count_shift: Shift value to get the error count
106 * @ways_shift: Shift value to get the error ways
107 */
108struct llcc_edac_reg_data {
109 char *name;
110 u64 synd_reg;
111 u64 count_status_reg;
112 u64 ways_status_reg;
113 u32 reg_cnt;
114 u32 count_mask;
115 u32 ways_mask;
116 u8 count_shift;
117 u8 ways_shift;
92}; 118};
93 119
94#if IS_ENABLED(CONFIG_QCOM_LLCC) 120#if IS_ENABLED(CONFIG_QCOM_LLCC)