diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-20 16:30:27 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-20 16:30:27 -0700 |
| commit | bfebeb16722d93caf7870b63aa7d094b6843479a (patch) | |
| tree | 48cfc8044f7604b99a127a3c0667ff20f57e22ef | |
| parent | 3933ec73cd9bbff4a98259d0eae606af4e2850a2 (diff) | |
| parent | 6b583a64fd1e019fd01626b46892ebf2361951c5 (diff) | |
| download | linux-bfebeb16722d93caf7870b63aa7d094b6843479a.tar.gz linux-bfebeb16722d93caf7870b63aa7d094b6843479a.tar.bz2 linux-bfebeb16722d93caf7870b63aa7d094b6843479a.zip | |
Merge tag 'rtc-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
Pull RTC updates from Alexandre Belloni:
"It is now possible to add custom sysfs attributes while avoiding a
possible race condition. Unused code has been removed resulting in a
nice reduction of the code base. And more drivers have been switched
to SPDX by their maintainers.
Summary:
Subsystem:
- new helpers to add custom sysfs attributes
- struct rtc_task removal along with rtc_irq_[un]register()
- rtc_irq_set_state and rtc_irq_set_freq are not exported anymore
Drivers:
- armada38x: reset after rtc power loss
- ds1307: now supports m41t11
- isl1208: now supports isl1219 and tamper detection
- pcf2127: internal SRAM support"
* tag 'rtc-4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (34 commits)
rtc: ds1307: simplify hwmon config
rtc: s5m: Add SPDX license identifier
rtc: maxim: Add SPDX license identifiers
rtc: isl1219: add device tree documentation
rtc: isl1208: set ev-evienb bit from device tree
rtc: isl1208: Add "evdet" interrupt source for isl1219
rtc: isl1208: add support for isl1219 with tamper detection
rtc: sysfs: facilitate attribute add to rtc device
rtc: remove struct rtc_task
char: rtc: remove task handling
rtc: pcf85063: preserve control register value between stop and start
rtc: sh: remove unused variable rtc_dev
rtc: unexport rtc_irq_set_*
rtc: simplify rtc_irq_set_state/rtc_irq_set_freq
rtc: remove irq_task and irq_task_lock
rtc: remove rtc_irq_register/rtc_irq_unregister
rtc: sh: remove dead code
rtc: sa1100: don't set PIE frequency
rtc: ds1307: support m41t11 variant
rtc: ds1307: fix data pointer to m41t0
...
28 files changed, 524 insertions, 971 deletions
diff --git a/Documentation/devicetree/bindings/rtc/isil,isl1219.txt b/Documentation/devicetree/bindings/rtc/isil,isl1219.txt new file mode 100644 index 000000000000..c3efd48e91c2 --- /dev/null +++ b/Documentation/devicetree/bindings/rtc/isil,isl1219.txt @@ -0,0 +1,29 @@ +Intersil ISL1219 I2C RTC/Alarm chip with event in + +ISL1219 has additional pins EVIN and #EVDET for tamper detection. + +Required properties supported by the device: + + - "compatible": must be "isil,isl1219" + - "reg": I2C bus address of the device + +Optional properties: + + - "interrupt-names": list which may contains "irq" and "evdet" + - "interrupts": list of interrupts for "irq" and "evdet" + - "isil,ev-evienb": if present EV.EVIENB bit is set to the specified + value for proper operation. + + +Example isl1219 node with #IRQ pin connected to SoC gpio1 pin12 + and #EVDET pin connected to SoC gpio2 pin 24: + + isl1219: rtc@68 { + compatible = "isil,isl1219"; + reg = <0x68>; + interrupt-names = "irq", "evdet"; + interrupts-extended = <&gpio1 12 IRQ_TYPE_EDGE_FALLING>, + <&gpio2 24 IRQ_TYPE_EDGE_FALLING>; + isil,ev-evienb = <1>; + }; + diff --git a/Documentation/devicetree/bindings/rtc/rtc-ds1307.txt b/Documentation/devicetree/bindings/rtc/rtc-ds1307.txt index 226cc93df875..eebfbe04207a 100644 --- a/Documentation/devicetree/bindings/rtc/rtc-ds1307.txt +++ b/Documentation/devicetree/bindings/rtc/rtc-ds1307.txt @@ -13,6 +13,7 @@ Required properties: "maxim,ds3231", "st,m41t0", "st,m41t00", + "st,m41t11", "microchip,mcp7940x", "microchip,mcp7941x", "pericom,pt7c4338", diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 94fedeeec035..4948c8bda6b1 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c @@ -193,14 +193,6 @@ static unsigned long rtc_freq; /* Current periodic IRQ rate */ static unsigned long rtc_irq_data; /* our output to the world */ static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */ -#ifdef RTC_IRQ -/* - * rtc_task_lock nests inside rtc_lock. - */ -static DEFINE_SPINLOCK(rtc_task_lock); -static rtc_task_t *rtc_callback; -#endif - /* * If this driver ever becomes modularised, it will be really nice * to make the epoch retain its value across module reload... @@ -264,11 +256,6 @@ static irqreturn_t rtc_interrupt(int irq, void *dev_id) spin_unlock(&rtc_lock); - /* Now do the rest of the actions */ - spin_lock(&rtc_task_lock); - if (rtc_callback) - rtc_callback->func(rtc_callback->private_data); - spin_unlock(&rtc_task_lock); wake_up_interruptible(&rtc_wait); kill_fasync(&rtc_async_queue, SIGIO, POLL_IN); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index a2ba5db36145..7d7be60a2413 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -244,15 +244,6 @@ config RTC_DRV_DS1307 This driver can also be built as a module. If so, the module will be called rtc-ds1307. -config RTC_DRV_DS1307_HWMON - bool "HWMON support for rtc-ds1307" - depends on RTC_DRV_DS1307 && HWMON - depends on !(RTC_DRV_DS1307=y && HWMON=m) - default y - help - Say Y here if you want to expose temperature sensor data on - rtc-ds1307 (only DS3231) - config RTC_DRV_DS1307_CENTURY bool "Century bit support for rtc-ds1307" depends on RTC_DRV_DS1307 @@ -1027,18 +1018,6 @@ config RTC_DS1685_PROC_REGS Unless you are debugging this driver, choose N. -config RTC_DS1685_SYSFS_REGS - bool "SysFS access to RTC register bits" - depends on RTC_DRV_DS1685_FAMILY && SYSFS - help - Enable this to provide access to the RTC control register bits - in /sys. Some of the bits are read-write, others are read-only. - - Keep in mind that reading Control C's bits automatically clears - all pending IRQ flags - this can cause lost interrupts. - - If you know that you need access to these bits, choose Y, Else N. - config RTC_DRV_DS1742 tristate "Maxim/Dallas DS1742/1743" depends on HAS_IOMEM diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index d37588f08055..0fca4d74c76b 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -68,7 +68,7 @@ static int rtc_suspend(struct device *dev) return 0; } - getnstimeofday64(&old_system); + ktime_get_real_ts64(&old_system); old_rtc.tv_sec = rtc_tm_to_time64(&tm); @@ -110,7 +110,7 @@ static int rtc_resume(struct device *dev) return 0; /* snapshot the current rtc and system time at resume */ - getnstimeofday64(&new_system); + ktime_get_real_ts64(&new_system); err = rtc_read_time(rtc, &tm); if (err < 0) { pr_debug("%s: fail to read rtc time\n", dev_name(&rtc->dev)); @@ -172,7 +172,6 @@ static struct rtc_device *rtc_allocate_device(void) mutex_init(&rtc->ops_lock); spin_lock_init(&rtc->irq_lock); - spin_lock_init(&rtc->irq_task_lock); init_waitqueue_head(&rtc->irq_queue); /* Init timerqueue */ diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index bac1eeb3d312..3d577e259e91 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -607,12 +607,6 @@ void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode) rtc->irq_data = (rtc->irq_data + (num << 8)) | (RTC_IRQF|mode); spin_unlock_irqrestore(&rtc->irq_lock, flags); - /* call the task func */ - spin_lock_irqsave(&rtc->irq_task_lock, flags); - if (rtc->irq_task) - rtc->irq_task->func(rtc->irq_task->private_data); - spin_unlock_irqrestore(&rtc->irq_task_lock, flags); - wake_up_interruptible(&rtc->irq_queue); kill_fasync(&rtc->async_queue, SIGIO, POLL_IN); } @@ -721,39 +715,6 @@ void rtc_class_close(struct rtc_device *rtc) } EXPORT_SYMBOL_GPL(rtc_class_close); -int rtc_irq_register(struct rtc_device *rtc, struct rtc_task *task) -{ - int retval = -EBUSY; - - if (task == NULL || task->func == NULL) - return -EINVAL; - - /* Cannot register while the char dev is in use */ - if (test_and_set_bit_lock(RTC_DEV_BUSY, &rtc->flags)) - return -EBUSY; - - spin_lock_irq(&rtc->irq_task_lock); - if (rtc->irq_task == NULL) { - rtc->irq_task = task; - retval = 0; - } - spin_unlock_irq(&rtc->irq_task_lock); - - clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); - - return retval; -} -EXPORT_SYMBOL_GPL(rtc_irq_register); - -void rtc_irq_unregister(struct rtc_device *rtc, struct rtc_task *task) -{ - spin_lock_irq(&rtc->irq_task_lock); - if (rtc->irq_task == task) - rtc->irq_task = NULL; - spin_unlock_irq(&rtc->irq_task_lock); -} -EXPORT_SYMBOL_GPL(rtc_irq_unregister); - static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled) { /* @@ -785,71 +746,45 @@ static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled) * Context: any * * Note that rtc_irq_set_freq() should previously have been used to - * specify the desired frequency of periodic IRQ task->func() callbacks. + * specify the desired frequency of periodic IRQ. */ -int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled) +int rtc_irq_set_state(struct rtc_device *rtc, int enabled) { int err = 0; - unsigned long flags; -retry: - spin_lock_irqsave(&rtc->irq_task_lock, flags); - if (rtc->irq_task != NULL && task == NULL) - err = -EBUSY; - else if (rtc->irq_task != task) - err = -EACCES; - else { - if (rtc_update_hrtimer(rtc, enabled) < 0) { - spin_unlock_irqrestore(&rtc->irq_task_lock, flags); - cpu_relax(); - goto retry; - } - rtc->pie_enabled = enabled; - } - spin_unlock_irqrestore(&rtc->irq_task_lock, flags); + while (rtc_update_hrtimer(rtc, enabled) < 0) + cpu_relax(); + + rtc->pie_enabled = enabled; trace_rtc_irq_set_state(enabled, err); return err; } -EXPORT_SYMBOL_GPL(rtc_irq_set_state); /** * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ * @rtc: the rtc device * @task: currently registered with rtc_irq_register() - * @freq: positive frequency with which task->func() will be called + * @freq: positive frequency * Context: any * * Note that rtc_irq_set_state() is used to enable or disable the * periodic IRQs. */ -int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq) +int rtc_irq_set_freq(struct rtc_device *rtc, int freq) { int err = 0; - unsigned long flags; if (freq <= 0 || freq > RTC_MAX_FREQ) return -EINVAL; -retry: - spin_lock_irqsave(&rtc->irq_task_lock, flags); - if (rtc->irq_task != NULL && task == NULL) - err = -EBUSY; - else if (rtc->irq_task != task) - err = -EACCES; - else { - rtc->irq_freq = freq; - if (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0) { - spin_unlock_irqrestore(&rtc->irq_task_lock, flags); - cpu_relax(); - goto retry; - } - } - spin_unlock_irqrestore(&rtc->irq_task_lock, flags); + + rtc->irq_freq = freq; + while (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0) + cpu_relax(); trace_rtc_irq_set_freq(freq, err); return err; } -EXPORT_SYMBOL_GPL(rtc_irq_set_freq); /** * rtc_timer_enqueue - Adds a rtc_timer to the rtc_device timerqueue @@ -979,8 +914,8 @@ again: timerqueue_del(&rtc->timerqueue, &timer->node); trace_rtc_timer_dequeue(timer); timer->enabled = 0; - if (timer->task.func) - timer->task.func(timer->task.private_data); + if (timer->func) + timer->func(timer->private_data); trace_rtc_timer_fired(timer); /* Re-add/fwd periodic timers */ @@ -1035,8 +970,8 @@ void rtc_timer_init(struct rtc_timer *timer, void (*f)(void *p), void *data) { timerqueue_init(&timer->node); timer->enabled = 0; - timer->task.func = f; - timer->task.private_data = data; + timer->func = f; + timer->private_data = data; } /* rtc_timer_start - Sets an rtc_timer to fire in the future diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c index 1e4978c96ffd..bde53c8ccee2 100644 --- a/drivers/rtc/rtc-armada38x.c +++ b/drivers/rtc/rtc-armada38x.c @@ -30,6 +30,8 @@ #define RTC_IRQ_FREQ_1HZ BIT(2) #define RTC_CCR 0x18 #define RTC_CCR_MODE BIT(15) +#define RTC_CONF_TEST 0x1C +#define RTC_NOMINAL_TIMING BIT(13) #define RTC_TIME 0xC #define RTC_ALARM1 0x10 @@ -75,6 +77,7 @@ struct armada38x_rtc { void __iomem *regs_soc; spinlock_t lock; int irq; + bool initialized; struct value_to_freq *val_to_freq; struct armada38x_rtc_data *data; }; @@ -226,6 +229,23 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm) return 0; } +static void armada38x_rtc_reset(struct armada38x_rtc *rtc) +{ + u32 reg; + + reg = rtc->data->read_rtc_reg(rtc, RTC_CONF_TEST); + /* If bits [7:0] are non-zero, assume RTC was uninitialized */ + if (reg & 0xff) { + rtc_delayed_write(0, rtc, RTC_CONF_TEST); + msleep(500); /* Oscillator startup time */ + rtc_delayed_write(0, rtc, RTC_TIME); + rtc_delayed_write(SOC_RTC_ALARM1 | SOC_RTC_ALARM2, rtc, + RTC_STATUS); + rtc_delayed_write(RTC_NOMINAL_TIMING, rtc, RTC_CCR); + } + rtc->initialized = true; +} + static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct armada38x_rtc *rtc = dev_get_drvdata(dev); @@ -237,6 +257,9 @@ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm) if (ret) goto out; + if (!rtc->initialized) + armada38x_rtc_reset(rtc); + spin_lock_irqsave(&rtc->lock, flags); rtc_delayed_write(time, rtc, RTC_TIME); spin_unlock_irqrestore(&rtc->lock, flags); diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c index d768f6747961..113493b52149 100644 --- a/drivers/rtc/rtc-bq4802.c +++ b/drivers/rtc/rtc-bq4802.c @@ -162,6 +162,10 @@ static int bq4802_probe(struct platform_device *pdev) } else if (p->r->flags & IORESOURCE_MEM) { p->regs = devm_ioremap(&pdev->dev, p->r->start, resource_size(p->r)); + if (!p->regs){ + err = -ENOMEM; + goto out; + } p->read = bq4802_read_mem; p->write = bq4802_write_mem; } else { diff --git a/drivers/rtc/rtc-core.h b/drivers/rtc/rtc-core.h index 0abf98983e13..ccc17a2e293d 100644 --- a/drivers/rtc/rtc-core.h +++ b/drivers/rtc/rtc-core.h @@ -40,9 +40,23 @@ static inline void rtc_proc_del_device(struct rtc_device *rtc) #ifdef CONFIG_RTC_INTF_SYSFS const struct attribute_group **rtc_get_dev_attribute_groups(void); +int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp); +int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps); #else static inline const struct attribute_group **rtc_get_dev_attribute_groups(void) { return NULL; } + +static inline +int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp) +{ + return 0; +} + +static inline +int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps) +{ + return 0; +} #endif diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index efa221e8bc22..43d962a9c210 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -341,11 +341,11 @@ static long rtc_dev_ioctl(struct file *file, return rtc_set_time(rtc, &tm); case RTC_PIE_ON: - err = rtc_irq_set_state(rtc, NULL, 1); + err = rtc_irq_set_state(rtc, 1); break; case RTC_PIE_OFF: - err = rtc_irq_set_state(rtc, NULL, 0); + err = rtc_irq_set_state(rtc, 0); break; case RTC_AIE_ON: @@ -365,7 +365,7 @@ static long rtc_dev_ioctl(struct file *file, return rtc_update_irq_enable(rtc, 0); case RTC_IRQP_SET: - err = rtc_irq_set_freq(rtc, NULL, arg); + err = rtc_irq_set_freq(rtc, arg); break; case RTC_IRQP_READ: @@ -427,7 +427,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file) /* Keep ioctl until all drivers are converted */ rtc_dev_ioctl(file, RTC_UIE_OFF, 0); rtc_update_irq_enable(rtc, 0); - rtc_irq_set_state(rtc, NULL, 0); + rtc_irq_set_state(rtc, 0); clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags); return 0; diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index e9ec4160d7f6..4b2b4627daeb 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -44,6 +44,7 @@ enum ds_type { ds_3231, m41t0, m41t00, + m41t11, mcp794xx, rx_8025, rx_8130, @@ -227,6 +228,11 @@ static const struct chip_desc chips[last_ds_type] = { .irq_handler = rx8130_irq, .rtc_ops = &rx8130_rtc_ops, }, + [m41t11] = { + /* this is battery backed SRAM */ + .nvram_offset = 8, + .nvram_size = 56, + }, [mcp794xx] = { .alarm = 1, /* this is battery backed SRAM */ @@ -249,6 +255,7 @@ static const struct i2c_device_id ds1307_id[] = { { "ds3231", ds_3231 }, { "m41t0", m41t0 }, { "m41t00", m41t00 }, + { "m41t11", m41t11 }, { "mcp7940x", mcp794xx }, { "mcp7941x", mcp794xx }, { "pt7c4338", ds_1307 }, @@ -299,13 +306,17 @@ static const struct of_device_id ds1307_of_match[] = { }, { .compatible = "st,m41t0", - .data = (void *)m41t00 + .data = (void *)m41t0 }, { .compatible = "st,m41t00", .data = (void *)m41t00 }, { + .compatible = "st,m41t11", + .data = (void *)m41t11 + }, + { .compatible = "microchip,mcp7940x", .data = (void *)mcp794xx }, @@ -347,6 +358,7 @@ static const struct acpi_device_id ds1307_acpi_ids[] = { { .id = "DS3231", .driver_data = ds_3231 }, { .id = "M41T0", .driver_data = m41t0 }, { .id = "M41T00", .driver_data = m41t00 }, + { .id = "M41T11", .driver_data = m41t11 }, { .id = "MCP7940X", .driver_data = mcp794xx }, { .id = "MCP7941X", .driver_data = mcp794xx }, { .id = "PT7C4338", .driver_data = ds_1307 }, @@ -1030,7 +1042,7 @@ static u8 ds1307_trickle_init(struct ds1307 *ds1307, /*----------------------------------------------------------------------*/ -#ifdef CONFIG_RTC_DRV_DS1307_HWMON +#if IS_REACHABLE(CONFIG_HWMON) /* * Temperature sensor support for ds3231 devices. @@ -1576,6 +1588,7 @@ read_rtc: case ds_1307: case m41t0: case m41t00: + case m41t11: /* clock halted? turn it on, so clock can tick. */ if (tmp & DS1307_BIT_CH) { regmap_write(ds1307->regmap, DS1307_REG_SECS, 0); @@ -1641,6 +1654,7 @@ read_rtc: case ds_1340: case m41t0: case m41t00: + case m41t11: /* * NOTE: ignores century bits; fix before deploying * systems that will run through year 2100. diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c index 5c0db6c8134c..6f39f683a98c 100644 --- a/drivers/rtc/rtc-ds1685.c +++ b/drivers/rtc/rtc-ds1685.c @@ -1188,552 +1188,6 @@ ds1685_rtc_sysfs_misc_grp = { .attrs = ds1685_rtc_sysfs_misc_attrs, }; -#ifdef CONFIG_RTC_DS1685_SYSFS_REGS -/** - * struct ds1685_rtc_ctrl_regs. - * @name: char pointer for the bit name. - * @reg: control register the bit is in. - * @bit: the bit's offset in the register. - */ -struct ds1685_rtc_ctrl_regs { - const char *name; - const u8 reg; - const u8 bit; -}; - -/* - * Ctrl register bit lookup table. - */ -static const struct ds1685_rtc_ctrl_regs -ds1685_ctrl_regs_table[] = { - { "uip", RTC_CTRL_A, RTC_CTRL_A_UIP }, - { "dv2", RTC_CTRL_A, RTC_CTRL_A_DV2 }, - { "dv1", RTC_CTRL_A, RTC_CTRL_A_DV1 }, - { "dv0", RTC_CTRL_A, RTC_CTRL_A_DV0 }, - { "rs3", RTC_CTRL_A, RTC_CTRL_A_RS3 }, - { "rs2", RTC_CTRL_A, RTC_CTRL_A_RS2 }, - { "rs1", RTC_CTRL_A, RTC_CTRL_A_RS1 }, - { "rs0", RTC_CTRL_A, RTC_CTRL_A_RS0 }, - { "set", RTC_CTRL_B, RTC_CTRL_B_SET }, - { "pie", RTC_CTRL_B, RTC_CTRL_B_PIE }, - { "aie", RTC_CTRL_B, RTC_CTRL_B_AIE }, - { "uie", RTC_CTRL_B, RTC_CTRL_B_UIE }, - { "sqwe", RTC_CTRL_B, RTC_CTRL_B_SQWE }, - { "dm", RTC_CTRL_B, RTC_CTRL_B_DM }, - { "2412", RTC_CTRL_B, RTC_CTRL_B_2412 }, - { "dse", RTC_CTRL_B, RTC_CTRL_B_DSE }, - { "irqf", RTC_CTRL_C, RTC_CTRL_C_IRQF }, - { "pf", RTC_CTRL_C, RTC_CTRL_C_PF }, - { "af", RTC_CTRL_C, RTC_CTRL_C_AF }, - { "uf", RTC_CTRL_C, RTC_CTRL_C_UF }, - { "vrt", RTC_CTRL_D, RTC_CTRL_D_VRT }, - { "vrt2", RTC_EXT_CTRL_4A, RTC_CTRL_4A_VRT2 }, - { "incr", RTC_EXT_CTRL_4A, RTC_CTRL_4A_INCR }, - { "pab", RTC_EXT_CTRL_4A, RTC_CTRL_4A_PAB }, - { "rf", RTC_EXT_CTRL_4A, RTC_CTRL_4A_RF }, - { "wf", RTC_EXT_CTRL_4A, RTC_CTRL_4A_WF }, - { "kf", RTC_EXT_CTRL_4A, RTC_CTRL_4A_KF }, -#if !defined(CONFIG_RTC_DRV_DS1685) && !defined(CONFIG_RTC_DRV_DS1689) - { "bme", RTC_EXT_CTRL_4A, RTC_CTRL_4A_BME }, -#endif - { "abe", RTC_EXT_CTRL_4B, RTC_CTRL_4B_ABE }, - { "e32k", RTC_EXT_CTRL_4B, RTC_CTRL_4B_E32K }, - { "cs", RTC_EXT_CTRL_4B, RTC_CTRL_4B_CS }, - { "rce", RTC_EXT_CTRL_4B, RTC_CTRL_4B_RCE }, - { "prs", RTC_EXT_CTRL_4B, RTC_CTRL_4B_PRS }, - { "rie", RTC_EXT_CTRL_4B, RTC_CTRL_4B_RIE }, - { "wie", RTC_EXT_CTRL_4B, RTC_CTRL_4B_WIE }, - { "kse", RTC_EXT_CTRL_4B, RTC_CTRL_4B_KSE }, - { NULL, 0, 0 }, -}; - -/** - * ds1685_rtc_sysfs_ctrl_regs_lookup - ctrl register bit lookup function. - * @name: ctrl register bit to look up in ds1685_ctrl_regs_table. - */ -static const struct ds1685_rtc_ctrl_regs* -ds1685_rtc_sysfs_ctrl_regs_lookup(const char *name) -{ - const struct ds1685_rtc_ctrl_regs *p = ds1685_ctrl_regs_table; - - for (; p->name != NULL; ++p) - if (strcmp(p->name, name) == 0) - return p; - - return NULL; -} - -/** - * ds1685_rtc_sysfs_ctrl_regs_show - reads a ctrl register bit via sysfs. - * @dev: pointer to device structure. - * @attr: pointer to device_attribute structure. - * @buf: pointer to char array to hold the output. - */ -static ssize_t -ds1685_rtc_sysfs_ctrl_regs_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - u8 tmp; - struct ds1685_priv *rtc = dev_get_drvdata(dev); - const struct ds1685_rtc_ctrl_regs *reg_info = - ds1685_rtc_sysfs_ctrl_regs_lookup(attr->attr.name); - - /* Make sure we actually matched something. */ - if (!reg_info) - return -EINVAL; - - /* No spinlock during a read -- mutex is already held. */ - ds1685_rtc_switch_to_bank1(rtc); - tmp = rtc->read(rtc, reg_info->reg) & reg_info->bit; - ds1685_rtc_switch_to_bank0(rtc); - - return sprintf(buf, "%d\n", (tmp ? 1 : 0)); -} - -/** - * ds1685_rtc_sysfs_ctrl_regs_store - writes a ctrl register bit via sysfs. - * @dev: pointer to device structure. - * @attr: pointer to device_attribute structure. - * @buf: pointer to char array to hold the output. - * @count: number of bytes written. - */ -static ssize_t -ds1685_rtc_sysfs_ctrl_regs_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ds1685_priv *rtc = dev_get_drvdata(dev); - u8 reg = 0, bit = 0, tmp; - unsigned long flags; - long int val = 0; - const struct ds1685_rtc_ctrl_regs *reg_info = - ds1685_rtc_sysfs_ctrl_regs_lookup(attr->attr.name); - - /* We only accept numbers. */ - if (kstrtol(buf, 10, &val) < 0) - return -EINVAL; - - /* bits are binary, 0 or 1 only. */ - if ((val != 0) && (val != 1)) - return -ERANGE; - - /* Make sure we actually matched something. */ - if (!reg_info) - return -EINVAL; - - reg = reg_info->reg; - bit = reg_info->bit; - - /* Safe to spinlock during a write. */ - ds1685_rtc_begin_ctrl_access(rtc, &flags); - tmp = rtc->read(rtc, reg); - rtc->write(rtc, reg, (val ? (tmp | bit) : (tmp & ~(bit)))); - ds1685_rtc_end_ctrl_access(rtc, flags); - - return count; -} - -/** - * DS1685_RTC_SYSFS_CTRL_REG_RO - device_attribute for read-only register bit. - * @bit: bit to read. - */ -#define DS1685_RTC_SYSFS_CTRL_REG_RO(bit) \ - static DEVICE_ATTR(bit, S_IRUGO, \ - ds1685_rtc_sysfs_ctrl_regs_show, NULL) - -/** - * DS1685_RTC_SYSFS_CTRL_REG_RW - device_attribute for read-write register bit. - * @bit: bit to read or write. - */ -#define DS1685_RTC_SYSFS_CTRL_REG_RW(bit) \ - static DEVICE_ATTR(bit, S_IRUGO | S_IWUSR, \ - ds1685_rtc_sysfs_ctrl_regs_show, \ - ds1685_rtc_sysfs_ctrl_regs_store) - -/* - * Control Register A bits. - */ -DS1685_RTC_SYSFS_CTRL_REG_RO(uip); -DS1685_RTC_SYSFS_CTRL_REG_RW(dv2); -DS1685_RTC_SYSFS_CTRL_REG_RW(dv1); -DS1685_RTC_SYSFS_CTRL_REG_RO(dv0); -DS1685_RTC_SYSFS_CTRL_REG_RW(rs3); -DS1685_RTC_SYSFS_CTRL_REG_RW(rs2); -DS1685_RTC_SYSFS_CTRL_REG_RW(rs1); -DS1685_RTC_SYSFS_CTRL_REG_RW(rs0); - -static struct attribute* -ds1685_rtc_sysfs_ctrla_attrs[] = { - &dev_attr_uip.attr, - &dev_attr_dv2.attr, - &dev_attr_dv1.attr, - &dev_attr_dv0.attr, - &dev_attr_rs3.attr, - &dev_attr_rs2.attr, - &dev_attr_rs1.attr, - &dev_attr_rs0.attr, - NULL, -}; - -static const struct attribute_group -ds1685_rtc_sysfs_ctrla_grp = { - .name = "ctrla", - .attrs = ds1685_rtc_sysfs_ctrla_attrs, -}; - - -/* - * Control Register B bits. - */ -DS1685_RTC_SYSFS_CTRL_REG_RO(set); -DS1685_RTC_SYSFS_CTRL_REG_RW(pie); -DS1685_RTC_SYSFS_CTRL_REG_RW(aie); -DS1685_RTC_SYSFS_CTRL_REG_RW(uie); -DS1685_RTC_SYSFS_CTRL_REG_RW(sqwe); -DS1685_RTC_SYSFS_CTRL_REG_RO(dm); -DS1685_RTC_SYSFS_CTRL_REG_RO(2412); -DS1685_RTC_SYSFS_CTRL_REG_RO(dse); - -static struct attribute* -ds1685_rtc_sysfs_ctrlb_attrs[] = { - &dev_attr_set.attr, - &dev_attr_pie.attr, - &dev_attr_aie.attr, - &dev_attr_uie.attr, - &dev_attr_sqwe.attr, - &dev_attr_dm.attr, - &dev_attr_2412.attr, - &dev_attr_dse.attr, - NULL, -}; - -static const struct attribute_group -ds1685_rtc_sysfs_ctrlb_grp = { - .name = "ctrlb", - .attrs = ds1685_rtc_sysfs_ctrlb_attrs, -}; - -/* - * Control Register C bits. - * - * Reading Control C clears these bits! Reading them individually can - * possibly cause an interrupt to be missed. Use the /proc interface - * to see all the bits in this register simultaneously. - */ -DS1685_RTC_SYSFS_CTRL_REG_RO(irqf); -DS1685_RTC_SYSFS_CTRL_REG_RO(pf); -DS1685_RTC_SYSFS_CTRL_REG_RO(af); -DS1685_RTC_SYSFS_CTRL_REG_RO(uf); - -static struct attribute* -ds1685_rtc_sysfs_ctrlc_attrs[] = { - &dev_attr_irqf.attr, - &dev_attr_pf.attr, - &dev_attr_af.attr, - &dev_attr_uf.attr, - NULL, -}; - -static const struct attribute_group -ds1685_rtc_sysfs_ctrlc_grp = { - .name = "ctrlc", - .attrs = ds1685_rtc_sysfs_ctrlc_attrs, -}; - -/* - * Control Register D bits. - */ -DS1685_RTC_SYSFS_CTRL_REG_RO(vrt); - -static struct attribute* -ds1685_rtc_sysfs_ctrld_attrs[] = { - &dev_attr_vrt.attr, - NULL, -}; - -static const struct attribute_group -ds1685_rtc_sysfs_ctrld_grp = { - .name = "ctrld", - .attrs = ds1685_rtc_sysfs_ctrld_attrs, -}; - -/* - * Control Register 4A bits. - */ -DS1685_RTC_SYSFS_CTRL_REG_RO(vrt2); -DS1685_RTC_SYSFS_CTRL_REG_RO(incr); -DS1685_RTC_SYSFS_CTRL_REG_RW(pab); -DS1685_RTC_SYSFS_CTRL_REG_RW(rf); -DS1685_RTC_SYSFS_CTRL_REG_RW(wf); -DS1685_RTC_SYSFS_CTRL_REG_RW(kf) |
