Commit | Line | Data |
---|---|---|
a636cd6c | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
684f7414 | 2 | /* |
b1999477 | 3 | * RTC I/O Bridge interfaces for CSR SiRFprimaII/atlas7 |
684f7414 ZS |
4 | * ARM access the registers of SYSRTC, GPSRTC and PWRC through this module |
5 | * | |
6 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | |
684f7414 ZS |
7 | */ |
8 | ||
9 | #include <linux/kernel.h> | |
10 | #include <linux/module.h> | |
11 | #include <linux/io.h> | |
b1999477 | 12 | #include <linux/regmap.h> |
684f7414 ZS |
13 | #include <linux/of.h> |
14 | #include <linux/of_address.h> | |
15 | #include <linux/of_device.h> | |
16 | #include <linux/of_platform.h> | |
17 | ||
18 | #define SIRFSOC_CPUIOBRG_CTRL 0x00 | |
19 | #define SIRFSOC_CPUIOBRG_WRBE 0x04 | |
20 | #define SIRFSOC_CPUIOBRG_ADDR 0x08 | |
21 | #define SIRFSOC_CPUIOBRG_DATA 0x0c | |
22 | ||
23 | /* | |
24 | * suspend asm codes will access this address to make system deepsleep | |
25 | * after DRAM becomes self-refresh | |
26 | */ | |
27 | void __iomem *sirfsoc_rtciobrg_base; | |
28 | static DEFINE_SPINLOCK(rtciobrg_lock); | |
29 | ||
30 | /* | |
31 | * symbols without lock are only used by suspend asm codes | |
32 | * and these symbols are not exported too | |
33 | */ | |
34 | void sirfsoc_rtc_iobrg_wait_sync(void) | |
35 | { | |
36 | while (readl_relaxed(sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL)) | |
37 | cpu_relax(); | |
38 | } | |
39 | ||
40 | void sirfsoc_rtc_iobrg_besyncing(void) | |
41 | { | |
42 | unsigned long flags; | |
43 | ||
44 | spin_lock_irqsave(&rtciobrg_lock, flags); | |
45 | ||
46 | sirfsoc_rtc_iobrg_wait_sync(); | |
47 | ||
48 | spin_unlock_irqrestore(&rtciobrg_lock, flags); | |
49 | } | |
50 | EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_besyncing); | |
51 | ||
52 | u32 __sirfsoc_rtc_iobrg_readl(u32 addr) | |
53 | { | |
54 | sirfsoc_rtc_iobrg_wait_sync(); | |
55 | ||
56 | writel_relaxed(0x00, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_WRBE); | |
57 | writel_relaxed(addr, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_ADDR); | |
58 | writel_relaxed(0x01, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL); | |
59 | ||
60 | sirfsoc_rtc_iobrg_wait_sync(); | |
61 | ||
62 | return readl_relaxed(sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_DATA); | |
63 | } | |
64 | ||
65 | u32 sirfsoc_rtc_iobrg_readl(u32 addr) | |
66 | { | |
67 | unsigned long flags, val; | |
68 | ||
b1999477 | 69 | /* TODO: add hwspinlock to sync with M3 */ |
684f7414 ZS |
70 | spin_lock_irqsave(&rtciobrg_lock, flags); |
71 | ||
72 | val = __sirfsoc_rtc_iobrg_readl(addr); | |
73 | ||
74 | spin_unlock_irqrestore(&rtciobrg_lock, flags); | |
75 | ||
76 | return val; | |
77 | } | |
78 | EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_readl); | |
79 | ||
80 | void sirfsoc_rtc_iobrg_pre_writel(u32 val, u32 addr) | |
81 | { | |
82 | sirfsoc_rtc_iobrg_wait_sync(); | |
83 | ||
84 | writel_relaxed(0xf1, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_WRBE); | |
85 | writel_relaxed(addr, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_ADDR); | |
86 | ||
87 | writel_relaxed(val, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_DATA); | |
88 | } | |
89 | ||
90 | void sirfsoc_rtc_iobrg_writel(u32 val, u32 addr) | |
91 | { | |
92 | unsigned long flags; | |
93 | ||
b1999477 | 94 | /* TODO: add hwspinlock to sync with M3 */ |
684f7414 ZS |
95 | spin_lock_irqsave(&rtciobrg_lock, flags); |
96 | ||
97 | sirfsoc_rtc_iobrg_pre_writel(val, addr); | |
98 | ||
99 | writel_relaxed(0x01, sirfsoc_rtciobrg_base + SIRFSOC_CPUIOBRG_CTRL); | |
100 | ||
101 | sirfsoc_rtc_iobrg_wait_sync(); | |
102 | ||
103 | spin_unlock_irqrestore(&rtciobrg_lock, flags); | |
104 | } | |
105 | EXPORT_SYMBOL_GPL(sirfsoc_rtc_iobrg_writel); | |
106 | ||
b1999477 GZ |
107 | |
108 | static int regmap_iobg_regwrite(void *context, unsigned int reg, | |
109 | unsigned int val) | |
110 | { | |
111 | sirfsoc_rtc_iobrg_writel(val, reg); | |
112 | return 0; | |
113 | } | |
114 | ||
115 | static int regmap_iobg_regread(void *context, unsigned int reg, | |
116 | unsigned int *val) | |
117 | { | |
118 | *val = (u32)sirfsoc_rtc_iobrg_readl(reg); | |
119 | return 0; | |
120 | } | |
121 | ||
122 | static struct regmap_bus regmap_iobg = { | |
123 | .reg_write = regmap_iobg_regwrite, | |
124 | .reg_read = regmap_iobg_regread, | |
125 | }; | |
126 | ||
127 | /** | |
128 | * devm_regmap_init_iobg(): Initialise managed register map | |
129 | * | |
130 | * @iobg: Device that will be interacted with | |
131 | * @config: Configuration for register map | |
132 | * | |
133 | * The return value will be an ERR_PTR() on error or a valid pointer | |
134 | * to a struct regmap. The regmap will be automatically freed by the | |
135 | * device management code. | |
136 | */ | |
137 | struct regmap *devm_regmap_init_iobg(struct device *dev, | |
138 | const struct regmap_config *config) | |
139 | { | |
140 | const struct regmap_bus *bus = ®map_iobg; | |
141 | ||
142 | return devm_regmap_init(dev, bus, dev, config); | |
143 | } | |
144 | EXPORT_SYMBOL_GPL(devm_regmap_init_iobg); | |
145 | ||
684f7414 ZS |
146 | static const struct of_device_id rtciobrg_ids[] = { |
147 | { .compatible = "sirf,prima2-rtciobg" }, | |
148 | {} | |
149 | }; | |
150 | ||
351a102d | 151 | static int sirfsoc_rtciobrg_probe(struct platform_device *op) |
684f7414 ZS |
152 | { |
153 | struct device_node *np = op->dev.of_node; | |
154 | ||
155 | sirfsoc_rtciobrg_base = of_iomap(np, 0); | |
156 | if (!sirfsoc_rtciobrg_base) | |
157 | panic("unable to map rtc iobrg registers\n"); | |
158 | ||
159 | return 0; | |
160 | } | |
161 | ||
162 | static struct platform_driver sirfsoc_rtciobrg_driver = { | |
163 | .probe = sirfsoc_rtciobrg_probe, | |
164 | .driver = { | |
165 | .name = "sirfsoc-rtciobrg", | |
684f7414 ZS |
166 | .of_match_table = rtciobrg_ids, |
167 | }, | |
168 | }; | |
169 | ||
170 | static int __init sirfsoc_rtciobrg_init(void) | |
171 | { | |
172 | return platform_driver_register(&sirfsoc_rtciobrg_driver); | |
173 | } | |
174 | postcore_initcall(sirfsoc_rtciobrg_init); | |
175 | ||
b1999477 GZ |
176 | MODULE_AUTHOR("Zhiwu Song <zhiwu.song@csr.com>"); |
177 | MODULE_AUTHOR("Barry Song <baohua.song@csr.com>"); | |
684f7414 | 178 | MODULE_DESCRIPTION("CSR SiRFprimaII rtc io bridge"); |
5b7356bb | 179 | MODULE_LICENSE("GPL v2"); |