Branch data Line data Source code
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 : 404 : 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 [ - + ]: 404 : if (!of_property_read_u32(np, "linux,revision", &val))
30 : 0 : system_rev = val;
31 [ - + ]: 404 : if (!of_property_read_u64(np, "linux,serial", &val64))
32 : 0 : system_serial_low = val64;
33 : 404 : }
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 : 36360 : 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 : 36360 : unsigned long p2b_offset = *((unsigned long *) data);
53 : :
54 [ + + ]: 36360 : if (!of_flat_dt_is_compatible(node, "brcm,bcm2708-usb"))
55 : : return 0;
56 : 404 : reg = of_get_flat_dt_prop(node, "reg", &len);
57 [ + - + - ]: 404 : 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 : 404 : map[0].virtual = (unsigned long) BCM2835_USB_VIRT_BASE;
66 : 404 : map[0].pfn = __phys_to_pfn(be32_to_cpu(reg[0]) - p2b_offset);
67 : 404 : map[0].length = be32_to_cpu(reg[1]);
68 : 404 : map[0].type = MT_DEVICE;
69 : 404 : map[1].virtual = (unsigned long) BCM2835_USB_VIRT_MPHI;
70 : 404 : map[1].pfn = __phys_to_pfn(be32_to_cpu(reg[2]) - p2b_offset);
71 : 404 : map[1].length = be32_to_cpu(reg[3]);
72 : 404 : map[1].type = MT_DEVICE;
73 : 404 : iotable_init(map, 2);
74 : :
75 : 404 : return 1;
76 : : }
77 : :
78 : 404 : 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 : 404 : root = of_get_flat_dt_root();
88 : : /* Find out how to map bus to physical address first from soc/ranges */
89 : 404 : soc = of_get_flat_dt_subnode_by_name(root, "soc");
90 [ + - ]: 404 : if (soc < 0)
91 : 0 : return;
92 : 404 : address_cells = of_get_flat_dt_prop(root, "#address-cells", &len);
93 [ + - + - ]: 404 : if (!address_cells || len < (sizeof(unsigned long)))
94 : : return;
95 : 404 : addr_cells = be32_to_cpu(address_cells[0]);
96 : 404 : ranges = of_get_flat_dt_prop(soc, "ranges", &len);
97 [ + - + - ]: 404 : if (!ranges || len < (sizeof(unsigned long) * (2 + addr_cells)))
98 : : return;
99 : 404 : 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 : 404 : 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
|