1ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler/* 2ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * Copyright (C) 1999 ARM Limited 3ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * Copyright (C) 2000 Deep Blue Solutions Ltd 4ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * Copyright 2006-2007,2010 Freescale Semiconductor, Inc. All Rights Reserved. 5ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * Copyright 2008 Juergen Beisert, kernel@pengutronix.de 6ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.com 7ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * 8ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * This program is free software; you can redistribute it and/or modify 9ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * it under the terms of the GNU General Public License as published by 10ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * the Free Software Foundation; either version 2 of the License, or 11ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * (at your option) any later version. 12ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * 13ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * This program is distributed in the hope that it will be useful, 14ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * but WITHOUT ANY WARRANTY; without even the implied warranty of 15ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * GNU General Public License for more details. 17ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler */ 18ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 19ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include <linux/kernel.h> 20ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include <linux/clk.h> 21ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include <linux/io.h> 22ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include <linux/err.h> 23ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include <linux/delay.h> 24ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include <linux/init.h> 25ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include <linux/module.h> 26ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 27ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include <asm/proc-fns.h> 285a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <asm/system_misc.h> 29ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 30ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include <mach/mxs.h> 31ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#include <mach/common.h> 32ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 33ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#define MX23_CLKCTRL_RESET_OFFSET 0x120 34ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#define MX28_CLKCTRL_RESET_OFFSET 0x1e0 35ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#define MXS_CLKCTRL_RESET_CHIP (1 << 1) 36ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 37ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#define MXS_MODULE_CLKGATE (1 << 30) 38ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#define MXS_MODULE_SFTRST (1 << 31) 39ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 40ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler#define CLKCTRL_TIMEOUT 10 /* 10 ms */ 41ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 42ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winklerstatic void __iomem *mxs_clkctrl_reset_addr; 43ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 44ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler/* 45cb43e23435a66d5ed90f804af9efe9096503979fTomas Winkler * Reset the system. It is called by machine_restart(). 46ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler */ 47ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winklervoid mxs_restart(char mode, const char *cmd) 48ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler{ 49ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler /* reset the chip */ 50ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler __mxs_setl(MXS_CLKCTRL_RESET_CHIP, mxs_clkctrl_reset_addr); 510e4817470be8d233fb58b5af7b938185dae94d67Tomas Winkler 52ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler pr_err("Failed to assert the chip reset\n"); 53fe45332ed289d91e57eca11bfd1ca75d6e420ab4Tomas Winkler 54fe45332ed289d91e57eca11bfd1ca75d6e420ab4Tomas Winkler /* Delay to allow the serial port to show the message */ 55fe45332ed289d91e57eca11bfd1ca75d6e420ab4Tomas Winkler mdelay(50); 56fe45332ed289d91e57eca11bfd1ca75d6e420ab4Tomas Winkler 57fe45332ed289d91e57eca11bfd1ca75d6e420ab4Tomas Winkler /* We'll take a jump through zero as a poor second */ 58fe45332ed289d91e57eca11bfd1ca75d6e420ab4Tomas Winkler soft_restart(0); 59fe45332ed289d91e57eca11bfd1ca75d6e420ab4Tomas Winkler} 60fe45332ed289d91e57eca11bfd1ca75d6e420ab4Tomas Winkler 61fe45332ed289d91e57eca11bfd1ca75d6e420ab4Tomas Winklerstatic int __init mxs_arch_reset_init(void) 62fe45332ed289d91e57eca11bfd1ca75d6e420ab4Tomas Winkler{ 63fe45332ed289d91e57eca11bfd1ca75d6e420ab4Tomas Winkler struct clk *clk; 64fe45332ed289d91e57eca11bfd1ca75d6e420ab4Tomas Winkler 65fe45332ed289d91e57eca11bfd1ca75d6e420ab4Tomas Winkler mxs_clkctrl_reset_addr = MXS_IO_ADDRESS(MXS_CLKCTRL_BASE_ADDR) + 66fe45332ed289d91e57eca11bfd1ca75d6e420ab4Tomas Winkler (cpu_is_mx23() ? MX23_CLKCTRL_RESET_OFFSET : 67ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler MX28_CLKCTRL_RESET_OFFSET); 68ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 69ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler clk = clk_get_sys("rtc", NULL); 70ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler if (!IS_ERR(clk)) 71ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler clk_prepare_enable(clk); 72ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 73ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler return 0; 74ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler} 75ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winklercore_initcall(mxs_arch_reset_init); 76ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 77ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler/* 78ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * Clear the bit and poll it cleared. This is usually called with 79ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * a reset address and mask being either SFTRST(bit 31) or CLKGATE 80ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * (bit 30). 81ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler */ 82ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winklerstatic int clear_poll_bit(void __iomem *addr, u32 mask) 83ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler{ 840df828f670b1fd8c469f3d60472ddca0d0f51fcfTomas Winkler int timeout = 0x400; 85ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 86ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler /* clear the bit */ 87ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler __mxs_clrl(mask, addr); 88ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 89ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler /* 90ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * SFTRST needs 3 GPMI clocks to settle, the reference manual 91ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler * recommends to wait 1us. 9251f50f815778b91c699fbcc3aac0dda891a7b795Tejun Heo */ 93ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler udelay(1); 94ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 95ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler /* poll the bit becoming clear */ 96ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler while ((__raw_readl(addr) & mask) && --timeout) 97ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler /* nothing */; 98ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 99ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler return !timeout; 100ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler} 101ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 102ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winklerint mxs_reset_block(void __iomem *reset_addr) 103ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler{ 104ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler int ret; 105ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler int timeout = 0x400; 106ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 107ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler /* clear and poll SFTRST */ 108ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler ret = clear_poll_bit(reset_addr, MXS_MODULE_SFTRST); 109ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler if (unlikely(ret)) 110ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler goto error; 111ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 112ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler /* clear CLKGATE */ 113ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler __mxs_clrl(MXS_MODULE_CLKGATE, reset_addr); 114ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 115ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler /* set SFTRST to reset the block */ 116ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler __mxs_setl(MXS_MODULE_SFTRST, reset_addr); 117ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler udelay(1); 118ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 119ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler /* poll CLKGATE becoming set */ 120ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler while ((!(__raw_readl(reset_addr) & MXS_MODULE_CLKGATE)) && --timeout) 121ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler /* nothing */; 122ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler if (unlikely(!timeout)) 123ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler goto error; 124ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 125ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler /* clear and poll SFTRST */ 126ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler ret = clear_poll_bit(reset_addr, MXS_MODULE_SFTRST); 127ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler if (unlikely(ret)) 128ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler goto error; 129ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 130ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler /* clear and poll CLKGATE */ 131ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler ret = clear_poll_bit(reset_addr, MXS_MODULE_CLKGATE); 132ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler if (unlikely(ret)) 133ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler goto error; 134ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 135ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler return 0; 136ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 137ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winklererror: 138ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler pr_err("%s(%p): module reset timeout\n", __func__, reset_addr); 139ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler return -ETIMEDOUT; 140ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler} 141ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas WinklerEXPORT_SYMBOL(mxs_reset_block); 142ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 143ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winklerint mxs_clkctrl_timeout(unsigned int reg_offset, unsigned int mask) 144ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler{ 145ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler unsigned long timeout = jiffies + msecs_to_jiffies(CLKCTRL_TIMEOUT); 146ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler while (readl_relaxed(MXS_IO_ADDRESS(MXS_CLKCTRL_BASE_ADDR) 147ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler + reg_offset) & mask) { 148ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler if (time_after(jiffies, timeout)) { 149ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler pr_err("Timeout at CLKCTRL + 0x%x\n", reg_offset); 150ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler return -ETIMEDOUT; 151ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler } 152ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler } 153ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler 154ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler return 0; 1550df828f670b1fd8c469f3d60472ddca0d0f51fcfTomas Winkler} 156ab69a5ae2bdc0b5e20e935a7b75f30aa3f4c3baeTomas Winkler