aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorChris DeBruin <cdeb5783@gmail.com>2016-07-12 17:15:46 -0400
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2016-07-19 13:11:54 -0400
commit0d981f81e0fded15827a8224234b3733e9c0038d (patch)
treebed7e6237c532f778446d7117c34f58d40ba4293 /drivers/rtc
parentc421ce7265ce0280453811f4447ede754ebe7e66 (diff)
rtc: pcf85063: Add support for the PCF85063A device
The current rtc-pcf85063 driver only supports the PCF85063TP device. Using the existing driver on a PCF85063A will result in the time being set correctly into the RTC, but the RTC is held in the stopped state. Therefore, the time will no longer advance and no error is indicated. The PCF85063A device has a bigger memory map than the PCF85063TP. The existing driver make use of an address rollover condition, but the rollover point is different in the two devices. Signed-off-by: Chris DeBruin <cdeb5783@gmail.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/rtc-pcf85063.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index 437638eb68a7..efb0a08ac117 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -16,6 +16,16 @@
16#include <linux/rtc.h> 16#include <linux/rtc.h>
17#include <linux/module.h> 17#include <linux/module.h>
18 18
19/*
20 * Information for this driver was pulled from the following datasheets.
21 *
22 * http://www.nxp.com/documents/data_sheet/PCF85063A.pdf
23 * http://www.nxp.com/documents/data_sheet/PCF85063TP.pdf
24 *
25 * PCF85063A -- Rev. 6 — 18 November 2015
26 * PCF85063TP -- Rev. 4 — 6 May 2015
27*/
28
19#define PCF85063_REG_CTRL1 0x00 /* status */ 29#define PCF85063_REG_CTRL1 0x00 /* status */
20#define PCF85063_REG_CTRL1_STOP BIT(5) 30#define PCF85063_REG_CTRL1_STOP BIT(5)
21#define PCF85063_REG_CTRL2 0x01 31#define PCF85063_REG_CTRL2 0x01
@@ -55,6 +65,22 @@ static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1)
55 return 0; 65 return 0;
56} 66}
57 67
68static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1)
69{
70 s32 ret;
71
72 /* start the clock */
73 ctrl1 &= PCF85063_REG_CTRL1_STOP;
74
75 ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1);
76 if (ret < 0) {
77 dev_err(&client->dev, "Failing to start the clock\n");
78 return -EIO;
79 }
80
81 return 0;
82}
83
58static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm) 84static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
59{ 85{
60 int rc; 86 int rc;
@@ -94,7 +120,8 @@ static int pcf85063_get_datetime(struct i2c_client *client, struct rtc_time *tm)
94static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm) 120static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
95{ 121{
96 int rc; 122 int rc;
97 u8 regs[8]; 123 u8 regs[7];
124 u8 ctrl1;
98 125
99 if ((tm->tm_year < 100) || (tm->tm_year > 199)) 126 if ((tm->tm_year < 100) || (tm->tm_year > 199))
100 return -EINVAL; 127 return -EINVAL;
@@ -103,7 +130,7 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
103 * to accurately set the time, reset the divider chain and keep it in 130 * to accurately set the time, reset the divider chain and keep it in
104 * reset state until all time/date registers are written 131 * reset state until all time/date registers are written
105 */ 132 */
106 rc = pcf85063_stop_clock(client, &regs[7]); 133 rc = pcf85063_stop_clock(client, &ctrl1);
107 if (rc != 0) 134 if (rc != 0)
108 return rc; 135 return rc;
109 136
@@ -125,13 +152,6 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
125 /* year and century */ 152 /* year and century */
126 regs[6] = bin2bcd(tm->tm_year - 100); 153 regs[6] = bin2bcd(tm->tm_year - 100);
127 154
128 /*
129 * after all time/date registers are written, let the 'address auto
130 * increment' feature wrap around and write register CTRL1 to re-enable
131 * the clock divider chain again
132 */
133 regs[7] &= ~PCF85063_REG_CTRL1_STOP;
134
135 /* write all registers at once */ 155 /* write all registers at once */
136 rc = i2c_smbus_write_i2c_block_data(client, PCF85063_REG_SC, 156 rc = i2c_smbus_write_i2c_block_data(client, PCF85063_REG_SC,
137 sizeof(regs), regs); 157 sizeof(regs), regs);
@@ -140,6 +160,15 @@ static int pcf85063_set_datetime(struct i2c_client *client, struct rtc_time *tm)
140 return rc; 160 return rc;
141 } 161 }
142 162
163 /*
164 * Write the control register as a separate action since the size of
165 * the register space is different between the PCF85063TP and
166 * PCF85063A devices. The rollover point can not be used.
167 */
168 rc = pcf85063_start_clock(client, ctrl1);
169 if (rc != 0)
170 return rc;
171
143 return 0; 172 return 0;
144} 173}
145 174