1*2874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
24ccf4beaSWolfram Sang /*
34ccf4beaSWolfram Sang * Copyright (C) 1999 ARM Limited
44ccf4beaSWolfram Sang * Copyright (C) 2000 Deep Blue Solutions Ltd
54ccf4beaSWolfram Sang * Copyright 2006-2007,2010 Freescale Semiconductor, Inc. All Rights Reserved.
64ccf4beaSWolfram Sang * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
74ccf4beaSWolfram Sang * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.com
84ccf4beaSWolfram Sang * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
94ccf4beaSWolfram Sang */
104ccf4beaSWolfram Sang
114ccf4beaSWolfram Sang #include <linux/io.h>
124ccf4beaSWolfram Sang #include <linux/errno.h>
134ccf4beaSWolfram Sang #include <linux/delay.h>
14b6d4f322SRasmus Villemoes #include <linux/compiler.h>
15b6d4f322SRasmus Villemoes #include <linux/export.h>
164ccf4beaSWolfram Sang #include <linux/stmp_device.h>
174ccf4beaSWolfram Sang
184ccf4beaSWolfram Sang #define STMP_MODULE_CLKGATE (1 << 30)
194ccf4beaSWolfram Sang #define STMP_MODULE_SFTRST (1 << 31)
204ccf4beaSWolfram Sang
214ccf4beaSWolfram Sang /*
224ccf4beaSWolfram Sang * Clear the bit and poll it cleared. This is usually called with
234ccf4beaSWolfram Sang * a reset address and mask being either SFTRST(bit 31) or CLKGATE
244ccf4beaSWolfram Sang * (bit 30).
254ccf4beaSWolfram Sang */
stmp_clear_poll_bit(void __iomem * addr,u32 mask)264ccf4beaSWolfram Sang static int stmp_clear_poll_bit(void __iomem *addr, u32 mask)
274ccf4beaSWolfram Sang {
284ccf4beaSWolfram Sang int timeout = 0x400;
294ccf4beaSWolfram Sang
304ccf4beaSWolfram Sang writel(mask, addr + STMP_OFFSET_REG_CLR);
314ccf4beaSWolfram Sang udelay(1);
324ccf4beaSWolfram Sang while ((readl(addr) & mask) && --timeout)
334ccf4beaSWolfram Sang /* nothing */;
344ccf4beaSWolfram Sang
354ccf4beaSWolfram Sang return !timeout;
364ccf4beaSWolfram Sang }
374ccf4beaSWolfram Sang
stmp_reset_block(void __iomem * reset_addr)384ccf4beaSWolfram Sang int stmp_reset_block(void __iomem *reset_addr)
394ccf4beaSWolfram Sang {
404ccf4beaSWolfram Sang int ret;
414ccf4beaSWolfram Sang int timeout = 0x400;
424ccf4beaSWolfram Sang
434ccf4beaSWolfram Sang /* clear and poll SFTRST */
444ccf4beaSWolfram Sang ret = stmp_clear_poll_bit(reset_addr, STMP_MODULE_SFTRST);
454ccf4beaSWolfram Sang if (unlikely(ret))
464ccf4beaSWolfram Sang goto error;
474ccf4beaSWolfram Sang
484ccf4beaSWolfram Sang /* clear CLKGATE */
494ccf4beaSWolfram Sang writel(STMP_MODULE_CLKGATE, reset_addr + STMP_OFFSET_REG_CLR);
504ccf4beaSWolfram Sang
514ccf4beaSWolfram Sang /* set SFTRST to reset the block */
524ccf4beaSWolfram Sang writel(STMP_MODULE_SFTRST, reset_addr + STMP_OFFSET_REG_SET);
534ccf4beaSWolfram Sang udelay(1);
544ccf4beaSWolfram Sang
554ccf4beaSWolfram Sang /* poll CLKGATE becoming set */
564ccf4beaSWolfram Sang while ((!(readl(reset_addr) & STMP_MODULE_CLKGATE)) && --timeout)
574ccf4beaSWolfram Sang /* nothing */;
584ccf4beaSWolfram Sang if (unlikely(!timeout))
594ccf4beaSWolfram Sang goto error;
604ccf4beaSWolfram Sang
614ccf4beaSWolfram Sang /* clear and poll SFTRST */
624ccf4beaSWolfram Sang ret = stmp_clear_poll_bit(reset_addr, STMP_MODULE_SFTRST);
634ccf4beaSWolfram Sang if (unlikely(ret))
644ccf4beaSWolfram Sang goto error;
654ccf4beaSWolfram Sang
664ccf4beaSWolfram Sang /* clear and poll CLKGATE */
674ccf4beaSWolfram Sang ret = stmp_clear_poll_bit(reset_addr, STMP_MODULE_CLKGATE);
684ccf4beaSWolfram Sang if (unlikely(ret))
694ccf4beaSWolfram Sang goto error;
704ccf4beaSWolfram Sang
714ccf4beaSWolfram Sang return 0;
724ccf4beaSWolfram Sang
734ccf4beaSWolfram Sang error:
744ccf4beaSWolfram Sang pr_err("%s(%p): module reset timeout\n", __func__, reset_addr);
754ccf4beaSWolfram Sang return -ETIMEDOUT;
764ccf4beaSWolfram Sang }
774ccf4beaSWolfram Sang EXPORT_SYMBOL(stmp_reset_block);
78