175a6faf6SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2828989adSSantosh Shilimkar /*
3828989adSSantosh Shilimkar * Keystone2 based boards and SOC related code.
4828989adSSantosh Shilimkar *
5828989adSSantosh Shilimkar * Copyright 2013 Texas Instruments, Inc.
6828989adSSantosh Shilimkar * Cyril Chemparathy <cyril@ti.com>
7828989adSSantosh Shilimkar * Santosh Shilimkar <santosh.shillimkar@ti.com>
8828989adSSantosh Shilimkar */
9*d33dbddfSAndrew Davis
10828989adSSantosh Shilimkar #include <linux/io.h>
1116fee29bSChristoph Hellwig #include <linux/dma-map-ops.h>
12828989adSSantosh Shilimkar #include <linux/init.h>
13*d33dbddfSAndrew Davis #include <linux/pm_runtime.h>
14*d33dbddfSAndrew Davis #include <linux/pm_clock.h>
15bbea06f3SSantosh Shilimkar #include <linux/memblock.h>
16*d33dbddfSAndrew Davis #include <linux/of.h>
17630c191bSRob Herring #include <linux/platform_device.h>
18828989adSSantosh Shilimkar
19828989adSSantosh Shilimkar #include <asm/setup.h>
20828989adSSantosh Shilimkar #include <asm/mach/map.h>
21828989adSSantosh Shilimkar #include <asm/mach/arch.h>
22828989adSSantosh Shilimkar #include <asm/mach/time.h>
23a9ff6961SLinus Walleij #include <asm/page.h>
245eb3da72SSantosh Shilimkar
2504a0137fSAndrew Davis #define KEYSTONE_LOW_PHYS_START 0x80000000ULL
2604a0137fSAndrew Davis #define KEYSTONE_LOW_PHYS_SIZE 0x80000000ULL /* 2G */
2704a0137fSAndrew Davis #define KEYSTONE_LOW_PHYS_END (KEYSTONE_LOW_PHYS_START + \
2804a0137fSAndrew Davis KEYSTONE_LOW_PHYS_SIZE - 1)
2904a0137fSAndrew Davis
3004a0137fSAndrew Davis #define KEYSTONE_HIGH_PHYS_START 0x800000000ULL
3104a0137fSAndrew Davis #define KEYSTONE_HIGH_PHYS_SIZE 0x400000000ULL /* 16G */
3204a0137fSAndrew Davis #define KEYSTONE_HIGH_PHYS_END (KEYSTONE_HIGH_PHYS_START + \
3304a0137fSAndrew Davis KEYSTONE_HIGH_PHYS_SIZE - 1)
3404a0137fSAndrew Davis
35*d33dbddfSAndrew Davis static struct dev_pm_domain keystone_pm_domain = {
36*d33dbddfSAndrew Davis .ops = {
37*d33dbddfSAndrew Davis USE_PM_CLK_RUNTIME_OPS
38*d33dbddfSAndrew Davis USE_PLATFORM_PM_SLEEP_OPS
39*d33dbddfSAndrew Davis },
40*d33dbddfSAndrew Davis };
41*d33dbddfSAndrew Davis
42*d33dbddfSAndrew Davis static struct pm_clk_notifier_block platform_domain_notifier = {
43*d33dbddfSAndrew Davis .pm_domain = &keystone_pm_domain,
44*d33dbddfSAndrew Davis .con_ids = { NULL },
45*d33dbddfSAndrew Davis };
46*d33dbddfSAndrew Davis
47*d33dbddfSAndrew Davis static const struct of_device_id of_keystone_table[] = {
48*d33dbddfSAndrew Davis {.compatible = "ti,k2hk"},
49*d33dbddfSAndrew Davis {.compatible = "ti,k2e"},
50*d33dbddfSAndrew Davis {.compatible = "ti,k2l"},
51*d33dbddfSAndrew Davis { /* end of list */ },
52*d33dbddfSAndrew Davis };
53*d33dbddfSAndrew Davis
keystone_pm_runtime_init(void)54*d33dbddfSAndrew Davis static int __init keystone_pm_runtime_init(void)
55*d33dbddfSAndrew Davis {
56*d33dbddfSAndrew Davis struct device_node *np;
57*d33dbddfSAndrew Davis
58*d33dbddfSAndrew Davis np = of_find_matching_node(NULL, of_keystone_table);
59*d33dbddfSAndrew Davis if (!np)
60*d33dbddfSAndrew Davis return 0;
61*d33dbddfSAndrew Davis
62*d33dbddfSAndrew Davis pm_clk_add_notifier(&platform_bus_type, &platform_domain_notifier);
63*d33dbddfSAndrew Davis
64*d33dbddfSAndrew Davis return 0;
65*d33dbddfSAndrew Davis }
66*d33dbddfSAndrew Davis
67cf141ae9SChristoph Hellwig #ifdef CONFIG_ARM_LPAE
keystone_platform_notifier(struct notifier_block * nb,unsigned long event,void * data)6814f37914SSantosh Shilimkar static int keystone_platform_notifier(struct notifier_block *nb,
6914f37914SSantosh Shilimkar unsigned long event, void *data)
7014f37914SSantosh Shilimkar {
7114f37914SSantosh Shilimkar struct device *dev = data;
7214f37914SSantosh Shilimkar
7314f37914SSantosh Shilimkar if (event != BUS_NOTIFY_ADD_DEVICE)
7414f37914SSantosh Shilimkar return NOTIFY_DONE;
7514f37914SSantosh Shilimkar
7614f37914SSantosh Shilimkar if (!dev)
7714f37914SSantosh Shilimkar return NOTIFY_BAD;
7814f37914SSantosh Shilimkar
7914f37914SSantosh Shilimkar if (!dev->of_node) {
80e0d07278SJim Quinlan int ret = dma_direct_set_offset(dev, KEYSTONE_HIGH_PHYS_START,
81e0d07278SJim Quinlan KEYSTONE_LOW_PHYS_START,
82e0d07278SJim Quinlan KEYSTONE_HIGH_PHYS_SIZE);
83e0d07278SJim Quinlan dev_err(dev, "set dma_offset%08llx%s\n",
84e0d07278SJim Quinlan KEYSTONE_HIGH_PHYS_START - KEYSTONE_LOW_PHYS_START,
85e0d07278SJim Quinlan ret ? " failed" : "");
8614f37914SSantosh Shilimkar }
8714f37914SSantosh Shilimkar return NOTIFY_OK;
8814f37914SSantosh Shilimkar }
89828989adSSantosh Shilimkar
9030b5f4d6SRussell King static struct notifier_block platform_nb = {
9130b5f4d6SRussell King .notifier_call = keystone_platform_notifier,
9230b5f4d6SRussell King };
93cf141ae9SChristoph Hellwig #endif /* CONFIG_ARM_LPAE */
9430b5f4d6SRussell King
keystone_init(void)95828989adSSantosh Shilimkar static void __init keystone_init(void)
96828989adSSantosh Shilimkar {
97cf141ae9SChristoph Hellwig #ifdef CONFIG_ARM_LPAE
98e0d07278SJim Quinlan if (PHYS_OFFSET >= KEYSTONE_HIGH_PHYS_START)
9914f37914SSantosh Shilimkar bus_register_notifier(&platform_bus_type, &platform_nb);
100cf141ae9SChristoph Hellwig #endif
10130b5f4d6SRussell King keystone_pm_runtime_init();
102828989adSSantosh Shilimkar }
103828989adSSantosh Shilimkar
keystone_pv_fixup(void)104c0b759d8SRussell King static long long __init keystone_pv_fixup(void)
1055eb3da72SSantosh Shilimkar {
106c8ca2b4bSRussell King long long offset;
107844b85ddSArnd Bergmann u64 mem_start, mem_end;
1085eb3da72SSantosh Shilimkar
109bbea06f3SSantosh Shilimkar mem_start = memblock_start_of_DRAM();
110bbea06f3SSantosh Shilimkar mem_end = memblock_end_of_DRAM();
1115eb3da72SSantosh Shilimkar
1125eb3da72SSantosh Shilimkar /* nothing to do if we are running out of the <32-bit space */
1135eb3da72SSantosh Shilimkar if (mem_start >= KEYSTONE_LOW_PHYS_START &&
1145eb3da72SSantosh Shilimkar mem_end <= KEYSTONE_LOW_PHYS_END)
115c8ca2b4bSRussell King return 0;
1165eb3da72SSantosh Shilimkar
1175eb3da72SSantosh Shilimkar if (mem_start < KEYSTONE_HIGH_PHYS_START ||
1185eb3da72SSantosh Shilimkar mem_end > KEYSTONE_HIGH_PHYS_END) {
1195eb3da72SSantosh Shilimkar pr_crit("Invalid address space for memory (%08llx-%08llx)\n",
120844b85ddSArnd Bergmann mem_start, mem_end);
121c8ca2b4bSRussell King return 0;
1225eb3da72SSantosh Shilimkar }
1235eb3da72SSantosh Shilimkar
124c8ca2b4bSRussell King offset = KEYSTONE_HIGH_PHYS_START - KEYSTONE_LOW_PHYS_START;
1255eb3da72SSantosh Shilimkar
1265eb3da72SSantosh Shilimkar /* Populate the arch idmap hook */
127981b6714SRussell King arch_phys_to_idmap_offset = -offset;
1285eb3da72SSantosh Shilimkar
129c8ca2b4bSRussell King return offset;
1305eb3da72SSantosh Shilimkar }
1315eb3da72SSantosh Shilimkar
132543c5040SUwe Kleine-König static const char *const keystone_match[] __initconst = {
13301cf228bSNishanth Menon "ti,k2hk",
13401cf228bSNishanth Menon "ti,k2e",
13501cf228bSNishanth Menon "ti,k2l",
1363b2d3dc9SNishanth Menon "ti,k2g",
1373babe306SIvan Khoronzhuk "ti,keystone",
138828989adSSantosh Shilimkar NULL,
139828989adSSantosh Shilimkar };
140828989adSSantosh Shilimkar
141828989adSSantosh Shilimkar DT_MACHINE_START(KEYSTONE, "Keystone")
142df595a9dSSantosh Shilimkar #if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
143df595a9dSSantosh Shilimkar .dma_zone_size = SZ_2G,
144df595a9dSSantosh Shilimkar #endif
145828989adSSantosh Shilimkar .init_machine = keystone_init,
146828989adSSantosh Shilimkar .dt_compat = keystone_match,
147c0b759d8SRussell King .pv_fixup = keystone_pv_fixup,
148828989adSSantosh Shilimkar MACHINE_END
149