linux/arch/arm/mach-tegra/reset.c
<<
>>
Prefs
   1/*
   2 * arch/arm/mach-tegra/reset.c
   3 *
   4 * Copyright (C) 2011,2012 NVIDIA Corporation.
   5 *
   6 * This software is licensed under the terms of the GNU General Public
   7 * License version 2, as published by the Free Software Foundation, and
   8 * may be copied, distributed, and modified under those terms.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 */
  16
  17#include <linux/init.h>
  18#include <linux/io.h>
  19#include <linux/cpumask.h>
  20#include <linux/bitops.h>
  21
  22#include <asm/cacheflush.h>
  23#include <asm/hardware/cache-l2x0.h>
  24
  25#include "iomap.h"
  26#include "irammap.h"
  27#include "reset.h"
  28#include "sleep.h"
  29#include "fuse.h"
  30
  31#define TEGRA_IRAM_RESET_BASE (TEGRA_IRAM_BASE + \
  32                                TEGRA_IRAM_RESET_HANDLER_OFFSET)
  33
  34static bool is_enabled;
  35
  36static void __init tegra_cpu_reset_handler_enable(void)
  37{
  38        void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_RESET_BASE);
  39        void __iomem *evp_cpu_reset =
  40                IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE + 0x100);
  41        void __iomem *sb_ctrl = IO_ADDRESS(TEGRA_SB_BASE);
  42        u32 reg;
  43
  44        BUG_ON(is_enabled);
  45        BUG_ON(tegra_cpu_reset_handler_size > TEGRA_IRAM_RESET_HANDLER_SIZE);
  46
  47        memcpy(iram_base, (void *)__tegra_cpu_reset_handler_start,
  48                        tegra_cpu_reset_handler_size);
  49
  50        /*
  51         * NOTE: This must be the one and only write to the EVP CPU reset
  52         *       vector in the entire system.
  53         */
  54        writel(TEGRA_IRAM_RESET_BASE + tegra_cpu_reset_handler_offset,
  55                        evp_cpu_reset);
  56        wmb();
  57        reg = readl(evp_cpu_reset);
  58
  59        /*
  60         * Prevent further modifications to the physical reset vector.
  61         *  NOTE: Has no effect on chips prior to Tegra30.
  62         */
  63        if (tegra_chip_id != TEGRA20) {
  64                reg = readl(sb_ctrl);
  65                reg |= 2;
  66                writel(reg, sb_ctrl);
  67                wmb();
  68        }
  69
  70        is_enabled = true;
  71}
  72
  73void __init tegra_cpu_reset_handler_init(void)
  74{
  75
  76#ifdef CONFIG_SMP
  77        __tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] =
  78                *((u32 *)cpu_possible_mask);
  79        __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_SECONDARY] =
  80                virt_to_phys((void *)tegra_secondary_startup);
  81#endif
  82
  83#ifdef CONFIG_PM_SLEEP
  84        __tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_LP2] =
  85                virt_to_phys((void *)tegra_resume);
  86#endif
  87
  88        tegra_cpu_reset_handler_enable();
  89}
  90