1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (C) 1999 ARM Limited |
4 | * Copyright (C) 2000 Deep Blue Solutions Ltd |
5 | * Copyright 2006-2007,2010 Freescale Semiconductor, Inc. All Rights Reserved. |
6 | * Copyright 2008 Juergen Beisert, kernel@pengutronix.de |
7 | * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.com |
8 | * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K. |
9 | */ |
10 | |
11 | #include <linux/io.h> |
12 | #include <linux/errno.h> |
13 | #include <linux/delay.h> |
14 | #include <linux/compiler.h> |
15 | #include <linux/export.h> |
16 | #include <linux/stmp_device.h> |
17 | |
18 | #define STMP_MODULE_CLKGATE (1 << 30) |
19 | #define STMP_MODULE_SFTRST (1 << 31) |
20 | |
21 | /* |
22 | * Clear the bit and poll it cleared. This is usually called with |
23 | * a reset address and mask being either SFTRST(bit 31) or CLKGATE |
24 | * (bit 30). |
25 | */ |
26 | static int stmp_clear_poll_bit(void __iomem *addr, u32 mask) |
27 | { |
28 | int timeout = 0x400; |
29 | |
30 | writel(val: mask, addr: addr + STMP_OFFSET_REG_CLR); |
31 | udelay(1); |
32 | while ((readl(addr) & mask) && --timeout) |
33 | /* nothing */; |
34 | |
35 | return !timeout; |
36 | } |
37 | |
38 | int stmp_reset_block(void __iomem *reset_addr) |
39 | { |
40 | int ret; |
41 | int timeout = 0x400; |
42 | |
43 | /* clear and poll SFTRST */ |
44 | ret = stmp_clear_poll_bit(addr: reset_addr, STMP_MODULE_SFTRST); |
45 | if (unlikely(ret)) |
46 | goto error; |
47 | |
48 | /* clear CLKGATE */ |
49 | writel(STMP_MODULE_CLKGATE, addr: reset_addr + STMP_OFFSET_REG_CLR); |
50 | |
51 | /* set SFTRST to reset the block */ |
52 | writel(STMP_MODULE_SFTRST, addr: reset_addr + STMP_OFFSET_REG_SET); |
53 | udelay(1); |
54 | |
55 | /* poll CLKGATE becoming set */ |
56 | while ((!(readl(addr: reset_addr) & STMP_MODULE_CLKGATE)) && --timeout) |
57 | /* nothing */; |
58 | if (unlikely(!timeout)) |
59 | goto error; |
60 | |
61 | /* clear and poll SFTRST */ |
62 | ret = stmp_clear_poll_bit(addr: reset_addr, STMP_MODULE_SFTRST); |
63 | if (unlikely(ret)) |
64 | goto error; |
65 | |
66 | /* clear and poll CLKGATE */ |
67 | ret = stmp_clear_poll_bit(addr: reset_addr, STMP_MODULE_CLKGATE); |
68 | if (unlikely(ret)) |
69 | goto error; |
70 | |
71 | return 0; |
72 | |
73 | error: |
74 | pr_err("%s(%p): module reset timeout\n" , __func__, reset_addr); |
75 | return -ETIMEDOUT; |
76 | } |
77 | EXPORT_SYMBOL(stmp_reset_block); |
78 | |