xref: /openbmc/linux/arch/arm/mach-keystone/keystone.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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