51c7732bebce7ff72e05afd04b5d78216686e883
[openwrt/staging/stintel.git] / target / linux / brcm2708 / patches-4.19 / 950-0198-dwc-otg-FIQ-Fix-bad-mode-in-data-abort-handler.patch
1 From f36b3119d83e03c9d0c684b8712b66a979c48124 Mon Sep 17 00:00:00 2001
2 From: Phil Elwell <phil@raspberrypi.org>
3 Date: Mon, 16 Jul 2018 14:40:13 +0100
4 Subject: [PATCH] dwc-otg: FIQ: Fix "bad mode in data abort handler"
5
6 Create a semi-static mapping for the USB registers early in the boot
7 process, before additional kernel threads are started, so all threads
8 will have the mappings from the start. This avoids the need for
9 data aborts to lazily update them.
10
11 See: https://github.com/raspberrypi/linux/issues/2450
12
13 Signed-off-by: Floris Bos <bos@je-eigen-domein.nl>
14 ---
15 arch/arm/mach-bcm/board_bcm2835.c | 69 +++++++++++++++++++++++
16 drivers/usb/host/dwc_otg/dwc_otg_driver.c | 2 +-
17 2 files changed, 70 insertions(+), 1 deletion(-)
18
19 --- a/arch/arm/mach-bcm/board_bcm2835.c
20 +++ b/arch/arm/mach-bcm/board_bcm2835.c
21 @@ -15,6 +15,7 @@
22 #include <linux/init.h>
23 #include <linux/irqchip.h>
24 #include <linux/of_address.h>
25 +#include <linux/of_fdt.h>
26 #include <asm/system_info.h>
27
28 #include <asm/mach/arch.h>
29 @@ -22,6 +23,9 @@
30
31 #include "platsmp.h"
32
33 +#define BCM2835_USB_VIRT_BASE 0xf0980000
34 +#define BCM2835_USB_VIRT_MPHI 0xf0006000
35 +
36 static void __init bcm2835_init(void)
37 {
38 struct device_node *np = of_find_node_by_path("/system");
39 @@ -34,6 +38,70 @@ static void __init bcm2835_init(void)
40 system_serial_low = val64;
41 }
42
43 +/*
44 + * We need to map registers that are going to be accessed by the FIQ
45 + * very early, before any kernel threads are spawned. Because if done
46 + * later, the mapping tables are not updated instantly but lazily upon
47 + * first access through a data abort handler. While that is fine
48 + * when executing regular kernel code, if the first access in a specific
49 + * thread happens while running FIQ code this will result in a panic.
50 + *
51 + * For more background see the following old mailing list thread:
52 + * https://www.spinics.net/lists/arm-kernel/msg325250.html
53 + */
54 +static int __init bcm2835_map_usb(unsigned long node, const char *uname,
55 + int depth, void *data)
56 +{
57 + struct map_desc map[2];
58 + const __be32 *reg;
59 + int len;
60 + unsigned long p2b_offset = *((unsigned long *) data);
61 +
62 + if (!of_flat_dt_is_compatible(node, "brcm,bcm2708-usb"))
63 + return 0;
64 + reg = of_get_flat_dt_prop(node, "reg", &len);
65 + if (!reg || len != (sizeof(unsigned long) * 4))
66 + return 0;
67 +
68 + /* Use information about the physical addresses of the
69 + * registers from the device tree, but use legacy
70 + * iotable_init() static mapping function to map them,
71 + * as ioremap() is not functional at this stage in boot.
72 + */
73 + map[0].virtual = (unsigned long) BCM2835_USB_VIRT_BASE;
74 + map[0].pfn = __phys_to_pfn(be32_to_cpu(reg[0]) - p2b_offset);
75 + map[0].length = be32_to_cpu(reg[1]);
76 + map[0].type = MT_DEVICE;
77 + map[1].virtual = (unsigned long) BCM2835_USB_VIRT_MPHI;
78 + map[1].pfn = __phys_to_pfn(be32_to_cpu(reg[2]) - p2b_offset);
79 + map[1].length = be32_to_cpu(reg[3]);
80 + map[1].type = MT_DEVICE;
81 + iotable_init(map, 2);
82 +
83 + return 1;
84 +}
85 +
86 +static void __init bcm2835_map_io(void)
87 +{
88 + const __be32 *ranges;
89 + int soc, len;
90 + unsigned long p2b_offset;
91 +
92 + debug_ll_io_init();
93 +
94 + /* Find out how to map bus to physical address first from soc/ranges */
95 + soc = of_get_flat_dt_subnode_by_name(of_get_flat_dt_root(), "soc");
96 + if (soc < 0)
97 + return;
98 + ranges = of_get_flat_dt_prop(soc, "ranges", &len);
99 + if (!ranges || len < (sizeof(unsigned long) * 3))
100 + return;
101 + p2b_offset = be32_to_cpu(ranges[0]) - be32_to_cpu(ranges[1]);
102 +
103 + /* Now search for bcm2708-usb node in device tree */
104 + of_scan_flat_dt(bcm2835_map_usb, &p2b_offset);
105 +}
106 +
107 static const char * const bcm2835_compat[] = {
108 #ifdef CONFIG_ARCH_MULTI_V6
109 "brcm,bcm2835",
110 @@ -46,6 +114,7 @@ static const char * const bcm2835_compat
111 };
112
113 DT_MACHINE_START(BCM2835, "BCM2835")
114 + .map_io = bcm2835_map_io,
115 .init_machine = bcm2835_init,
116 .dt_compat = bcm2835_compat,
117 .smp = smp_ops(bcm2836_smp_ops),
118 --- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
119 +++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
120 @@ -837,7 +837,7 @@ static int dwc_otg_driver_probe(
121 retval = -ENOMEM;
122 goto fail;
123 }
124 - dev_dbg(&_dev->dev, "base=0x%08x\n",
125 + dev_info(&_dev->dev, "base=0x%08x\n",
126 (unsigned)dwc_otg_device->os_dep.base);
127 #endif
128