xref: /openbmc/linux/drivers/reset/reset-lpc18xx.c (revision 1a55cad1)
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 
36 struct 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 
47 static void __iomem *rgu_base;
48 
49 static 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 
60 static 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  */
73 static 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 
97 static 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 
103 static 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 */
110 static 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 
127 static 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 
139 static const 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 
146 static 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 
215 dis_clks:
216 	clk_disable_unprepare(rc->clk_delay);
217 dis_clk_reg:
218 	clk_disable_unprepare(rc->clk_reg);
219 
220 	return ret;
221 }
222 
223 static 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 
240 static const struct of_device_id lpc18xx_rgu_match[] = {
241 	{ .compatible = "nxp,lpc1850-rgu" },
242 	{ }
243 };
244 MODULE_DEVICE_TABLE(of, lpc18xx_rgu_match);
245 
246 static 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 };
254 module_platform_driver(lpc18xx_rgu_driver);
255 
256 MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
257 MODULE_DESCRIPTION("Reset driver for LPC18xx/43xx RGU");
258 MODULE_LICENSE("GPL v2");
259