Merge tag 'v5.15.57' into rpi-5.15.y
[platform/kernel/linux-rpi.git] / arch / arm / mach-bcm / board_bcm2835.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2010 Broadcom
4  */
5
6 #include <linux/init.h>
7 #include <linux/irqchip.h>
8 #include <linux/mm.h>
9 #include <linux/of_address.h>
10 #include <linux/of_fdt.h>
11 #include <asm/system_info.h>
12
13 #include <asm/mach/arch.h>
14 #include <asm/mach/map.h>
15 #include <asm/memory.h>
16 #include <asm/pgtable.h>
17
18 #include "platsmp.h"
19
20 #define BCM2835_USB_VIRT_BASE   (VMALLOC_START)
21 #define BCM2835_USB_VIRT_MPHI   (VMALLOC_START + 0x10000)
22
23 static void __init bcm2835_init(void)
24 {
25         struct device_node *np = of_find_node_by_path("/system");
26         u32 val;
27         u64 val64;
28
29         if (!of_property_read_u32(np, "linux,revision", &val))
30                 system_rev = val;
31         if (!of_property_read_u64(np, "linux,serial", &val64))
32                 system_serial_low = val64;
33 }
34
35 /*
36  * We need to map registers that are going to be accessed by the FIQ
37  * very early, before any kernel threads are spawned. Because if done
38  * later, the mapping tables are not updated instantly but lazily upon
39  * first access through a data abort handler. While that is fine
40  * when executing regular kernel code, if the first access in a specific
41  * thread happens while running FIQ code this will result in a panic.
42  *
43  * For more background see the following old mailing list thread:
44  * https://www.spinics.net/lists/arm-kernel/msg325250.html
45  */
46 static int __init bcm2835_map_usb(unsigned long node, const char *uname,
47                                         int depth, void *data)
48 {
49         struct map_desc map[2];
50         const __be32 *reg;
51         int len;
52         unsigned long p2b_offset = *((unsigned long *) data);
53
54         if (!of_flat_dt_is_compatible(node, "brcm,bcm2708-usb"))
55                 return 0;
56         reg = of_get_flat_dt_prop(node, "reg", &len);
57         if (!reg || len != (sizeof(unsigned long) * 4))
58                 return 0;
59
60         /* Use information about the physical addresses of the
61          * registers from the device tree, but use legacy
62          * iotable_init() static mapping function to map them,
63          * as ioremap() is not functional at this stage in boot.
64          */
65         map[0].virtual = (unsigned long) BCM2835_USB_VIRT_BASE;
66         map[0].pfn = __phys_to_pfn(be32_to_cpu(reg[0]) - p2b_offset);
67         map[0].length = be32_to_cpu(reg[1]);
68         map[0].type = MT_DEVICE;
69         map[1].virtual = (unsigned long) BCM2835_USB_VIRT_MPHI;
70         map[1].pfn = __phys_to_pfn(be32_to_cpu(reg[2]) - p2b_offset);
71         map[1].length = be32_to_cpu(reg[3]);
72         map[1].type = MT_DEVICE;
73                 iotable_init(map, 2);
74
75         return 1;
76 }
77
78 static void __init bcm2835_map_io(void)
79 {
80         const __be32 *ranges, *address_cells;
81         unsigned long root, addr_cells;
82         int soc, len;
83         unsigned long p2b_offset;
84
85         debug_ll_io_init();
86
87         root = of_get_flat_dt_root();
88         /* Find out how to map bus to physical address first from soc/ranges */
89         soc = of_get_flat_dt_subnode_by_name(root, "soc");
90         if (soc < 0)
91                 return;
92         address_cells = of_get_flat_dt_prop(root, "#address-cells", &len);
93         if (!address_cells || len < (sizeof(unsigned long)))
94                 return;
95         addr_cells = be32_to_cpu(address_cells[0]);
96         ranges = of_get_flat_dt_prop(soc, "ranges", &len);
97         if (!ranges || len < (sizeof(unsigned long) * (2 + addr_cells)))
98                 return;
99         p2b_offset = be32_to_cpu(ranges[0]) - be32_to_cpu(ranges[addr_cells]);
100
101         /* Now search for bcm2708-usb node in device tree */
102         of_scan_flat_dt(bcm2835_map_usb, &p2b_offset);
103 }
104
105 static const char * const bcm2835_compat[] = {
106 #ifdef CONFIG_ARCH_MULTI_V6
107         "brcm,bcm2835",
108 #endif
109 #ifdef CONFIG_ARCH_MULTI_V7
110         "brcm,bcm2836",
111         "brcm,bcm2837",
112 #endif
113         NULL
114 };
115
116 DT_MACHINE_START(BCM2835, "BCM2835")
117         .map_io = bcm2835_map_io,
118         .init_machine = bcm2835_init,
119         .dt_compat = bcm2835_compat,
120         .smp = smp_ops(bcm2836_smp_ops),
121 MACHINE_END
122
123 static const char * const bcm2711_compat[] = {
124 #ifdef CONFIG_ARCH_MULTI_V7
125         "brcm,bcm2711",
126 #endif
127         NULL
128 };
129
130 DT_MACHINE_START(BCM2711, "BCM2711")
131 #if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
132         .dma_zone_size  = SZ_1G,
133 #endif
134         .map_io = bcm2835_map_io,
135         .init_machine = bcm2835_init,
136         .dt_compat = bcm2711_compat,
137         .smp = smp_ops(bcm2836_smp_ops),
138 MACHINE_END