summaryrefslogtreecommitdiff
path: root/drivers/rtc/rtc-nvidia-vrs10.c
blob: b157966985581b23f026803d6578c4ad8d25f9e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
// SPDX-License-Identifier: GPL-2.0-only
/*
 * NVIDIA Voltage Regulator Specification RTC
 *
 * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES.
 * All rights reserved.
 */

#include <linux/bits.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/rtc.h>

#define NVVRS_REG_VENDOR_ID			0x00
#define NVVRS_REG_MODEL_REV			0x01

/*  Interrupts registers */
#define NVVRS_REG_INT_SRC1			0x10
#define NVVRS_REG_INT_SRC2			0x11
#define NVVRS_REG_INT_VENDOR			0x12

/* Control Registers */
#define NVVRS_REG_CTL_1				0x28
#define NVVRS_REG_CTL_2				0x29

/* RTC Registers */
#define NVVRS_REG_RTC_T3			0x70
#define NVVRS_REG_RTC_T2			0x71
#define NVVRS_REG_RTC_T1			0x72
#define NVVRS_REG_RTC_T0			0x73
#define NVVRS_REG_RTC_A3			0x74
#define NVVRS_REG_RTC_A2			0x75
#define NVVRS_REG_RTC_A1			0x76
#define NVVRS_REG_RTC_A0			0x77

/* Interrupt Mask */
#define NVVRS_INT_SRC1_RSTIRQ_MASK		BIT(0)
#define NVVRS_INT_SRC1_OSC_MASK			BIT(1)
#define NVVRS_INT_SRC1_EN_MASK			BIT(2)
#define NVVRS_INT_SRC1_RTC_MASK			BIT(3)
#define NVVRS_INT_SRC1_PEC_MASK			BIT(4)
#define NVVRS_INT_SRC1_WDT_MASK			BIT(5)
#define NVVRS_INT_SRC1_EM_PD_MASK		BIT(6)
#define NVVRS_INT_SRC1_INTERNAL_MASK		BIT(7)
#define NVVRS_INT_SRC2_PBSP_MASK		BIT(0)
#define NVVRS_INT_SRC2_ECC_DED_MASK		BIT(1)
#define NVVRS_INT_SRC2_TSD_MASK			BIT(2)
#define NVVRS_INT_SRC2_LDO_MASK			BIT(3)
#define NVVRS_INT_SRC2_BIST_MASK		BIT(4)
#define NVVRS_INT_SRC2_RT_CRC_MASK		BIT(5)
#define NVVRS_INT_SRC2_VENDOR_MASK		BIT(7)
#define NVVRS_INT_VENDOR0_MASK			BIT(0)
#define NVVRS_INT_VENDOR1_MASK			BIT(1)
#define NVVRS_INT_VENDOR2_MASK			BIT(2)
#define NVVRS_INT_VENDOR3_MASK			BIT(3)
#define NVVRS_INT_VENDOR4_MASK			BIT(4)
#define NVVRS_INT_VENDOR5_MASK			BIT(5)
#define NVVRS_INT_VENDOR6_MASK			BIT(6)
#define NVVRS_INT_VENDOR7_MASK			BIT(7)

/* Controller Register Mask */
#define NVVRS_REG_CTL_1_FORCE_SHDN		(BIT(0) | BIT(1))
#define NVVRS_REG_CTL_1_FORCE_ACT		BIT(2)
#define NVVRS_REG_CTL_1_FORCE_INT		BIT(3)
#define NVVRS_REG_CTL_2_EN_PEC			BIT(0)
#define NVVRS_REG_CTL_2_REQ_PEC			BIT(1)
#define NVVRS_REG_CTL_2_RTC_PU			BIT(2)
#define NVVRS_REG_CTL_2_RTC_WAKE		BIT(3)
#define NVVRS_REG_CTL_2_RST_DLY			0xF0

#define ALARM_RESET_VAL				0xffffffff
#define NVVRS_MIN_MODEL_REV			0x40

enum nvvrs_irq_regs {
	NVVRS_IRQ_REG_INT_SRC1 = 0,
	NVVRS_IRQ_REG_INT_SRC2 = 1,
	NVVRS_IRQ_REG_INT_VENDOR = 2,
	NVVRS_IRQ_REG_COUNT = 3,
};

struct nvvrs_rtc_info {
	struct device          *dev;
	struct i2c_client      *client;
	struct rtc_device      *rtc;
	unsigned int           irq;
};

static int nvvrs_update_bits(struct nvvrs_rtc_info *info, u8 reg,
			     u8 mask, u8 value)
{
	int ret;
	u8 val;

	ret = i2c_smbus_read_byte_data(info->client, reg);
	if (ret < 0)
		return ret;

	val = (u8)ret;
	val &= ~mask;
	val |= (value & mask);

	return i2c_smbus_write_byte_data(info->client, reg, val);
}

static int nvvrs_rtc_write_alarm(struct i2c_client *client, u8 *time)
{
	int ret;

	ret = i2c_smbus_write_byte_data(client, NVVRS_REG_RTC_A3, time[3]);
	if (ret < 0)
		return ret;

	ret = i2c_smbus_write_byte_data(client, NVVRS_REG_RTC_A2, time[2]);
	if (ret < 0)
		return ret;

	ret = i2c_smbus_write_byte_data(client, NVVRS_REG_RTC_A1, time[1]);
	if (ret < 0)
		return ret;

	return i2c_smbus_write_byte_data(client, NVVRS_REG_RTC_A0, time[0]);
}

static int nvvrs_rtc_enable_alarm(struct nvvrs_rtc_info *info)
{
	int ret;

	/* Set RTC_WAKE bit for autonomous wake from sleep */
	ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, NVVRS_REG_CTL_2_RTC_WAKE,
				NVVRS_REG_CTL_2_RTC_WAKE);
	if (ret < 0)
		return ret;

	/* Set RTC_PU bit for autonomous wake from shutdown */
	ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, NVVRS_REG_CTL_2_RTC_PU,
				NVVRS_REG_CTL_2_RTC_PU);
	if (ret < 0)
		return ret;

	return 0;
}

static int nvvrs_rtc_disable_alarm(struct nvvrs_rtc_info *info)
{
	struct i2c_client *client = info->client;
	u8 val[4];
	int ret;

	/* Clear RTC_WAKE bit */
	ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, NVVRS_REG_CTL_2_RTC_WAKE,
				0);
	if (ret < 0)
		return ret;

	/* Clear RTC_PU bit */
	ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2, NVVRS_REG_CTL_2_RTC_PU,
				0);
	if (ret < 0)
		return ret;

	/* Write ALARM_RESET_VAL in RTC Alarm register to disable alarm */
	val[0] = 0xff;
	val[1] = 0xff;
	val[2] = 0xff;
	val[3] = 0xff;

	ret = nvvrs_rtc_write_alarm(client, val);
	if (ret < 0)
		return ret;

	return 0;
}

static int nvvrs_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
	struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
	time64_t secs = 0;
	int ret;
	u8 val;

	/*
	 * Multi-byte transfers are not supported with PEC enabled
	 * Read MSB first to avoid coherency issues
	 */
	ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_T3);
	if (ret < 0)
		return ret;

	val = (u8)ret;
	secs |= (time64_t)val << 24;

	ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_T2);
	if (ret < 0)
		return ret;

	val = (u8)ret;
	secs |= (time64_t)val << 16;

	ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_T1);
	if (ret < 0)
		return ret;

	val = (u8)ret;
	secs |= (time64_t)val << 8;

	ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_T0);
	if (ret < 0)
		return ret;

	val = (u8)ret;
	secs |= val;

	rtc_time64_to_tm(secs, tm);

	return 0;
}

static int nvvrs_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
	struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
	time64_t secs;
	u8 time[4];
	int ret;

	secs = rtc_tm_to_time64(tm);
	time[0] = secs & 0xff;
	time[1] = (secs >> 8) & 0xff;
	time[2] = (secs >> 16) & 0xff;
	time[3] = (secs >> 24) & 0xff;

	ret = i2c_smbus_write_byte_data(info->client, NVVRS_REG_RTC_T3, time[3]);
	if (ret < 0)
		return ret;

	ret = i2c_smbus_write_byte_data(info->client, NVVRS_REG_RTC_T2, time[2]);
	if (ret < 0)
		return ret;

	ret = i2c_smbus_write_byte_data(info->client, NVVRS_REG_RTC_T1, time[1]);
	if (ret < 0)
		return ret;

	ret = i2c_smbus_write_byte_data(info->client, NVVRS_REG_RTC_T0, time[0]);

	return ret;
}

static int nvvrs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
	time64_t alarm_val = 0;
	int ret;
	u8 val;

	/* Multi-byte transfers are not supported with PEC enabled */
	ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_A3);
	if (ret < 0)
		return ret;

	val = (u8)ret;
	alarm_val |= (time64_t)val << 24;

	ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_A2);
	if (ret < 0)
		return ret;

	val = (u8)ret;
	alarm_val |= (time64_t)val << 16;

	ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_A1);
	if (ret < 0)
		return ret;

	val = (u8)ret;
	alarm_val |= (time64_t)val << 8;

	ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_RTC_A0);
	if (ret < 0)
		return ret;

	val = (u8)ret;
	alarm_val |= val;

	if (alarm_val == ALARM_RESET_VAL)
		alrm->enabled = 0;
	else
		alrm->enabled = 1;

	rtc_time64_to_tm(alarm_val, &alrm->time);

	return 0;
}

static int nvvrs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
	struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
	time64_t secs;
	u8 time[4];
	int ret;

	if (!alrm->enabled) {
		ret = nvvrs_rtc_disable_alarm(info);
		if (ret < 0)
			return ret;
	}

	ret = nvvrs_rtc_enable_alarm(info);
	if (ret < 0)
		return ret;

	secs = rtc_tm_to_time64(&alrm->time);
	time[0] = secs & 0xff;
	time[1] = (secs >> 8) & 0xff;
	time[2] = (secs >> 16) & 0xff;
	time[3] = (secs >> 24) & 0xff;

	ret = nvvrs_rtc_write_alarm(info->client, time);

	return ret;
}

static int nvvrs_pseq_irq_clear(struct nvvrs_rtc_info *info)
{
	unsigned int i;
	int ret;

	for (i = 0; i < NVVRS_IRQ_REG_COUNT; i++) {
		ret = i2c_smbus_read_byte_data(info->client,
					       NVVRS_REG_INT_SRC1 + i);
		if (ret < 0) {
			dev_err(info->dev, "Failed to read INT_SRC%d : %d\n",
				i + 1, ret);
			return ret;
		}

		ret = i2c_smbus_write_byte_data(info->client,
						NVVRS_REG_INT_SRC1 + i,
						(u8)ret);
		if (ret < 0) {
			dev_err(info->dev, "Failed to clear INT_SRC%d : %d\n",
				i + 1, ret);
			return ret;
		}
	}

	return 0;
}

static irqreturn_t nvvrs_rtc_irq_handler(int irq, void *data)
{
	struct nvvrs_rtc_info *info = data;
	int ret;

	/* Check for RTC alarm interrupt */
	ret = i2c_smbus_read_byte_data(info->client, NVVRS_REG_INT_SRC1);
	if (ret < 0)
		return IRQ_NONE;

	if (ret & NVVRS_INT_SRC1_RTC_MASK) {
		rtc_lock(info->rtc);
		rtc_update_irq(info->rtc, 1, RTC_IRQF | RTC_AF);
		rtc_unlock(info->rtc);
	}

	/* Clear all interrupts */
	if (nvvrs_pseq_irq_clear(info) < 0)
		return IRQ_NONE;

	return IRQ_HANDLED;
}

static int nvvrs_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
	/*
	 * This hardware does not support enabling/disabling the alarm IRQ
	 * independently. The alarm is disabled by clearing the alarm time
	 * via set_alarm().
	 */
	return 0;
}

static const struct rtc_class_ops nvvrs_rtc_ops = {
	.read_time = nvvrs_rtc_read_time,
	.set_time = nvvrs_rtc_set_time,
	.read_alarm = nvvrs_rtc_read_alarm,
	.set_alarm = nvvrs_rtc_set_alarm,
	.alarm_irq_enable = nvvrs_rtc_alarm_irq_enable,
};

static int nvvrs_pseq_vendor_info(struct nvvrs_rtc_info *info)
{
	struct i2c_client *client = info->client;
	u8 vendor_id, model_rev;
	int ret;

	ret = i2c_smbus_read_byte_data(client, NVVRS_REG_VENDOR_ID);
	if (ret < 0)
		return dev_err_probe(&client->dev, ret,
				     "Failed to read Vendor ID\n");

	vendor_id = (u8)ret;

	ret = i2c_smbus_read_byte_data(client, NVVRS_REG_MODEL_REV);
	if (ret < 0)
		return dev_err_probe(&client->dev, ret,
				     "Failed to read Model Revision\n");

	model_rev = (u8)ret;

	if (model_rev < NVVRS_MIN_MODEL_REV) {
		return dev_err_probe(&client->dev, -ENODEV,
				     "Chip revision 0x%02x is not supported!\n",
				     model_rev);
	}

	dev_dbg(&client->dev, "NVVRS Vendor ID: 0x%02x, Model Rev: 0x%02x\n",
		vendor_id, model_rev);

	return 0;
}

static int nvvrs_rtc_probe(struct i2c_client *client)
{
	struct nvvrs_rtc_info *info;
	int ret;

	info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);
	if (!info)
		return -ENOMEM;

	if (client->irq <= 0)
		return dev_err_probe(&client->dev, -EINVAL, "No IRQ specified\n");

	info->irq = client->irq;
	info->dev = &client->dev;
	client->flags |= I2C_CLIENT_PEC;
	i2c_set_clientdata(client, info);
	info->client = client;

	/* Check vendor info */
	if (nvvrs_pseq_vendor_info(info) < 0)
		return dev_err_probe(&client->dev, -EINVAL,
				     "Failed to get vendor info\n");

	/* Clear any pending IRQs before requesting IRQ handler */
	if (nvvrs_pseq_irq_clear(info) < 0)
		return dev_err_probe(&client->dev, -EINVAL,
				     "Failed to clear interrupts\n");

	/* Allocate RTC device */
	info->rtc = devm_rtc_allocate_device(info->dev);
	if (IS_ERR(info->rtc))
		return PTR_ERR(info->rtc);

	info->rtc->ops = &nvvrs_rtc_ops;
	info->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
	info->rtc->range_max = RTC_TIMESTAMP_END_2099;

	/* Request RTC IRQ */
	ret = devm_request_threaded_irq(info->dev, info->irq, NULL,
					nvvrs_rtc_irq_handler, IRQF_ONESHOT,
					"nvvrs-rtc", info);
	if (ret < 0) {
		dev_err_probe(info->dev, ret, "Failed to request RTC IRQ\n");
		return ret;
	}

	/* RTC as a wakeup source */
	devm_device_init_wakeup(info->dev);

	return devm_rtc_register_device(info->rtc);
}

#ifdef CONFIG_PM_SLEEP
static int nvvrs_rtc_suspend(struct device *dev)
{
	struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
	int ret;

	if (device_may_wakeup(dev)) {
		/* Set RTC_WAKE bit for auto wake system from suspend state */
		ret = nvvrs_update_bits(info, NVVRS_REG_CTL_2,
					NVVRS_REG_CTL_2_RTC_WAKE,
					NVVRS_REG_CTL_2_RTC_WAKE);
		if (ret < 0) {
			dev_err(info->dev, "Failed to set RTC_WAKE bit (%d)\n",
				ret);
			return ret;
		}

		return enable_irq_wake(info->irq);
	}

	return 0;
}

static int nvvrs_rtc_resume(struct device *dev)
{
	struct nvvrs_rtc_info *info = dev_get_drvdata(dev);
	int ret;

	if (device_may_wakeup(dev)) {
		/* Clear FORCE_ACT bit */
		ret = nvvrs_update_bits(info, NVVRS_REG_CTL_1,
					NVVRS_REG_CTL_1_FORCE_ACT, 0);
		if (ret < 0) {
			dev_err(info->dev, "Failed to clear FORCE_ACT bit (%d)\n",
				ret);
			return ret;
		}

		return disable_irq_wake(info->irq);
	}

	return 0;
}

#endif
static SIMPLE_DEV_PM_OPS(nvvrs_rtc_pm_ops, nvvrs_rtc_suspend, nvvrs_rtc_resume);

static const struct of_device_id nvvrs_rtc_of_match[] = {
	{ .compatible = "nvidia,vrs-10" },
	{ },
};
MODULE_DEVICE_TABLE(of, nvvrs_rtc_of_match);

static struct i2c_driver nvvrs_rtc_driver = {
	.driver		= {
		.name   = "rtc-nvidia-vrs10",
		.pm     = &nvvrs_rtc_pm_ops,
		.of_match_table = nvvrs_rtc_of_match,
	},
	.probe		= nvvrs_rtc_probe,
};

module_i2c_driver(nvvrs_rtc_driver);

MODULE_AUTHOR("Shubhi Garg <shgarg@nvidia.com>");
MODULE_DESCRIPTION("NVIDIA Voltage Regulator Specification RTC driver");
MODULE_LICENSE("GPL");