Logo Search packages:      
Sourcecode: linux version File versions  Download package

system.c

/*
 * Copyright (C) 1999 ARM Limited
 * Copyright (C) 2000 Deep Blue Solutions Ltd
 * Copyright 2006-2007,2010 Freescale Semiconductor, Inc. All Rights Reserved.
 * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
 * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.com
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/init.h>

#include <asm/proc-fns.h>
#include <asm/system.h>

#include <mach/mxs.h>
#include <mach/common.h>

#define MX23_CLKCTRL_RESET_OFFSET   0x120
#define MX28_CLKCTRL_RESET_OFFSET   0x1e0
#define MXS_CLKCTRL_RESET_CHIP            (1 << 1)

#define MXS_MODULE_CLKGATE          (1 << 30)
#define MXS_MODULE_SFTRST           (1 << 31)

static void __iomem *mxs_clkctrl_reset_addr;

/*
 * Reset the system. It is called by machine_restart().
 */
void arch_reset(char mode, const char *cmd)
{
      /* reset the chip */
      __mxs_setl(MXS_CLKCTRL_RESET_CHIP, mxs_clkctrl_reset_addr);

      pr_err("Failed to assert the chip reset\n");

      /* Delay to allow the serial port to show the message */
      mdelay(50);

      /* We'll take a jump through zero as a poor second */
      cpu_reset(0);
}

static int __init mxs_arch_reset_init(void)
{
      struct clk *clk;

      mxs_clkctrl_reset_addr = MXS_IO_ADDRESS(MXS_CLKCTRL_BASE_ADDR) +
                        (cpu_is_mx23() ? MX23_CLKCTRL_RESET_OFFSET :
                                     MX28_CLKCTRL_RESET_OFFSET);

      clk = clk_get_sys("rtc", NULL);
      if (!IS_ERR(clk))
            clk_enable(clk);

      return 0;
}
core_initcall(mxs_arch_reset_init);

/*
 * Clear the bit and poll it cleared.  This is usually called with
 * a reset address and mask being either SFTRST(bit 31) or CLKGATE
 * (bit 30).
 */
static int clear_poll_bit(void __iomem *addr, u32 mask)
{
      int timeout = 0x400;

      /* clear the bit */
      __mxs_clrl(mask, addr);

      /*
       * SFTRST needs 3 GPMI clocks to settle, the reference manual
       * recommends to wait 1us.
       */
      udelay(1);

      /* poll the bit becoming clear */
      while ((__raw_readl(addr) & mask) && --timeout)
            /* nothing */;

      return !timeout;
}

int mxs_reset_block(void __iomem *reset_addr)
{
      int ret;
      int timeout = 0x400;

      /* clear and poll SFTRST */
      ret = clear_poll_bit(reset_addr, MXS_MODULE_SFTRST);
      if (unlikely(ret))
            goto error;

      /* clear CLKGATE */
      __mxs_clrl(MXS_MODULE_CLKGATE, reset_addr);

      /* set SFTRST to reset the block */
      __mxs_setl(MXS_MODULE_SFTRST, reset_addr);
      udelay(1);

      /* poll CLKGATE becoming set */
      while ((!(__raw_readl(reset_addr) & MXS_MODULE_CLKGATE)) && --timeout)
            /* nothing */;
      if (unlikely(!timeout))
            goto error;

      /* clear and poll SFTRST */
      ret = clear_poll_bit(reset_addr, MXS_MODULE_SFTRST);
      if (unlikely(ret))
            goto error;

      /* clear and poll CLKGATE */
      ret = clear_poll_bit(reset_addr, MXS_MODULE_CLKGATE);
      if (unlikely(ret))
            goto error;

      return 0;

error:
      pr_err("%s(%p): module reset timeout\n", __func__, reset_addr);
      return -ETIMEDOUT;
}

Generated by  Doxygen 1.6.0   Back to index