~ubuntu-branches/ubuntu/quantal/linux-lowlatency/quantal-proposed

« back to all changes in this revision

Viewing changes to drivers/rtc/rtc-da9052.c

  • Committer: Package Import Robot
  • Author(s): Andy Whitcroft, Andy Whitcroft
  • Date: 2012-06-21 09:16:38 UTC
  • Revision ID: package-import@ubuntu.com-20120621091638-gubhv4nox8xez1ct
Tags: 3.5.0-1.1
[ Andy Whitcroft]

* Rebuild lowlatency against Ubuntu-3.5.0-1.1
* All new configuration system to allow configuration deltas to be
  exposed via debian.lowlatency/config-delta

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Real time clock driver for DA9052
 
3
 *
 
4
 * Copyright(c) 2012 Dialog Semiconductor Ltd.
 
5
 *
 
6
 * Author: Dajun Dajun Chen <dajun.chen@diasemi.com>
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License as published by
 
10
 * the Free Software Foundation; either version 2 of the License, or
 
11
 * (at your option) any later version.
 
12
 *
 
13
 */
 
14
 
 
15
#include <linux/module.h>
 
16
#include <linux/platform_device.h>
 
17
#include <linux/rtc.h>
 
18
 
 
19
#include <linux/mfd/da9052/da9052.h>
 
20
#include <linux/mfd/da9052/reg.h>
 
21
 
 
22
#define rtc_err(da9052, fmt, ...) \
 
23
                dev_err(da9052->dev, "%s: " fmt, __func__, ##__VA_ARGS__)
 
24
 
 
25
struct da9052_rtc {
 
26
        struct rtc_device *rtc;
 
27
        struct da9052 *da9052;
 
28
        int irq;
 
29
};
 
30
 
 
31
static int da9052_rtc_enable_alarm(struct da9052 *da9052, bool enable)
 
32
{
 
33
        int ret;
 
34
        if (enable) {
 
35
                ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG,
 
36
                                        DA9052_ALARM_Y_ALARM_ON,
 
37
                                        DA9052_ALARM_Y_ALARM_ON);
 
38
                if (ret != 0)
 
39
                        rtc_err(da9052, "Failed to enable ALM: %d\n", ret);
 
40
        } else {
 
41
                ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG,
 
42
                                        DA9052_ALARM_Y_ALARM_ON, 0);
 
43
                if (ret != 0)
 
44
                        rtc_err(da9052, "Write error: %d\n", ret);
 
45
        }
 
46
        return ret;
 
47
}
 
48
 
 
49
static irqreturn_t da9052_rtc_irq(int irq, void *data)
 
50
{
 
51
        struct da9052_rtc *rtc = data;
 
52
        int ret;
 
53
 
 
54
        ret = da9052_reg_read(rtc->da9052, DA9052_ALARM_MI_REG);
 
55
        if (ret < 0) {
 
56
                rtc_err(rtc->da9052, "Read error: %d\n", ret);
 
57
                return IRQ_NONE;
 
58
        }
 
59
 
 
60
        if (ret & DA9052_ALARMMI_ALARMTYPE) {
 
61
                da9052_rtc_enable_alarm(rtc->da9052, 0);
 
62
                rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_AF);
 
63
        } else
 
64
                rtc_update_irq(rtc->rtc, 1, RTC_IRQF | RTC_PF);
 
65
 
 
66
        return IRQ_HANDLED;
 
67
}
 
68
 
 
69
static int da9052_read_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm)
 
70
{
 
71
        int ret;
 
72
        uint8_t v[5];
 
73
 
 
74
        ret = da9052_group_read(da9052, DA9052_ALARM_MI_REG, 5, v);
 
75
        if (ret != 0) {
 
76
                rtc_err(da9052, "Failed to group read ALM: %d\n", ret);
 
77
                return ret;
 
78
        }
 
79
 
 
80
        rtc_tm->tm_year = (v[4] & DA9052_RTC_YEAR) + 100;
 
81
        rtc_tm->tm_mon  = (v[3] & DA9052_RTC_MONTH) - 1;
 
82
        rtc_tm->tm_mday = v[2] & DA9052_RTC_DAY;
 
83
        rtc_tm->tm_hour = v[1] & DA9052_RTC_HOUR;
 
84
        rtc_tm->tm_min  = v[0] & DA9052_RTC_MIN;
 
85
 
 
86
        ret = rtc_valid_tm(rtc_tm);
 
87
        if (ret != 0)
 
88
                return ret;
 
89
        return ret;
 
90
}
 
91
 
 
92
static int da9052_set_alarm(struct da9052 *da9052, struct rtc_time *rtc_tm)
 
93
{
 
94
        int ret;
 
95
        uint8_t v[3];
 
96
 
 
97
        rtc_tm->tm_year -= 100;
 
98
        rtc_tm->tm_mon += 1;
 
99
 
 
100
        ret = da9052_reg_update(da9052, DA9052_ALARM_MI_REG,
 
101
                                DA9052_RTC_MIN, rtc_tm->tm_min);
 
102
        if (ret != 0) {
 
103
                rtc_err(da9052, "Failed to write ALRM MIN: %d\n", ret);
 
104
                return ret;
 
105
        }
 
106
 
 
107
        v[0] = rtc_tm->tm_hour;
 
108
        v[1] = rtc_tm->tm_mday;
 
109
        v[2] = rtc_tm->tm_mon;
 
110
 
 
111
        ret = da9052_group_write(da9052, DA9052_ALARM_H_REG, 3, v);
 
112
        if (ret < 0)
 
113
                return ret;
 
114
 
 
115
        ret = da9052_reg_update(da9052, DA9052_ALARM_Y_REG,
 
116
                                DA9052_RTC_YEAR, rtc_tm->tm_year);
 
117
        if (ret != 0)
 
118
                rtc_err(da9052, "Failed to write ALRM YEAR: %d\n", ret);
 
119
 
 
120
        return ret;
 
121
}
 
122
 
 
123
static int da9052_rtc_get_alarm_status(struct da9052 *da9052)
 
124
{
 
125
        int ret;
 
126
 
 
127
        ret = da9052_reg_read(da9052, DA9052_ALARM_Y_REG);
 
128
        if (ret < 0) {
 
129
                rtc_err(da9052, "Failed to read ALM: %d\n", ret);
 
130
                return ret;
 
131
        }
 
132
        ret &= DA9052_ALARM_Y_ALARM_ON;
 
133
        return (ret > 0) ? 1 : 0;
 
134
}
 
135
 
 
136
static int da9052_rtc_read_time(struct device *dev, struct rtc_time *rtc_tm)
 
137
{
 
138
        struct da9052_rtc *rtc = dev_get_drvdata(dev);
 
139
        uint8_t v[6];
 
140
        int ret;
 
141
 
 
142
        ret = da9052_group_read(rtc->da9052, DA9052_COUNT_S_REG, 6, v);
 
143
        if (ret < 0) {
 
144
                rtc_err(rtc->da9052, "Failed to read RTC time : %d\n", ret);
 
145
                return ret;
 
146
        }
 
147
 
 
148
        rtc_tm->tm_year = (v[5] & DA9052_RTC_YEAR) + 100;
 
149
        rtc_tm->tm_mon  = (v[4] & DA9052_RTC_MONTH) - 1;
 
150
        rtc_tm->tm_mday = v[3] & DA9052_RTC_DAY;
 
151
        rtc_tm->tm_hour = v[2] & DA9052_RTC_HOUR;
 
152
        rtc_tm->tm_min  = v[1] & DA9052_RTC_MIN;
 
153
        rtc_tm->tm_sec  = v[0] & DA9052_RTC_SEC;
 
154
 
 
155
        ret = rtc_valid_tm(rtc_tm);
 
156
        if (ret != 0) {
 
157
                rtc_err(rtc->da9052, "rtc_valid_tm failed: %d\n", ret);
 
158
                return ret;
 
159
        }
 
160
 
 
161
        return 0;
 
162
}
 
163
 
 
164
static int da9052_rtc_set_time(struct device *dev, struct rtc_time *tm)
 
165
{
 
166
        struct da9052_rtc *rtc;
 
167
        uint8_t v[6];
 
168
 
 
169
        rtc = dev_get_drvdata(dev);
 
170
 
 
171
        v[0] = tm->tm_sec;
 
172
        v[1] = tm->tm_min;
 
173
        v[2] = tm->tm_hour;
 
174
        v[3] = tm->tm_mday;
 
175
        v[4] = tm->tm_mon + 1;
 
176
        v[5] = tm->tm_year - 100;
 
177
 
 
178
        return da9052_group_write(rtc->da9052, DA9052_COUNT_S_REG, 6, v);
 
179
}
 
180
 
 
181
static int da9052_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
182
{
 
183
        int ret;
 
184
        struct rtc_time *tm = &alrm->time;
 
185
        struct da9052_rtc *rtc = dev_get_drvdata(dev);
 
186
 
 
187
        ret = da9052_read_alarm(rtc->da9052, tm);
 
188
 
 
189
        if (ret)
 
190
                return ret;
 
191
 
 
192
        alrm->enabled = da9052_rtc_get_alarm_status(rtc->da9052);
 
193
 
 
194
        return 0;
 
195
}
 
196
 
 
197
static int da9052_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
198
{
 
199
        int ret;
 
200
        struct rtc_time *tm = &alrm->time;
 
201
        struct da9052_rtc *rtc = dev_get_drvdata(dev);
 
202
 
 
203
        ret = da9052_rtc_enable_alarm(rtc->da9052, 0);
 
204
        if (ret < 0)
 
205
                return ret;
 
206
 
 
207
        ret = da9052_set_alarm(rtc->da9052, tm);
 
208
        if (ret)
 
209
                return ret;
 
210
 
 
211
        ret = da9052_rtc_enable_alarm(rtc->da9052, 1);
 
212
 
 
213
        return ret;
 
214
}
 
215
 
 
216
static int da9052_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 
217
{
 
218
        struct da9052_rtc *rtc = dev_get_drvdata(dev);
 
219
 
 
220
        return da9052_rtc_enable_alarm(rtc->da9052, enabled);
 
221
}
 
222
 
 
223
static const struct rtc_class_ops da9052_rtc_ops = {
 
224
        .read_time      = da9052_rtc_read_time,
 
225
        .set_time       = da9052_rtc_set_time,
 
226
        .read_alarm     = da9052_rtc_read_alarm,
 
227
        .set_alarm      = da9052_rtc_set_alarm,
 
228
        .alarm_irq_enable = da9052_rtc_alarm_irq_enable,
 
229
};
 
230
 
 
231
static int __devinit da9052_rtc_probe(struct platform_device *pdev)
 
232
{
 
233
        struct da9052_rtc *rtc;
 
234
        int ret;
 
235
 
 
236
        rtc = devm_kzalloc(&pdev->dev, sizeof(struct da9052_rtc), GFP_KERNEL);
 
237
        if (!rtc)
 
238
                return -ENOMEM;
 
239
 
 
240
        rtc->da9052 = dev_get_drvdata(pdev->dev.parent);
 
241
        platform_set_drvdata(pdev, rtc);
 
242
        rtc->irq = platform_get_irq_byname(pdev, "ALM");
 
243
        ret = request_threaded_irq(rtc->irq, NULL, da9052_rtc_irq,
 
244
                                   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
 
245
                                   "ALM", rtc);
 
246
        if (ret != 0) {
 
247
                rtc_err(rtc->da9052, "irq registration failed: %d\n", ret);
 
248
                goto err_mem;
 
249
        }
 
250
 
 
251
        rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
 
252
                                       &da9052_rtc_ops, THIS_MODULE);
 
253
        if (IS_ERR(rtc->rtc)) {
 
254
                ret = PTR_ERR(rtc->rtc);
 
255
                goto err_free_irq;
 
256
        }
 
257
 
 
258
        return 0;
 
259
 
 
260
err_free_irq:
 
261
        free_irq(rtc->irq, rtc);
 
262
err_mem:
 
263
        devm_kfree(&pdev->dev, rtc);
 
264
        return ret;
 
265
}
 
266
 
 
267
static int __devexit da9052_rtc_remove(struct platform_device *pdev)
 
268
{
 
269
        struct da9052_rtc *rtc = pdev->dev.platform_data;
 
270
 
 
271
        rtc_device_unregister(rtc->rtc);
 
272
        free_irq(rtc->irq, rtc);
 
273
        platform_set_drvdata(pdev, NULL);
 
274
        devm_kfree(&pdev->dev, rtc);
 
275
 
 
276
        return 0;
 
277
}
 
278
 
 
279
static struct platform_driver da9052_rtc_driver = {
 
280
        .probe  = da9052_rtc_probe,
 
281
        .remove = __devexit_p(da9052_rtc_remove),
 
282
        .driver = {
 
283
                .name   = "da9052-rtc",
 
284
                .owner  = THIS_MODULE,
 
285
        },
 
286
};
 
287
 
 
288
module_platform_driver(da9052_rtc_driver);
 
289
 
 
290
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
 
291
MODULE_DESCRIPTION("RTC driver for Dialog DA9052 PMIC");
 
292
MODULE_LICENSE("GPL");
 
293
MODULE_ALIAS("platform:da9052-rtc");