diff options
Diffstat (limited to 'arch/arm/mach-prima2/rstc.c')
-rw-r--r-- | arch/arm/mach-prima2/rstc.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/arch/arm/mach-prima2/rstc.c b/arch/arm/mach-prima2/rstc.c new file mode 100644 index 00000000000..492cfa8d261 --- /dev/null +++ b/arch/arm/mach-prima2/rstc.c | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * reset controller for CSR SiRFprimaII | ||
3 | * | ||
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | ||
5 | * | ||
6 | * Licensed under GPLv2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/mutex.h> | ||
11 | #include <linux/io.h> | ||
12 | #include <linux/delay.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/of.h> | ||
15 | #include <linux/of_address.h> | ||
16 | |||
17 | void __iomem *sirfsoc_rstc_base; | ||
18 | static DEFINE_MUTEX(rstc_lock); | ||
19 | |||
20 | static struct of_device_id rstc_ids[] = { | ||
21 | { .compatible = "sirf,prima2-rstc" }, | ||
22 | {}, | ||
23 | }; | ||
24 | |||
25 | static int __init sirfsoc_of_rstc_init(void) | ||
26 | { | ||
27 | struct device_node *np; | ||
28 | |||
29 | np = of_find_matching_node(NULL, rstc_ids); | ||
30 | if (!np) | ||
31 | panic("unable to find compatible rstc node in dtb\n"); | ||
32 | |||
33 | sirfsoc_rstc_base = of_iomap(np, 0); | ||
34 | if (!sirfsoc_rstc_base) | ||
35 | panic("unable to map rstc cpu registers\n"); | ||
36 | |||
37 | of_node_put(np); | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | early_initcall(sirfsoc_of_rstc_init); | ||
42 | |||
43 | int sirfsoc_reset_device(struct device *dev) | ||
44 | { | ||
45 | const unsigned int *prop = of_get_property(dev->of_node, "reset-bit", NULL); | ||
46 | unsigned int reset_bit; | ||
47 | |||
48 | if (!prop) | ||
49 | return -ENODEV; | ||
50 | |||
51 | reset_bit = be32_to_cpup(prop); | ||
52 | |||
53 | mutex_lock(&rstc_lock); | ||
54 | |||
55 | /* | ||
56 | * Writing 1 to this bit resets corresponding block. Writing 0 to this | ||
57 | * bit de-asserts reset signal of the corresponding block. | ||
58 | * datasheet doesn't require explicit delay between the set and clear | ||
59 | * of reset bit. it could be shorter if tests pass. | ||
60 | */ | ||
61 | writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | reset_bit, | ||
62 | sirfsoc_rstc_base + (reset_bit / 32) * 4); | ||
63 | msleep(10); | ||
64 | writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~reset_bit, | ||
65 | sirfsoc_rstc_base + (reset_bit / 32) * 4); | ||
66 | |||
67 | mutex_unlock(&rstc_lock); | ||
68 | |||
69 | return 0; | ||
70 | } | ||