aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-hisi/hisilicon.c
blob: 9610f7db4067cea2758b4946388dcafa068f3413 (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
149
150
151
152
153
154
155
156
157
158
159
160
161
/*
 * (Hisilicon's SoC based) flattened device tree enabled machine
 *
 * Copyright (c) 2012-2013 Hisilicon Ltd.
 * Copyright (c) 2012-2013 Linaro Ltd.
 *
 * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
*/

#include <linux/ahci_platform.h>
#include <linux/clk-provider.h>
#include <linux/clocksource.h>
#include <linux/irqchip.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>

#include <asm/dma-iommu.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/proc-fns.h>

#include <asm/mach/arch.h>
#include <asm/mach/map.h>

#include "core.h"

#define HI3620_SYSCTRL_PHYS_BASE		0xfc802000
#define HI3620_SYSCTRL_VIRT_BASE		0xfe802000

/*
 * This table is only for optimization. Since ioremap() could always share
 * the same mapping if it's defined as static IO mapping.
 *
 * Without this table, system could also work. The cost is some virtual address
 * spaces wasted since ioremap() may be called multi times for the same
 * IO space.
 */
static struct map_desc hi3620_io_desc[] __initdata = {
	{
		/* sysctrl */
		.pfn		= __phys_to_pfn(HI3620_SYSCTRL_PHYS_BASE),
		.virtual	= HI3620_SYSCTRL_VIRT_BASE,
		.length		= 0x1000,
		.type		= MT_DEVICE,
	},
};

static void __init hi3620_map_io(void)
{
	debug_ll_io_init();
	iotable_init(hi3620_io_desc, ARRAY_SIZE(hi3620_io_desc));
}

static void __init hi3xxx_init(void)
{
	l2x0_of_init(0, ~0);
	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}

static void hi3xxx_restart(enum reboot_mode mode, const char *cmd)
{
	struct device_node *np;
	void __iomem *base;
	int offset;

	np = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
	if (!np) {
		pr_err("failed to find hisilicon,sysctrl node\n");
		return;
	}
	base = of_iomap(np, 0);
	if (!base) {
		pr_err("failed to map address in hisilicon,sysctrl node\n");
		return;
	}
	if (of_property_read_u32(np, "reboot-offset", &offset) < 0) {
		pr_err("failed to find reboot-offset property\n");
		return;
	}
	writel_relaxed(0xdeadbeef, base + offset);

	while (1)
		cpu_do_idle();
}

static const char *hi3xxx_compat[] __initconst = {
	"hisilicon,hi3620-hi4511",
	NULL,
};

DT_MACHINE_START(HI3620, "Hisilicon Hi3620 (Flattened Device Tree)")
	.map_io		= hi3620_map_io,
	.dt_compat	= hi3xxx_compat,
	.smp		= smp_ops(hi3xxx_smp_ops),
	.init_machine	= hi3xxx_init,
	.restart	= hi3xxx_restart,
MACHINE_END

#ifdef CONFIG_ARCH_HIP04
static const char *hip04_compat[] __initconst = {
	"hisilicon,hip04-d01",
	NULL,
};

#ifdef CONFIG_ARM_SMMU
#define HIP04_AHCI_IOVA_START		0x20000000
#define HIP04_AHCI_IOVA_SIZE		0x8000000

static int hip04_ahci_init(struct device *dev, void __iomem *addr)
{
	struct dma_iommu_mapping *mapping;
	int ret;

	mapping = arm_iommu_create_mapping(&platform_bus_type,
					   HIP04_AHCI_IOVA_START,
					   HIP04_AHCI_IOVA_SIZE);
	if (IS_ERR(mapping))
		return PTR_ERR(mapping);

	ret = arm_iommu_attach_device(dev, mapping);
	return ret;
}

static void hip04_ahci_exit(struct device *dev)
{
	struct dma_iommu_mapping *mapping;

	mapping = to_dma_iommu_mapping(dev);
	arm_iommu_detach_device(dev);
	arm_iommu_release_mapping(mapping);
}

static struct ahci_platform_data hip04_ahci_pdata = {
	.init	= hip04_ahci_init,
	.exit	= hip04_ahci_exit,
};

static const struct of_dev_auxdata hip04_auxdata_lookup[] = {
	OF_DEV_AUXDATA("hisilicon,hisi-ahci", 0xea000000, "ahci",
			&hip04_ahci_pdata),
	{}
};

static void __init hip04_init_machine(void)
{
	of_platform_populate(NULL, of_default_bus_match_table,
			     hip04_auxdata_lookup, NULL);
}
#endif

DT_MACHINE_START(HIP04, "Hisilicon HiP04 (Flattened Device Tree)")
	.dt_compat	= hip04_compat,
	.smp_init	= smp_init_ops(hip04_smp_init_ops),
#ifdef CONFIG_ARM_SMMU
	.init_machine	= hip04_init_machine,
#endif
MACHINE_END
#endif