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