summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-keystone/keystone.c
blob: f63671a3024c3e92f2ffb4c93ea0edb6399d8561 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Keystone2 based boards and SOC related code.
 *
 * Copyright 2013 Texas Instruments, Inc.
 *	Cyril Chemparathy <cyril@ti.com>
 *	Santosh Shilimkar <santosh.shillimkar@ti.com>
 */

#include <linux/io.h>
#include <linux/dma-map-ops.h>
#include <linux/init.h>
#include <linux/pm_runtime.h>
#include <linux/pm_clock.h>
#include <linux/memblock.h>
#include <linux/of.h>
#include <linux/platform_device.h>

#include <asm/setup.h>
#include <asm/mach/map.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <asm/page.h>

#define KEYSTONE_LOW_PHYS_START		0x80000000ULL
#define KEYSTONE_LOW_PHYS_SIZE		0x80000000ULL /* 2G */
#define KEYSTONE_LOW_PHYS_END		(KEYSTONE_LOW_PHYS_START + \
					 KEYSTONE_LOW_PHYS_SIZE - 1)

#define KEYSTONE_HIGH_PHYS_START	0x800000000ULL
#define KEYSTONE_HIGH_PHYS_SIZE		0x400000000ULL	/* 16G */
#define KEYSTONE_HIGH_PHYS_END		(KEYSTONE_HIGH_PHYS_START + \
					 KEYSTONE_HIGH_PHYS_SIZE - 1)

static struct dev_pm_domain keystone_pm_domain = {
	.ops = {
		USE_PM_CLK_RUNTIME_OPS
		USE_PLATFORM_PM_SLEEP_OPS
	},
};

static struct pm_clk_notifier_block platform_domain_notifier = {
	.pm_domain = &keystone_pm_domain,
	.con_ids = { NULL },
};

static const struct of_device_id of_keystone_table[] = {
	{.compatible = "ti,k2hk"},
	{.compatible = "ti,k2e"},
	{.compatible = "ti,k2l"},
	{ /* end of list */ },
};

static int __init keystone_pm_runtime_init(void)
{
	struct device_node *np;

	np = of_find_matching_node(NULL, of_keystone_table);
	if (!np)
		return 0;

	pm_clk_add_notifier(&platform_bus_type, &platform_domain_notifier);

	return 0;
}

#ifdef CONFIG_ARM_LPAE
static int keystone_platform_notifier(struct notifier_block *nb,
				      unsigned long event, void *data)
{
	struct device *dev = data;

	if (event != BUS_NOTIFY_ADD_DEVICE)
		return NOTIFY_DONE;

	if (!dev)
		return NOTIFY_BAD;

	if (!dev->of_node) {
		int ret = dma_direct_set_offset(dev, KEYSTONE_HIGH_PHYS_START,
						KEYSTONE_LOW_PHYS_START,
						KEYSTONE_HIGH_PHYS_SIZE);
		dev_err(dev, "set dma_offset%08llx%s\n",
			KEYSTONE_HIGH_PHYS_START - KEYSTONE_LOW_PHYS_START,
			ret ? " failed" : "");
	}
	return NOTIFY_OK;
}

static struct notifier_block platform_nb = {
	.notifier_call = keystone_platform_notifier,
};
#endif /* CONFIG_ARM_LPAE */

static void __init keystone_init(void)
{
#ifdef CONFIG_ARM_LPAE
	if (PHYS_OFFSET >= KEYSTONE_HIGH_PHYS_START)
		bus_register_notifier(&platform_bus_type, &platform_nb);
#endif
	keystone_pm_runtime_init();
}

static long long __init keystone_pv_fixup(void)
{
	long long offset;
	u64 mem_start, mem_end;

	mem_start = memblock_start_of_DRAM();
	mem_end = memblock_end_of_DRAM();

	/* nothing to do if we are running out of the <32-bit space */
	if (mem_start >= KEYSTONE_LOW_PHYS_START &&
	    mem_end   <= KEYSTONE_LOW_PHYS_END)
		return 0;

	if (mem_start < KEYSTONE_HIGH_PHYS_START ||
	    mem_end   > KEYSTONE_HIGH_PHYS_END) {
		pr_crit("Invalid address space for memory (%08llx-%08llx)\n",
		        mem_start, mem_end);
		return 0;
	}

	offset = KEYSTONE_HIGH_PHYS_START - KEYSTONE_LOW_PHYS_START;

	/* Populate the arch idmap hook */
	arch_phys_to_idmap_offset = -offset;

	return offset;
}

static const char *const keystone_match[] __initconst = {
	"ti,k2hk",
	"ti,k2e",
	"ti,k2l",
	"ti,k2g",
	"ti,keystone",
	NULL,
};

DT_MACHINE_START(KEYSTONE, "Keystone")
#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
	.dma_zone_size	= SZ_2G,
#endif
	.init_machine	= keystone_init,
	.dt_compat	= keystone_match,
	.pv_fixup	= keystone_pv_fixup,
MACHINE_END