root/arch/arm/mach-highbank/highbank.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. highbank_scu_map_io
  2. highbank_l2c310_write_sec
  3. highbank_init_irq
  4. highbank_power_off
  5. highbank_platform_notifier
  6. hb_keys_notifier
  7. highbank_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright 2010-2011 Calxeda, Inc.
   4  */
   5 #include <linux/clk.h>
   6 #include <linux/clkdev.h>
   7 #include <linux/clocksource.h>
   8 #include <linux/dma-mapping.h>
   9 #include <linux/input.h>
  10 #include <linux/io.h>
  11 #include <linux/irqchip.h>
  12 #include <linux/pl320-ipc.h>
  13 #include <linux/of.h>
  14 #include <linux/of_irq.h>
  15 #include <linux/of_address.h>
  16 #include <linux/reboot.h>
  17 #include <linux/amba/bus.h>
  18 #include <linux/platform_device.h>
  19 #include <linux/psci.h>
  20 
  21 #include <asm/hardware/cache-l2x0.h>
  22 #include <asm/mach/arch.h>
  23 #include <asm/mach/map.h>
  24 
  25 #include "core.h"
  26 #include "sysregs.h"
  27 
  28 void __iomem *sregs_base;
  29 void __iomem *scu_base_addr;
  30 
  31 static void __init highbank_scu_map_io(void)
  32 {
  33         unsigned long base;
  34 
  35         /* Get SCU base */
  36         asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
  37 
  38         scu_base_addr = ioremap(base, SZ_4K);
  39 }
  40 
  41 
  42 static void highbank_l2c310_write_sec(unsigned long val, unsigned reg)
  43 {
  44         if (reg == L2X0_CTRL)
  45                 highbank_smc1(0x102, val);
  46         else
  47                 WARN_ONCE(1, "Highbank L2C310: ignoring write to reg 0x%x\n",
  48                           reg);
  49 }
  50 
  51 static void __init highbank_init_irq(void)
  52 {
  53         irqchip_init();
  54 
  55         if (of_find_compatible_node(NULL, NULL, "arm,cortex-a9"))
  56                 highbank_scu_map_io();
  57 }
  58 
  59 static void highbank_power_off(void)
  60 {
  61         highbank_set_pwr_shutdown();
  62 
  63         while (1)
  64                 cpu_do_idle();
  65 }
  66 
  67 static int highbank_platform_notifier(struct notifier_block *nb,
  68                                   unsigned long event, void *__dev)
  69 {
  70         struct resource *res;
  71         int reg = -1;
  72         u32 val;
  73         struct device *dev = __dev;
  74 
  75         if (event != BUS_NOTIFY_ADD_DEVICE)
  76                 return NOTIFY_DONE;
  77 
  78         if (of_device_is_compatible(dev->of_node, "calxeda,hb-ahci"))
  79                 reg = 0xc;
  80         else if (of_device_is_compatible(dev->of_node, "calxeda,hb-sdhci"))
  81                 reg = 0x18;
  82         else if (of_device_is_compatible(dev->of_node, "arm,pl330"))
  83                 reg = 0x20;
  84         else if (of_device_is_compatible(dev->of_node, "calxeda,hb-xgmac")) {
  85                 res = platform_get_resource(to_platform_device(dev),
  86                                             IORESOURCE_MEM, 0);
  87                 if (res) {
  88                         if (res->start == 0xfff50000)
  89                                 reg = 0;
  90                         else if (res->start == 0xfff51000)
  91                                 reg = 4;
  92                 }
  93         }
  94 
  95         if (reg < 0)
  96                 return NOTIFY_DONE;
  97 
  98         if (of_property_read_bool(dev->of_node, "dma-coherent")) {
  99                 val = readl(sregs_base + reg);
 100                 writel(val | 0xff01, sregs_base + reg);
 101                 set_dma_ops(dev, &arm_coherent_dma_ops);
 102         }
 103 
 104         return NOTIFY_OK;
 105 }
 106 
 107 static struct notifier_block highbank_amba_nb = {
 108         .notifier_call = highbank_platform_notifier,
 109 };
 110 
 111 static struct notifier_block highbank_platform_nb = {
 112         .notifier_call = highbank_platform_notifier,
 113 };
 114 
 115 static struct platform_device highbank_cpuidle_device = {
 116         .name = "cpuidle-calxeda",
 117 };
 118 
 119 static int hb_keys_notifier(struct notifier_block *nb, unsigned long event, void *data)
 120 {
 121         u32 key = *(u32 *)data;
 122 
 123         if (event != 0x1000)
 124                 return 0;
 125 
 126         if (key == KEY_POWER)
 127                 orderly_poweroff(false);
 128         else if (key == 0xffff)
 129                 ctrl_alt_del();
 130 
 131         return 0;
 132 }
 133 static struct notifier_block hb_keys_nb = {
 134         .notifier_call = hb_keys_notifier,
 135 };
 136 
 137 static void __init highbank_init(void)
 138 {
 139         struct device_node *np;
 140 
 141         /* Map system registers */
 142         np = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs");
 143         sregs_base = of_iomap(np, 0);
 144         WARN_ON(!sregs_base);
 145 
 146         pm_power_off = highbank_power_off;
 147         highbank_pm_init();
 148 
 149         bus_register_notifier(&platform_bus_type, &highbank_platform_nb);
 150         bus_register_notifier(&amba_bustype, &highbank_amba_nb);
 151 
 152         pl320_ipc_register_notifier(&hb_keys_nb);
 153 
 154         if (psci_ops.cpu_suspend)
 155                 platform_device_register(&highbank_cpuidle_device);
 156 }
 157 
 158 static const char *const highbank_match[] __initconst = {
 159         "calxeda,highbank",
 160         "calxeda,ecx-2000",
 161         NULL,
 162 };
 163 
 164 DT_MACHINE_START(HIGHBANK, "Highbank")
 165 #if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
 166         .dma_zone_size  = (4ULL * SZ_1G),
 167 #endif
 168         .l2c_aux_val    = 0,
 169         .l2c_aux_mask   = ~0,
 170         .l2c_write_sec  = highbank_l2c310_write_sec,
 171         .init_irq       = highbank_init_irq,
 172         .init_machine   = highbank_init,
 173         .dt_compat      = highbank_match,
 174         .restart        = highbank_restart,
 175 MACHINE_END

/* [<][>][^][v][top][bottom][index][help] */