From 33df2ee1bb59b8cd14e3a375d826a40de21f388c Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Wed, 17 Jun 2009 16:26:08 -0700 Subject: rtc: rtc-ds1307 add ds1388 Extend the ds1307 driver to support ds1388 too. Signed-off-by: Joakim Tjernlund Signed-off-by: Alessandro Zummo Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-ds1307.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers/rtc/rtc-ds1307.c') diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 2c4a65302a9..52e2427e5a9 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -31,6 +31,7 @@ enum ds_type { ds_1338, ds_1339, ds_1340, + ds_1388, m41t00, rx_8025, // rs5c372 too? different address... @@ -94,6 +95,7 @@ enum ds_type { struct ds1307 { + u8 offset; /* register's offset */ u8 regs[11]; enum ds_type type; unsigned long flags; @@ -138,6 +140,7 @@ static const struct i2c_device_id ds1307_id[] = { { "ds1337", ds_1337 }, { "ds1338", ds_1338 }, { "ds1339", ds_1339 }, + { "ds1388", ds_1388 }, { "ds1340", ds_1340 }, { "m41t00", m41t00 }, { "rx8025", rx_8025 }, @@ -291,7 +294,7 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t) /* read the RTC date and time registers all at once */ tmp = ds1307->read_block_data(ds1307->client, - DS1307_REG_SECS, 7, ds1307->regs); + ds1307->offset, 7, ds1307->regs); if (tmp != 7) { dev_err(dev, "%s error %d\n", "read", tmp); return -EIO; @@ -367,7 +370,8 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) "write", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); - result = ds1307->write_block_data(ds1307->client, 0, 7, buf); + result = ds1307->write_block_data(ds1307->client, + ds1307->offset, 7, buf); if (result < 0) { dev_err(dev, "%s error %d\n", "write", result); return result; @@ -632,9 +636,12 @@ static int __devinit ds1307_probe(struct i2c_client *client, if (!(ds1307 = kzalloc(sizeof(struct ds1307), GFP_KERNEL))) return -ENOMEM; - ds1307->client = client; i2c_set_clientdata(client, ds1307); - ds1307->type = id->driver_data; + + ds1307->client = client; + ds1307->type = id->driver_data; + ds1307->offset = 0; + buf = ds1307->regs; if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { ds1307->read_block_data = i2c_smbus_read_i2c_block_data; @@ -751,6 +758,9 @@ static int __devinit ds1307_probe(struct i2c_client *client, hour); } break; + case ds_1388: + ds1307->offset = 1; /* Seconds starts at 1 */ + break; default: break; } @@ -814,6 +824,7 @@ read_rtc: case rx_8025: case ds_1337: case ds_1339: + case ds_1388: break; } -- cgit v1.2.3-70-g09d2 From 97f902b7be4dd6ba03c6aa8d3400783ed687ebd1 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 17 Jun 2009 16:26:10 -0700 Subject: rtc: rtc-ds1307 add ds3231 Add ds3231 variant. For that, the BBSQI bit position was changed from a simple define into a lookup-array as it differs. This also removes writing to an unused bit in case of the ds1337. Signed-off-by: Wolfram Sang Acked-by: David Brownell Signed-off-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-ds1307.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers/rtc/rtc-ds1307.c') diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 52e2427e5a9..8a6f9a9f9cb 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -32,6 +32,7 @@ enum ds_type { ds_1339, ds_1340, ds_1388, + ds_3231, m41t00, rx_8025, // rs5c372 too? different address... @@ -67,6 +68,7 @@ enum ds_type { #define DS1337_REG_CONTROL 0x0e # define DS1337_BIT_nEOSC 0x80 # define DS1339_BIT_BBSQI 0x20 +# define DS3231_BIT_BBSQW 0x40 /* same as BBSQI */ # define DS1337_BIT_RS2 0x10 # define DS1337_BIT_RS1 0x08 # define DS1337_BIT_INTCN 0x04 @@ -130,6 +132,9 @@ static const struct chip_desc chips[] = { }, [ds_1340] = { }, +[ds_3231] = { + .alarm = 1, +}, [m41t00] = { }, [rx_8025] = { @@ -142,6 +147,7 @@ static const struct i2c_device_id ds1307_id[] = { { "ds1339", ds_1339 }, { "ds1388", ds_1388 }, { "ds1340", ds_1340 }, + { "ds3231", ds_3231 }, { "m41t00", m41t00 }, { "rx8025", rx_8025 }, { } @@ -356,6 +362,7 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) switch (ds1307->type) { case ds_1337: case ds_1339: + case ds_3231: buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY; break; case ds_1340: @@ -628,6 +635,11 @@ static int __devinit ds1307_probe(struct i2c_client *client, struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); int want_irq = false; unsigned char *buf; + static const int bbsqi_bitpos[] = { + [ds_1337] = 0, + [ds_1339] = DS1339_BIT_BBSQI, + [ds_3231] = DS3231_BIT_BBSQW, + }; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA) && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) @@ -654,6 +666,7 @@ static int __devinit ds1307_probe(struct i2c_client *client, switch (ds1307->type) { case ds_1337: case ds_1339: + case ds_3231: /* has IRQ? */ if (ds1307->client->irq > 0 && chip->alarm) { INIT_WORK(&ds1307->work, ds1307_work); @@ -673,12 +686,12 @@ static int __devinit ds1307_probe(struct i2c_client *client, ds1307->regs[0] &= ~DS1337_BIT_nEOSC; /* Using IRQ? Disable the square wave and both alarms. - * For ds1339, be sure alarms can trigger when we're - * running on Vbackup (BBSQI); we assume ds1337 will - * ignore that bit + * For some variants, be sure alarms can trigger when we're + * running on Vbackup (BBSQI/BBSQW) */ if (want_irq) { - ds1307->regs[0] |= DS1337_BIT_INTCN | DS1339_BIT_BBSQI; + ds1307->regs[0] |= DS1337_BIT_INTCN + | bbsqi_bitpos[ds1307->type]; ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE); } @@ -825,6 +838,7 @@ read_rtc: case ds_1337: case ds_1339: case ds_1388: + case ds_3231: break; } -- cgit v1.2.3-70-g09d2 From e6229bec25be4ba00f31dd26e25721cc96c22262 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Thu, 18 Jun 2009 16:49:09 -0700 Subject: rtc: make rtc_update_irq callable with irqs enabled The rtc_update_irq() might be called with irqs enabled, if a interrupt handler was registered without IRQF_DISABLED. Use spin_lock_irqsave/spin_unlock_irqrestore instead of spin_lock/spin_unlock. Also update kerneldoc and drivers which do extra work to follow the current interface spec, as suggestted by David Brownell. Signed-off-by: Atsushi Nemoto Cc: Alessandro Zummo Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/interface.c | 12 +++++++----- drivers/rtc/rtc-dev.c | 6 ++---- drivers/rtc/rtc-ds1305.c | 3 --- drivers/rtc/rtc-ds1307.c | 5 ----- drivers/rtc/rtc-ds1374.c | 5 ----- drivers/rtc/rtc-test.c | 2 -- 6 files changed, 9 insertions(+), 24 deletions(-) (limited to 'drivers/rtc/rtc-ds1307.c') diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 4348c4b0d45..4cdb31a362c 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -371,19 +371,21 @@ EXPORT_SYMBOL_GPL(rtc_update_irq_enable); * @rtc: the rtc device * @num: how many irqs are being reported (usually one) * @events: mask of RTC_IRQF with one or more of RTC_PF, RTC_AF, RTC_UF - * Context: in_interrupt(), irqs blocked + * Context: any */ void rtc_update_irq(struct rtc_device *rtc, unsigned long num, unsigned long events) { - spin_lock(&rtc->irq_lock); + unsigned long flags; + + spin_lock_irqsave(&rtc->irq_lock, flags); rtc->irq_data = (rtc->irq_data + (num << 8)) | events; - spin_unlock(&rtc->irq_lock); + spin_unlock_irqrestore(&rtc->irq_lock, flags); - spin_lock(&rtc->irq_task_lock); + spin_lock_irqsave(&rtc->irq_task_lock, flags); if (rtc->irq_task) rtc->irq_task->func(rtc->irq_task->private_data); - spin_unlock(&rtc->irq_task_lock); + spin_unlock_irqrestore(&rtc->irq_task_lock, flags); wake_up_interruptible(&rtc->irq_queue); kill_fasync(&rtc->async_queue, SIGIO, POLL_IN); diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 45152f4952d..8a11de9552c 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -60,8 +60,7 @@ static void rtc_uie_task(struct work_struct *work) err = rtc_read_time(rtc, &tm); - local_irq_disable(); - spin_lock(&rtc->irq_lock); + spin_lock_irq(&rtc->irq_lock); if (rtc->stop_uie_polling || err) { rtc->uie_task_active = 0; } else if (rtc->oldsecs != tm.tm_sec) { @@ -74,10 +73,9 @@ static void rtc_uie_task(struct work_struct *work) } else if (schedule_work(&rtc->uie_task) == 0) { rtc->uie_task_active = 0; } - spin_unlock(&rtc->irq_lock); + spin_unlock_irq(&rtc->irq_lock); if (num) rtc_update_irq(rtc, num, RTC_UF | RTC_IRQF); - local_irq_enable(); } static void rtc_uie_timer(unsigned long data) { diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index fc372df6534..8f410e59d9f 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -499,10 +499,7 @@ static void ds1305_work(struct work_struct *work) if (!test_bit(FLAG_EXITING, &ds1305->flags)) enable_irq(spi->irq); - /* rtc_update_irq() requires an IRQ-disabled context */ - local_irq_disable(); rtc_update_irq(ds1305->rtc, 1, RTC_AF | RTC_IRQF); - local_irq_enable(); } /* diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 8a6f9a9f9cb..47a93c022d9 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -267,12 +267,7 @@ static void ds1307_work(struct work_struct *work) control &= ~DS1337_BIT_A1IE; i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, control); - /* rtc_update_irq() assumes that it is called - * from IRQ-disabled context. - */ - local_irq_disable(); rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF); - local_irq_enable(); } out: diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 4d32e328f6c..32b27739ec2 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -296,12 +296,7 @@ static void ds1374_work(struct work_struct *work) control &= ~(DS1374_REG_CR_WACE | DS1374_REG_CR_AIE); i2c_smbus_write_byte_data(client, DS1374_REG_CR, control); - /* rtc_update_irq() assumes that it is called - * from IRQ-disabled context. - */ - local_irq_disable(); rtc_update_irq(ds1374->rtc, 1, RTC_AF | RTC_IRQF); - local_irq_enable(); } out: diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index e478280ff62..51725f7755b 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -93,7 +93,6 @@ static ssize_t test_irq_store(struct device *dev, struct rtc_device *rtc = platform_get_drvdata(plat_dev); retval = count; - local_irq_disable(); if (strncmp(buf, "tick", 4) == 0) rtc_update_irq(rtc, 1, RTC_PF | RTC_IRQF); else if (strncmp(buf, "alarm", 5) == 0) @@ -102,7 +101,6 @@ static ssize_t test_irq_store(struct device *dev, rtc_update_irq(rtc, 1, RTC_UF | RTC_IRQF); else retval = -EINVAL; - local_irq_enable(); return retval; } -- cgit v1.2.3-70-g09d2