linux/arch/arm/mach-omap2/omap4-common.c
<<
>>
Prefs
   1/*
   2 * OMAP4 specific common source file.
   3 *
   4 * Copyright (C) 2010 Texas Instruments, Inc.
   5 * Author:
   6 *      Santosh Shilimkar <santosh.shilimkar@ti.com>
   7 *
   8 *
   9 * This program is free software,you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12 */
  13
  14#include <linux/kernel.h>
  15#include <linux/init.h>
  16#include <linux/io.h>
  17#include <linux/irq.h>
  18#include <linux/irqchip.h>
  19#include <linux/platform_device.h>
  20#include <linux/memblock.h>
  21#include <linux/of_irq.h>
  22#include <linux/of_platform.h>
  23#include <linux/export.h>
  24#include <linux/irqchip/arm-gic.h>
  25#include <linux/of_address.h>
  26
  27#include <asm/hardware/cache-l2x0.h>
  28#include <asm/mach/map.h>
  29#include <asm/memblock.h>
  30#include <asm/smp_twd.h>
  31
  32#include "omap-wakeupgen.h"
  33#include "soc.h"
  34#include "iomap.h"
  35#include "common.h"
  36#include "mmc.h"
  37#include "hsmmc.h"
  38#include "prminst44xx.h"
  39#include "prcm_mpu44xx.h"
  40#include "omap4-sar-layout.h"
  41#include "omap-secure.h"
  42#include "sram.h"
  43
  44#ifdef CONFIG_CACHE_L2X0
  45static void __iomem *l2cache_base;
  46#endif
  47
  48static void __iomem *sar_ram_base;
  49static void __iomem *gic_dist_base_addr;
  50static void __iomem *twd_base;
  51
  52#define IRQ_LOCALTIMER          29
  53
  54#ifdef CONFIG_OMAP4_ERRATA_I688
  55/* Used to implement memory barrier on DRAM path */
  56#define OMAP4_DRAM_BARRIER_VA                   0xfe600000
  57
  58void __iomem *dram_sync, *sram_sync;
  59
  60static phys_addr_t paddr;
  61static u32 size;
  62
  63void omap_bus_sync(void)
  64{
  65        if (dram_sync && sram_sync) {
  66                writel_relaxed(readl_relaxed(dram_sync), dram_sync);
  67                writel_relaxed(readl_relaxed(sram_sync), sram_sync);
  68                isb();
  69        }
  70}
  71EXPORT_SYMBOL(omap_bus_sync);
  72
  73/* Steal one page physical memory for barrier implementation */
  74int __init omap_barrier_reserve_memblock(void)
  75{
  76
  77        size = ALIGN(PAGE_SIZE, SZ_1M);
  78        paddr = arm_memblock_steal(size, SZ_1M);
  79
  80        return 0;
  81}
  82
  83void __init omap_barriers_init(void)
  84{
  85        struct map_desc dram_io_desc[1];
  86
  87        dram_io_desc[0].virtual = OMAP4_DRAM_BARRIER_VA;
  88        dram_io_desc[0].pfn = __phys_to_pfn(paddr);
  89        dram_io_desc[0].length = size;
  90        dram_io_desc[0].type = MT_MEMORY_SO;
  91        iotable_init(dram_io_desc, ARRAY_SIZE(dram_io_desc));
  92        dram_sync = (void __iomem *) dram_io_desc[0].virtual;
  93        sram_sync = (void __iomem *) OMAP4_SRAM_VA;
  94
  95        pr_info("OMAP4: Map 0x%08llx to 0x%08lx for dram barrier\n",
  96                (long long) paddr, dram_io_desc[0].virtual);
  97
  98}
  99#else
 100void __init omap_barriers_init(void)
 101{}
 102#endif
 103
 104void __init gic_init_irq(void)
 105{
 106        void __iomem *omap_irq_base;
 107
 108        /* Static mapping, never released */
 109        gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K);
 110        BUG_ON(!gic_dist_base_addr);
 111
 112        twd_base = ioremap(OMAP44XX_LOCAL_TWD_BASE, SZ_4K);
 113        BUG_ON(!twd_base);
 114
 115        /* Static mapping, never released */
 116        omap_irq_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
 117        BUG_ON(!omap_irq_base);
 118
 119        omap_wakeupgen_init();
 120
 121        gic_init(0, 29, gic_dist_base_addr, omap_irq_base);
 122}
 123
 124void gic_dist_disable(void)
 125{
 126        if (gic_dist_base_addr)
 127                __raw_writel(0x0, gic_dist_base_addr + GIC_DIST_CTRL);
 128}
 129
 130bool gic_dist_disabled(void)
 131{
 132        return !(__raw_readl(gic_dist_base_addr + GIC_DIST_CTRL) & 0x1);
 133}
 134
 135void gic_timer_retrigger(void)
 136{
 137        u32 twd_int = __raw_readl(twd_base + TWD_TIMER_INTSTAT);
 138        u32 gic_int = __raw_readl(gic_dist_base_addr + GIC_DIST_PENDING_SET);
 139        u32 twd_ctrl = __raw_readl(twd_base + TWD_TIMER_CONTROL);
 140
 141        if (twd_int && !(gic_int & BIT(IRQ_LOCALTIMER))) {
 142                /*
 143                 * The local timer interrupt got lost while the distributor was
 144                 * disabled.  Ack the pending interrupt, and retrigger it.
 145                 */
 146                pr_warn("%s: lost localtimer interrupt\n", __func__);
 147                __raw_writel(1, twd_base + TWD_TIMER_INTSTAT);
 148                if (!(twd_ctrl & TWD_TIMER_CONTROL_PERIODIC)) {
 149                        __raw_writel(1, twd_base + TWD_TIMER_COUNTER);
 150                        twd_ctrl |= TWD_TIMER_CONTROL_ENABLE;
 151                        __raw_writel(twd_ctrl, twd_base + TWD_TIMER_CONTROL);
 152                }
 153        }
 154}
 155
 156#ifdef CONFIG_CACHE_L2X0
 157
 158void __iomem *omap4_get_l2cache_base(void)
 159{
 160        return l2cache_base;
 161}
 162
 163static void omap4_l2x0_disable(void)
 164{
 165        /* Disable PL310 L2 Cache controller */
 166        omap_smc1(0x102, 0x0);
 167}
 168
 169static void omap4_l2x0_set_debug(unsigned long val)
 170{
 171        /* Program PL310 L2 Cache controller debug register */
 172        omap_smc1(0x100, val);
 173}
 174
 175static int __init omap_l2_cache_init(void)
 176{
 177        u32 aux_ctrl = 0;
 178
 179        /*
 180         * To avoid code running on other OMAPs in
 181         * multi-omap builds
 182         */
 183        if (!cpu_is_omap44xx())
 184                return -ENODEV;
 185
 186        /* Static mapping, never released */
 187        l2cache_base = ioremap(OMAP44XX_L2CACHE_BASE, SZ_4K);
 188        if (WARN_ON(!l2cache_base))
 189                return -ENOMEM;
 190
 191        /*
 192         * 16-way associativity, parity disabled
 193         * Way size - 32KB (es1.0)
 194         * Way size - 64KB (es2.0 +)
 195         */
 196        aux_ctrl = ((1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT) |
 197                        (0x1 << 25) |
 198                        (0x1 << L2X0_AUX_CTRL_NS_LOCKDOWN_SHIFT) |
 199                        (0x1 << L2X0_AUX_CTRL_NS_INT_CTRL_SHIFT));
 200
 201        if (omap_rev() == OMAP4430_REV_ES1_0) {
 202                aux_ctrl |= 0x2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT;
 203        } else {
 204                aux_ctrl |= ((0x3 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) |
 205                        (1 << L2X0_AUX_CTRL_SHARE_OVERRIDE_SHIFT) |
 206                        (1 << L2X0_AUX_CTRL_DATA_PREFETCH_SHIFT) |
 207                        (1 << L2X0_AUX_CTRL_INSTR_PREFETCH_SHIFT) |
 208                        (1 << L2X0_AUX_CTRL_EARLY_BRESP_SHIFT));
 209        }
 210        if (omap_rev() != OMAP4430_REV_ES1_0)
 211                omap_smc1(0x109, aux_ctrl);
 212
 213        /* Enable PL310 L2 Cache controller */
 214        omap_smc1(0x102, 0x1);
 215
 216        if (of_have_populated_dt())
 217                l2x0_of_init(aux_ctrl, L2X0_AUX_CTRL_MASK);
 218        else
 219                l2x0_init(l2cache_base, aux_ctrl, L2X0_AUX_CTRL_MASK);
 220
 221        /*
 222         * Override default outer_cache.disable with a OMAP4
 223         * specific one
 224        */
 225        outer_cache.disable = omap4_l2x0_disable;
 226        outer_cache.set_debug = omap4_l2x0_set_debug;
 227
 228        return 0;
 229}
 230omap_early_initcall(omap_l2_cache_init);
 231#endif
 232
 233void __iomem *omap4_get_sar_ram_base(void)
 234{
 235        return sar_ram_base;
 236}
 237
 238/*
 239 * SAR RAM used to save and restore the HW
 240 * context in low power modes
 241 */
 242static int __init omap4_sar_ram_init(void)
 243{
 244        unsigned long sar_base;
 245
 246        /*
 247         * To avoid code running on other OMAPs in
 248         * multi-omap builds
 249         */
 250        if (cpu_is_omap44xx())
 251                sar_base = OMAP44XX_SAR_RAM_BASE;
 252        else if (soc_is_omap54xx())
 253                sar_base = OMAP54XX_SAR_RAM_BASE;
 254        else
 255                return -ENOMEM;
 256
 257        /* Static mapping, never released */
 258        sar_ram_base = ioremap(sar_base, SZ_16K);
 259        if (WARN_ON(!sar_ram_base))
 260                return -ENOMEM;
 261
 262        return 0;
 263}
 264omap_early_initcall(omap4_sar_ram_init);
 265
 266void __init omap_gic_of_init(void)
 267{
 268        struct device_node *np;
 269
 270        /* Extract GIC distributor and TWD bases for OMAP4460 ROM Errata WA */
 271        if (!cpu_is_omap446x())
 272                goto skip_errata_init;
 273
 274        np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-gic");
 275        gic_dist_base_addr = of_iomap(np, 0);
 276        WARN_ON(!gic_dist_base_addr);
 277
 278        np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-twd-timer");
 279        twd_base = of_iomap(np, 0);
 280        WARN_ON(!twd_base);
 281
 282skip_errata_init:
 283        omap_wakeupgen_init();
 284        irqchip_init();
 285}
 286
 287#if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 288static int omap4_twl6030_hsmmc_late_init(struct device *dev)
 289{
 290        int irq = 0;
 291        struct platform_device *pdev = container_of(dev,
 292                                struct platform_device, dev);
 293        struct omap_mmc_platform_data *pdata = dev->platform_data;
 294
 295        /* Setting MMC1 Card detect Irq */
 296        if (pdev->id == 0) {
 297                irq = twl6030_mmc_card_detect_config();
 298                if (irq < 0) {
 299                        dev_err(dev, "%s: Error card detect config(%d)\n",
 300                                __func__, irq);
 301                        return irq;
 302                }
 303                pdata->slots[0].card_detect_irq = irq;
 304                pdata->slots[0].card_detect = twl6030_mmc_card_detect;
 305        }
 306        return 0;
 307}
 308
 309static __init void omap4_twl6030_hsmmc_set_late_init(struct device *dev)
 310{
 311        struct omap_mmc_platform_data *pdata;
 312
 313        /* dev can be null if CONFIG_MMC_OMAP_HS is not set */
 314        if (!dev) {
 315                pr_err("Failed %s\n", __func__);
 316                return;
 317        }
 318        pdata = dev->platform_data;
 319        pdata->init =   omap4_twl6030_hsmmc_late_init;
 320}
 321
 322int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
 323{
 324        struct omap2_hsmmc_info *c;
 325
 326        omap_hsmmc_init(controllers);
 327        for (c = controllers; c->mmc; c++) {
 328                /* pdev can be null if CONFIG_MMC_OMAP_HS is not set */
 329                if (!c->pdev)
 330                        continue;
 331                omap4_twl6030_hsmmc_set_late_init(&c->pdev->dev);
 332        }
 333
 334        return 0;
 335}
 336#else
 337int __init omap4_twl6030_hsmmc_init(struct omap2_hsmmc_info *controllers)
 338{
 339        return 0;
 340}
 341#endif
 342
 343/**
 344 * omap44xx_restart - trigger a software restart of the SoC
 345 * @mode: the "reboot mode", see arch/arm/kernel/{setup,process}.c
 346 * @cmd: passed from the userspace program rebooting the system (if provided)
 347 *
 348 * Resets the SoC.  For @cmd, see the 'reboot' syscall in
 349 * kernel/sys.c.  No return value.
 350 */
 351void omap44xx_restart(char mode, const char *cmd)
 352{
 353        /* XXX Should save 'cmd' into scratchpad for use after reboot */
 354        omap4_prminst_global_warm_sw_reset(); /* never returns */
 355        while (1);
 356}
 357
 358