~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno
  • Date: 2011-06-07 12:14:05 UTC
  • mfrom: (43.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110607121405-i3h1rd7nrnd2b73h
Tags: 2.6.39-2
[ Ben Hutchings ]
* [x86] Enable BACKLIGHT_APPLE, replacing BACKLIGHT_MBP_NVIDIA
  (Closes: #627492)
* cgroups: Disable memory resource controller by default. Allow it
  to be enabled using kernel parameter 'cgroup_enable=memory'.
* rt2800usb: Enable support for more USB devices including
  Linksys WUSB600N (Closes: #596626) (this change was accidentally
  omitted from 2.6.39-1)
* [x86] Remove Celeron from list of processors supporting PAE. Most
  'Celeron M' models do not.
* Update debconf template translations:
  - Swedish (Martin Bagge) (Closes: #628932)
  - French (David Prévot) (Closes: #628191)
* aufs: Update for 2.6.39 (Closes: #627837)
* Add stable 2.6.39.1, including:
  - ext4: dont set PageUptodate in ext4_end_bio()
  - pata_cmd64x: fix boot crash on parisc (Closes: #622997, #622745)
  - ext3: Fix fs corruption when make_indexed_dir() fails
  - netfilter: nf_ct_sip: validate Content-Length in TCP SIP messages
  - sctp: fix race between sctp_bind_addr_free() and
    sctp_bind_addr_conflict()
  - sctp: fix memory leak of the ASCONF queue when free asoc
  - md/bitmap: fix saving of events_cleared and other state
  - cdc_acm: Fix oops when Droids MuIn LCD is connected
  - cx88: Fix conversion from BKL to fine-grained locks (Closes: #619827)
  - keys: Set cred->user_ns in key_replace_session_keyring (CVE-2011-2184)
  - tmpfs: fix race between truncate and writepage
  - nfs41: Correct offset for LAYOUTCOMMIT
  - xen/mmu: fix a race window causing leave_mm BUG()
  - ext4: fix possible use-after-free in ext4_remove_li_request()
  For the complete list of changes, see:
   http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.1
* Bump ABI to 2
* netfilter: Enable IP_SET, IP_SET_BITMAP_IP, IP_SET_BITMAP_IPMAC,
  IP_SET_BITMAP_PORT, IP_SET_HASH_IP, IP_SET_HASH_IPPORT,
  IP_SET_HASH_IPPORTIP, IP_SET_HASH_IPPORTNET, IP_SET_HASH_NET,
  IP_SET_HASH_NETPORT, IP_SET_LIST_SET, NETFILTER_XT_SET as modules
  (Closes: #629401)

[ Aurelien Jarno ]
* [mipsel/loongson-2f] Disable_SCSI_LPFC to workaround GCC ICE.

Show diffs side-by-side

added added

removed removed

Lines of Context:
39
39
#define ISL1208_REG_SR_BAT     (1<<1)   /* battery */
40
40
#define ISL1208_REG_SR_RTCF    (1<<0)   /* rtc fail */
41
41
#define ISL1208_REG_INT 0x08
 
42
#define ISL1208_REG_INT_ALME   (1<<6)   /* alarm enable */
 
43
#define ISL1208_REG_INT_IM     (1<<7)   /* interrupt/alarm mode */
42
44
#define ISL1208_REG_09  0x09    /* reserved */
43
45
#define ISL1208_REG_ATR 0x0a
44
46
#define ISL1208_REG_DTR 0x0b
202
204
}
203
205
 
204
206
static int
 
207
isl1208_rtc_toggle_alarm(struct i2c_client *client, int enable)
 
208
{
 
209
        int icr = i2c_smbus_read_byte_data(client, ISL1208_REG_INT);
 
210
 
 
211
        if (icr < 0) {
 
212
                dev_err(&client->dev, "%s: reading INT failed\n", __func__);
 
213
                return icr;
 
214
        }
 
215
 
 
216
        if (enable)
 
217
                icr |= ISL1208_REG_INT_ALME | ISL1208_REG_INT_IM;
 
218
        else
 
219
                icr &= ~(ISL1208_REG_INT_ALME | ISL1208_REG_INT_IM);
 
220
 
 
221
        icr = i2c_smbus_write_byte_data(client, ISL1208_REG_INT, icr);
 
222
        if (icr < 0) {
 
223
                dev_err(&client->dev, "%s: writing INT failed\n", __func__);
 
224
                return icr;
 
225
        }
 
226
 
 
227
        return 0;
 
228
}
 
229
 
 
230
static int
205
231
isl1208_rtc_proc(struct device *dev, struct seq_file *seq)
206
232
{
207
233
        struct i2c_client *const client = to_i2c_client(dev);
288
314
{
289
315
        struct rtc_time *const tm = &alarm->time;
290
316
        u8 regs[ISL1208_ALARM_SECTION_LEN] = { 0, };
291
 
        int sr;
 
317
        int icr, yr, sr = isl1208_i2c_get_sr(client);
292
318
 
293
 
        sr = isl1208_i2c_get_sr(client);
294
319
        if (sr < 0) {
295
320
                dev_err(&client->dev, "%s: reading SR failed\n", __func__);
296
321
                return sr;
313
338
                bcd2bin(regs[ISL1208_REG_MOA - ISL1208_REG_SCA] & 0x1f) - 1;
314
339
        tm->tm_wday = bcd2bin(regs[ISL1208_REG_DWA - ISL1208_REG_SCA] & 0x03);
315
340
 
 
341
        /* The alarm doesn't store the year so get it from the rtc section */
 
342
        yr = i2c_smbus_read_byte_data(client, ISL1208_REG_YR);
 
343
        if (yr < 0) {
 
344
                dev_err(&client->dev, "%s: reading RTC YR failed\n", __func__);
 
345
                return yr;
 
346
        }
 
347
        tm->tm_year = bcd2bin(yr) + 100;
 
348
 
 
349
        icr = i2c_smbus_read_byte_data(client, ISL1208_REG_INT);
 
350
        if (icr < 0) {
 
351
                dev_err(&client->dev, "%s: reading INT failed\n", __func__);
 
352
                return icr;
 
353
        }
 
354
        alarm->enabled = !!(icr & ISL1208_REG_INT_ALME);
 
355
 
 
356
        return 0;
 
357
}
 
358
 
 
359
static int
 
360
isl1208_i2c_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
 
361
{
 
362
        struct rtc_time *alarm_tm = &alarm->time;
 
363
        u8 regs[ISL1208_ALARM_SECTION_LEN] = { 0, };
 
364
        const int offs = ISL1208_REG_SCA;
 
365
        unsigned long rtc_secs, alarm_secs;
 
366
        struct rtc_time rtc_tm;
 
367
        int err, enable;
 
368
 
 
369
        err = isl1208_i2c_read_time(client, &rtc_tm);
 
370
        if (err)
 
371
                return err;
 
372
        err = rtc_tm_to_time(&rtc_tm, &rtc_secs);
 
373
        if (err)
 
374
                return err;
 
375
        err = rtc_tm_to_time(alarm_tm, &alarm_secs);
 
376
        if (err)
 
377
                return err;
 
378
 
 
379
        /* If the alarm time is before the current time disable the alarm */
 
380
        if (!alarm->enabled || alarm_secs <= rtc_secs)
 
381
                enable = 0x00;
 
382
        else
 
383
                enable = 0x80;
 
384
 
 
385
        /* Program the alarm and enable it for each setting */
 
386
        regs[ISL1208_REG_SCA - offs] = bin2bcd(alarm_tm->tm_sec) | enable;
 
387
        regs[ISL1208_REG_MNA - offs] = bin2bcd(alarm_tm->tm_min) | enable;
 
388
        regs[ISL1208_REG_HRA - offs] = bin2bcd(alarm_tm->tm_hour) |
 
389
                ISL1208_REG_HR_MIL | enable;
 
390
 
 
391
        regs[ISL1208_REG_DTA - offs] = bin2bcd(alarm_tm->tm_mday) | enable;
 
392
        regs[ISL1208_REG_MOA - offs] = bin2bcd(alarm_tm->tm_mon + 1) | enable;
 
393
        regs[ISL1208_REG_DWA - offs] = bin2bcd(alarm_tm->tm_wday & 7) | enable;
 
394
 
 
395
        /* write ALARM registers */
 
396
        err = isl1208_i2c_set_regs(client, offs, regs,
 
397
                                  ISL1208_ALARM_SECTION_LEN);
 
398
        if (err < 0) {
 
399
                dev_err(&client->dev, "%s: writing ALARM section failed\n",
 
400
                        __func__);
 
401
                return err;
 
402
        }
 
403
 
 
404
        err = isl1208_rtc_toggle_alarm(client, enable);
 
405
        if (err)
 
406
                return err;
 
407
 
316
408
        return 0;
317
409
}
318
410
 
391
483
        return isl1208_i2c_read_alarm(to_i2c_client(dev), alarm);
392
484
}
393
485
 
 
486
static int
 
487
isl1208_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 
488
{
 
489
        return isl1208_i2c_set_alarm(to_i2c_client(dev), alarm);
 
490
}
 
491
 
 
492
static irqreturn_t
 
493
isl1208_rtc_interrupt(int irq, void *data)
 
494
{
 
495
        unsigned long timeout = jiffies + msecs_to_jiffies(1000);
 
496
        struct i2c_client *client = data;
 
497
        int handled = 0, sr, err;
 
498
 
 
499
        /*
 
500
         * I2C reads get NAK'ed if we read straight away after an interrupt?
 
501
         * Using a mdelay/msleep didn't seem to help either, so we work around
 
502
         * this by continually trying to read the register for a short time.
 
503
         */
 
504
        while (1) {
 
505
                sr = isl1208_i2c_get_sr(client);
 
506
                if (sr >= 0)
 
507
                        break;
 
508
 
 
509
                if (time_after(jiffies, timeout)) {
 
510
                        dev_err(&client->dev, "%s: reading SR failed\n",
 
511
                                __func__);
 
512
                        return sr;
 
513
                }
 
514
        }
 
515
 
 
516
        if (sr & ISL1208_REG_SR_ALM) {
 
517
                dev_dbg(&client->dev, "alarm!\n");
 
518
 
 
519
                /* Clear the alarm */
 
520
                sr &= ~ISL1208_REG_SR_ALM;
 
521
                sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr);
 
522
                if (sr < 0)
 
523
                        dev_err(&client->dev, "%s: writing SR failed\n",
 
524
                                __func__);
 
525
                else
 
526
                        handled = 1;
 
527
 
 
528
                /* Disable the alarm */
 
529
                err = isl1208_rtc_toggle_alarm(client, 0);
 
530
                if (err)
 
531
                        return err;
 
532
        }
 
533
 
 
534
        return handled ? IRQ_HANDLED : IRQ_NONE;
 
535
}
 
536
 
394
537
static const struct rtc_class_ops isl1208_rtc_ops = {
395
538
        .proc = isl1208_rtc_proc,
396
539
        .read_time = isl1208_rtc_read_time,
397
540
        .set_time = isl1208_rtc_set_time,
398
541
        .read_alarm = isl1208_rtc_read_alarm,
399
 
        /*.set_alarm    = isl1208_rtc_set_alarm, */
 
542
        .set_alarm = isl1208_rtc_set_alarm,
400
543
};
401
544
 
402
545
/* sysfs interface */
488
631
        dev_info(&client->dev,
489
632
                 "chip found, driver version " DRV_VERSION "\n");
490
633
 
 
634
        if (client->irq > 0) {
 
635
                rc = request_threaded_irq(client->irq, NULL,
 
636
                                          isl1208_rtc_interrupt,
 
637
                                          IRQF_SHARED,
 
638
                                          isl1208_driver.driver.name, client);
 
639
                if (!rc) {
 
640
                        device_init_wakeup(&client->dev, 1);
 
641
                        enable_irq_wake(client->irq);
 
642
                } else {
 
643
                        dev_err(&client->dev,
 
644
                                "Unable to request irq %d, no alarm support\n",
 
645
                                client->irq);
 
646
                        client->irq = 0;
 
647
                }
 
648
        }
 
649
 
491
650
        rtc = rtc_device_register(isl1208_driver.driver.name,
492
651
                                  &client->dev, &isl1208_rtc_ops,
493
652
                                  THIS_MODULE);
494
 
        if (IS_ERR(rtc))
495
 
                return PTR_ERR(rtc);
 
653
        if (IS_ERR(rtc)) {
 
654
                rc = PTR_ERR(rtc);
 
655
                goto exit_free_irq;
 
656
        }
496
657
 
497
658
        i2c_set_clientdata(client, rtc);
498
659
 
514
675
 
515
676
exit_unregister:
516
677
        rtc_device_unregister(rtc);
 
678
exit_free_irq:
 
679
        if (client->irq)
 
680
                free_irq(client->irq, client);
517
681
 
518
682
        return rc;
519
683
}
525
689
 
526
690
        sysfs_remove_group(&client->dev.kobj, &isl1208_rtc_sysfs_files);
527
691
        rtc_device_unregister(rtc);
 
692
        if (client->irq)
 
693
                free_irq(client->irq, client);
528
694
 
529
695
        return 0;
530
696
}