1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // Copyright (c) 2022 Nuvoton Technology Corporation |
3 | |
4 | #include <linux/bcd.h> |
5 | #include <linux/clk-provider.h> |
6 | #include <linux/err.h> |
7 | #include <linux/i2c.h> |
8 | #include <linux/module.h> |
9 | #include <linux/of.h> |
10 | #include <linux/rtc.h> |
11 | #include <linux/slab.h> |
12 | |
13 | #define NCT3018Y_REG_SC 0x00 /* seconds */ |
14 | #define NCT3018Y_REG_SCA 0x01 /* alarm */ |
15 | #define NCT3018Y_REG_MN 0x02 |
16 | #define NCT3018Y_REG_MNA 0x03 /* alarm */ |
17 | #define NCT3018Y_REG_HR 0x04 |
18 | #define NCT3018Y_REG_HRA 0x05 /* alarm */ |
19 | #define NCT3018Y_REG_DW 0x06 |
20 | #define NCT3018Y_REG_DM 0x07 |
21 | #define NCT3018Y_REG_MO 0x08 |
22 | #define NCT3018Y_REG_YR 0x09 |
23 | #define NCT3018Y_REG_CTRL 0x0A /* timer control */ |
24 | #define NCT3018Y_REG_ST 0x0B /* status */ |
25 | #define NCT3018Y_REG_CLKO 0x0C /* clock out */ |
26 | #define NCT3018Y_REG_PART 0x21 /* part info */ |
27 | |
28 | #define NCT3018Y_BIT_AF BIT(7) |
29 | #define NCT3018Y_BIT_ST BIT(7) |
30 | #define NCT3018Y_BIT_DM BIT(6) |
31 | #define NCT3018Y_BIT_HF BIT(5) |
32 | #define NCT3018Y_BIT_DSM BIT(4) |
33 | #define NCT3018Y_BIT_AIE BIT(3) |
34 | #define NCT3018Y_BIT_OFIE BIT(2) |
35 | #define NCT3018Y_BIT_CIE BIT(1) |
36 | #define NCT3018Y_BIT_TWO BIT(0) |
37 | |
38 | #define NCT3018Y_REG_BAT_MASK 0x07 |
39 | #define NCT3018Y_REG_CLKO_F_MASK 0x03 /* frequenc mask */ |
40 | #define NCT3018Y_REG_CLKO_CKE 0x80 /* clock out enabled */ |
41 | #define NCT3018Y_REG_PART_NCT3018Y 0x02 |
42 | |
43 | struct nct3018y { |
44 | struct rtc_device *rtc; |
45 | struct i2c_client *client; |
46 | int part_num; |
47 | #ifdef CONFIG_COMMON_CLK |
48 | struct clk_hw clkout_hw; |
49 | #endif |
50 | }; |
51 | |
52 | static int nct3018y_set_alarm_mode(struct i2c_client *client, bool on) |
53 | { |
54 | int err, flags; |
55 | |
56 | dev_dbg(&client->dev, "%s:on:%d\n" , __func__, on); |
57 | |
58 | flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CTRL); |
59 | if (flags < 0) { |
60 | dev_dbg(&client->dev, |
61 | "Failed to read NCT3018Y_REG_CTRL\n" ); |
62 | return flags; |
63 | } |
64 | |
65 | if (on) |
66 | flags |= NCT3018Y_BIT_AIE; |
67 | else |
68 | flags &= ~NCT3018Y_BIT_AIE; |
69 | |
70 | flags |= NCT3018Y_BIT_CIE; |
71 | err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_CTRL, value: flags); |
72 | if (err < 0) { |
73 | dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_CTRL\n" ); |
74 | return err; |
75 | } |
76 | |
77 | flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_ST); |
78 | if (flags < 0) { |
79 | dev_dbg(&client->dev, |
80 | "Failed to read NCT3018Y_REG_ST\n" ); |
81 | return flags; |
82 | } |
83 | |
84 | flags &= ~(NCT3018Y_BIT_AF); |
85 | err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_ST, value: flags); |
86 | if (err < 0) { |
87 | dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_ST\n" ); |
88 | return err; |
89 | } |
90 | |
91 | return 0; |
92 | } |
93 | |
94 | static int nct3018y_get_alarm_mode(struct i2c_client *client, unsigned char *alarm_enable, |
95 | unsigned char *alarm_flag) |
96 | { |
97 | int flags; |
98 | |
99 | if (alarm_enable) { |
100 | dev_dbg(&client->dev, "%s:NCT3018Y_REG_CTRL\n" , __func__); |
101 | flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CTRL); |
102 | if (flags < 0) |
103 | return flags; |
104 | *alarm_enable = flags & NCT3018Y_BIT_AIE; |
105 | dev_dbg(&client->dev, "%s:alarm_enable:%x\n" , __func__, *alarm_enable); |
106 | |
107 | } |
108 | |
109 | if (alarm_flag) { |
110 | dev_dbg(&client->dev, "%s:NCT3018Y_REG_ST\n" , __func__); |
111 | flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_ST); |
112 | if (flags < 0) |
113 | return flags; |
114 | *alarm_flag = flags & NCT3018Y_BIT_AF; |
115 | dev_dbg(&client->dev, "%s:alarm_flag:%x\n" , __func__, *alarm_flag); |
116 | } |
117 | |
118 | return 0; |
119 | } |
120 | |
121 | static irqreturn_t nct3018y_irq(int irq, void *dev_id) |
122 | { |
123 | struct nct3018y *nct3018y = i2c_get_clientdata(client: dev_id); |
124 | struct i2c_client *client = nct3018y->client; |
125 | int err; |
126 | unsigned char alarm_flag; |
127 | unsigned char alarm_enable; |
128 | |
129 | dev_dbg(&client->dev, "%s:irq:%d\n" , __func__, irq); |
130 | err = nct3018y_get_alarm_mode(client: nct3018y->client, alarm_enable: &alarm_enable, alarm_flag: &alarm_flag); |
131 | if (err) |
132 | return IRQ_NONE; |
133 | |
134 | if (alarm_flag) { |
135 | dev_dbg(&client->dev, "%s:alarm flag:%x\n" , |
136 | __func__, alarm_flag); |
137 | rtc_update_irq(rtc: nct3018y->rtc, num: 1, RTC_IRQF | RTC_AF); |
138 | nct3018y_set_alarm_mode(client: nct3018y->client, on: 0); |
139 | dev_dbg(&client->dev, "%s:IRQ_HANDLED\n" , __func__); |
140 | return IRQ_HANDLED; |
141 | } |
142 | |
143 | return IRQ_NONE; |
144 | } |
145 | |
146 | /* |
147 | * In the routines that deal directly with the nct3018y hardware, we use |
148 | * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. |
149 | */ |
150 | static int nct3018y_rtc_read_time(struct device *dev, struct rtc_time *tm) |
151 | { |
152 | struct i2c_client *client = to_i2c_client(dev); |
153 | unsigned char buf[10]; |
154 | int err; |
155 | |
156 | err = i2c_smbus_read_i2c_block_data(client, NCT3018Y_REG_ST, length: 1, values: buf); |
157 | if (err < 0) |
158 | return err; |
159 | |
160 | if (!buf[0]) { |
161 | dev_dbg(&client->dev, " voltage <=1.7, date/time is not reliable.\n" ); |
162 | return -EINVAL; |
163 | } |
164 | |
165 | err = i2c_smbus_read_i2c_block_data(client, NCT3018Y_REG_SC, length: sizeof(buf), values: buf); |
166 | if (err < 0) |
167 | return err; |
168 | |
169 | tm->tm_sec = bcd2bin(buf[0] & 0x7F); |
170 | tm->tm_min = bcd2bin(buf[2] & 0x7F); |
171 | tm->tm_hour = bcd2bin(buf[4] & 0x3F); |
172 | tm->tm_wday = buf[6] & 0x07; |
173 | tm->tm_mday = bcd2bin(buf[7] & 0x3F); |
174 | tm->tm_mon = bcd2bin(buf[8] & 0x1F) - 1; |
175 | tm->tm_year = bcd2bin(buf[9]) + 100; |
176 | |
177 | return 0; |
178 | } |
179 | |
180 | static int nct3018y_rtc_set_time(struct device *dev, struct rtc_time *tm) |
181 | { |
182 | struct i2c_client *client = to_i2c_client(dev); |
183 | struct nct3018y *nct3018y = dev_get_drvdata(dev); |
184 | unsigned char buf[4] = {0}; |
185 | int err, flags; |
186 | int restore_flags = 0; |
187 | |
188 | flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CTRL); |
189 | if (flags < 0) { |
190 | dev_dbg(&client->dev, "Failed to read NCT3018Y_REG_CTRL.\n" ); |
191 | return flags; |
192 | } |
193 | |
194 | /* Check and set TWO bit */ |
195 | if (nct3018y->part_num == NCT3018Y_REG_PART_NCT3018Y && !(flags & NCT3018Y_BIT_TWO)) { |
196 | restore_flags = 1; |
197 | flags |= NCT3018Y_BIT_TWO; |
198 | err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_CTRL, value: flags); |
199 | if (err < 0) { |
200 | dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_CTRL.\n" ); |
201 | return err; |
202 | } |
203 | } |
204 | |
205 | buf[0] = bin2bcd(tm->tm_sec); |
206 | err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_SC, value: buf[0]); |
207 | if (err < 0) { |
208 | dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_SC\n" ); |
209 | return err; |
210 | } |
211 | |
212 | buf[0] = bin2bcd(tm->tm_min); |
213 | err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_MN, value: buf[0]); |
214 | if (err < 0) { |
215 | dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_MN\n" ); |
216 | return err; |
217 | } |
218 | |
219 | buf[0] = bin2bcd(tm->tm_hour); |
220 | err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_HR, value: buf[0]); |
221 | if (err < 0) { |
222 | dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_HR\n" ); |
223 | return err; |
224 | } |
225 | |
226 | buf[0] = tm->tm_wday & 0x07; |
227 | buf[1] = bin2bcd(tm->tm_mday); |
228 | buf[2] = bin2bcd(tm->tm_mon + 1); |
229 | buf[3] = bin2bcd(tm->tm_year - 100); |
230 | err = i2c_smbus_write_i2c_block_data(client, NCT3018Y_REG_DW, |
231 | length: sizeof(buf), values: buf); |
232 | if (err < 0) { |
233 | dev_dbg(&client->dev, "Unable to write for day and mon and year\n" ); |
234 | return -EIO; |
235 | } |
236 | |
237 | /* Restore TWO bit */ |
238 | if (restore_flags) { |
239 | if (nct3018y->part_num == NCT3018Y_REG_PART_NCT3018Y) |
240 | flags &= ~NCT3018Y_BIT_TWO; |
241 | |
242 | err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_CTRL, value: flags); |
243 | if (err < 0) { |
244 | dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_CTRL.\n" ); |
245 | return err; |
246 | } |
247 | } |
248 | |
249 | return err; |
250 | } |
251 | |
252 | static int nct3018y_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm) |
253 | { |
254 | struct i2c_client *client = to_i2c_client(dev); |
255 | unsigned char buf[5]; |
256 | int err; |
257 | |
258 | err = i2c_smbus_read_i2c_block_data(client, NCT3018Y_REG_SCA, |
259 | length: sizeof(buf), values: buf); |
260 | if (err < 0) { |
261 | dev_dbg(&client->dev, "Unable to read date\n" ); |
262 | return -EIO; |
263 | } |
264 | |
265 | dev_dbg(&client->dev, "%s: raw data is sec=%02x, min=%02x hr=%02x\n" , |
266 | __func__, buf[0], buf[2], buf[4]); |
267 | |
268 | tm->time.tm_sec = bcd2bin(buf[0] & 0x7F); |
269 | tm->time.tm_min = bcd2bin(buf[2] & 0x7F); |
270 | tm->time.tm_hour = bcd2bin(buf[4] & 0x3F); |
271 | |
272 | err = nct3018y_get_alarm_mode(client, alarm_enable: &tm->enabled, alarm_flag: &tm->pending); |
273 | if (err < 0) |
274 | return err; |
275 | |
276 | dev_dbg(&client->dev, "%s:s=%d m=%d, hr=%d, enabled=%d, pending=%d\n" , |
277 | __func__, tm->time.tm_sec, tm->time.tm_min, |
278 | tm->time.tm_hour, tm->enabled, tm->pending); |
279 | |
280 | return 0; |
281 | } |
282 | |
283 | static int nct3018y_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm) |
284 | { |
285 | struct i2c_client *client = to_i2c_client(dev); |
286 | int err; |
287 | |
288 | dev_dbg(dev, "%s, sec=%d, min=%d hour=%d tm->enabled:%d\n" , |
289 | __func__, tm->time.tm_sec, tm->time.tm_min, tm->time.tm_hour, |
290 | tm->enabled); |
291 | |
292 | err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_SCA, bin2bcd(tm->time.tm_sec)); |
293 | if (err < 0) { |
294 | dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_SCA\n" ); |
295 | return err; |
296 | } |
297 | |
298 | err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_MNA, bin2bcd(tm->time.tm_min)); |
299 | if (err < 0) { |
300 | dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_MNA\n" ); |
301 | return err; |
302 | } |
303 | |
304 | err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_HRA, bin2bcd(tm->time.tm_hour)); |
305 | if (err < 0) { |
306 | dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_HRA\n" ); |
307 | return err; |
308 | } |
309 | |
310 | return nct3018y_set_alarm_mode(client, on: tm->enabled); |
311 | } |
312 | |
313 | static int nct3018y_irq_enable(struct device *dev, unsigned int enabled) |
314 | { |
315 | dev_dbg(dev, "%s: alarm enable=%d\n" , __func__, enabled); |
316 | |
317 | return nct3018y_set_alarm_mode(to_i2c_client(dev), on: enabled); |
318 | } |
319 | |
320 | static int nct3018y_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) |
321 | { |
322 | struct i2c_client *client = to_i2c_client(dev); |
323 | int status, flags = 0; |
324 | |
325 | switch (cmd) { |
326 | case RTC_VL_READ: |
327 | status = i2c_smbus_read_byte_data(client, NCT3018Y_REG_ST); |
328 | if (status < 0) |
329 | return status; |
330 | |
331 | if (!(status & NCT3018Y_REG_BAT_MASK)) |
332 | flags |= RTC_VL_DATA_INVALID; |
333 | |
334 | return put_user(flags, (unsigned int __user *)arg); |
335 | |
336 | default: |
337 | return -ENOIOCTLCMD; |
338 | } |
339 | } |
340 | |
341 | #ifdef CONFIG_COMMON_CLK |
342 | /* |
343 | * Handling of the clkout |
344 | */ |
345 | |
346 | #define clkout_hw_to_nct3018y(_hw) container_of(_hw, struct nct3018y, clkout_hw) |
347 | |
348 | static const int clkout_rates[] = { |
349 | 32768, |
350 | 1024, |
351 | 32, |
352 | 1, |
353 | }; |
354 | |
355 | static unsigned long nct3018y_clkout_recalc_rate(struct clk_hw *hw, |
356 | unsigned long parent_rate) |
357 | { |
358 | struct nct3018y *nct3018y = clkout_hw_to_nct3018y(hw); |
359 | struct i2c_client *client = nct3018y->client; |
360 | int flags; |
361 | |
362 | flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CLKO); |
363 | if (flags < 0) |
364 | return 0; |
365 | |
366 | flags &= NCT3018Y_REG_CLKO_F_MASK; |
367 | return clkout_rates[flags]; |
368 | } |
369 | |
370 | static long nct3018y_clkout_round_rate(struct clk_hw *hw, unsigned long rate, |
371 | unsigned long *prate) |
372 | { |
373 | int i; |
374 | |
375 | for (i = 0; i < ARRAY_SIZE(clkout_rates); i++) |
376 | if (clkout_rates[i] <= rate) |
377 | return clkout_rates[i]; |
378 | |
379 | return 0; |
380 | } |
381 | |
382 | static int nct3018y_clkout_set_rate(struct clk_hw *hw, unsigned long rate, |
383 | unsigned long parent_rate) |
384 | { |
385 | struct nct3018y *nct3018y = clkout_hw_to_nct3018y(hw); |
386 | struct i2c_client *client = nct3018y->client; |
387 | int i, flags; |
388 | |
389 | flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CLKO); |
390 | if (flags < 0) |
391 | return flags; |
392 | |
393 | for (i = 0; i < ARRAY_SIZE(clkout_rates); i++) |
394 | if (clkout_rates[i] == rate) { |
395 | flags &= ~NCT3018Y_REG_CLKO_F_MASK; |
396 | flags |= i; |
397 | return i2c_smbus_write_byte_data(client, NCT3018Y_REG_CLKO, value: flags); |
398 | } |
399 | |
400 | return -EINVAL; |
401 | } |
402 | |
403 | static int nct3018y_clkout_control(struct clk_hw *hw, bool enable) |
404 | { |
405 | struct nct3018y *nct3018y = clkout_hw_to_nct3018y(hw); |
406 | struct i2c_client *client = nct3018y->client; |
407 | int flags; |
408 | |
409 | flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CLKO); |
410 | if (flags < 0) |
411 | return flags; |
412 | |
413 | if (enable) |
414 | flags |= NCT3018Y_REG_CLKO_CKE; |
415 | else |
416 | flags &= ~NCT3018Y_REG_CLKO_CKE; |
417 | |
418 | return i2c_smbus_write_byte_data(client, NCT3018Y_REG_CLKO, value: flags); |
419 | } |
420 | |
421 | static int nct3018y_clkout_prepare(struct clk_hw *hw) |
422 | { |
423 | return nct3018y_clkout_control(hw, enable: 1); |
424 | } |
425 | |
426 | static void nct3018y_clkout_unprepare(struct clk_hw *hw) |
427 | { |
428 | nct3018y_clkout_control(hw, enable: 0); |
429 | } |
430 | |
431 | static int nct3018y_clkout_is_prepared(struct clk_hw *hw) |
432 | { |
433 | struct nct3018y *nct3018y = clkout_hw_to_nct3018y(hw); |
434 | struct i2c_client *client = nct3018y->client; |
435 | int flags; |
436 | |
437 | flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CLKO); |
438 | if (flags < 0) |
439 | return flags; |
440 | |
441 | return flags & NCT3018Y_REG_CLKO_CKE; |
442 | } |
443 | |
444 | static const struct clk_ops nct3018y_clkout_ops = { |
445 | .prepare = nct3018y_clkout_prepare, |
446 | .unprepare = nct3018y_clkout_unprepare, |
447 | .is_prepared = nct3018y_clkout_is_prepared, |
448 | .recalc_rate = nct3018y_clkout_recalc_rate, |
449 | .round_rate = nct3018y_clkout_round_rate, |
450 | .set_rate = nct3018y_clkout_set_rate, |
451 | }; |
452 | |
453 | static struct clk *nct3018y_clkout_register_clk(struct nct3018y *nct3018y) |
454 | { |
455 | struct i2c_client *client = nct3018y->client; |
456 | struct device_node *node = client->dev.of_node; |
457 | struct clk *clk; |
458 | struct clk_init_data init; |
459 | |
460 | init.name = "nct3018y-clkout" ; |
461 | init.ops = &nct3018y_clkout_ops; |
462 | init.flags = 0; |
463 | init.parent_names = NULL; |
464 | init.num_parents = 0; |
465 | nct3018y->clkout_hw.init = &init; |
466 | |
467 | /* optional override of the clockname */ |
468 | of_property_read_string(np: node, propname: "clock-output-names" , out_string: &init.name); |
469 | |
470 | /* register the clock */ |
471 | clk = devm_clk_register(dev: &client->dev, hw: &nct3018y->clkout_hw); |
472 | |
473 | if (!IS_ERR(ptr: clk)) |
474 | of_clk_add_provider(np: node, clk_src_get: of_clk_src_simple_get, data: clk); |
475 | |
476 | return clk; |
477 | } |
478 | #endif |
479 | |
480 | static const struct rtc_class_ops nct3018y_rtc_ops = { |
481 | .read_time = nct3018y_rtc_read_time, |
482 | .set_time = nct3018y_rtc_set_time, |
483 | .read_alarm = nct3018y_rtc_read_alarm, |
484 | .set_alarm = nct3018y_rtc_set_alarm, |
485 | .alarm_irq_enable = nct3018y_irq_enable, |
486 | .ioctl = nct3018y_ioctl, |
487 | }; |
488 | |
489 | static int nct3018y_probe(struct i2c_client *client) |
490 | { |
491 | struct nct3018y *nct3018y; |
492 | int err, flags; |
493 | |
494 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_I2C | |
495 | I2C_FUNC_SMBUS_BYTE | |
496 | I2C_FUNC_SMBUS_BLOCK_DATA)) |
497 | return -ENODEV; |
498 | |
499 | nct3018y = devm_kzalloc(dev: &client->dev, size: sizeof(struct nct3018y), |
500 | GFP_KERNEL); |
501 | if (!nct3018y) |
502 | return -ENOMEM; |
503 | |
504 | i2c_set_clientdata(client, data: nct3018y); |
505 | nct3018y->client = client; |
506 | device_set_wakeup_capable(dev: &client->dev, capable: 1); |
507 | |
508 | flags = i2c_smbus_read_byte_data(client, NCT3018Y_REG_CTRL); |
509 | if (flags < 0) { |
510 | dev_dbg(&client->dev, "%s: read error\n" , __func__); |
511 | return flags; |
512 | } else if (flags & NCT3018Y_BIT_TWO) { |
513 | dev_dbg(&client->dev, "%s: NCT3018Y_BIT_TWO is set\n" , __func__); |
514 | } |
515 | |
516 | nct3018y->part_num = i2c_smbus_read_byte_data(client, NCT3018Y_REG_PART); |
517 | if (nct3018y->part_num < 0) { |
518 | dev_dbg(&client->dev, "Failed to read NCT3018Y_REG_PART.\n" ); |
519 | return nct3018y->part_num; |
520 | } else if (nct3018y->part_num == NCT3018Y_REG_PART_NCT3018Y) { |
521 | flags = NCT3018Y_BIT_HF; |
522 | err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_CTRL, value: flags); |
523 | if (err < 0) { |
524 | dev_dbg(&client->dev, "Unable to write NCT3018Y_REG_CTRL.\n" ); |
525 | return err; |
526 | } |
527 | } |
528 | |
529 | flags = 0; |
530 | err = i2c_smbus_write_byte_data(client, NCT3018Y_REG_ST, value: flags); |
531 | if (err < 0) { |
532 | dev_dbg(&client->dev, "%s: write error\n" , __func__); |
533 | return err; |
534 | } |
535 | |
536 | nct3018y->rtc = devm_rtc_allocate_device(dev: &client->dev); |
537 | if (IS_ERR(ptr: nct3018y->rtc)) |
538 | return PTR_ERR(ptr: nct3018y->rtc); |
539 | |
540 | nct3018y->rtc->ops = &nct3018y_rtc_ops; |
541 | nct3018y->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; |
542 | nct3018y->rtc->range_max = RTC_TIMESTAMP_END_2099; |
543 | |
544 | if (client->irq > 0) { |
545 | err = devm_request_threaded_irq(dev: &client->dev, irq: client->irq, |
546 | NULL, thread_fn: nct3018y_irq, |
547 | IRQF_ONESHOT | IRQF_TRIGGER_FALLING, |
548 | devname: "nct3018y" , dev_id: client); |
549 | if (err) { |
550 | dev_dbg(&client->dev, "unable to request IRQ %d\n" , client->irq); |
551 | return err; |
552 | } |
553 | } else { |
554 | clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, addr: nct3018y->rtc->features); |
555 | clear_bit(RTC_FEATURE_ALARM, addr: nct3018y->rtc->features); |
556 | } |
557 | |
558 | #ifdef CONFIG_COMMON_CLK |
559 | /* register clk in common clk framework */ |
560 | nct3018y_clkout_register_clk(nct3018y); |
561 | #endif |
562 | |
563 | return devm_rtc_register_device(nct3018y->rtc); |
564 | } |
565 | |
566 | static const struct i2c_device_id nct3018y_id[] = { |
567 | { "nct3018y" , 0 }, |
568 | { } |
569 | }; |
570 | MODULE_DEVICE_TABLE(i2c, nct3018y_id); |
571 | |
572 | static const struct of_device_id nct3018y_of_match[] = { |
573 | { .compatible = "nuvoton,nct3018y" }, |
574 | {} |
575 | }; |
576 | MODULE_DEVICE_TABLE(of, nct3018y_of_match); |
577 | |
578 | static struct i2c_driver nct3018y_driver = { |
579 | .driver = { |
580 | .name = "rtc-nct3018y" , |
581 | .of_match_table = nct3018y_of_match, |
582 | }, |
583 | .probe = nct3018y_probe, |
584 | .id_table = nct3018y_id, |
585 | }; |
586 | |
587 | module_i2c_driver(nct3018y_driver); |
588 | |
589 | MODULE_AUTHOR("Medad CChien <ctcchien@nuvoton.com>" ); |
590 | MODULE_AUTHOR("Mia Lin <mimi05633@gmail.com>" ); |
591 | MODULE_DESCRIPTION("Nuvoton NCT3018Y RTC driver" ); |
592 | MODULE_LICENSE("GPL" ); |
593 | |