diff options
Diffstat (limited to 'drivers/rtc/rtc-pcf8563.c')
| -rw-r--r-- | drivers/rtc/rtc-pcf8563.c | 44 | 
1 files changed, 43 insertions, 1 deletions
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index bc0677de199..97a3284bb7c 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -64,6 +64,7 @@ struct pcf8563 {  	 * 1970...2069.  	 */  	int c_polarity;	/* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */ +	int voltage_low; /* incicates if a low_voltage was detected */  };  /* @@ -86,9 +87,11 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm)  		return -EIO;  	} -	if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) +	if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) { +		pcf8563->voltage_low = 1;  		dev_info(&client->dev,  			"low voltage detected, date/time is not reliable.\n"); +	}  	dev_dbg(&client->dev,  		"%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, " @@ -173,6 +176,44 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm)  	return 0;  } +#ifdef CONFIG_RTC_INTF_DEV +static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) +{ +	struct pcf8563 *pcf8563 = i2c_get_clientdata(to_i2c_client(dev)); +	struct rtc_time tm; + +	switch (cmd) { +	case RTC_VL_READ: +		if (pcf8563->voltage_low) +			dev_info(dev, "low voltage detected, date/time is not reliable.\n"); + +		if (copy_to_user((void __user *)arg, &pcf8563->voltage_low, +					sizeof(int))) +			return -EFAULT; +		return 0; +	case RTC_VL_CLR: +		/* +		 * Clear the VL bit in the seconds register in case +		 * the time has not been set already (which would +		 * have cleared it). This does not really matter +		 * because of the cached voltage_low value but do it +		 * anyway for consistency. +		 */ +		if (pcf8563_get_datetime(to_i2c_client(dev), &tm)) +			pcf8563_set_datetime(to_i2c_client(dev), &tm); + +		/* Clear the cached value. */ +		pcf8563->voltage_low = 0; + +		return 0; +	default: +		return -ENOIOCTLCMD; +	} +} +#else +#define pcf8563_rtc_ioctl NULL +#endif +  static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)  {  	return pcf8563_get_datetime(to_i2c_client(dev), tm); @@ -184,6 +225,7 @@ static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)  }  static const struct rtc_class_ops pcf8563_rtc_ops = { +	.ioctl		= pcf8563_rtc_ioctl,  	.read_time	= pcf8563_rtc_read_time,  	.set_time	= pcf8563_rtc_set_time,  };  |