1220e6cf7SRob Herring /* 2220e6cf7SRob Herring * Copyright 2010-2011 Calxeda, Inc. 3220e6cf7SRob Herring * 4220e6cf7SRob Herring * This program is free software; you can redistribute it and/or modify it 5220e6cf7SRob Herring * under the terms and conditions of the GNU General Public License, 6220e6cf7SRob Herring * version 2, as published by the Free Software Foundation. 7220e6cf7SRob Herring * 8220e6cf7SRob Herring * This program is distributed in the hope it will be useful, but WITHOUT 9220e6cf7SRob Herring * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10220e6cf7SRob Herring * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11220e6cf7SRob Herring * more details. 12220e6cf7SRob Herring * 13220e6cf7SRob Herring * You should have received a copy of the GNU General Public License along with 14220e6cf7SRob Herring * this program. If not, see <http://www.gnu.org/licenses/>. 15220e6cf7SRob Herring */ 16220e6cf7SRob Herring #include <linux/clk.h> 17220e6cf7SRob Herring #include <linux/clkdev.h> 180583fe47SRob Herring #include <linux/clocksource.h> 191dc737c4SRob Herring #include <linux/dma-mapping.h> 20220e6cf7SRob Herring #include <linux/io.h> 210529e315SRob Herring #include <linux/irqchip.h> 22220e6cf7SRob Herring #include <linux/of.h> 23220e6cf7SRob Herring #include <linux/of_irq.h> 24220e6cf7SRob Herring #include <linux/of_platform.h> 25220e6cf7SRob Herring #include <linux/of_address.h> 261dc737c4SRob Herring #include <linux/amba/bus.h> 27d34bcdebSPrashant Gaikwad #include <linux/clk-provider.h> 2860a66e37SDaniel Lezcano #include <linux/platform_device.h> 29220e6cf7SRob Herring 30dd68eb02SRob Herring #include <asm/psci.h> 31220e6cf7SRob Herring #include <asm/hardware/cache-l2x0.h> 32220e6cf7SRob Herring #include <asm/mach/arch.h> 3352530343SRob Herring #include <asm/mach/map.h> 34220e6cf7SRob Herring 35220e6cf7SRob Herring #include "core.h" 36220e6cf7SRob Herring #include "sysregs.h" 37220e6cf7SRob Herring 38220e6cf7SRob Herring void __iomem *sregs_base; 397a2848d3SRob Herring void __iomem *scu_base_addr; 40220e6cf7SRob Herring 41220e6cf7SRob Herring static void __init highbank_scu_map_io(void) 42220e6cf7SRob Herring { 43220e6cf7SRob Herring unsigned long base; 44220e6cf7SRob Herring 45220e6cf7SRob Herring /* Get SCU base */ 46220e6cf7SRob Herring asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base)); 47220e6cf7SRob Herring 487a2848d3SRob Herring scu_base_addr = ioremap(base, SZ_4K); 49220e6cf7SRob Herring } 50220e6cf7SRob Herring 51220e6cf7SRob Herring 528e56130dSRob Herring static void highbank_l2x0_disable(void) 538e56130dSRob Herring { 548e56130dSRob Herring /* Disable PL310 L2 Cache controller */ 558e56130dSRob Herring highbank_smc1(0x102, 0x0); 568e56130dSRob Herring } 578e56130dSRob Herring 58220e6cf7SRob Herring static void __init highbank_init_irq(void) 59220e6cf7SRob Herring { 600529e315SRob Herring irqchip_init(); 618e56130dSRob Herring 627a2848d3SRob Herring if (of_find_compatible_node(NULL, NULL, "arm,cortex-a9")) 637a2848d3SRob Herring highbank_scu_map_io(); 647a2848d3SRob Herring 658e56130dSRob Herring /* Enable PL310 L2 Cache controller */ 66a56a5cf1SRob Herring if (IS_ENABLED(CONFIG_CACHE_L2X0) && 67a56a5cf1SRob Herring of_find_compatible_node(NULL, NULL, "arm,pl310-cache")) { 688e56130dSRob Herring highbank_smc1(0x102, 0x1); 69220e6cf7SRob Herring l2x0_of_init(0, ~0UL); 708e56130dSRob Herring outer_cache.disable = highbank_l2x0_disable; 71a56a5cf1SRob Herring } 72220e6cf7SRob Herring } 73220e6cf7SRob Herring 74220e6cf7SRob Herring static void __init highbank_timer_init(void) 75220e6cf7SRob Herring { 76220e6cf7SRob Herring struct device_node *np; 77220e6cf7SRob Herring 78220e6cf7SRob Herring /* Map system registers */ 79220e6cf7SRob Herring np = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs"); 80220e6cf7SRob Herring sregs_base = of_iomap(np, 0); 81220e6cf7SRob Herring WARN_ON(!sregs_base); 82220e6cf7SRob Herring 83d34bcdebSPrashant Gaikwad of_clk_init(NULL); 847ac9b9ebSMarc Zyngier 85da4a686aSRob Herring clocksource_of_init(); 86220e6cf7SRob Herring } 87220e6cf7SRob Herring 88220e6cf7SRob Herring static void highbank_power_off(void) 89220e6cf7SRob Herring { 90c05ee88fSRob Herring highbank_set_pwr_shutdown(); 91220e6cf7SRob Herring 92220e6cf7SRob Herring while (1) 93220e6cf7SRob Herring cpu_do_idle(); 94220e6cf7SRob Herring } 95220e6cf7SRob Herring 961dc737c4SRob Herring static int highbank_platform_notifier(struct notifier_block *nb, 971dc737c4SRob Herring unsigned long event, void *__dev) 981dc737c4SRob Herring { 991dc737c4SRob Herring struct resource *res; 1001dc737c4SRob Herring int reg = -1; 101e64bf95eSRob Herring u32 val; 1021dc737c4SRob Herring struct device *dev = __dev; 1031dc737c4SRob Herring 1041dc737c4SRob Herring if (event != BUS_NOTIFY_ADD_DEVICE) 1051dc737c4SRob Herring return NOTIFY_DONE; 1061dc737c4SRob Herring 1071dc737c4SRob Herring if (of_device_is_compatible(dev->of_node, "calxeda,hb-ahci")) 1081dc737c4SRob Herring reg = 0xc; 1091dc737c4SRob Herring else if (of_device_is_compatible(dev->of_node, "calxeda,hb-sdhci")) 1101dc737c4SRob Herring reg = 0x18; 1111dc737c4SRob Herring else if (of_device_is_compatible(dev->of_node, "arm,pl330")) 1121dc737c4SRob Herring reg = 0x20; 1131dc737c4SRob Herring else if (of_device_is_compatible(dev->of_node, "calxeda,hb-xgmac")) { 1141dc737c4SRob Herring res = platform_get_resource(to_platform_device(dev), 1151dc737c4SRob Herring IORESOURCE_MEM, 0); 1161dc737c4SRob Herring if (res) { 1171dc737c4SRob Herring if (res->start == 0xfff50000) 1181dc737c4SRob Herring reg = 0; 1191dc737c4SRob Herring else if (res->start == 0xfff51000) 1201dc737c4SRob Herring reg = 4; 1211dc737c4SRob Herring } 1221dc737c4SRob Herring } 1231dc737c4SRob Herring 1241dc737c4SRob Herring if (reg < 0) 1251dc737c4SRob Herring return NOTIFY_DONE; 1261dc737c4SRob Herring 1271dc737c4SRob Herring if (of_property_read_bool(dev->of_node, "dma-coherent")) { 128e64bf95eSRob Herring val = readl(sregs_base + reg); 129e64bf95eSRob Herring writel(val | 0xff01, sregs_base + reg); 1301dc737c4SRob Herring set_dma_ops(dev, &arm_coherent_dma_ops); 131e64bf95eSRob Herring } 1321dc737c4SRob Herring 1331dc737c4SRob Herring return NOTIFY_OK; 1341dc737c4SRob Herring } 1351dc737c4SRob Herring 1361dc737c4SRob Herring static struct notifier_block highbank_amba_nb = { 1371dc737c4SRob Herring .notifier_call = highbank_platform_notifier, 1381dc737c4SRob Herring }; 1391dc737c4SRob Herring 1401dc737c4SRob Herring static struct notifier_block highbank_platform_nb = { 1411dc737c4SRob Herring .notifier_call = highbank_platform_notifier, 1421dc737c4SRob Herring }; 1431dc737c4SRob Herring 14460a66e37SDaniel Lezcano static struct platform_device highbank_cpuidle_device = { 14560a66e37SDaniel Lezcano .name = "cpuidle-calxeda", 14660a66e37SDaniel Lezcano }; 14760a66e37SDaniel Lezcano 148220e6cf7SRob Herring static void __init highbank_init(void) 149220e6cf7SRob Herring { 150220e6cf7SRob Herring pm_power_off = highbank_power_off; 151a283580cSRob Herring highbank_pm_init(); 152220e6cf7SRob Herring 1531dc737c4SRob Herring bus_register_notifier(&platform_bus_type, &highbank_platform_nb); 1541dc737c4SRob Herring bus_register_notifier(&amba_bustype, &highbank_amba_nb); 1551dc737c4SRob Herring 156220e6cf7SRob Herring of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); 15760a66e37SDaniel Lezcano 158a410146cSRob Herring if (psci_ops.cpu_suspend) 15960a66e37SDaniel Lezcano platform_device_register(&highbank_cpuidle_device); 160220e6cf7SRob Herring } 161220e6cf7SRob Herring 162220e6cf7SRob Herring static const char *highbank_match[] __initconst = { 163220e6cf7SRob Herring "calxeda,highbank", 164e095c0d1SRob Herring "calxeda,ecx-2000", 165220e6cf7SRob Herring NULL, 166220e6cf7SRob Herring }; 167220e6cf7SRob Herring 168220e6cf7SRob Herring DT_MACHINE_START(HIGHBANK, "Highbank") 169a6a39834SRob Herring #if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE) 170a6a39834SRob Herring .dma_zone_size = (4ULL * SZ_1G), 171a6a39834SRob Herring #endif 172220e6cf7SRob Herring .init_irq = highbank_init_irq, 1736bb27d73SStephen Warren .init_time = highbank_timer_init, 174220e6cf7SRob Herring .init_machine = highbank_init, 175220e6cf7SRob Herring .dt_compat = highbank_match, 17600e9967eSRussell King .restart = highbank_restart, 177220e6cf7SRob Herring MACHINE_END 178