Merge tag 'char-misc-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[platform/kernel/linux-starfive.git] / drivers / hwmon / sfctemp.c
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
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
77 static void sfctemp_power_down(struct sfctemp *sfctemp)
78 {
79         writel(SFCTEMP_PD, sfctemp->regs);
80 }
81
82 static void sfctemp_run(struct sfctemp *sfctemp)
83 {
84         writel(SFCTEMP_RSTN | SFCTEMP_RUN, sfctemp->regs);
85         udelay(1);
86 }
87
88 static void sfctemp_stop(struct sfctemp *sfctemp)
89 {
90         writel(SFCTEMP_RSTN, sfctemp->regs);
91 }
92
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
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
151 static void sfctemp_disable_action(void *data)
152 {
153         sfctemp_disable(data);
154 }
155
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
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
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
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
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");