blob: 70922e9ac27fa85991fd23deec7d467b71741522 [file] [log] [blame]
Joachim Eastwoodc392b652015-05-06 00:10:26 +02001/*
2 * Reset driver for NXP LPC18xx/43xx Reset Generation Unit (RGU).
3 *
4 * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 */
11
12#include <linux/clk.h>
13#include <linux/delay.h>
14#include <linux/err.h>
15#include <linux/io.h>
16#include <linux/module.h>
17#include <linux/of.h>
18#include <linux/platform_device.h>
19#include <linux/reboot.h>
20#include <linux/reset-controller.h>
21#include <linux/spinlock.h>
22
23/* LPC18xx RGU registers */
24#define LPC18XX_RGU_CTRL0 0x100
25#define LPC18XX_RGU_CTRL1 0x104
26#define LPC18XX_RGU_ACTIVE_STATUS0 0x150
27#define LPC18XX_RGU_ACTIVE_STATUS1 0x154
28
29#define LPC18XX_RGU_RESETS_PER_REG 32
30
31/* Internal reset outputs */
32#define LPC18XX_RGU_CORE_RST 0
33#define LPC43XX_RGU_M0SUB_RST 12
34#define LPC43XX_RGU_M0APP_RST 56
35
36struct lpc18xx_rgu_data {
37 struct reset_controller_dev rcdev;
38 struct clk *clk_delay;
39 struct clk *clk_reg;
40 void __iomem *base;
41 spinlock_t lock;
42 u32 delay_us;
43};
44
45#define to_rgu_data(p) container_of(p, struct lpc18xx_rgu_data, rcdev)
46
47static void __iomem *rgu_base;
48
49static int lpc18xx_rgu_restart(struct notifier_block *this, unsigned long mode,
50 void *cmd)
51{
52 writel(BIT(LPC18XX_RGU_CORE_RST), rgu_base + LPC18XX_RGU_CTRL0);
53 mdelay(2000);
54
55 pr_emerg("%s: unable to restart system\n", __func__);
56
57 return NOTIFY_DONE;
58}
59
60static struct notifier_block lpc18xx_rgu_restart_nb = {
61 .notifier_call = lpc18xx_rgu_restart,
62 .priority = 192,
63};
64
65/*
66 * The LPC18xx RGU has mostly self-deasserting resets except for the
67 * two reset lines going to the internal Cortex-M0 cores.
68 *
69 * To prevent the M0 core resets from accidentally getting deasserted
70 * status register must be check and bits in control register set to
71 * preserve the state.
72 */
73static int lpc18xx_rgu_setclear_reset(struct reset_controller_dev *rcdev,
74 unsigned long id, bool set)
75{
76 struct lpc18xx_rgu_data *rc = to_rgu_data(rcdev);
77 u32 stat_offset = LPC18XX_RGU_ACTIVE_STATUS0;
78 u32 ctrl_offset = LPC18XX_RGU_CTRL0;
79 unsigned long flags;
80 u32 stat, rst_bit;
81
82 stat_offset += (id / LPC18XX_RGU_RESETS_PER_REG) * sizeof(u32);
83 ctrl_offset += (id / LPC18XX_RGU_RESETS_PER_REG) * sizeof(u32);
84 rst_bit = 1 << (id % LPC18XX_RGU_RESETS_PER_REG);
85
86 spin_lock_irqsave(&rc->lock, flags);
87 stat = ~readl(rc->base + stat_offset);
88 if (set)
89 writel(stat | rst_bit, rc->base + ctrl_offset);
90 else
91 writel(stat & ~rst_bit, rc->base + ctrl_offset);
92 spin_unlock_irqrestore(&rc->lock, flags);
93
94 return 0;
95}
96
97static int lpc18xx_rgu_assert(struct reset_controller_dev *rcdev,
98 unsigned long id)
99{
100 return lpc18xx_rgu_setclear_reset(rcdev, id, true);
101}
102
103static int lpc18xx_rgu_deassert(struct reset_controller_dev *rcdev,
104 unsigned long id)
105{
106 return lpc18xx_rgu_setclear_reset(rcdev, id, false);
107}
108
109/* Only M0 cores require explicit reset deassert */
110static int lpc18xx_rgu_reset(struct reset_controller_dev *rcdev,
111 unsigned long id)
112{
113 struct lpc18xx_rgu_data *rc = to_rgu_data(rcdev);
114
115 lpc18xx_rgu_assert(rcdev, id);
116 udelay(rc->delay_us);
117
118 switch (id) {
119 case LPC43XX_RGU_M0SUB_RST:
120 case LPC43XX_RGU_M0APP_RST:
121 lpc18xx_rgu_setclear_reset(rcdev, id, false);
122 }
123
124 return 0;
125}
126
127static int lpc18xx_rgu_status(struct reset_controller_dev *rcdev,
128 unsigned long id)
129{
130 struct lpc18xx_rgu_data *rc = to_rgu_data(rcdev);
131 u32 bit, offset = LPC18XX_RGU_ACTIVE_STATUS0;
132
133 offset += (id / LPC18XX_RGU_RESETS_PER_REG) * sizeof(u32);
134 bit = 1 << (id % LPC18XX_RGU_RESETS_PER_REG);
135
136 return !(readl(rc->base + offset) & bit);
137}
138
139static struct reset_control_ops lpc18xx_rgu_ops = {
140 .reset = lpc18xx_rgu_reset,
141 .assert = lpc18xx_rgu_assert,
142 .deassert = lpc18xx_rgu_deassert,
143 .status = lpc18xx_rgu_status,
144};
145
146static int lpc18xx_rgu_probe(struct platform_device *pdev)
147{
148 struct lpc18xx_rgu_data *rc;
149 struct resource *res;
150 u32 fcclk, firc;
151 int ret;
152
153 rc = devm_kzalloc(&pdev->dev, sizeof(*rc), GFP_KERNEL);
154 if (!rc)
155 return -ENOMEM;
156
157 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
158 rc->base = devm_ioremap_resource(&pdev->dev, res);
159 if (IS_ERR(rc->base))
160 return PTR_ERR(rc->base);
161
162 rc->clk_reg = devm_clk_get(&pdev->dev, "reg");
163 if (IS_ERR(rc->clk_reg)) {
164 dev_err(&pdev->dev, "reg clock not found\n");
165 return PTR_ERR(rc->clk_reg);
166 }
167
168 rc->clk_delay = devm_clk_get(&pdev->dev, "delay");
169 if (IS_ERR(rc->clk_delay)) {
170 dev_err(&pdev->dev, "delay clock not found\n");
171 return PTR_ERR(rc->clk_delay);
172 }
173
174 ret = clk_prepare_enable(rc->clk_reg);
175 if (ret) {
176 dev_err(&pdev->dev, "unable to enable reg clock\n");
177 return ret;
178 }
179
180 ret = clk_prepare_enable(rc->clk_delay);
181 if (ret) {
182 dev_err(&pdev->dev, "unable to enable delay clock\n");
183 goto dis_clk_reg;
184 }
185
186 fcclk = clk_get_rate(rc->clk_reg) / USEC_PER_SEC;
187 firc = clk_get_rate(rc->clk_delay) / USEC_PER_SEC;
188 if (fcclk == 0 || firc == 0)
189 rc->delay_us = 2;
190 else
191 rc->delay_us = DIV_ROUND_UP(fcclk, firc * firc);
192
193 spin_lock_init(&rc->lock);
194
195 rc->rcdev.owner = THIS_MODULE;
196 rc->rcdev.nr_resets = 64;
197 rc->rcdev.ops = &lpc18xx_rgu_ops;
198 rc->rcdev.of_node = pdev->dev.of_node;
199
200 platform_set_drvdata(pdev, rc);
201
202 ret = reset_controller_register(&rc->rcdev);
203 if (ret) {
204 dev_err(&pdev->dev, "unable to register device\n");
205 goto dis_clks;
206 }
207
208 rgu_base = rc->base;
209 ret = register_restart_handler(&lpc18xx_rgu_restart_nb);
210 if (ret)
211 dev_warn(&pdev->dev, "failed to register restart handler\n");
212
213 return 0;
214
215dis_clks:
216 clk_disable_unprepare(rc->clk_delay);
217dis_clk_reg:
218 clk_disable_unprepare(rc->clk_reg);
219
220 return ret;
221}
222
223static int lpc18xx_rgu_remove(struct platform_device *pdev)
224{
225 struct lpc18xx_rgu_data *rc = platform_get_drvdata(pdev);
226 int ret;
227
228 ret = unregister_restart_handler(&lpc18xx_rgu_restart_nb);
229 if (ret)
230 dev_warn(&pdev->dev, "failed to unregister restart handler\n");
231
232 reset_controller_unregister(&rc->rcdev);
233
234 clk_disable_unprepare(rc->clk_delay);
235 clk_disable_unprepare(rc->clk_reg);
236
237 return 0;
238}
239
240static const struct of_device_id lpc18xx_rgu_match[] = {
241 { .compatible = "nxp,lpc1850-rgu" },
242 { }
243};
244MODULE_DEVICE_TABLE(of, lpc18xx_rgu_match);
245
246static struct platform_driver lpc18xx_rgu_driver = {
247 .probe = lpc18xx_rgu_probe,
248 .remove = lpc18xx_rgu_remove,
249 .driver = {
250 .name = "lpc18xx-reset",
251 .of_match_table = lpc18xx_rgu_match,
252 },
253};
254module_platform_driver(lpc18xx_rgu_driver);
255
256MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
257MODULE_DESCRIPTION("Reset driver for LPC18xx/43xx RGU");
258MODULE_LICENSE("GPL v2");