• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // SPDX-License-Identifier: GPL-2.0-only
2  /*
3   * Dallas DS1216 RTC driver
4   *
5   * Copyright (c) 2007 Thomas Bogendoerfer
6   *
7   */
8  
9  #include <linux/module.h>
10  #include <linux/rtc.h>
11  #include <linux/platform_device.h>
12  #include <linux/bcd.h>
13  #include <linux/slab.h>
14  
15  struct ds1216_regs {
16  	u8 tsec;
17  	u8 sec;
18  	u8 min;
19  	u8 hour;
20  	u8 wday;
21  	u8 mday;
22  	u8 month;
23  	u8 year;
24  };
25  
26  #define DS1216_HOUR_1224	(1 << 7)
27  #define DS1216_HOUR_AMPM	(1 << 5)
28  
29  struct ds1216_priv {
30  	struct rtc_device *rtc;
31  	void __iomem *ioaddr;
32  };
33  
34  static const u8 magic[] = {
35  	0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c
36  };
37  
38  /*
39   * Read the 64 bit we'd like to have - It a series
40   * of 64 bits showing up in the LSB of the base register.
41   *
42   */
ds1216_read(u8 __iomem * ioaddr,u8 * buf)43  static void ds1216_read(u8 __iomem *ioaddr, u8 *buf)
44  {
45  	unsigned char c;
46  	int i, j;
47  
48  	for (i = 0; i < 8; i++) {
49  		c = 0;
50  		for (j = 0; j < 8; j++)
51  			c |= (readb(ioaddr) & 0x1) << j;
52  		buf[i] = c;
53  	}
54  }
55  
ds1216_write(u8 __iomem * ioaddr,const u8 * buf)56  static void ds1216_write(u8 __iomem *ioaddr, const u8 *buf)
57  {
58  	unsigned char c;
59  	int i, j;
60  
61  	for (i = 0; i < 8; i++) {
62  		c = buf[i];
63  		for (j = 0; j < 8; j++) {
64  			writeb(c, ioaddr);
65  			c = c >> 1;
66  		}
67  	}
68  }
69  
ds1216_switch_ds_to_clock(u8 __iomem * ioaddr)70  static void ds1216_switch_ds_to_clock(u8 __iomem *ioaddr)
71  {
72  	/* Reset magic pointer */
73  	readb(ioaddr);
74  	/* Write 64 bit magic to DS1216 */
75  	ds1216_write(ioaddr, magic);
76  }
77  
ds1216_rtc_read_time(struct device * dev,struct rtc_time * tm)78  static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm)
79  {
80  	struct ds1216_priv *priv = dev_get_drvdata(dev);
81  	struct ds1216_regs regs;
82  
83  	ds1216_switch_ds_to_clock(priv->ioaddr);
84  	ds1216_read(priv->ioaddr, (u8 *)&regs);
85  
86  	tm->tm_sec = bcd2bin(regs.sec);
87  	tm->tm_min = bcd2bin(regs.min);
88  	if (regs.hour & DS1216_HOUR_1224) {
89  		/* AM/PM mode */
90  		tm->tm_hour = bcd2bin(regs.hour & 0x1f);
91  		if (regs.hour & DS1216_HOUR_AMPM)
92  			tm->tm_hour += 12;
93  	} else
94  		tm->tm_hour = bcd2bin(regs.hour & 0x3f);
95  	tm->tm_wday = (regs.wday & 7) - 1;
96  	tm->tm_mday = bcd2bin(regs.mday & 0x3f);
97  	tm->tm_mon = bcd2bin(regs.month & 0x1f);
98  	tm->tm_year = bcd2bin(regs.year);
99  	if (tm->tm_year < 70)
100  		tm->tm_year += 100;
101  
102  	return 0;
103  }
104  
ds1216_rtc_set_time(struct device * dev,struct rtc_time * tm)105  static int ds1216_rtc_set_time(struct device *dev, struct rtc_time *tm)
106  {
107  	struct ds1216_priv *priv = dev_get_drvdata(dev);
108  	struct ds1216_regs regs;
109  
110  	ds1216_switch_ds_to_clock(priv->ioaddr);
111  	ds1216_read(priv->ioaddr, (u8 *)&regs);
112  
113  	regs.tsec = 0; /* clear 0.1 and 0.01 seconds */
114  	regs.sec = bin2bcd(tm->tm_sec);
115  	regs.min = bin2bcd(tm->tm_min);
116  	regs.hour &= DS1216_HOUR_1224;
117  	if (regs.hour && tm->tm_hour > 12) {
118  		regs.hour |= DS1216_HOUR_AMPM;
119  		tm->tm_hour -= 12;
120  	}
121  	regs.hour |= bin2bcd(tm->tm_hour);
122  	regs.wday &= ~7;
123  	regs.wday |= tm->tm_wday;
124  	regs.mday = bin2bcd(tm->tm_mday);
125  	regs.month = bin2bcd(tm->tm_mon);
126  	regs.year = bin2bcd(tm->tm_year % 100);
127  
128  	ds1216_switch_ds_to_clock(priv->ioaddr);
129  	ds1216_write(priv->ioaddr, (u8 *)&regs);
130  	return 0;
131  }
132  
133  static const struct rtc_class_ops ds1216_rtc_ops = {
134  	.read_time	= ds1216_rtc_read_time,
135  	.set_time	= ds1216_rtc_set_time,
136  };
137  
ds1216_rtc_probe(struct platform_device * pdev)138  static int __init ds1216_rtc_probe(struct platform_device *pdev)
139  {
140  	struct ds1216_priv *priv;
141  	u8 dummy[8];
142  
143  	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
144  	if (!priv)
145  		return -ENOMEM;
146  
147  	platform_set_drvdata(pdev, priv);
148  
149  	priv->ioaddr = devm_platform_ioremap_resource(pdev, 0);
150  	if (IS_ERR(priv->ioaddr))
151  		return PTR_ERR(priv->ioaddr);
152  
153  	priv->rtc = devm_rtc_device_register(&pdev->dev, "ds1216",
154  					&ds1216_rtc_ops, THIS_MODULE);
155  	if (IS_ERR(priv->rtc))
156  		return PTR_ERR(priv->rtc);
157  
158  	/* dummy read to get clock into a known state */
159  	ds1216_read(priv->ioaddr, dummy);
160  	return 0;
161  }
162  
163  static struct platform_driver ds1216_rtc_platform_driver = {
164  	.driver		= {
165  		.name	= "rtc-ds1216",
166  	},
167  };
168  
169  module_platform_driver_probe(ds1216_rtc_platform_driver, ds1216_rtc_probe);
170  
171  MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
172  MODULE_DESCRIPTION("DS1216 RTC driver");
173  MODULE_LICENSE("GPL");
174  MODULE_ALIAS("platform:rtc-ds1216");
175