19952f691SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2220e6cf7SRob Herring /*
3220e6cf7SRob Herring  * Copyright 2010-2011 Calxeda, Inc.
4220e6cf7SRob Herring  */
5220e6cf7SRob Herring #include <linux/clk.h>
6220e6cf7SRob Herring #include <linux/clkdev.h>
70583fe47SRob Herring #include <linux/clocksource.h>
80a0f0d8bSChristoph Hellwig #include <linux/dma-map-ops.h>
938431148SRob Herring #include <linux/input.h>
10220e6cf7SRob Herring #include <linux/io.h>
110529e315SRob Herring #include <linux/irqchip.h>
12f2fc42b6SSuman Anna #include <linux/pl320-ipc.h>
13220e6cf7SRob Herring #include <linux/of.h>
14220e6cf7SRob Herring #include <linux/of_irq.h>
15220e6cf7SRob Herring #include <linux/of_address.h>
1638431148SRob Herring #include <linux/reboot.h>
171dc737c4SRob Herring #include <linux/amba/bus.h>
1860a66e37SDaniel Lezcano #include <linux/platform_device.h>
19be120397SMark Rutland #include <linux/psci.h>
20220e6cf7SRob Herring 
21220e6cf7SRob Herring #include <asm/hardware/cache-l2x0.h>
22220e6cf7SRob Herring #include <asm/mach/arch.h>
2352530343SRob Herring #include <asm/mach/map.h>
24220e6cf7SRob Herring 
25220e6cf7SRob Herring #include "core.h"
26220e6cf7SRob Herring #include "sysregs.h"
27220e6cf7SRob Herring 
28220e6cf7SRob Herring void __iomem *sregs_base;
297a2848d3SRob Herring void __iomem *scu_base_addr;
30220e6cf7SRob Herring 
highbank_scu_map_io(void)31220e6cf7SRob Herring static void __init highbank_scu_map_io(void)
32220e6cf7SRob Herring {
33220e6cf7SRob Herring 	unsigned long base;
34220e6cf7SRob Herring 
35220e6cf7SRob Herring 	/* Get SCU base */
36220e6cf7SRob Herring 	asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
37220e6cf7SRob Herring 
387a2848d3SRob Herring 	scu_base_addr = ioremap(base, SZ_4K);
39220e6cf7SRob Herring }
40220e6cf7SRob Herring 
41220e6cf7SRob Herring 
highbank_l2c310_write_sec(unsigned long val,unsigned reg)420074fb2cSRussell King static void highbank_l2c310_write_sec(unsigned long val, unsigned reg)
438e56130dSRob Herring {
440074fb2cSRussell King 	if (reg == L2X0_CTRL)
450074fb2cSRussell King 		highbank_smc1(0x102, val);
460074fb2cSRussell King 	else
470074fb2cSRussell King 		WARN_ONCE(1, "Highbank L2C310: ignoring write to reg 0x%x\n",
480074fb2cSRussell King 			  reg);
498e56130dSRob Herring }
508e56130dSRob Herring 
highbank_init_irq(void)51220e6cf7SRob Herring static void __init highbank_init_irq(void)
52220e6cf7SRob Herring {
530529e315SRob Herring 	irqchip_init();
548e56130dSRob Herring 
557a2848d3SRob Herring 	if (of_find_compatible_node(NULL, NULL, "arm,cortex-a9"))
567a2848d3SRob Herring 		highbank_scu_map_io();
57220e6cf7SRob Herring }
58220e6cf7SRob Herring 
highbank_power_off(void)59220e6cf7SRob Herring static void highbank_power_off(void)
60220e6cf7SRob Herring {
61c05ee88fSRob Herring 	highbank_set_pwr_shutdown();
62220e6cf7SRob Herring 
63220e6cf7SRob Herring 	while (1)
64220e6cf7SRob Herring 		cpu_do_idle();
65220e6cf7SRob Herring }
66220e6cf7SRob Herring 
highbank_platform_notifier(struct notifier_block * nb,unsigned long event,void * __dev)671dc737c4SRob Herring static int highbank_platform_notifier(struct notifier_block *nb,
681dc737c4SRob Herring 				  unsigned long event, void *__dev)
691dc737c4SRob Herring {
701dc737c4SRob Herring 	struct resource *res;
711dc737c4SRob Herring 	int reg = -1;
72e64bf95eSRob Herring 	u32 val;
731dc737c4SRob Herring 	struct device *dev = __dev;
741dc737c4SRob Herring 
751dc737c4SRob Herring 	if (event != BUS_NOTIFY_ADD_DEVICE)
761dc737c4SRob Herring 		return NOTIFY_DONE;
771dc737c4SRob Herring 
781dc737c4SRob Herring 	if (of_device_is_compatible(dev->of_node, "calxeda,hb-ahci"))
791dc737c4SRob Herring 		reg = 0xc;
801dc737c4SRob Herring 	else if (of_device_is_compatible(dev->of_node, "calxeda,hb-sdhci"))
811dc737c4SRob Herring 		reg = 0x18;
821dc737c4SRob Herring 	else if (of_device_is_compatible(dev->of_node, "arm,pl330"))
831dc737c4SRob Herring 		reg = 0x20;
841dc737c4SRob Herring 	else if (of_device_is_compatible(dev->of_node, "calxeda,hb-xgmac")) {
851dc737c4SRob Herring 		res = platform_get_resource(to_platform_device(dev),
861dc737c4SRob Herring 					    IORESOURCE_MEM, 0);
871dc737c4SRob Herring 		if (res) {
881dc737c4SRob Herring 			if (res->start == 0xfff50000)
891dc737c4SRob Herring 				reg = 0;
901dc737c4SRob Herring 			else if (res->start == 0xfff51000)
911dc737c4SRob Herring 				reg = 4;
921dc737c4SRob Herring 		}
931dc737c4SRob Herring 	}
941dc737c4SRob Herring 
951dc737c4SRob Herring 	if (reg < 0)
961dc737c4SRob Herring 		return NOTIFY_DONE;
971dc737c4SRob Herring 
981dc737c4SRob Herring 	if (of_property_read_bool(dev->of_node, "dma-coherent")) {
99e64bf95eSRob Herring 		val = readl(sregs_base + reg);
100e64bf95eSRob Herring 		writel(val | 0xff01, sregs_base + reg);
101*ae626eb9SChristoph Hellwig 		dev->dma_coherent = true;
102e64bf95eSRob Herring 	}
1031dc737c4SRob Herring 
1041dc737c4SRob Herring 	return NOTIFY_OK;
1051dc737c4SRob Herring }
1061dc737c4SRob Herring 
1071dc737c4SRob Herring static struct notifier_block highbank_amba_nb = {
1081dc737c4SRob Herring 	.notifier_call = highbank_platform_notifier,
1091dc737c4SRob Herring };
1101dc737c4SRob Herring 
1111dc737c4SRob Herring static struct notifier_block highbank_platform_nb = {
1121dc737c4SRob Herring 	.notifier_call = highbank_platform_notifier,
1131dc737c4SRob Herring };
1141dc737c4SRob Herring 
11560a66e37SDaniel Lezcano static struct platform_device highbank_cpuidle_device = {
11660a66e37SDaniel Lezcano 	.name = "cpuidle-calxeda",
11760a66e37SDaniel Lezcano };
11860a66e37SDaniel Lezcano 
hb_keys_notifier(struct notifier_block * nb,unsigned long event,void * data)11938431148SRob Herring static int hb_keys_notifier(struct notifier_block *nb, unsigned long event, void *data)
12038431148SRob Herring {
12138431148SRob Herring 	u32 key = *(u32 *)data;
12238431148SRob Herring 
12338431148SRob Herring 	if (event != 0x1000)
12438431148SRob Herring 		return 0;
12538431148SRob Herring 
12638431148SRob Herring 	if (key == KEY_POWER)
12738431148SRob Herring 		orderly_poweroff(false);
12838431148SRob Herring 	else if (key == 0xffff)
12938431148SRob Herring 		ctrl_alt_del();
13038431148SRob Herring 
13138431148SRob Herring 	return 0;
13238431148SRob Herring }
13338431148SRob Herring static struct notifier_block hb_keys_nb = {
13438431148SRob Herring 	.notifier_call = hb_keys_notifier,
13538431148SRob Herring };
13638431148SRob Herring 
highbank_init(void)137220e6cf7SRob Herring static void __init highbank_init(void)
138220e6cf7SRob Herring {
13926cae166SSebastian Hesselbarth 	struct device_node *np;
14026cae166SSebastian Hesselbarth 
14126cae166SSebastian Hesselbarth 	/* Map system registers */
14226cae166SSebastian Hesselbarth 	np = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs");
14326cae166SSebastian Hesselbarth 	sregs_base = of_iomap(np, 0);
14426cae166SSebastian Hesselbarth 	WARN_ON(!sregs_base);
14526cae166SSebastian Hesselbarth 
146220e6cf7SRob Herring 	pm_power_off = highbank_power_off;
147a283580cSRob Herring 	highbank_pm_init();
148220e6cf7SRob Herring 
1491dc737c4SRob Herring 	bus_register_notifier(&platform_bus_type, &highbank_platform_nb);
1501dc737c4SRob Herring 	bus_register_notifier(&amba_bustype, &highbank_amba_nb);
1511dc737c4SRob Herring 
15238431148SRob Herring 	pl320_ipc_register_notifier(&hb_keys_nb);
15338431148SRob Herring 
154a410146cSRob Herring 	if (psci_ops.cpu_suspend)
15560a66e37SDaniel Lezcano 		platform_device_register(&highbank_cpuidle_device);
156220e6cf7SRob Herring }
157220e6cf7SRob Herring 
158543c5040SUwe Kleine-König static const char *const highbank_match[] __initconst = {
159220e6cf7SRob Herring 	"calxeda,highbank",
160e095c0d1SRob Herring 	"calxeda,ecx-2000",
161220e6cf7SRob Herring 	NULL,
162220e6cf7SRob Herring };
163220e6cf7SRob Herring 
164220e6cf7SRob Herring DT_MACHINE_START(HIGHBANK, "Highbank")
165a6a39834SRob Herring #if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
166a6a39834SRob Herring 	.dma_zone_size	= (4ULL * SZ_1G),
167a6a39834SRob Herring #endif
168513b9a08SRussell King 	.l2c_aux_val	= 0,
169513b9a08SRussell King 	.l2c_aux_mask	= ~0,
170513b9a08SRussell King 	.l2c_write_sec	= highbank_l2c310_write_sec,
171220e6cf7SRob Herring 	.init_irq	= highbank_init_irq,
172220e6cf7SRob Herring 	.init_machine	= highbank_init,
173220e6cf7SRob Herring 	.dt_compat	= highbank_match,
17400e9967eSRussell King 	.restart	= highbank_restart,
175220e6cf7SRob Herring MACHINE_END
176