hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/bus/brcmstb_gisb.c
....@@ -1,14 +1,6 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2014-2017 Broadcom
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
- * 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.
124 */
135
146 #include <linux/init.h>
....@@ -38,8 +30,22 @@
3830 #define ARB_ERR_CAP_STATUS_WRITE (1 << 1)
3931 #define ARB_ERR_CAP_STATUS_VALID (1 << 0)
4032
33
+#define ARB_BP_CAP_CLEAR (1 << 0)
34
+#define ARB_BP_CAP_STATUS_PROT_SHIFT 14
35
+#define ARB_BP_CAP_STATUS_TYPE (1 << 13)
36
+#define ARB_BP_CAP_STATUS_RSP_SHIFT 10
37
+#define ARB_BP_CAP_STATUS_MASK GENMASK(1, 0)
38
+#define ARB_BP_CAP_STATUS_BS_SHIFT 2
39
+#define ARB_BP_CAP_STATUS_WRITE (1 << 1)
40
+#define ARB_BP_CAP_STATUS_VALID (1 << 0)
41
+
4142 enum {
4243 ARB_TIMER,
44
+ ARB_BP_CAP_CLR,
45
+ ARB_BP_CAP_HI_ADDR,
46
+ ARB_BP_CAP_ADDR,
47
+ ARB_BP_CAP_STATUS,
48
+ ARB_BP_CAP_MASTER,
4349 ARB_ERR_CAP_CLR,
4450 ARB_ERR_CAP_HI_ADDR,
4551 ARB_ERR_CAP_ADDR,
....@@ -49,6 +55,11 @@
4955
5056 static const int gisb_offsets_bcm7038[] = {
5157 [ARB_TIMER] = 0x00c,
58
+ [ARB_BP_CAP_CLR] = 0x014,
59
+ [ARB_BP_CAP_HI_ADDR] = -1,
60
+ [ARB_BP_CAP_ADDR] = 0x0b8,
61
+ [ARB_BP_CAP_STATUS] = 0x0c0,
62
+ [ARB_BP_CAP_MASTER] = -1,
5263 [ARB_ERR_CAP_CLR] = 0x0c4,
5364 [ARB_ERR_CAP_HI_ADDR] = -1,
5465 [ARB_ERR_CAP_ADDR] = 0x0c8,
....@@ -58,6 +69,11 @@
5869
5970 static const int gisb_offsets_bcm7278[] = {
6071 [ARB_TIMER] = 0x008,
72
+ [ARB_BP_CAP_CLR] = 0x01c,
73
+ [ARB_BP_CAP_HI_ADDR] = -1,
74
+ [ARB_BP_CAP_ADDR] = 0x220,
75
+ [ARB_BP_CAP_STATUS] = 0x230,
76
+ [ARB_BP_CAP_MASTER] = 0x234,
6177 [ARB_ERR_CAP_CLR] = 0x7f8,
6278 [ARB_ERR_CAP_HI_ADDR] = -1,
6379 [ARB_ERR_CAP_ADDR] = 0x7e0,
....@@ -67,6 +83,11 @@
6783
6884 static const int gisb_offsets_bcm7400[] = {
6985 [ARB_TIMER] = 0x00c,
86
+ [ARB_BP_CAP_CLR] = 0x014,
87
+ [ARB_BP_CAP_HI_ADDR] = -1,
88
+ [ARB_BP_CAP_ADDR] = 0x0b8,
89
+ [ARB_BP_CAP_STATUS] = 0x0c0,
90
+ [ARB_BP_CAP_MASTER] = 0x0c4,
7091 [ARB_ERR_CAP_CLR] = 0x0c8,
7192 [ARB_ERR_CAP_HI_ADDR] = -1,
7293 [ARB_ERR_CAP_ADDR] = 0x0cc,
....@@ -76,6 +97,11 @@
7697
7798 static const int gisb_offsets_bcm7435[] = {
7899 [ARB_TIMER] = 0x00c,
100
+ [ARB_BP_CAP_CLR] = 0x014,
101
+ [ARB_BP_CAP_HI_ADDR] = -1,
102
+ [ARB_BP_CAP_ADDR] = 0x158,
103
+ [ARB_BP_CAP_STATUS] = 0x160,
104
+ [ARB_BP_CAP_MASTER] = 0x164,
79105 [ARB_ERR_CAP_CLR] = 0x168,
80106 [ARB_ERR_CAP_HI_ADDR] = -1,
81107 [ARB_ERR_CAP_ADDR] = 0x16c,
....@@ -85,6 +111,11 @@
85111
86112 static const int gisb_offsets_bcm7445[] = {
87113 [ARB_TIMER] = 0x008,
114
+ [ARB_BP_CAP_CLR] = 0x010,
115
+ [ARB_BP_CAP_HI_ADDR] = -1,
116
+ [ARB_BP_CAP_ADDR] = 0x1d8,
117
+ [ARB_BP_CAP_STATUS] = 0x1e0,
118
+ [ARB_BP_CAP_MASTER] = 0x1e4,
88119 [ARB_ERR_CAP_CLR] = 0x7e4,
89120 [ARB_ERR_CAP_HI_ADDR] = 0x7e8,
90121 [ARB_ERR_CAP_ADDR] = 0x7ec,
....@@ -133,6 +164,16 @@
133164 return value;
134165 }
135166
167
+static u64 gisb_read_bp_address(struct brcmstb_gisb_arb_device *gdev)
168
+{
169
+ u64 value;
170
+
171
+ value = gisb_read(gdev, ARB_BP_CAP_ADDR);
172
+ value |= (u64)gisb_read(gdev, ARB_BP_CAP_HI_ADDR) << 32;
173
+
174
+ return value;
175
+}
176
+
136177 static void gisb_write(struct brcmstb_gisb_arb_device *gdev, u32 val, int reg)
137178 {
138179 int offset = gdev->gisb_offsets[reg];
....@@ -150,8 +191,7 @@
150191 struct device_attribute *attr,
151192 char *buf)
152193 {
153
- struct platform_device *pdev = to_platform_device(dev);
154
- struct brcmstb_gisb_arb_device *gdev = platform_get_drvdata(pdev);
194
+ struct brcmstb_gisb_arb_device *gdev = dev_get_drvdata(dev);
155195 u32 timeout;
156196
157197 mutex_lock(&gdev->lock);
....@@ -165,8 +205,7 @@
165205 struct device_attribute *attr,
166206 const char *buf, size_t count)
167207 {
168
- struct platform_device *pdev = to_platform_device(dev);
169
- struct brcmstb_gisb_arb_device *gdev = platform_get_drvdata(pdev);
208
+ struct brcmstb_gisb_arb_device *gdev = dev_get_drvdata(dev);
170209 int val, ret;
171210
172211 ret = kstrtoint(buf, 10, &val);
....@@ -220,8 +259,8 @@
220259 m_name = m_fmt;
221260 }
222261
223
- pr_crit("%s: %s at 0x%llx [%c %s], core: %s\n",
224
- __func__, reason, arb_addr,
262
+ pr_crit("GISB: %s at 0x%llx [%c %s], core: %s\n",
263
+ reason, arb_addr,
225264 cap_status & ARB_ERR_CAP_STATUS_WRITE ? 'W' : 'R',
226265 cap_status & ARB_ERR_CAP_STATUS_TIMEOUT ? "timeout" : "",
227266 m_name);
....@@ -265,6 +304,41 @@
265304 static irqreturn_t brcmstb_gisb_tea_handler(int irq, void *dev_id)
266305 {
267306 brcmstb_gisb_arb_decode_addr(dev_id, "target abort");
307
+
308
+ return IRQ_HANDLED;
309
+}
310
+
311
+static irqreturn_t brcmstb_gisb_bp_handler(int irq, void *dev_id)
312
+{
313
+ struct brcmstb_gisb_arb_device *gdev = dev_id;
314
+ const char *m_name;
315
+ u32 bp_status;
316
+ u64 arb_addr;
317
+ u32 master;
318
+ char m_fmt[11];
319
+
320
+ bp_status = gisb_read(gdev, ARB_BP_CAP_STATUS);
321
+
322
+ /* Invalid captured address, bail out */
323
+ if (!(bp_status & ARB_BP_CAP_STATUS_VALID))
324
+ return IRQ_HANDLED;
325
+
326
+ /* Read the address and master */
327
+ arb_addr = gisb_read_bp_address(gdev);
328
+ master = gisb_read(gdev, ARB_BP_CAP_MASTER);
329
+
330
+ m_name = brcmstb_gisb_master_to_str(gdev, master);
331
+ if (!m_name) {
332
+ snprintf(m_fmt, sizeof(m_fmt), "0x%08x", master);
333
+ m_name = m_fmt;
334
+ }
335
+
336
+ pr_crit("GISB: breakpoint at 0x%llx [%c], core: %s\n",
337
+ arb_addr, bp_status & ARB_BP_CAP_STATUS_WRITE ? 'W' : 'R',
338
+ m_name);
339
+
340
+ /* clear the GISB error */
341
+ gisb_write(gdev, ARB_ERR_CAP_CLEAR, ARB_ERR_CAP_CLR);
268342
269343 return IRQ_HANDLED;
270344 }
....@@ -327,13 +401,14 @@
327401 struct brcmstb_gisb_arb_device *gdev;
328402 const struct of_device_id *of_id;
329403 struct resource *r;
330
- int err, timeout_irq, tea_irq;
404
+ int err, timeout_irq, tea_irq, bp_irq;
331405 unsigned int num_masters, j = 0;
332406 int i, first, last;
333407
334408 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
335409 timeout_irq = platform_get_irq(pdev, 0);
336410 tea_irq = platform_get_irq(pdev, 1);
411
+ bp_irq = platform_get_irq(pdev, 2);
337412
338413 gdev = devm_kzalloc(&pdev->dev, sizeof(*gdev), GFP_KERNEL);
339414 if (!gdev)
....@@ -365,6 +440,15 @@
365440 gdev);
366441 if (err < 0)
367442 return err;
443
+
444
+ /* Interrupt is optional */
445
+ if (bp_irq > 0) {
446
+ err = devm_request_irq(&pdev->dev, bp_irq,
447
+ brcmstb_gisb_bp_handler, 0, pdev->name,
448
+ gdev);
449
+ if (err < 0)
450
+ return err;
451
+ }
368452
369453 /* If we do not have a valid mask, assume all masters are enabled */
370454 if (of_property_read_u32(dn, "brcm,gisb-arb-master-mask",
....@@ -409,8 +493,8 @@
409493 &gisb_panic_notifier);
410494 }
411495
412
- dev_info(&pdev->dev, "registered mem: %p, irqs: %d, %d\n",
413
- gdev->base, timeout_irq, tea_irq);
496
+ dev_info(&pdev->dev, "registered irqs: %d, %d\n",
497
+ timeout_irq, tea_irq);
414498
415499 return 0;
416500 }
....@@ -418,8 +502,7 @@
418502 #ifdef CONFIG_PM_SLEEP
419503 static int brcmstb_gisb_arb_suspend(struct device *dev)
420504 {
421
- struct platform_device *pdev = to_platform_device(dev);
422
- struct brcmstb_gisb_arb_device *gdev = platform_get_drvdata(pdev);
505
+ struct brcmstb_gisb_arb_device *gdev = dev_get_drvdata(dev);
423506
424507 gdev->saved_timeout = gisb_read(gdev, ARB_TIMER);
425508
....@@ -431,8 +514,7 @@
431514 */
432515 static int brcmstb_gisb_arb_resume_noirq(struct device *dev)
433516 {
434
- struct platform_device *pdev = to_platform_device(dev);
435
- struct brcmstb_gisb_arb_device *gdev = platform_get_drvdata(pdev);
517
+ struct brcmstb_gisb_arb_device *gdev = dev_get_drvdata(dev);
436518
437519 gisb_write(gdev, gdev->saved_timeout, ARB_TIMER);
438520