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