~ubuntu-branches/ubuntu/karmic/linux-mvl-dove/karmic-proposed

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Bader
  • Date: 2010-03-10 22:24:12 UTC
  • mto: (15.1.2 karmic-security)
  • mto: This revision was merged to the branch mainline in revision 18.
  • Revision ID: james.westby@ubuntu.com-20100310222412-k86m3r53jw0je7x1
Tags: upstream-2.6.31
ImportĀ upstreamĀ versionĀ 2.6.31

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
 
18
18
#define RTC_TIME_REG_OFFS       0
19
 
#define  RTC_SECONDS_OFFS       0
20
 
#define  RTC_MINUTES_OFFS       8
21
 
#define  RTC_HOURS_OFFS         16
22
 
#define  RTC_WDAY_OFFS          24
23
 
#define  RTC_HOURS_12H_MODE             (1 << 22) /* 12 hours mode */
 
19
#define RTC_SECONDS_OFFS        0
 
20
#define RTC_MINUTES_OFFS        8
 
21
#define RTC_HOURS_OFFS          16
 
22
#define RTC_WDAY_OFFS           24
 
23
#define RTC_HOURS_12H_MODE              (1 << 22) /* 12 hours mode */
24
24
 
25
25
#define RTC_DATE_REG_OFFS       4
26
 
#define  RTC_MDAY_OFFS          0
27
 
#define  RTC_MONTH_OFFS         8
28
 
#define  RTC_YEAR_OFFS          16
29
 
 
30
 
#define RTC_ALARM_TIME_REG_OFFS 8
31
 
#define RTC_ALARM_DATE_REG_OFFS 0xc
32
 
#define  RTC_ALARM_VALID        (1 << 7)
33
 
 
34
 
#define RTC_ALARM_INTERRUPT_MASK_REG_OFFS       0x10
35
 
#define RTC_ALARM_INTERRUPT_CASUE_REG_OFFS      0x14
 
26
#define RTC_MDAY_OFFS           0
 
27
#define RTC_MONTH_OFFS          8
 
28
#define RTC_YEAR_OFFS           16
 
29
 
36
30
 
37
31
struct rtc_plat_data {
38
32
        struct rtc_device *rtc;
39
33
        void __iomem *ioaddr;
40
 
        int             irq;
41
34
};
42
35
 
43
36
static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm)
88
81
        /* hw counts from year 2000, but tm_year is relative to 1900 */
89
82
        tm->tm_year = bcd2bin(year) + 100;
90
83
 
91
 
        if (rtc_valid_tm(tm) < 0) {
92
 
                /* The HW default value when no battery found can be invalid */
93
 
                rtc_time_to_tm(0, tm);
94
 
        }
95
 
        return 0;
96
 
}
97
 
 
98
 
static int mv_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
99
 
{
100
 
        struct rtc_plat_data *pdata = dev_get_drvdata(dev);
101
 
        void __iomem *ioaddr = pdata->ioaddr;
102
 
        u32     rtc_time, rtc_date;
103
 
        unsigned int year, month, day, hour, minute, second, wday;
104
 
 
105
 
        rtc_time = readl(ioaddr + RTC_ALARM_TIME_REG_OFFS);
106
 
        rtc_date = readl(ioaddr + RTC_ALARM_DATE_REG_OFFS);
107
 
 
108
 
        second = rtc_time & 0x7f;
109
 
        minute = (rtc_time >> RTC_MINUTES_OFFS) & 0x7f;
110
 
        hour = (rtc_time >> RTC_HOURS_OFFS) & 0x3f; /* assume 24 hours mode */
111
 
        wday = (rtc_time >> RTC_WDAY_OFFS) & 0x7;
112
 
 
113
 
        day = rtc_date & 0x3f;
114
 
        month = (rtc_date >> RTC_MONTH_OFFS) & 0x3f;
115
 
        year = (rtc_date >> RTC_YEAR_OFFS) & 0xff;
116
 
 
117
 
        alm->time.tm_sec = bcd2bin(second);
118
 
        alm->time.tm_min = bcd2bin(minute);
119
 
        alm->time.tm_hour = bcd2bin(hour);
120
 
        alm->time.tm_mday = bcd2bin(day);
121
 
        alm->time.tm_wday = bcd2bin(wday);
122
 
        alm->time.tm_mon = bcd2bin(month) - 1;
123
 
        /* hw counts from year 2000, but tm_year is relative to 1900 */
124
 
        alm->time.tm_year = bcd2bin(year) + 100;
125
 
 
126
 
        if (rtc_valid_tm(&alm->time) < 0) {
127
 
                dev_err(dev, "retrieved alarm date/time is not valid.\n");
128
 
                rtc_time_to_tm(0, &alm->time);
129
 
        }
130
 
 
131
 
        alm->enabled = !!readl(ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS);
132
 
        return 0;
133
 
}
134
 
 
135
 
static int mv_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
136
 
{
137
 
        struct rtc_plat_data *pdata = dev_get_drvdata(dev);
138
 
        void __iomem *ioaddr = pdata->ioaddr;
139
 
        u32 rtc_reg = 0;
140
 
 
141
 
        if (alm->time.tm_sec >= 0)
142
 
                rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_sec))
143
 
                        << RTC_SECONDS_OFFS;
144
 
        if (alm->time.tm_min >= 0)
145
 
                rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_min))
146
 
                        << RTC_MINUTES_OFFS;
147
 
        if (alm->time.tm_hour >= 0)
148
 
                rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_hour))
149
 
                        << RTC_HOURS_OFFS;
150
 
 
151
 
        writel(rtc_reg, ioaddr + RTC_ALARM_TIME_REG_OFFS);
152
 
 
153
 
        if (alm->time.tm_mday >= 0)
154
 
                rtc_reg = (RTC_ALARM_VALID | bin2bcd(alm->time.tm_mday))
155
 
                        << RTC_MDAY_OFFS;
156
 
        else
157
 
                rtc_reg = 0;
158
 
 
159
 
        if (alm->time.tm_mon >= 0)
160
 
                rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_mon + 1))
161
 
                        << RTC_MONTH_OFFS;
162
 
 
163
 
        if (alm->time.tm_year >= 0)
164
 
                rtc_reg |= (RTC_ALARM_VALID | bin2bcd(alm->time.tm_year % 100))
165
 
                        << RTC_YEAR_OFFS;
166
 
 
167
 
        writel(rtc_reg, ioaddr + RTC_ALARM_DATE_REG_OFFS);
168
 
        writel(0, ioaddr + RTC_ALARM_INTERRUPT_CASUE_REG_OFFS);
169
 
        writel(alm->enabled ? 1 : 0, 
170
 
               ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS);
171
 
        
172
 
        return 0;
173
 
}
174
 
 
175
 
static int mv_rtc_ioctl(struct device *dev, unsigned int cmd,
176
 
                        unsigned long arg)
177
 
{
178
 
        struct platform_device *pdev = to_platform_device(dev);
179
 
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
180
 
        void __iomem *ioaddr = pdata->ioaddr;
181
 
 
182
 
        if (pdata->irq < 0)
183
 
                return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */
184
 
        switch (cmd) {
185
 
        case RTC_AIE_OFF:
186
 
                writel(0, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS);
187
 
                break;
188
 
        case RTC_AIE_ON:
189
 
                writel(1, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS);
190
 
                break;
191
 
        default:
192
 
                return -ENOIOCTLCMD;
193
 
        }
194
 
        return 0;
195
 
}
196
 
 
197
 
 
198
 
static irqreturn_t mv_rtc_interrupt(int irq, void *data)
199
 
{
200
 
        struct rtc_plat_data *pdata = data;
201
 
        void __iomem *ioaddr = pdata->ioaddr;
202
 
 
203
 
        /* alarm irq? */
204
 
        if (!readl(ioaddr + RTC_ALARM_INTERRUPT_CASUE_REG_OFFS))
205
 
                return IRQ_NONE; 
206
 
        
207
 
        /* clear interrupt */
208
 
        writel(0, ioaddr + RTC_ALARM_INTERRUPT_CASUE_REG_OFFS); 
209
 
        rtc_update_irq(pdata->rtc, 1, RTC_IRQF | RTC_AF);
210
 
        return IRQ_HANDLED;
 
84
        return rtc_valid_tm(tm);
211
85
}
212
86
 
213
87
static const struct rtc_class_ops mv_rtc_ops = {
215
89
        .set_time       = mv_rtc_set_time,
216
90
};
217
91
 
218
 
static const struct rtc_class_ops mv_rtc_alarm_ops = {
219
 
        .read_time      = mv_rtc_read_time,
220
 
        .set_time       = mv_rtc_set_time,
221
 
        .read_alarm     = mv_rtc_read_alarm,
222
 
        .set_alarm      = mv_rtc_set_alarm,
223
 
        .ioctl          = mv_rtc_ioctl,
224
 
 
225
 
};
226
 
 
227
 
static int __devinit mv_rtc_probe(struct platform_device *pdev)
 
92
static int __init mv_rtc_probe(struct platform_device *pdev)
228
93
{
229
94
        struct resource *res;
230
95
        struct rtc_plat_data *pdata;
254
119
                dev_err(&pdev->dev, "24 Hours mode not supported.\n");
255
120
                return -EINVAL;
256
121
        }
 
122
 
257
123
        /* make sure it is actually functional */
258
124
        if (rtc_time == 0x01000000) {
259
125
                ssleep(1);
264
130
                }
265
131
        }
266
132
 
267
 
        pdata->irq = platform_get_irq(pdev, 0);
268
 
 
269
133
        platform_set_drvdata(pdev, pdata);
270
 
 
271
 
        if(pdata->irq >= 0) {
272
 
                device_init_wakeup(&pdev->dev, 1);
273
 
                pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
274
 
                                                 &mv_rtc_alarm_ops, THIS_MODULE);
275
 
        } else
276
 
                pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
277
 
                                                 &mv_rtc_ops, THIS_MODULE);
 
134
        pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
 
135
                                         &mv_rtc_ops, THIS_MODULE);
278
136
        if (IS_ERR(pdata->rtc))
279
137
                return PTR_ERR(pdata->rtc);
280
138
 
281
 
        if(pdata->irq >= 0) {
282
 
                writel(0, pdata->ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS);
283
 
                if (devm_request_irq(&pdev->dev, pdata->irq, mv_rtc_interrupt,
284
 
                                     IRQF_DISABLED | IRQF_SHARED,
285
 
                                     pdev->name, pdata) < 0) {
286
 
                        dev_warn(&pdev->dev, "interrupt not available.\n");
287
 
                        pdata->irq = -1;
288
 
                }
289
 
        }
290
 
 
291
139
        return 0;
292
140
}
293
141
 
295
143
{
296
144
        struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
297
145
 
298
 
        if(pdata->irq >= 0)
299
 
                device_init_wakeup(&pdev->dev, 0);
300
 
 
301
146
        rtc_device_unregister(pdata->rtc);
302
147
        return 0;
303
148
}