xref: /linux/drivers/hwmon/sfctemp.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
4  * Copyright (C) 2021 Samin Guo <samin.guo@starfivetech.com>
5  */
6 
7 #include <linux/bits.h>
8 #include <linux/clk.h>
9 #include <linux/delay.h>
10 #include <linux/hwmon.h>
11 #include <linux/io.h>
12 #include <linux/module.h>
13 #include <linux/mutex.h>
14 #include <linux/of.h>
15 #include <linux/platform_device.h>
16 #include <linux/reset.h>
17 
18 /*
19  * TempSensor reset. The RSTN can be de-asserted once the analog core has
20  * powered up. Trst(min 100ns)
21  * 0:reset  1:de-assert
22  */
23 #define SFCTEMP_RSTN	BIT(0)
24 
25 /*
26  * TempSensor analog core power down. The analog core will be powered up
27  * Tpu(min 50us) after PD is de-asserted. RSTN should be held low until the
28  * analog core is powered up.
29  * 0:power up  1:power down
30  */
31 #define SFCTEMP_PD	BIT(1)
32 
33 /*
34  * TempSensor start conversion enable.
35  * 0:disable  1:enable
36  */
37 #define SFCTEMP_RUN	BIT(2)
38 
39 /*
40  * TempSensor conversion value output.
41  * Temp(C)=DOUT*Y/4094 - K
42  */
43 #define SFCTEMP_DOUT_POS	16
44 #define SFCTEMP_DOUT_MSK	GENMASK(27, 16)
45 
46 /* DOUT to Celcius conversion constants */
47 #define SFCTEMP_Y1000	237500L
48 #define SFCTEMP_Z	4094L
49 #define SFCTEMP_K1000	81100L
50 
51 struct sfctemp {
52 	/* serialize access to hardware register and enabled below */
53 	struct mutex lock;
54 	void __iomem *regs;
55 	struct clk *clk_sense;
56 	struct clk *clk_bus;
57 	struct reset_control *rst_sense;
58 	struct reset_control *rst_bus;
59 	bool enabled;
60 };
61 
sfctemp_power_up(struct sfctemp * sfctemp)62 static void sfctemp_power_up(struct sfctemp *sfctemp)
63 {
64 	/* make sure we're powered down first */
65 	writel(SFCTEMP_PD, sfctemp->regs);
66 	udelay(1);
67 
68 	writel(0, sfctemp->regs);
69 	/* wait t_pu(50us) + t_rst(100ns) */
70 	usleep_range(60, 200);
71 
72 	/* de-assert reset */
73 	writel(SFCTEMP_RSTN, sfctemp->regs);
74 	udelay(1); /* wait t_su(500ps) */
75 }
76 
sfctemp_power_down(struct sfctemp * sfctemp)77 static void sfctemp_power_down(struct sfctemp *sfctemp)
78 {
79 	writel(SFCTEMP_PD, sfctemp->regs);
80 }
81 
sfctemp_run(struct sfctemp * sfctemp)82 static void sfctemp_run(struct sfctemp *sfctemp)
83 {
84 	writel(SFCTEMP_RSTN | SFCTEMP_RUN, sfctemp->regs);
85 	udelay(1);
86 }
87 
sfctemp_stop(struct sfctemp * sfctemp)88 static void sfctemp_stop(struct sfctemp *sfctemp)
89 {
90 	writel(SFCTEMP_RSTN, sfctemp->regs);
91 }
92 
sfctemp_enable(struct sfctemp * sfctemp)93 static int sfctemp_enable(struct sfctemp *sfctemp)
94 {
95 	int ret = 0;
96 
97 	mutex_lock(&sfctemp->lock);
98 	if (sfctemp->enabled)
99 		goto done;
100 
101 	ret = clk_prepare_enable(sfctemp->clk_bus);
102 	if (ret)
103 		goto err;
104 	ret = reset_control_deassert(sfctemp->rst_bus);
105 	if (ret)
106 		goto err_disable_bus;
107 
108 	ret = clk_prepare_enable(sfctemp->clk_sense);
109 	if (ret)
110 		goto err_assert_bus;
111 	ret = reset_control_deassert(sfctemp->rst_sense);
112 	if (ret)
113 		goto err_disable_sense;
114 
115 	sfctemp_power_up(sfctemp);
116 	sfctemp_run(sfctemp);
117 	sfctemp->enabled = true;
118 done:
119 	mutex_unlock(&sfctemp->lock);
120 	return ret;
121 
122 err_disable_sense:
123 	clk_disable_unprepare(sfctemp->clk_sense);
124 err_assert_bus:
125 	reset_control_assert(sfctemp->rst_bus);
126 err_disable_bus:
127 	clk_disable_unprepare(sfctemp->clk_bus);
128 err:
129 	mutex_unlock(&sfctemp->lock);
130 	return ret;
131 }
132 
sfctemp_disable(struct sfctemp * sfctemp)133 static int sfctemp_disable(struct sfctemp *sfctemp)
134 {
135 	mutex_lock(&sfctemp->lock);
136 	if (!sfctemp->enabled)
137 		goto done;
138 
139 	sfctemp_stop(sfctemp);
140 	sfctemp_power_down(sfctemp);
141 	reset_control_assert(sfctemp->rst_sense);
142 	clk_disable_unprepare(sfctemp->clk_sense);
143 	reset_control_assert(sfctemp->rst_bus);
144 	clk_disable_unprepare(sfctemp->clk_bus);
145 	sfctemp->enabled = false;
146 done:
147 	mutex_unlock(&sfctemp->lock);
148 	return 0;
149 }
150 
sfctemp_disable_action(void * data)151 static void sfctemp_disable_action(void *data)
152 {
153 	sfctemp_disable(data);
154 }
155 
sfctemp_convert(struct sfctemp * sfctemp,long * val)156 static int sfctemp_convert(struct sfctemp *sfctemp, long *val)
157 {
158 	int ret;
159 
160 	mutex_lock(&sfctemp->lock);
161 	if (!sfctemp->enabled) {
162 		ret = -ENODATA;
163 		goto out;
164 	}
165 
166 	/* calculate temperature in milli Celcius */
167 	*val = (long)((readl(sfctemp->regs) & SFCTEMP_DOUT_MSK) >> SFCTEMP_DOUT_POS)
168 		* SFCTEMP_Y1000 / SFCTEMP_Z - SFCTEMP_K1000;
169 
170 	ret = 0;
171 out:
172 	mutex_unlock(&sfctemp->lock);
173 	return ret;
174 }
175 
sfctemp_is_visible(const void * data,enum hwmon_sensor_types type,u32 attr,int channel)176 static umode_t sfctemp_is_visible(const void *data, enum hwmon_sensor_types type,
177 				  u32 attr, int channel)
178 {
179 	switch (type) {
180 	case hwmon_temp:
181 		switch (attr) {
182 		case hwmon_temp_enable:
183 			return 0644;
184 		case hwmon_temp_input:
185 			return 0444;
186 		default:
187 			return 0;
188 		}
189 	default:
190 		return 0;
191 	}
192 }
193 
sfctemp_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)194 static int sfctemp_read(struct device *dev, enum hwmon_sensor_types type,
195 			u32 attr, int channel, long *val)
196 {
197 	struct sfctemp *sfctemp = dev_get_drvdata(dev);
198 
199 	switch (type) {
200 	case hwmon_temp:
201 		switch (attr) {
202 		case hwmon_temp_enable:
203 			*val = sfctemp->enabled;
204 			return 0;
205 		case hwmon_temp_input:
206 			return sfctemp_convert(sfctemp, val);
207 		default:
208 			return -EINVAL;
209 		}
210 	default:
211 		return -EINVAL;
212 	}
213 }
214 
sfctemp_write(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long val)215 static int sfctemp_write(struct device *dev, enum hwmon_sensor_types type,
216 			 u32 attr, int channel, long val)
217 {
218 	struct sfctemp *sfctemp = dev_get_drvdata(dev);
219 
220 	switch (type) {
221 	case hwmon_temp:
222 		switch (attr) {
223 		case hwmon_temp_enable:
224 			if (val == 0)
225 				return sfctemp_disable(sfctemp);
226 			if (val == 1)
227 				return sfctemp_enable(sfctemp);
228 			return -EINVAL;
229 		default:
230 			return -EINVAL;
231 		}
232 	default:
233 		return -EINVAL;
234 	}
235 }
236 
237 static const struct hwmon_channel_info *sfctemp_info[] = {
238 	HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
239 	HWMON_CHANNEL_INFO(temp, HWMON_T_ENABLE | HWMON_T_INPUT),
240 	NULL
241 };
242 
243 static const struct hwmon_ops sfctemp_hwmon_ops = {
244 	.is_visible = sfctemp_is_visible,
245 	.read = sfctemp_read,
246 	.write = sfctemp_write,
247 };
248 
249 static const struct hwmon_chip_info sfctemp_chip_info = {
250 	.ops = &sfctemp_hwmon_ops,
251 	.info = sfctemp_info,
252 };
253 
sfctemp_probe(struct platform_device * pdev)254 static int sfctemp_probe(struct platform_device *pdev)
255 {
256 	struct device *dev = &pdev->dev;
257 	struct device *hwmon_dev;
258 	struct sfctemp *sfctemp;
259 	int ret;
260 
261 	sfctemp = devm_kzalloc(dev, sizeof(*sfctemp), GFP_KERNEL);
262 	if (!sfctemp)
263 		return -ENOMEM;
264 
265 	dev_set_drvdata(dev, sfctemp);
266 	mutex_init(&sfctemp->lock);
267 
268 	sfctemp->regs = devm_platform_ioremap_resource(pdev, 0);
269 	if (IS_ERR(sfctemp->regs))
270 		return PTR_ERR(sfctemp->regs);
271 
272 	sfctemp->clk_sense = devm_clk_get(dev, "sense");
273 	if (IS_ERR(sfctemp->clk_sense))
274 		return dev_err_probe(dev, PTR_ERR(sfctemp->clk_sense),
275 				     "error getting sense clock\n");
276 
277 	sfctemp->clk_bus = devm_clk_get(dev, "bus");
278 	if (IS_ERR(sfctemp->clk_bus))
279 		return dev_err_probe(dev, PTR_ERR(sfctemp->clk_bus),
280 				     "error getting bus clock\n");
281 
282 	sfctemp->rst_sense = devm_reset_control_get_exclusive(dev, "sense");
283 	if (IS_ERR(sfctemp->rst_sense))
284 		return dev_err_probe(dev, PTR_ERR(sfctemp->rst_sense),
285 				     "error getting sense reset\n");
286 
287 	sfctemp->rst_bus = devm_reset_control_get_exclusive(dev, "bus");
288 	if (IS_ERR(sfctemp->rst_bus))
289 		return dev_err_probe(dev, PTR_ERR(sfctemp->rst_bus),
290 				     "error getting busreset\n");
291 
292 	ret = reset_control_assert(sfctemp->rst_sense);
293 	if (ret)
294 		return dev_err_probe(dev, ret, "error asserting sense reset\n");
295 
296 	ret = reset_control_assert(sfctemp->rst_bus);
297 	if (ret)
298 		return dev_err_probe(dev, ret, "error asserting bus reset\n");
299 
300 	ret = devm_add_action(dev, sfctemp_disable_action, sfctemp);
301 	if (ret)
302 		return ret;
303 
304 	ret = sfctemp_enable(sfctemp);
305 	if (ret)
306 		return dev_err_probe(dev, ret, "error enabling temperature sensor\n");
307 
308 	hwmon_dev = devm_hwmon_device_register_with_info(dev, "sfctemp", sfctemp,
309 							 &sfctemp_chip_info, NULL);
310 	return PTR_ERR_OR_ZERO(hwmon_dev);
311 }
312 
313 static const struct of_device_id sfctemp_of_match[] = {
314 	{ .compatible = "starfive,jh7100-temp" },
315 	{ .compatible = "starfive,jh7110-temp" },
316 	{ /* sentinel */ }
317 };
318 MODULE_DEVICE_TABLE(of, sfctemp_of_match);
319 
320 static struct platform_driver sfctemp_driver = {
321 	.probe  = sfctemp_probe,
322 	.driver = {
323 		.name = "sfctemp",
324 		.of_match_table = sfctemp_of_match,
325 	},
326 };
327 module_platform_driver(sfctemp_driver);
328 
329 MODULE_AUTHOR("Emil Renner Berthing");
330 MODULE_DESCRIPTION("StarFive JH71x0 temperature sensor driver");
331 MODULE_LICENSE("GPL");
332