1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Keystone2 based boards and SOC related code. |
4 | * |
5 | * Copyright 2013 Texas Instruments, Inc. |
6 | * Cyril Chemparathy <cyril@ti.com> |
7 | * Santosh Shilimkar <santosh.shillimkar@ti.com> |
8 | */ |
9 | |
10 | #include <linux/io.h> |
11 | #include <linux/dma-map-ops.h> |
12 | #include <linux/init.h> |
13 | #include <linux/pm_runtime.h> |
14 | #include <linux/pm_clock.h> |
15 | #include <linux/memblock.h> |
16 | #include <linux/of.h> |
17 | #include <linux/platform_device.h> |
18 | |
19 | #include <asm/setup.h> |
20 | #include <asm/mach/map.h> |
21 | #include <asm/mach/arch.h> |
22 | #include <asm/mach/time.h> |
23 | #include <asm/page.h> |
24 | |
25 | #define KEYSTONE_LOW_PHYS_START 0x80000000ULL |
26 | #define KEYSTONE_LOW_PHYS_SIZE 0x80000000ULL /* 2G */ |
27 | #define KEYSTONE_LOW_PHYS_END (KEYSTONE_LOW_PHYS_START + \ |
28 | KEYSTONE_LOW_PHYS_SIZE - 1) |
29 | |
30 | #define KEYSTONE_HIGH_PHYS_START 0x800000000ULL |
31 | #define KEYSTONE_HIGH_PHYS_SIZE 0x400000000ULL /* 16G */ |
32 | #define KEYSTONE_HIGH_PHYS_END (KEYSTONE_HIGH_PHYS_START + \ |
33 | KEYSTONE_HIGH_PHYS_SIZE - 1) |
34 | |
35 | static struct dev_pm_domain keystone_pm_domain = { |
36 | .ops = { |
37 | USE_PM_CLK_RUNTIME_OPS |
38 | USE_PLATFORM_PM_SLEEP_OPS |
39 | }, |
40 | }; |
41 | |
42 | static struct pm_clk_notifier_block platform_domain_notifier = { |
43 | .pm_domain = &keystone_pm_domain, |
44 | .con_ids = { NULL }, |
45 | }; |
46 | |
47 | static const struct of_device_id of_keystone_table[] = { |
48 | {.compatible = "ti,k2hk" }, |
49 | {.compatible = "ti,k2e" }, |
50 | {.compatible = "ti,k2l" }, |
51 | { /* end of list */ }, |
52 | }; |
53 | |
54 | static int __init keystone_pm_runtime_init(void) |
55 | { |
56 | struct device_node *np; |
57 | |
58 | np = of_find_matching_node(NULL, matches: of_keystone_table); |
59 | if (!np) |
60 | return 0; |
61 | |
62 | pm_clk_add_notifier(bus: &platform_bus_type, clknb: &platform_domain_notifier); |
63 | |
64 | return 0; |
65 | } |
66 | |
67 | #ifdef CONFIG_ARM_LPAE |
68 | static int keystone_platform_notifier(struct notifier_block *nb, |
69 | unsigned long event, void *data) |
70 | { |
71 | struct device *dev = data; |
72 | |
73 | if (event != BUS_NOTIFY_ADD_DEVICE) |
74 | return NOTIFY_DONE; |
75 | |
76 | if (!dev) |
77 | return NOTIFY_BAD; |
78 | |
79 | if (!dev->of_node) { |
80 | int ret = dma_direct_set_offset(dev, KEYSTONE_HIGH_PHYS_START, |
81 | KEYSTONE_LOW_PHYS_START, |
82 | KEYSTONE_HIGH_PHYS_SIZE); |
83 | dev_err(dev, "set dma_offset%08llx%s\n" , |
84 | KEYSTONE_HIGH_PHYS_START - KEYSTONE_LOW_PHYS_START, |
85 | ret ? " failed" : "" ); |
86 | } |
87 | return NOTIFY_OK; |
88 | } |
89 | |
90 | static struct notifier_block platform_nb = { |
91 | .notifier_call = keystone_platform_notifier, |
92 | }; |
93 | #endif /* CONFIG_ARM_LPAE */ |
94 | |
95 | static void __init keystone_init(void) |
96 | { |
97 | #ifdef CONFIG_ARM_LPAE |
98 | if (PHYS_OFFSET >= KEYSTONE_HIGH_PHYS_START) |
99 | bus_register_notifier(&platform_bus_type, &platform_nb); |
100 | #endif |
101 | keystone_pm_runtime_init(); |
102 | } |
103 | |
104 | static long long __init keystone_pv_fixup(void) |
105 | { |
106 | long long offset; |
107 | u64 mem_start, mem_end; |
108 | |
109 | mem_start = memblock_start_of_DRAM(); |
110 | mem_end = memblock_end_of_DRAM(); |
111 | |
112 | /* nothing to do if we are running out of the <32-bit space */ |
113 | if (mem_start >= KEYSTONE_LOW_PHYS_START && |
114 | mem_end <= KEYSTONE_LOW_PHYS_END) |
115 | return 0; |
116 | |
117 | if (mem_start < KEYSTONE_HIGH_PHYS_START || |
118 | mem_end > KEYSTONE_HIGH_PHYS_END) { |
119 | pr_crit("Invalid address space for memory (%08llx-%08llx)\n" , |
120 | mem_start, mem_end); |
121 | return 0; |
122 | } |
123 | |
124 | offset = KEYSTONE_HIGH_PHYS_START - KEYSTONE_LOW_PHYS_START; |
125 | |
126 | /* Populate the arch idmap hook */ |
127 | arch_phys_to_idmap_offset = -offset; |
128 | |
129 | return offset; |
130 | } |
131 | |
132 | static const char *const keystone_match[] __initconst = { |
133 | "ti,k2hk" , |
134 | "ti,k2e" , |
135 | "ti,k2l" , |
136 | "ti,k2g" , |
137 | "ti,keystone" , |
138 | NULL, |
139 | }; |
140 | |
141 | DT_MACHINE_START(KEYSTONE, "Keystone" ) |
142 | #if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE) |
143 | .dma_zone_size = SZ_2G, |
144 | #endif |
145 | .init_machine = keystone_init, |
146 | .dt_compat = keystone_match, |
147 | .pv_fixup = keystone_pv_fixup, |
148 | MACHINE_END |
149 | |