Skip to content

Commit 8ae83b6

Browse files
krzkalexandrebelloni
authored andcommitted
rtc: s5m: Make register configuration per S2MPS device to remove exceptions
Before updating time and alarm the driver must set appropriate mask in UDR register. For that purpose the driver uses common register configuration and a lot of exceptions per device in the code. The exceptions are not obvious, for example except the change in the logic sometimes the fields are swapped (WUDR and AUDR between S2MPS14 and S2MPS15). This leads to quite complicated code. Try to make it more obvious by: 1. Documenting the UDR masks for devices and operations. 2. Adding fields in register configuration structure for each operation (read time, write time and alarm). 3. Splitting the configuration per S2MPS13, S2MPS14 and S2MPS15 thus removing exceptions for them. Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com> Tested-by: Alim Akhtar <alim.akhtar@samsung.com> Acked-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
1 parent 67a6025 commit 8ae83b6

File tree

2 files changed

+77
-35
lines changed

2 files changed

+77
-35
lines changed

drivers/rtc/rtc-s5m.c

Lines changed: 75 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,22 @@
3838
*/
3939
#define UDR_READ_RETRY_CNT 5
4040

41-
/* Registers used by the driver which are different between chipsets. */
41+
/*
42+
* Registers used by the driver which are different between chipsets.
43+
*
44+
* Operations like read time and write alarm/time require updating
45+
* specific fields in UDR register. These fields usually are auto-cleared
46+
* (with some exceptions).
47+
*
48+
* Table of operations per device:
49+
*
50+
* Device | Write time | Read time | Write alarm
51+
* =================================================
52+
* S5M8767 | UDR + TIME | | UDR
53+
* S2MPS11/14 | WUDR | RUDR | WUDR + RUDR
54+
* S2MPS13 | WUDR | RUDR | WUDR + AUDR
55+
* S2MPS15 | WUDR | RUDR | AUDR
56+
*/
4257
struct s5m_rtc_reg_config {
4358
/* Number of registers used for setting time/alarm0/alarm1 */
4459
unsigned int regs_count;
@@ -58,8 +73,13 @@ struct s5m_rtc_reg_config {
5873
unsigned int udr_update;
5974
/* Auto-cleared mask in UDR field for writing time and alarm */
6075
unsigned int autoclear_udr_mask;
61-
/* Mask for UDR field in 'udr_update' register */
62-
unsigned int udr_mask;
76+
/*
77+
* Masks in UDR field for time and alarm operations.
78+
* The read time mask can be 0. Rest should not.
79+
*/
80+
unsigned int read_time_udr_mask;
81+
unsigned int write_time_udr_mask;
82+
unsigned int write_alarm_udr_mask;
6383
};
6484

6585
/* Register map for S5M8763 and S5M8767 */
@@ -71,22 +91,54 @@ static const struct s5m_rtc_reg_config s5m_rtc_regs = {
7191
.alarm1 = S5M_ALARM1_SEC,
7292
.udr_update = S5M_RTC_UDR_CON,
7393
.autoclear_udr_mask = S5M_RTC_UDR_MASK,
74-
.udr_mask = S5M_RTC_UDR_MASK,
94+
.read_time_udr_mask = 0, /* Not needed */
95+
.write_time_udr_mask = S5M_RTC_UDR_MASK | S5M_RTC_TIME_EN_MASK,
96+
.write_alarm_udr_mask = S5M_RTC_UDR_MASK,
97+
};
98+
99+
/* Register map for S2MPS13 */
100+
static const struct s5m_rtc_reg_config s2mps13_rtc_regs = {
101+
.regs_count = 7,
102+
.time = S2MPS_RTC_SEC,
103+
.ctrl = S2MPS_RTC_CTRL,
104+
.alarm0 = S2MPS_ALARM0_SEC,
105+
.alarm1 = S2MPS_ALARM1_SEC,
106+
.udr_update = S2MPS_RTC_UDR_CON,
107+
.autoclear_udr_mask = S2MPS_RTC_WUDR_MASK,
108+
.read_time_udr_mask = S2MPS_RTC_RUDR_MASK,
109+
.write_time_udr_mask = S2MPS_RTC_WUDR_MASK,
110+
.write_alarm_udr_mask = S2MPS_RTC_WUDR_MASK | S2MPS13_RTC_AUDR_MASK,
111+
};
112+
113+
/* Register map for S2MPS11/14 */
114+
static const struct s5m_rtc_reg_config s2mps14_rtc_regs = {
115+
.regs_count = 7,
116+
.time = S2MPS_RTC_SEC,
117+
.ctrl = S2MPS_RTC_CTRL,
118+
.alarm0 = S2MPS_ALARM0_SEC,
119+
.alarm1 = S2MPS_ALARM1_SEC,
120+
.udr_update = S2MPS_RTC_UDR_CON,
121+
.autoclear_udr_mask = S2MPS_RTC_WUDR_MASK,
122+
.read_time_udr_mask = S2MPS_RTC_RUDR_MASK,
123+
.write_time_udr_mask = S2MPS_RTC_WUDR_MASK,
124+
.write_alarm_udr_mask = S2MPS_RTC_WUDR_MASK | S2MPS_RTC_RUDR_MASK,
75125
};
76126

77127
/*
78-
* Register map for S2MPS14.
79-
* It may be also suitable for S2MPS11 but this was not tested.
128+
* Register map for S2MPS15 - in comparison to S2MPS14 the WUDR and AUDR bits
129+
* are swapped.
80130
*/
81-
static const struct s5m_rtc_reg_config s2mps_rtc_regs = {
131+
static const struct s5m_rtc_reg_config s2mps15_rtc_regs = {
82132
.regs_count = 7,
83133
.time = S2MPS_RTC_SEC,
84134
.ctrl = S2MPS_RTC_CTRL,
85135
.alarm0 = S2MPS_ALARM0_SEC,
86136
.alarm1 = S2MPS_ALARM1_SEC,
87137
.udr_update = S2MPS_RTC_UDR_CON,
88138
.autoclear_udr_mask = S2MPS_RTC_WUDR_MASK,
89-
.udr_mask = S2MPS_RTC_WUDR_MASK,
139+
.read_time_udr_mask = S2MPS_RTC_RUDR_MASK,
140+
.write_time_udr_mask = S2MPS15_RTC_WUDR_MASK,
141+
.write_alarm_udr_mask = S2MPS15_RTC_AUDR_MASK,
90142
};
91143

92144
struct s5m_rtc_info {
@@ -223,21 +275,7 @@ static inline int s5m8767_rtc_set_time_reg(struct s5m_rtc_info *info)
223275
return ret;
224276
}
225277

226-
switch (info->device_type) {
227-
case S5M8763X:
228-
case S5M8767X:
229-
data |= info->regs->udr_mask | S5M_RTC_TIME_EN_MASK;
230-
case S2MPS15X:
231-
/* As per UM, for write time register, set WUDR bit to high */
232-
data |= S2MPS15_RTC_WUDR_MASK;
233-
break;
234-
case S2MPS14X:
235-
case S2MPS13X:
236-
data |= info->regs->udr_mask;
237-
break;
238-
default:
239-
return -EINVAL;
240-
}
278+
data |= info->regs->write_time_udr_mask;
241279

242280
ret = regmap_write(info->regmap, info->regs->udr_update, data);
243281
if (ret < 0) {
@@ -262,22 +300,16 @@ static inline int s5m8767_rtc_set_alarm_reg(struct s5m_rtc_info *info)
262300
return ret;
263301
}
264302

265-
data |= info->regs->udr_mask;
303+
data |= info->regs->write_alarm_udr_mask;
266304
switch (info->device_type) {
267305
case S5M8763X:
268306
case S5M8767X:
269307
data &= ~S5M_RTC_TIME_EN_MASK;
270308
break;
271309
case S2MPS15X:
272-
/* As per UM, for write alarm, set A_UDR(bit[4]) to high
273-
* udr_mask above sets bit[4]
274-
*/
275-
break;
276310
case S2MPS14X:
277-
data |= S2MPS_RTC_RUDR_MASK;
278-
break;
279311
case S2MPS13X:
280-
data |= S2MPS13_RTC_AUDR_MASK;
312+
/* No exceptions needed */
281313
break;
282314
default:
283315
return -EINVAL;
@@ -338,11 +370,11 @@ static int s5m_rtc_read_time(struct device *dev, struct rtc_time *tm)
338370
u8 data[info->regs->regs_count];
339371
int ret;
340372

341-
if (info->device_type == S2MPS15X || info->device_type == S2MPS14X ||
342-
info->device_type == S2MPS13X) {
373+
if (info->regs->read_time_udr_mask) {
343374
ret = regmap_update_bits(info->regmap,
344375
info->regs->udr_update,
345-
S2MPS_RTC_RUDR_MASK, S2MPS_RTC_RUDR_MASK);
376+
info->regs->read_time_udr_mask,
377+
info->regs->read_time_udr_mask);
346378
if (ret) {
347379
dev_err(dev,
348380
"Failed to prepare registers for time reading: %d\n",
@@ -709,10 +741,18 @@ static int s5m_rtc_probe(struct platform_device *pdev)
709741

710742
switch (platform_get_device_id(pdev)->driver_data) {
711743
case S2MPS15X:
744+
regmap_cfg = &s2mps14_rtc_regmap_config;
745+
info->regs = &s2mps15_rtc_regs;
746+
alarm_irq = S2MPS14_IRQ_RTCA0;
747+
break;
712748
case S2MPS14X:
749+
regmap_cfg = &s2mps14_rtc_regmap_config;
750+
info->regs = &s2mps14_rtc_regs;
751+
alarm_irq = S2MPS14_IRQ_RTCA0;
752+
break;
713753
case S2MPS13X:
714754
regmap_cfg = &s2mps14_rtc_regmap_config;
715-
info->regs = &s2mps_rtc_regs;
755+
info->regs = &s2mps13_rtc_regs;
716756
alarm_irq = S2MPS14_IRQ_RTCA0;
717757
break;
718758
case S5M8763X:

include/linux/mfd/samsung/rtc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ enum s2mps_rtc_reg {
105105
#define S5M_RTC_UDR_MASK (1 << S5M_RTC_UDR_SHIFT)
106106
#define S2MPS_RTC_WUDR_SHIFT 4
107107
#define S2MPS_RTC_WUDR_MASK (1 << S2MPS_RTC_WUDR_SHIFT)
108+
#define S2MPS15_RTC_AUDR_SHIFT 4
109+
#define S2MPS15_RTC_AUDR_MASK (1 << S2MPS15_RTC_AUDR_SHIFT)
108110
#define S2MPS13_RTC_AUDR_SHIFT 1
109111
#define S2MPS13_RTC_AUDR_MASK (1 << S2MPS13_RTC_AUDR_SHIFT)
110112
#define S2MPS15_RTC_WUDR_SHIFT 1

0 commit comments

Comments
 (0)