root/arch/arm/mach-integrator/integrator_ap.c

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

DEFINITIONS

This source file includes following definitions.
  1. ap_map_io
  2. irq_suspend
  3. irq_resume
  4. irq_syscore_init
  5. integrator_uart_set_mctrl
  6. ap_init_early
  7. ap_init_irq_of
  8. ap_init_of

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *  linux/arch/arm/mach-integrator/integrator_ap.c
   4  *
   5  *  Copyright (C) 2000-2003 Deep Blue Solutions Ltd
   6  */
   7 #include <linux/kernel.h>
   8 #include <linux/init.h>
   9 #include <linux/syscore_ops.h>
  10 #include <linux/amba/bus.h>
  11 #include <linux/io.h>
  12 #include <linux/irqchip.h>
  13 #include <linux/of_irq.h>
  14 #include <linux/of_address.h>
  15 #include <linux/of_platform.h>
  16 #include <linux/termios.h>
  17 #include <linux/mfd/syscon.h>
  18 #include <linux/regmap.h>
  19 
  20 #include <asm/mach/arch.h>
  21 #include <asm/mach/map.h>
  22 
  23 #include "hardware.h"
  24 #include "cm.h"
  25 #include "common.h"
  26 #include "lm.h"
  27 
  28 /* Regmap to the AP system controller */
  29 static struct regmap *ap_syscon_map;
  30 
  31 /*
  32  * All IO addresses are mapped onto VA 0xFFFx.xxxx, where x.xxxx
  33  * is the (PA >> 12).
  34  *
  35  * Setup a VA for the Integrator interrupt controller (for header #0,
  36  * just for now).
  37  */
  38 #define VA_IC_BASE      __io_address(INTEGRATOR_IC_BASE)
  39 
  40 /*
  41  * Logical      Physical
  42  * f1400000     14000000        Interrupt controller
  43  * f1600000     16000000        UART 0
  44  */
  45 
  46 static struct map_desc ap_io_desc[] __initdata __maybe_unused = {
  47         {
  48                 .virtual        = IO_ADDRESS(INTEGRATOR_IC_BASE),
  49                 .pfn            = __phys_to_pfn(INTEGRATOR_IC_BASE),
  50                 .length         = SZ_4K,
  51                 .type           = MT_DEVICE
  52         }, {
  53                 .virtual        = IO_ADDRESS(INTEGRATOR_UART0_BASE),
  54                 .pfn            = __phys_to_pfn(INTEGRATOR_UART0_BASE),
  55                 .length         = SZ_4K,
  56                 .type           = MT_DEVICE
  57         }
  58 };
  59 
  60 static void __init ap_map_io(void)
  61 {
  62         iotable_init(ap_io_desc, ARRAY_SIZE(ap_io_desc));
  63 }
  64 
  65 #ifdef CONFIG_PM
  66 static unsigned long ic_irq_enable;
  67 
  68 static int irq_suspend(void)
  69 {
  70         ic_irq_enable = readl(VA_IC_BASE + IRQ_ENABLE);
  71         return 0;
  72 }
  73 
  74 static void irq_resume(void)
  75 {
  76         /* disable all irq sources */
  77         cm_clear_irqs();
  78         writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
  79         writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
  80 
  81         writel(ic_irq_enable, VA_IC_BASE + IRQ_ENABLE_SET);
  82 }
  83 #else
  84 #define irq_suspend NULL
  85 #define irq_resume NULL
  86 #endif
  87 
  88 static struct syscore_ops irq_syscore_ops = {
  89         .suspend        = irq_suspend,
  90         .resume         = irq_resume,
  91 };
  92 
  93 static int __init irq_syscore_init(void)
  94 {
  95         register_syscore_ops(&irq_syscore_ops);
  96 
  97         return 0;
  98 }
  99 
 100 device_initcall(irq_syscore_init);
 101 
 102 /*
 103  * For the PL010 found in the Integrator/AP some of the UART control is
 104  * implemented in the system controller and accessed using a callback
 105  * from the driver.
 106  */
 107 static void integrator_uart_set_mctrl(struct amba_device *dev,
 108                                 void __iomem *base, unsigned int mctrl)
 109 {
 110         unsigned int ctrls = 0, ctrlc = 0, rts_mask, dtr_mask;
 111         u32 phybase = dev->res.start;
 112         int ret;
 113 
 114         if (phybase == INTEGRATOR_UART0_BASE) {
 115                 /* UART0 */
 116                 rts_mask = 1 << 4;
 117                 dtr_mask = 1 << 5;
 118         } else {
 119                 /* UART1 */
 120                 rts_mask = 1 << 6;
 121                 dtr_mask = 1 << 7;
 122         }
 123 
 124         if (mctrl & TIOCM_RTS)
 125                 ctrlc |= rts_mask;
 126         else
 127                 ctrls |= rts_mask;
 128 
 129         if (mctrl & TIOCM_DTR)
 130                 ctrlc |= dtr_mask;
 131         else
 132                 ctrls |= dtr_mask;
 133 
 134         ret = regmap_write(ap_syscon_map,
 135                            INTEGRATOR_SC_CTRLS_OFFSET,
 136                            ctrls);
 137         if (ret)
 138                 pr_err("MODEM: unable to write PL010 UART CTRLS\n");
 139 
 140         ret = regmap_write(ap_syscon_map,
 141                            INTEGRATOR_SC_CTRLC_OFFSET,
 142                            ctrlc);
 143         if (ret)
 144                 pr_err("MODEM: unable to write PL010 UART CRTLC\n");
 145 }
 146 
 147 struct amba_pl010_data ap_uart_data = {
 148         .set_mctrl = integrator_uart_set_mctrl,
 149 };
 150 
 151 void __init ap_init_early(void)
 152 {
 153 }
 154 
 155 static void __init ap_init_irq_of(void)
 156 {
 157         cm_init();
 158         irqchip_init();
 159 }
 160 
 161 /* For the Device Tree, add in the UART callbacks as AUXDATA */
 162 static struct of_dev_auxdata ap_auxdata_lookup[] __initdata = {
 163         OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART0_BASE,
 164                 "uart0", &ap_uart_data),
 165         OF_DEV_AUXDATA("arm,primecell", INTEGRATOR_UART1_BASE,
 166                 "uart1", &ap_uart_data),
 167         { /* sentinel */ },
 168 };
 169 
 170 static const struct of_device_id ap_syscon_match[] = {
 171         { .compatible = "arm,integrator-ap-syscon"},
 172         { },
 173 };
 174 
 175 static void __init ap_init_of(void)
 176 {
 177         u32 sc_dec;
 178         struct device_node *syscon;
 179         int ret;
 180         int i;
 181 
 182         of_platform_default_populate(NULL, ap_auxdata_lookup, NULL);
 183 
 184         syscon = of_find_matching_node(NULL, ap_syscon_match);
 185         if (!syscon)
 186                 return;
 187         ap_syscon_map = syscon_node_to_regmap(syscon);
 188         if (IS_ERR(ap_syscon_map)) {
 189                 pr_crit("could not find Integrator/AP system controller\n");
 190                 return;
 191         }
 192 
 193         ret = regmap_read(ap_syscon_map,
 194                           INTEGRATOR_SC_DEC_OFFSET,
 195                           &sc_dec);
 196         if (ret) {
 197                 pr_crit("could not read from Integrator/AP syscon\n");
 198                 return;
 199         }
 200 
 201         for (i = 0; i < 4; i++) {
 202                 struct lm_device *lmdev;
 203 
 204                 if ((sc_dec & (16 << i)) == 0)
 205                         continue;
 206 
 207                 lmdev = kzalloc(sizeof(struct lm_device), GFP_KERNEL);
 208                 if (!lmdev)
 209                         continue;
 210 
 211                 lmdev->resource.start = 0xc0000000 + 0x10000000 * i;
 212                 lmdev->resource.end = lmdev->resource.start + 0x0fffffff;
 213                 lmdev->resource.flags = IORESOURCE_MEM;
 214                 lmdev->irq = irq_of_parse_and_map(syscon, i);
 215                 lmdev->id = i;
 216 
 217                 lm_device_register(lmdev);
 218         }
 219 }
 220 
 221 static const char * ap_dt_board_compat[] = {
 222         "arm,integrator-ap",
 223         NULL,
 224 };
 225 
 226 DT_MACHINE_START(INTEGRATOR_AP_DT, "ARM Integrator/AP (Device Tree)")
 227         .reserve        = integrator_reserve,
 228         .map_io         = ap_map_io,
 229         .init_early     = ap_init_early,
 230         .init_irq       = ap_init_irq_of,
 231         .init_machine   = ap_init_of,
 232         .dt_compat      = ap_dt_board_compat,
 233 MACHINE_END

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