hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/rtc/rtc-pcf85363.c
....@@ -1,15 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0
12 /*
23 * drivers/rtc/rtc-pcf85363.c
34 *
45 * Driver for NXP PCF85363 real-time clock.
56 *
67 * Copyright (C) 2017 Eric Nelson
7
- *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License version 2 as
10
- * published by the Free Software Foundation.
11
- *
12
- * Based loosely on rtc-8583 by Russell King, Wolfram Sang and Juergen Beisert
138 */
149 #include <linux/module.h>
1510 #include <linux/i2c.h>
....@@ -112,12 +107,14 @@
112107
113108 #define NVRAM_SIZE 0x40
114109
115
-static struct i2c_driver pcf85363_driver;
116
-
117110 struct pcf85363 {
118
- struct device *dev;
119111 struct rtc_device *rtc;
120112 struct regmap *regmap;
113
+};
114
+
115
+struct pcf85x63_config {
116
+ struct regmap_config regmap;
117
+ unsigned int num_nvram;
121118 };
122119
123120 static int pcf85363_rtc_read_time(struct device *dev, struct rtc_time *tm)
....@@ -316,54 +313,102 @@
316313 val, bytes);
317314 }
318315
319
-static const struct regmap_config regmap_config = {
320
- .reg_bits = 8,
321
- .val_bits = 8,
322
- .max_register = 0x7f,
316
+static int pcf85x63_nvram_read(void *priv, unsigned int offset, void *val,
317
+ size_t bytes)
318
+{
319
+ struct pcf85363 *pcf85363 = priv;
320
+ unsigned int tmp_val;
321
+ int ret;
322
+
323
+ ret = regmap_read(pcf85363->regmap, CTRL_RAMBYTE, &tmp_val);
324
+ (*(unsigned char *) val) = (unsigned char) tmp_val;
325
+
326
+ return ret;
327
+}
328
+
329
+static int pcf85x63_nvram_write(void *priv, unsigned int offset, void *val,
330
+ size_t bytes)
331
+{
332
+ struct pcf85363 *pcf85363 = priv;
333
+ unsigned char tmp_val;
334
+
335
+ tmp_val = *((unsigned char *)val);
336
+ return regmap_write(pcf85363->regmap, CTRL_RAMBYTE,
337
+ (unsigned int)tmp_val);
338
+}
339
+
340
+static const struct pcf85x63_config pcf_85263_config = {
341
+ .regmap = {
342
+ .reg_bits = 8,
343
+ .val_bits = 8,
344
+ .max_register = 0x2f,
345
+ },
346
+ .num_nvram = 1
347
+};
348
+
349
+static const struct pcf85x63_config pcf_85363_config = {
350
+ .regmap = {
351
+ .reg_bits = 8,
352
+ .val_bits = 8,
353
+ .max_register = 0x7f,
354
+ },
355
+ .num_nvram = 2
323356 };
324357
325358 static int pcf85363_probe(struct i2c_client *client,
326359 const struct i2c_device_id *id)
327360 {
328361 struct pcf85363 *pcf85363;
329
- struct nvmem_config nvmem_cfg = {
330
- .name = "pcf85363-",
331
- .word_size = 1,
332
- .stride = 1,
333
- .size = NVRAM_SIZE,
334
- .reg_read = pcf85363_nvram_read,
335
- .reg_write = pcf85363_nvram_write,
362
+ const struct pcf85x63_config *config = &pcf_85363_config;
363
+ const void *data = of_device_get_match_data(&client->dev);
364
+ static struct nvmem_config nvmem_cfg[] = {
365
+ {
366
+ .name = "pcf85x63-",
367
+ .word_size = 1,
368
+ .stride = 1,
369
+ .size = 1,
370
+ .reg_read = pcf85x63_nvram_read,
371
+ .reg_write = pcf85x63_nvram_write,
372
+ }, {
373
+ .name = "pcf85363-",
374
+ .word_size = 1,
375
+ .stride = 1,
376
+ .size = NVRAM_SIZE,
377
+ .reg_read = pcf85363_nvram_read,
378
+ .reg_write = pcf85363_nvram_write,
379
+ },
336380 };
337
- int ret;
381
+ int ret, i;
338382
339
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
340
- return -ENODEV;
383
+ if (data)
384
+ config = data;
341385
342386 pcf85363 = devm_kzalloc(&client->dev, sizeof(struct pcf85363),
343387 GFP_KERNEL);
344388 if (!pcf85363)
345389 return -ENOMEM;
346390
347
- pcf85363->regmap = devm_regmap_init_i2c(client, &regmap_config);
391
+ pcf85363->regmap = devm_regmap_init_i2c(client, &config->regmap);
348392 if (IS_ERR(pcf85363->regmap)) {
349393 dev_err(&client->dev, "regmap allocation failed\n");
350394 return PTR_ERR(pcf85363->regmap);
351395 }
352396
353
- pcf85363->dev = &client->dev;
354397 i2c_set_clientdata(client, pcf85363);
355398
356
- pcf85363->rtc = devm_rtc_allocate_device(pcf85363->dev);
399
+ pcf85363->rtc = devm_rtc_allocate_device(&client->dev);
357400 if (IS_ERR(pcf85363->rtc))
358401 return PTR_ERR(pcf85363->rtc);
359402
360403 pcf85363->rtc->ops = &rtc_ops;
404
+ pcf85363->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
405
+ pcf85363->rtc->range_max = RTC_TIMESTAMP_END_2099;
361406
362407 if (client->irq > 0) {
363408 regmap_write(pcf85363->regmap, CTRL_FLAGS, 0);
364409 regmap_update_bits(pcf85363->regmap, CTRL_PIN_IO,
365410 PIN_IO_INTA_OUT, PIN_IO_INTAPM);
366
- ret = devm_request_threaded_irq(pcf85363->dev, client->irq,
411
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
367412 NULL, pcf85363_rtc_handle_irq,
368413 IRQF_TRIGGER_LOW | IRQF_ONESHOT,
369414 "pcf85363", client);
....@@ -375,15 +420,18 @@
375420
376421 ret = rtc_register_device(pcf85363->rtc);
377422
378
- nvmem_cfg.priv = pcf85363;
379
- rtc_nvmem_register(pcf85363->rtc, &nvmem_cfg);
423
+ for (i = 0; i < config->num_nvram; i++) {
424
+ nvmem_cfg[i].priv = pcf85363;
425
+ rtc_nvmem_register(pcf85363->rtc, &nvmem_cfg[i]);
426
+ }
380427
381428 return ret;
382429 }
383430
384431 static const struct of_device_id dev_ids[] = {
385
- { .compatible = "nxp,pcf85363" },
386
- {}
432
+ { .compatible = "nxp,pcf85263", .data = &pcf_85263_config },
433
+ { .compatible = "nxp,pcf85363", .data = &pcf_85363_config },
434
+ { /* sentinel */ }
387435 };
388436 MODULE_DEVICE_TABLE(of, dev_ids);
389437
....@@ -398,5 +446,5 @@
398446 module_i2c_driver(pcf85363_driver);
399447
400448 MODULE_AUTHOR("Eric Nelson");
401
-MODULE_DESCRIPTION("pcf85363 I2C RTC driver");
449
+MODULE_DESCRIPTION("pcf85263/pcf85363 I2C RTC driver");
402450 MODULE_LICENSE("GPL");