1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2000-2003 Deep Blue Solutions Ltd |
4 | */ |
5 | #include <linux/types.h> |
6 | #include <linux/kernel.h> |
7 | #include <linux/init.h> |
8 | #include <linux/device.h> |
9 | #include <linux/export.h> |
10 | #include <linux/spinlock.h> |
11 | #include <linux/interrupt.h> |
12 | #include <linux/irq.h> |
13 | #include <linux/memblock.h> |
14 | #include <linux/sched.h> |
15 | #include <linux/smp.h> |
16 | #include <linux/amba/bus.h> |
17 | #include <linux/amba/serial.h> |
18 | #include <linux/io.h> |
19 | #include <linux/stat.h> |
20 | #include <linux/of.h> |
21 | #include <linux/of_address.h> |
22 | #include <linux/pgtable.h> |
23 | |
24 | #include <asm/mach-types.h> |
25 | #include <asm/mach/time.h> |
26 | |
27 | #include "integrator-hardware.h" |
28 | #include "integrator-cm.h" |
29 | #include "integrator.h" |
30 | |
31 | static DEFINE_RAW_SPINLOCK(cm_lock); |
32 | static void __iomem *cm_base; |
33 | |
34 | /** |
35 | * cm_get - get the value from the CM_CTRL register |
36 | */ |
37 | u32 cm_get(void) |
38 | { |
39 | return readl(addr: cm_base + INTEGRATOR_HDR_CTRL_OFFSET); |
40 | } |
41 | |
42 | /** |
43 | * cm_control - update the CM_CTRL register. |
44 | * @mask: bits to change |
45 | * @set: bits to set |
46 | */ |
47 | void cm_control(u32 mask, u32 set) |
48 | { |
49 | unsigned long flags; |
50 | u32 val; |
51 | |
52 | raw_spin_lock_irqsave(&cm_lock, flags); |
53 | val = readl(addr: cm_base + INTEGRATOR_HDR_CTRL_OFFSET) & ~mask; |
54 | writel(val: val | set, addr: cm_base + INTEGRATOR_HDR_CTRL_OFFSET); |
55 | raw_spin_unlock_irqrestore(&cm_lock, flags); |
56 | } |
57 | |
58 | void cm_clear_irqs(void) |
59 | { |
60 | /* disable core module IRQs */ |
61 | writel(val: 0xffffffffU, addr: cm_base + INTEGRATOR_HDR_IC_OFFSET + |
62 | IRQ_ENABLE_CLEAR); |
63 | } |
64 | |
65 | static const struct of_device_id cm_match[] = { |
66 | { .compatible = "arm,core-module-integrator" }, |
67 | { }, |
68 | }; |
69 | |
70 | void cm_init(void) |
71 | { |
72 | struct device_node *cm = of_find_matching_node(NULL, matches: cm_match); |
73 | |
74 | if (!cm) { |
75 | pr_crit("no core module node found in device tree\n" ); |
76 | return; |
77 | } |
78 | cm_base = of_iomap(node: cm, index: 0); |
79 | if (!cm_base) { |
80 | pr_crit("could not remap core module\n" ); |
81 | return; |
82 | } |
83 | cm_clear_irqs(); |
84 | } |
85 | |
86 | /* |
87 | * We need to stop things allocating the low memory; ideally we need a |
88 | * better implementation of GFP_DMA which does not assume that DMA-able |
89 | * memory starts at zero. |
90 | */ |
91 | void __init integrator_reserve(void) |
92 | { |
93 | memblock_reserve(base: PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET); |
94 | } |
95 | |