brintos

brintos / linux-shallow public Read only

0
0
Text · 9.0 KiB · 7acf849 Raw
359 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * DS1286 Real Time Clock interface for Linux4 *5 * Copyright (C) 1998, 1999, 2000 Ralf Baechle6 * Copyright (C) 2008 Thomas Bogendoerfer7 *8 * Based on code written by Paul Gortmaker.9 */10 11#include <linux/module.h>12#include <linux/rtc.h>13#include <linux/platform_device.h>14#include <linux/bcd.h>15#include <linux/rtc/ds1286.h>16#include <linux/io.h>17#include <linux/slab.h>18 19struct ds1286_priv {20	struct rtc_device *rtc;21	u32 __iomem *rtcregs;22	spinlock_t lock;23};24 25static inline u8 ds1286_rtc_read(struct ds1286_priv *priv, int reg)26{27	return __raw_readl(&priv->rtcregs[reg]) & 0xff;28}29 30static inline void ds1286_rtc_write(struct ds1286_priv *priv, u8 data, int reg)31{32	__raw_writel(data, &priv->rtcregs[reg]);33}34 35 36static int ds1286_alarm_irq_enable(struct device *dev, unsigned int enabled)37{38	struct ds1286_priv *priv = dev_get_drvdata(dev);39	unsigned long flags;40	unsigned char val;41 42	/* Allow or mask alarm interrupts */43	spin_lock_irqsave(&priv->lock, flags);44	val = ds1286_rtc_read(priv, RTC_CMD);45	if (enabled)46		val &=  ~RTC_TDM;47	else48		val |=  RTC_TDM;49	ds1286_rtc_write(priv, val, RTC_CMD);50	spin_unlock_irqrestore(&priv->lock, flags);51 52	return 0;53}54 55#ifdef CONFIG_RTC_INTF_DEV56 57static int ds1286_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)58{59	struct ds1286_priv *priv = dev_get_drvdata(dev);60	unsigned long flags;61	unsigned char val;62 63	switch (cmd) {64	case RTC_WIE_OFF:65		/* Mask watchdog int. enab. bit	*/66		spin_lock_irqsave(&priv->lock, flags);67		val = ds1286_rtc_read(priv, RTC_CMD);68		val |= RTC_WAM;69		ds1286_rtc_write(priv, val, RTC_CMD);70		spin_unlock_irqrestore(&priv->lock, flags);71		break;72	case RTC_WIE_ON:73		/* Allow watchdog interrupts.	*/74		spin_lock_irqsave(&priv->lock, flags);75		val = ds1286_rtc_read(priv, RTC_CMD);76		val &= ~RTC_WAM;77		ds1286_rtc_write(priv, val, RTC_CMD);78		spin_unlock_irqrestore(&priv->lock, flags);79		break;80	default:81		return -ENOIOCTLCMD;82	}83	return 0;84}85 86#else87#define ds1286_ioctl    NULL88#endif89 90#ifdef CONFIG_PROC_FS91 92static int ds1286_proc(struct device *dev, struct seq_file *seq)93{94	struct ds1286_priv *priv = dev_get_drvdata(dev);95	unsigned char month, cmd, amode;96	const char *s;97 98	month = ds1286_rtc_read(priv, RTC_MONTH);99	seq_printf(seq,100		   "oscillator\t: %s\n"101		   "square_wave\t: %s\n",102		   (month & RTC_EOSC) ? "disabled" : "enabled",103		   (month & RTC_ESQW) ? "disabled" : "enabled");104 105	amode = ((ds1286_rtc_read(priv, RTC_MINUTES_ALARM) & 0x80) >> 5) |106		((ds1286_rtc_read(priv, RTC_HOURS_ALARM) & 0x80) >> 6) |107		((ds1286_rtc_read(priv, RTC_DAY_ALARM) & 0x80) >> 7);108	switch (amode) {109	case 7:110		s = "each minute";111		break;112	case 3:113		s = "minutes match";114		break;115	case 1:116		s = "hours and minutes match";117		break;118	case 0:119		s = "days, hours and minutes match";120		break;121	default:122		s = "invalid";123		break;124	}125	seq_printf(seq, "alarm_mode\t: %s\n", s);126 127	cmd = ds1286_rtc_read(priv, RTC_CMD);128	seq_printf(seq,129		   "alarm_enable\t: %s\n"130		   "wdog_alarm\t: %s\n"131		   "alarm_mask\t: %s\n"132		   "wdog_alarm_mask\t: %s\n"133		   "interrupt_mode\t: %s\n"134		   "INTB_mode\t: %s_active\n"135		   "interrupt_pins\t: %s\n",136		   (cmd & RTC_TDF) ? "yes" : "no",137		   (cmd & RTC_WAF) ? "yes" : "no",138		   (cmd & RTC_TDM) ? "disabled" : "enabled",139		   (cmd & RTC_WAM) ? "disabled" : "enabled",140		   (cmd & RTC_PU_LVL) ? "pulse" : "level",141		   (cmd & RTC_IBH_LO) ? "low" : "high",142		   (cmd & RTC_IPSW) ? "unswapped" : "swapped");143	return 0;144}145 146#else147#define ds1286_proc     NULL148#endif149 150static int ds1286_read_time(struct device *dev, struct rtc_time *tm)151{152	struct ds1286_priv *priv = dev_get_drvdata(dev);153	unsigned char save_control;154	unsigned long flags;155	unsigned long uip_watchdog = jiffies;156 157	/*158	 * read RTC once any update in progress is done. The update159	 * can take just over 2ms. We wait 10 to 20ms. There is no need to160	 * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.161	 * If you need to know *exactly* when a second has started, enable162	 * periodic update complete interrupts, (via ioctl) and then163	 * immediately read /dev/rtc which will block until you get the IRQ.164	 * Once the read clears, read the RTC time (again via ioctl). Easy.165	 */166 167	if (ds1286_rtc_read(priv, RTC_CMD) & RTC_TE)168		while (time_before(jiffies, uip_watchdog + 2*HZ/100))169			barrier();170 171	/*172	 * Only the values that we read from the RTC are set. We leave173	 * tm_wday, tm_yday and tm_isdst untouched. Even though the174	 * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated175	 * by the RTC when initially set to a non-zero value.176	 */177	spin_lock_irqsave(&priv->lock, flags);178	save_control = ds1286_rtc_read(priv, RTC_CMD);179	ds1286_rtc_write(priv, (save_control|RTC_TE), RTC_CMD);180 181	tm->tm_sec = ds1286_rtc_read(priv, RTC_SECONDS);182	tm->tm_min = ds1286_rtc_read(priv, RTC_MINUTES);183	tm->tm_hour = ds1286_rtc_read(priv, RTC_HOURS) & 0x3f;184	tm->tm_mday = ds1286_rtc_read(priv, RTC_DATE);185	tm->tm_mon = ds1286_rtc_read(priv, RTC_MONTH) & 0x1f;186	tm->tm_year = ds1286_rtc_read(priv, RTC_YEAR);187 188	ds1286_rtc_write(priv, save_control, RTC_CMD);189	spin_unlock_irqrestore(&priv->lock, flags);190 191	tm->tm_sec = bcd2bin(tm->tm_sec);192	tm->tm_min = bcd2bin(tm->tm_min);193	tm->tm_hour = bcd2bin(tm->tm_hour);194	tm->tm_mday = bcd2bin(tm->tm_mday);195	tm->tm_mon = bcd2bin(tm->tm_mon);196	tm->tm_year = bcd2bin(tm->tm_year);197 198	/*199	 * Account for differences between how the RTC uses the values200	 * and how they are defined in a struct rtc_time;201	 */202	if (tm->tm_year < 45)203		tm->tm_year += 30;204	tm->tm_year += 40;205	if (tm->tm_year < 70)206		tm->tm_year += 100;207 208	tm->tm_mon--;209 210	return 0;211}212 213static int ds1286_set_time(struct device *dev, struct rtc_time *tm)214{215	struct ds1286_priv *priv = dev_get_drvdata(dev);216	unsigned char mon, day, hrs, min, sec;217	unsigned char save_control;218	unsigned int yrs;219	unsigned long flags;220 221	yrs = tm->tm_year + 1900;222	mon = tm->tm_mon + 1;   /* tm_mon starts at zero */223	day = tm->tm_mday;224	hrs = tm->tm_hour;225	min = tm->tm_min;226	sec = tm->tm_sec;227 228	if (yrs < 1970)229		return -EINVAL;230 231	yrs -= 1940;232	if (yrs > 255)    /* They are unsigned */233		return -EINVAL;234 235	if (yrs >= 100)236		yrs -= 100;237 238	sec = bin2bcd(sec);239	min = bin2bcd(min);240	hrs = bin2bcd(hrs);241	day = bin2bcd(day);242	mon = bin2bcd(mon);243	yrs = bin2bcd(yrs);244 245	spin_lock_irqsave(&priv->lock, flags);246	save_control = ds1286_rtc_read(priv, RTC_CMD);247	ds1286_rtc_write(priv, (save_control|RTC_TE), RTC_CMD);248 249	ds1286_rtc_write(priv, yrs, RTC_YEAR);250	ds1286_rtc_write(priv, mon, RTC_MONTH);251	ds1286_rtc_write(priv, day, RTC_DATE);252	ds1286_rtc_write(priv, hrs, RTC_HOURS);253	ds1286_rtc_write(priv, min, RTC_MINUTES);254	ds1286_rtc_write(priv, sec, RTC_SECONDS);255	ds1286_rtc_write(priv, 0, RTC_HUNDREDTH_SECOND);256 257	ds1286_rtc_write(priv, save_control, RTC_CMD);258	spin_unlock_irqrestore(&priv->lock, flags);259	return 0;260}261 262static int ds1286_read_alarm(struct device *dev, struct rtc_wkalrm *alm)263{264	struct ds1286_priv *priv = dev_get_drvdata(dev);265	unsigned long flags;266 267	/*268	 * Only the values that we read from the RTC are set. That269	 * means only tm_wday, tm_hour, tm_min.270	 */271	spin_lock_irqsave(&priv->lock, flags);272	alm->time.tm_min = ds1286_rtc_read(priv, RTC_MINUTES_ALARM) & 0x7f;273	alm->time.tm_hour = ds1286_rtc_read(priv, RTC_HOURS_ALARM)  & 0x1f;274	alm->time.tm_wday = ds1286_rtc_read(priv, RTC_DAY_ALARM)    & 0x07;275	ds1286_rtc_read(priv, RTC_CMD);276	spin_unlock_irqrestore(&priv->lock, flags);277 278	alm->time.tm_min = bcd2bin(alm->time.tm_min);279	alm->time.tm_hour = bcd2bin(alm->time.tm_hour);280	alm->time.tm_sec = 0;281	return 0;282}283 284static int ds1286_set_alarm(struct device *dev, struct rtc_wkalrm *alm)285{286	struct ds1286_priv *priv = dev_get_drvdata(dev);287	unsigned char hrs, min, sec;288 289	hrs = alm->time.tm_hour;290	min = alm->time.tm_min;291	sec = alm->time.tm_sec;292 293	if (hrs >= 24)294		hrs = 0xff;295 296	if (min >= 60)297		min = 0xff;298 299	if (sec != 0)300		return -EINVAL;301 302	min = bin2bcd(min);303	hrs = bin2bcd(hrs);304 305	spin_lock(&priv->lock);306	ds1286_rtc_write(priv, hrs, RTC_HOURS_ALARM);307	ds1286_rtc_write(priv, min, RTC_MINUTES_ALARM);308	spin_unlock(&priv->lock);309 310	return 0;311}312 313static const struct rtc_class_ops ds1286_ops = {314	.ioctl		= ds1286_ioctl,315	.proc		= ds1286_proc,316	.read_time	= ds1286_read_time,317	.set_time	= ds1286_set_time,318	.read_alarm	= ds1286_read_alarm,319	.set_alarm	= ds1286_set_alarm,320	.alarm_irq_enable = ds1286_alarm_irq_enable,321};322 323static int ds1286_probe(struct platform_device *pdev)324{325	struct rtc_device *rtc;326	struct ds1286_priv *priv;327 328	priv = devm_kzalloc(&pdev->dev, sizeof(struct ds1286_priv), GFP_KERNEL);329	if (!priv)330		return -ENOMEM;331 332	priv->rtcregs = devm_platform_ioremap_resource(pdev, 0);333	if (IS_ERR(priv->rtcregs))334		return PTR_ERR(priv->rtcregs);335 336	spin_lock_init(&priv->lock);337	platform_set_drvdata(pdev, priv);338	rtc = devm_rtc_device_register(&pdev->dev, "ds1286", &ds1286_ops,339					THIS_MODULE);340	if (IS_ERR(rtc))341		return PTR_ERR(rtc);342	priv->rtc = rtc;343	return 0;344}345 346static struct platform_driver ds1286_platform_driver = {347	.driver		= {348		.name	= "rtc-ds1286",349	},350	.probe		= ds1286_probe,351};352 353module_platform_driver(ds1286_platform_driver);354 355MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");356MODULE_DESCRIPTION("DS1286 RTC driver");357MODULE_LICENSE("GPL");358MODULE_ALIAS("platform:rtc-ds1286");359