1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2008-2009 ST-Ericsson SA |
4 | * |
5 | * Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com> |
6 | */ |
7 | #include <linux/types.h> |
8 | #include <linux/init.h> |
9 | #include <linux/device.h> |
10 | #include <linux/amba/bus.h> |
11 | #include <linux/interrupt.h> |
12 | #include <linux/irq.h> |
13 | #include <linux/irqchip.h> |
14 | #include <linux/irqchip/arm-gic.h> |
15 | #include <linux/mfd/dbx500-prcmu.h> |
16 | #include <linux/platform_data/arm-ux500-pm.h> |
17 | #include <linux/platform_device.h> |
18 | #include <linux/io.h> |
19 | #include <linux/of.h> |
20 | #include <linux/of_address.h> |
21 | #include <linux/of_platform.h> |
22 | #include <linux/regulator/machine.h> |
23 | |
24 | #include <asm/outercache.h> |
25 | #include <asm/hardware/cache-l2x0.h> |
26 | #include <asm/mach/map.h> |
27 | #include <asm/mach/arch.h> |
28 | |
29 | static int __init ux500_l2x0_unlock(void) |
30 | { |
31 | int i; |
32 | struct device_node *np; |
33 | void __iomem *l2x0_base; |
34 | |
35 | np = of_find_compatible_node(NULL, NULL, compat: "arm,pl310-cache" ); |
36 | l2x0_base = of_iomap(node: np, index: 0); |
37 | of_node_put(node: np); |
38 | if (!l2x0_base) |
39 | return -ENODEV; |
40 | |
41 | /* |
42 | * Unlock Data and Instruction Lock if locked. Ux500 U-Boot versions |
43 | * apparently locks both caches before jumping to the kernel. The |
44 | * l2x0 core will not touch the unlock registers if the l2x0 is |
45 | * already enabled, so we do it right here instead. The PL310 has |
46 | * 8 sets of registers, one per possible CPU. |
47 | */ |
48 | for (i = 0; i < 8; i++) { |
49 | writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_D_BASE + |
50 | i * L2X0_LOCKDOWN_STRIDE); |
51 | writel_relaxed(0x0, l2x0_base + L2X0_LOCKDOWN_WAY_I_BASE + |
52 | i * L2X0_LOCKDOWN_STRIDE); |
53 | } |
54 | iounmap(addr: l2x0_base); |
55 | return 0; |
56 | } |
57 | |
58 | static void ux500_l2c310_write_sec(unsigned long val, unsigned reg) |
59 | { |
60 | /* |
61 | * We can't write to secure registers as we are in non-secure |
62 | * mode, until we have some SMI service available. |
63 | */ |
64 | } |
65 | |
66 | /* |
67 | * FIXME: Should we set up the GPIO domain here? |
68 | * |
69 | * The problem is that we cannot put the interrupt resources into the platform |
70 | * device until the irqdomain has been added. Right now, we set the GIC interrupt |
71 | * domain from init_irq(), then load the gpio driver from |
72 | * core_initcall(nmk_gpio_init) and add the platform devices from |
73 | * arch_initcall(customize_machine). |
74 | * |
75 | * This feels fragile because it depends on the gpio device getting probed |
76 | * _before_ any device uses the gpio interrupts. |
77 | */ |
78 | static void __init ux500_init_irq(void) |
79 | { |
80 | struct device_node *np; |
81 | struct resource r; |
82 | |
83 | irqchip_init(); |
84 | prcmu_early_init(); |
85 | np = of_find_compatible_node(NULL, NULL, compat: "stericsson,db8500-prcmu" ); |
86 | of_address_to_resource(dev: np, index: 0, r: &r); |
87 | of_node_put(node: np); |
88 | if (!r.start) { |
89 | pr_err("could not find PRCMU base resource\n" ); |
90 | return; |
91 | } |
92 | ux500_pm_init(phy_base: r.start, size: r.end-r.start); |
93 | |
94 | /* Unlock before init */ |
95 | ux500_l2x0_unlock(); |
96 | outer_cache.write_sec = ux500_l2c310_write_sec; |
97 | } |
98 | |
99 | static void ux500_restart(enum reboot_mode mode, const char *cmd) |
100 | { |
101 | local_irq_disable(); |
102 | local_fiq_disable(); |
103 | |
104 | prcmu_system_reset(reset_code: 0); |
105 | } |
106 | |
107 | static const struct of_device_id u8500_local_bus_nodes[] = { |
108 | /* only create devices below soc node */ |
109 | { .compatible = "stericsson,db8500" , }, |
110 | { .compatible = "simple-bus" }, |
111 | { }, |
112 | }; |
113 | |
114 | static void __init u8500_init_machine(void) |
115 | { |
116 | of_platform_populate(NULL, matches: u8500_local_bus_nodes, |
117 | NULL, NULL); |
118 | } |
119 | |
120 | static const char * stericsson_dt_platform_compat[] = { |
121 | "st-ericsson,u8500" , |
122 | "st-ericsson,u9500" , |
123 | NULL, |
124 | }; |
125 | |
126 | DT_MACHINE_START(U8500_DT, "ST-Ericsson Ux5x0 platform (Device Tree Support)" ) |
127 | .l2c_aux_val = 0, |
128 | .l2c_aux_mask = ~0, |
129 | .init_irq = ux500_init_irq, |
130 | .init_machine = u8500_init_machine, |
131 | .dt_compat = stericsson_dt_platform_compat, |
132 | .restart = ux500_restart, |
133 | MACHINE_END |
134 | |