Back to home page

LXR

 
 

    


0001 /*
0002  * Copyright (C) 1999 ARM Limited
0003  * Copyright (C) 2000 Deep Blue Solutions Ltd
0004  * Copyright 2006-2007,2010 Freescale Semiconductor, Inc. All Rights Reserved.
0005  * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
0006  * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.com
0007  * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
0008  *
0009  * This program is free software; you can redistribute it and/or modify
0010  * it under the terms of the GNU General Public License as published by
0011  * the Free Software Foundation; either version 2 of the License, or
0012  * (at your option) any later version.
0013  */
0014 
0015 #include <linux/io.h>
0016 #include <linux/errno.h>
0017 #include <linux/delay.h>
0018 #include <linux/compiler.h>
0019 #include <linux/export.h>
0020 #include <linux/stmp_device.h>
0021 
0022 #define STMP_MODULE_CLKGATE (1 << 30)
0023 #define STMP_MODULE_SFTRST  (1 << 31)
0024 
0025 /*
0026  * Clear the bit and poll it cleared.  This is usually called with
0027  * a reset address and mask being either SFTRST(bit 31) or CLKGATE
0028  * (bit 30).
0029  */
0030 static int stmp_clear_poll_bit(void __iomem *addr, u32 mask)
0031 {
0032     int timeout = 0x400;
0033 
0034     writel(mask, addr + STMP_OFFSET_REG_CLR);
0035     udelay(1);
0036     while ((readl(addr) & mask) && --timeout)
0037         /* nothing */;
0038 
0039     return !timeout;
0040 }
0041 
0042 int stmp_reset_block(void __iomem *reset_addr)
0043 {
0044     int ret;
0045     int timeout = 0x400;
0046 
0047     /* clear and poll SFTRST */
0048     ret = stmp_clear_poll_bit(reset_addr, STMP_MODULE_SFTRST);
0049     if (unlikely(ret))
0050         goto error;
0051 
0052     /* clear CLKGATE */
0053     writel(STMP_MODULE_CLKGATE, reset_addr + STMP_OFFSET_REG_CLR);
0054 
0055     /* set SFTRST to reset the block */
0056     writel(STMP_MODULE_SFTRST, reset_addr + STMP_OFFSET_REG_SET);
0057     udelay(1);
0058 
0059     /* poll CLKGATE becoming set */
0060     while ((!(readl(reset_addr) & STMP_MODULE_CLKGATE)) && --timeout)
0061         /* nothing */;
0062     if (unlikely(!timeout))
0063         goto error;
0064 
0065     /* clear and poll SFTRST */
0066     ret = stmp_clear_poll_bit(reset_addr, STMP_MODULE_SFTRST);
0067     if (unlikely(ret))
0068         goto error;
0069 
0070     /* clear and poll CLKGATE */
0071     ret = stmp_clear_poll_bit(reset_addr, STMP_MODULE_CLKGATE);
0072     if (unlikely(ret))
0073         goto error;
0074 
0075     return 0;
0076 
0077 error:
0078     pr_err("%s(%p): module reset timeout\n", __func__, reset_addr);
0079     return -ETIMEDOUT;
0080 }
0081 EXPORT_SYMBOL(stmp_reset_block);