uboot/arch/nds32/cpu/n1213/ag101/cpu.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
   4 * Marius Groeger <mgroeger@sysgo.de>
   5 *
   6 * (C) Copyright 2002
   7 * Gary Jennejohn, DENX Software Engineering, <gj@denx.de>
   8 *
   9 * Copyright (C) 2011 Andes Technology Corporation
  10 * Shawn Lin, Andes Technology Corporation <nobuhiro@andestech.com>
  11 * Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
  12 *
  13 * See file CREDITS for list of people who contributed to this
  14 * project.
  15 *
  16 * This program is free software; you can redistribute it and/or
  17 * modify it under the terms of the GNU General Public License as
  18 * published by the Free Software Foundation; either version 2 of
  19 * the License, or (at your option) any later version.
  20 *
  21 * This program is distributed in the hope that it will be useful,
  22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24 * GNU General Public License for more details.
  25 *
  26 * You should have received a copy of the GNU General Public License
  27 * along with this program; if not, write to the Free Software
  28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  29 * MA 02111-1307 USA
  30 */
  31
  32/* CPU specific code */
  33#include <common.h>
  34#include <command.h>
  35#include <watchdog.h>
  36#include <asm/cache.h>
  37
  38#include <faraday/ftwdt010_wdt.h>
  39
  40/*
  41 * cleanup_before_linux() is called just before we call linux
  42 * it prepares the processor for linux
  43 *
  44 * we disable interrupt and caches.
  45 */
  46int cleanup_before_linux(void)
  47{
  48        disable_interrupts();
  49
  50#ifdef CONFIG_MMU
  51        /* turn off I/D-cache */
  52        icache_disable();
  53        dcache_disable();
  54
  55        /* flush I/D-cache */
  56        invalidate_icac();
  57        invalidate_dcac();
  58#endif
  59
  60        return 0;
  61}
  62
  63int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  64{
  65        disable_interrupts();
  66
  67        /*
  68         * reset to the base addr of andesboot.
  69         * currently no ROM loader at addr 0.
  70         * do not use reset_cpu(0);
  71         */
  72#ifdef CONFIG_FTWDT010_WATCHDOG
  73        /*
  74         * workaround: if we use CONFIG_HW_WATCHDOG with ftwdt010, will lead
  75         * automatic hardware reset when booting Linux.
  76         * Please do not use CONFIG_HW_WATCHDOG and WATCHDOG_RESET() here.
  77         */
  78        ftwdt010_wdt_reset();
  79        while (1)
  80                ;
  81#endif /* CONFIG_FTWDT010_WATCHDOG */
  82
  83        /*NOTREACHED*/
  84}
  85
  86static inline unsigned long CACHE_LINE_SIZE(enum cache_t cache)
  87{
  88        if (cache == ICACHE)
  89                return 8 << (((GET_ICM_CFG() & ICM_CFG_MSK_ISZ) \
  90                                        >> ICM_CFG_OFF_ISZ) - 1);
  91        else
  92                return 8 << (((GET_DCM_CFG() & DCM_CFG_MSK_DSZ) \
  93                                        >> DCM_CFG_OFF_DSZ) - 1);
  94}
  95
  96void dcache_flush_range(unsigned long start, unsigned long end)
  97{
  98        unsigned long line_size;
  99
 100        line_size = CACHE_LINE_SIZE(DCACHE);
 101
 102        while (end > start) {
 103                __asm__ volatile ("\n\tcctl %0, L1D_VA_WB" : : "r"(start));
 104                __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL" : : "r"(start));
 105                start += line_size;
 106        }
 107}
 108
 109void icache_inval_range(unsigned long start, unsigned long end)
 110{
 111        unsigned long line_size;
 112
 113        line_size = CACHE_LINE_SIZE(ICACHE);
 114        while (end > start) {
 115                __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL" : : "r"(start));
 116                start += line_size;
 117        }
 118}
 119
 120void flush_cache(unsigned long addr, unsigned long size)
 121{
 122        dcache_flush_range(addr, addr + size);
 123        icache_inval_range(addr, addr + size);
 124}
 125
 126void icache_enable(void)
 127{
 128        __asm__ __volatile__ (
 129                "mfsr   $p0, $mr8\n\t"
 130                "ori    $p0, $p0, 0x01\n\t"
 131                "mtsr   $p0, $mr8\n\t"
 132                "isb\n\t"
 133        );
 134}
 135
 136void icache_disable(void)
 137{
 138        __asm__ __volatile__ (
 139                "mfsr   $p0, $mr8\n\t"
 140                "li     $p1, ~0x01\n\t"
 141                "and    $p0, $p0, $p1\n\t"
 142                "mtsr   $p0, $mr8\n\t"
 143                "isb\n\t"
 144        );
 145}
 146
 147int icache_status(void)
 148{
 149        int ret;
 150
 151         __asm__ __volatile__ (
 152                "mfsr   $p0, $mr8\n\t"
 153                "andi   %0,  $p0, 0x01\n\t"
 154                : "=r" (ret)
 155                :
 156                : "memory"
 157        );
 158
 159         return ret;
 160}
 161
 162void dcache_enable(void)
 163{
 164         __asm__ __volatile__ (
 165                "mfsr   $p0, $mr8\n\t"
 166                "ori    $p0, $p0, 0x02\n\t"
 167                "mtsr   $p0, $mr8\n\t"
 168                "isb\n\t"
 169        );
 170}
 171
 172void dcache_disable(void)
 173{
 174         __asm__ __volatile__ (
 175                "mfsr   $p0, $mr8\n\t"
 176                "li     $p1, ~0x02\n\t"
 177                "and    $p0, $p0, $p1\n\t"
 178                "mtsr   $p0, $mr8\n\t"
 179                "isb\n\t"
 180        );
 181}
 182
 183int dcache_status(void)
 184{
 185        int ret;
 186
 187        __asm__ __volatile__ (
 188                "mfsr   $p0, $mr8\n\t"
 189                "andi   %0, $p0, 0x02\n\t"
 190                : "=r" (ret)
 191                :
 192                : "memory"
 193         );
 194
 195         return ret;
 196}
 197