1/*
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");
259