Commit bfebeb16 authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 3933ec73 6b583a64
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>;
};
...@@ -13,6 +13,7 @@ Required properties: ...@@ -13,6 +13,7 @@ Required properties:
"maxim,ds3231", "maxim,ds3231",
"st,m41t0", "st,m41t0",
"st,m41t00", "st,m41t00",
"st,m41t11",
"microchip,mcp7940x", "microchip,mcp7940x",
"microchip,mcp7941x", "microchip,mcp7941x",
"pericom,pt7c4338", "pericom,pt7c4338",
......
...@@ -193,14 +193,6 @@ static unsigned long rtc_freq; /* Current periodic IRQ rate */ ...@@ -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_irq_data; /* our output to the world */
static unsigned long rtc_max_user_freq = 64; /* > this, need CAP_SYS_RESOURCE */ 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 * If this driver ever becomes modularised, it will be really nice
* to make the epoch retain its value across module reload... * to make the epoch retain its value across module reload...
...@@ -264,11 +256,6 @@ static irqreturn_t rtc_interrupt(int irq, void *dev_id) ...@@ -264,11 +256,6 @@ static irqreturn_t rtc_interrupt(int irq, void *dev_id)
spin_unlock(&rtc_lock); 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); wake_up_interruptible(&rtc_wait);
kill_fasync(&rtc_async_queue, SIGIO, POLL_IN); kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
......
...@@ -244,15 +244,6 @@ config RTC_DRV_DS1307 ...@@ -244,15 +244,6 @@ config RTC_DRV_DS1307
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-ds1307. 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 config RTC_DRV_DS1307_CENTURY
bool "Century bit support for rtc-ds1307" bool "Century bit support for rtc-ds1307"
depends on RTC_DRV_DS1307 depends on RTC_DRV_DS1307
...@@ -1027,18 +1018,6 @@ config RTC_DS1685_PROC_REGS ...@@ -1027,18 +1018,6 @@ config RTC_DS1685_PROC_REGS
Unless you are debugging this driver, choose N. 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 config RTC_DRV_DS1742
tristate "Maxim/Dallas DS1742/1743" tristate "Maxim/Dallas DS1742/1743"
depends on HAS_IOMEM depends on HAS_IOMEM
......
...@@ -68,7 +68,7 @@ static int rtc_suspend(struct device *dev) ...@@ -68,7 +68,7 @@ static int rtc_suspend(struct device *dev)
return 0; return 0;
} }
getnstimeofday64(&old_system); ktime_get_real_ts64(&old_system);
old_rtc.tv_sec = rtc_tm_to_time64(&tm); old_rtc.tv_sec = rtc_tm_to_time64(&tm);
...@@ -110,7 +110,7 @@ static int rtc_resume(struct device *dev) ...@@ -110,7 +110,7 @@ static int rtc_resume(struct device *dev)
return 0; return 0;
/* snapshot the current rtc and system time at resume */ /* snapshot the current rtc and system time at resume */
getnstimeofday64(&new_system); ktime_get_real_ts64(&new_system);
err = rtc_read_time(rtc, &tm); err = rtc_read_time(rtc, &tm);
if (err < 0) { if (err < 0) {
pr_debug("%s: fail to read rtc time\n", dev_name(&rtc->dev)); 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) ...@@ -172,7 +172,6 @@ static struct rtc_device *rtc_allocate_device(void)
mutex_init(&rtc->ops_lock); mutex_init(&rtc->ops_lock);
spin_lock_init(&rtc->irq_lock); spin_lock_init(&rtc->irq_lock);
spin_lock_init(&rtc->irq_task_lock);
init_waitqueue_head(&rtc->irq_queue); init_waitqueue_head(&rtc->irq_queue);
/* Init timerqueue */ /* Init timerqueue */
......
...@@ -607,12 +607,6 @@ void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode) ...@@ -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); rtc->irq_data = (rtc->irq_data + (num << 8)) | (RTC_IRQF|mode);
spin_unlock_irqrestore(&rtc->irq_lock, flags); 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); wake_up_interruptible(&rtc->irq_queue);
kill_fasync(&rtc->async_queue, SIGIO, POLL_IN); kill_fasync(&rtc->async_queue, SIGIO, POLL_IN);
} }
...@@ -721,39 +715,6 @@ void rtc_class_close(struct rtc_device *rtc) ...@@ -721,39 +715,6 @@ void rtc_class_close(struct rtc_device *rtc)
} }
EXPORT_SYMBOL_GPL(rtc_class_close); 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) 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) ...@@ -785,71 +746,45 @@ static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled)
* Context: any * Context: any
* *
* Note that rtc_irq_set_freq() should previously have been used to * 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; int err = 0;
unsigned long flags;
retry: while (rtc_update_hrtimer(rtc, enabled) < 0)
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(); cpu_relax();
goto retry;
}
rtc->pie_enabled = enabled; rtc->pie_enabled = enabled;
}
spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
trace_rtc_irq_set_state(enabled, err); trace_rtc_irq_set_state(enabled, err);
return err; return err;
} }
EXPORT_SYMBOL_GPL(rtc_irq_set_state);
/** /**
* rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ
* @rtc: the rtc device * @rtc: the rtc device
* @task: currently registered with rtc_irq_register() * @task: currently registered with rtc_irq_register()
* @freq: positive frequency with which task->func() will be called * @freq: positive frequency
* Context: any * Context: any
* *
* Note that rtc_irq_set_state() is used to enable or disable the * Note that rtc_irq_set_state() is used to enable or disable the
* periodic IRQs. * 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; int err = 0;
unsigned long flags;
if (freq <= 0 || freq > RTC_MAX_FREQ) if (freq <= 0 || freq > RTC_MAX_FREQ)
return -EINVAL; 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; rtc->irq_freq = freq;
if (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0) { while (rtc->pie_enabled && rtc_update_hrtimer(rtc, 1) < 0)
spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
cpu_relax(); cpu_relax();
goto retry;
}
}
spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
trace_rtc_irq_set_freq(freq, err); trace_rtc_irq_set_freq(freq, err);
return err; return err;
} }
EXPORT_SYMBOL_GPL(rtc_irq_set_freq);
/** /**
* rtc_timer_enqueue - Adds a rtc_timer to the rtc_device timerqueue * rtc_timer_enqueue - Adds a rtc_timer to the rtc_device timerqueue
...@@ -979,8 +914,8 @@ void rtc_timer_do_work(struct work_struct *work) ...@@ -979,8 +914,8 @@ void rtc_timer_do_work(struct work_struct *work)
timerqueue_del(&rtc->timerqueue, &timer->node); timerqueue_del(&rtc->timerqueue, &timer->node);
trace_rtc_timer_dequeue(timer); trace_rtc_timer_dequeue(timer);
timer->enabled = 0; timer->enabled = 0;
if (timer->task.func) if (timer->func)
timer->task.func(timer->task.private_data); timer->func(timer->private_data);
trace_rtc_timer_fired(timer); trace_rtc_timer_fired(timer);
/* Re-add/fwd periodic timers */ /* Re-add/fwd periodic timers */
...@@ -1035,8 +970,8 @@ void rtc_timer_init(struct rtc_timer *timer, void (*f)(void *p), void *data) ...@@ -1035,8 +970,8 @@ void rtc_timer_init(struct rtc_timer *timer, void (*f)(void *p), void *data)
{ {
timerqueue_init(&timer->node); timerqueue_init(&timer->node);
timer->enabled = 0; timer->enabled = 0;
timer->task.func = f; timer->func = f;
timer->task.private_data = data; timer->private_data = data;
} }
/* rtc_timer_start - Sets an rtc_timer to fire in the future /* rtc_timer_start - Sets an rtc_timer to fire in the future
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#define RTC_IRQ_FREQ_1HZ BIT(2) #define RTC_IRQ_FREQ_1HZ BIT(2)
#define RTC_CCR 0x18 #define RTC_CCR 0x18
#define RTC_CCR_MODE BIT(15) #define RTC_CCR_MODE BIT(15)
#define RTC_CONF_TEST 0x1C
#define RTC_NOMINAL_TIMING BIT(13)
#define RTC_TIME 0xC #define RTC_TIME 0xC
#define RTC_ALARM1 0x10 #define RTC_ALARM1 0x10
...@@ -75,6 +77,7 @@ struct armada38x_rtc { ...@@ -75,6 +77,7 @@ struct armada38x_rtc {
void __iomem *regs_soc; void __iomem *regs_soc;
spinlock_t lock; spinlock_t lock;
int irq; int irq;
bool initialized;
struct value_to_freq *val_to_freq; struct value_to_freq *val_to_freq;
struct armada38x_rtc_data *data; struct armada38x_rtc_data *data;
}; };
...@@ -226,6 +229,23 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm) ...@@ -226,6 +229,23 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
return 0; 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) static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
{ {
struct armada38x_rtc *rtc = dev_get_drvdata(dev); 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) ...@@ -237,6 +257,9 @@ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
if (ret) if (ret)
goto out; goto out;
if (!rtc->initialized)
armada38x_rtc_reset(rtc);
spin_lock_irqsave(&rtc->lock, flags); spin_lock_irqsave(&rtc->lock, flags);
rtc_delayed_write(time, rtc, RTC_TIME); rtc_delayed_write(time, rtc, RTC_TIME);
spin_unlock_irqrestore(&rtc->lock, flags); spin_unlock_irqrestore(&rtc->lock, flags);
......
...@@ -162,6 +162,10 @@ static int bq4802_probe(struct platform_device *pdev) ...@@ -162,6 +162,10 @@ static int bq4802_probe(struct platform_device *pdev)
} else if (p->r->flags & IORESOURCE_MEM) { } else if (p->r->flags & IORESOURCE_MEM) {
p->regs = devm_ioremap(&pdev->dev, p->r->start, p->regs = devm_ioremap(&pdev->dev, p->r->start,
resource_size(p->r)); resource_size(p->r));
if (!p->regs){
err = -ENOMEM;
goto out;
}
p->read = bq4802_read_mem; p->read = bq4802_read_mem;
p->write = bq4802_write_mem; p->write = bq4802_write_mem;
} else { } else {
......
...@@ -40,9 +40,23 @@ static inline void rtc_proc_del_device(struct rtc_device *rtc) ...@@ -40,9 +40,23 @@ static inline void rtc_proc_del_device(struct rtc_device *rtc)
#ifdef CONFIG_RTC_INTF_SYSFS #ifdef CONFIG_RTC_INTF_SYSFS
const struct attribute_group **rtc_get_dev_attribute_groups(void); 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 #else
static inline const struct attribute_group **rtc_get_dev_attribute_groups(void) static inline const struct attribute_group **rtc_get_dev_attribute_groups(void)
{ {
return NULL; 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 #endif
...@@ -341,11 +341,11 @@ static long rtc_dev_ioctl(struct file *file, ...@@ -341,11 +341,11 @@ static long rtc_dev_ioctl(struct file *file,
return rtc_set_time(rtc, &tm); return rtc_set_time(rtc, &tm);
case RTC_PIE_ON: case RTC_PIE_ON:
err = rtc_irq_set_state(rtc, NULL, 1); err = rtc_irq_set_state(rtc, 1);
break; break;
case RTC_PIE_OFF: case RTC_PIE_OFF:
err = rtc_irq_set_state(rtc, NULL, 0); err = rtc_irq_set_state(rtc, 0);
break; break;
case RTC_AIE_ON: case RTC_AIE_ON:
...@@ -365,7 +365,7 @@ static long rtc_dev_ioctl(struct file *file, ...@@ -365,7 +365,7 @@ static long rtc_dev_ioctl(struct file *file,
return rtc_update_irq_enable(rtc, 0); return rtc_update_irq_enable(rtc, 0);
case RTC_IRQP_SET: case RTC_IRQP_SET:
err = rtc_irq_set_freq(rtc, NULL, arg); err = rtc_irq_set_freq(rtc, arg);
break; break;
case RTC_IRQP_READ: case RTC_IRQP_READ:
...@@ -427,7 +427,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file) ...@@ -427,7 +427,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file)
/* Keep ioctl until all drivers are converted */ /* Keep ioctl until all drivers are converted */
rtc_dev_ioctl(file, RTC_UIE_OFF, 0); rtc_dev_ioctl(file, RTC_UIE_OFF, 0);
rtc_update_irq_enable(rtc, 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); clear_bit_unlock(RTC_DEV_BUSY, &rtc->flags);
return 0; return 0;
......
...@@ -44,6 +44,7 @@ enum ds_type { ...@@ -44,6 +44,7 @@ enum ds_type {
ds_3231, ds_3231,
m41t0, m41t0,
m41t00, m41t00,
m41t11,
mcp794xx, mcp794xx,
rx_8025, rx_8025,
rx_8130, rx_8130,
...@@ -227,6 +228,11 @@ static const struct chip_desc chips[last_ds_type] = { ...@@ -227,6 +228,11 @@ static const struct chip_desc chips[last_ds_type] = {
.irq_handler = rx8130_irq, .irq_handler = rx8130_irq,
.rtc_ops = &rx8130_rtc_ops, .rtc_ops = &rx8130_rtc_ops,
}, },
[m41t11] = {
/* this is battery backed SRAM */
.nvram_offset = 8,
.nvram_size = 56,
},
[mcp794xx] = { [mcp794xx] = {
.alarm = 1, .alarm = 1,
/* this is battery backed SRAM */ /* this is battery backed SRAM */
...@@ -249,6 +255,7 @@ static const struct i2c_device_id ds1307_id[] = { ...@@ -249,6 +255,7 @@ static const struct i2c_device_id ds1307_id[] = {
{ "ds3231", ds_3231 }, { "ds3231", ds_3231 },
{ "m41t0", m41t0 }, { "m41t0", m41t0 },
{ "m41t00", m41t00 }, { "m41t00", m41t00 },
{ "m41t11", m41t11 },
{ "mcp7940x", mcp794xx }, { "mcp7940x", mcp794xx },
{ "mcp7941x", mcp794xx }, { "mcp7941x", mcp794xx },
{ "pt7c4338", ds_1307 }, { "pt7c4338", ds_1307 },
...@@ -299,12 +306,16 @@ static const struct of_device_id ds1307_of_match[] = { ...@@ -299,12 +306,16 @@ static const struct of_device_id ds1307_of_match[] = {
}, },
{ {
.compatible = "st,m41t0", .compatible = "st,m41t0",
.data = (void *)m41t00 .data = (void *)m41t0
}, },
{ {
.compatible = "st,m41t00", .compatible = "st,m41t00",
.data = (void *)m41t00 .data = (void *)m41t00
}, },
{
.compatible = "st,m41t11",
.data = (void *)m41t11
},
{ {
.compatible = "microchip,mcp7940x", .compatible = "microchip,mcp7940x",
.data = (void *)mcp794xx .data = (void *)mcp794xx
...@@ -347,6 +358,7 @@ static const struct acpi_device_id ds1307_acpi_ids[] = { ...@@ -347,6 +358,7 @@ static const struct acpi_device_id ds1307_acpi_ids[] = {
{ .id = "DS3231", .driver_data = ds_3231 }, { .id = "DS3231", .driver_data = ds_3231 },
{ .id = "M41T0", .driver_data = m41t0 }, { .id = "M41T0", .driver_data = m41t0 },
{ .id = "M41T00", .driver_data = m41t00 }, { .id = "M41T00", .driver_data = m41t00 },
{ .id = "M41T11", .driver_data = m41t11 },
{ .id = "MCP7940X", .driver_data = mcp794xx }, { .id = "MCP7940X", .driver_data = mcp794xx },
{ .id = "MCP7941X", .driver_data = mcp794xx }, { .id = "MCP7941X", .driver_data = mcp794xx },
{ .id = "PT7C4338", .driver_data = ds_1307 }, { .id = "PT7C4338", .driver_data = ds_1307 },
...@@ -1030,7 +1042,7 @@ static u8 ds1307_trickle_init(struct ds1307 *ds1307, ...@@ -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. * Temperature sensor support for ds3231 devices.
...@@ -1576,6 +1588,7 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -1576,6 +1588,7 @@ static int ds1307_probe(struct i2c_client *client,
case ds_1307: case ds_1307:
case m41t0: case m41t0:
case m41t00: case m41t00:
case m41t11:
/* clock halted? turn it on, so clock can tick. */ /* clock halted? turn it on, so clock can tick. */
if (tmp & DS1307_BIT_CH) { if (tmp & DS1307_BIT_CH) {
regmap_write(ds1307->regmap, DS1307_REG_SECS, 0); regmap_write(ds1307->regmap, DS1307_REG_SECS, 0);
...@@ -1641,6 +1654,7 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -1641,6 +1654,7 @@ static int ds1307_probe(struct i2c_client *client,
case ds_1340: case ds_1340:
case m41t0: case m41t0:
case m41t00: case m41t00:
case m41t11:
/* /*
* NOTE: ignores century bits; fix before deploying * NOTE: ignores century bits; fix before deploying
* systems that will run through year 2100. * systems that will run through year 2100.
......
This diff is collapsed.
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#include "rtc-core.h"
#include <linux/of_irq.h>
/* Register map */ /* Register map */
/* rtc section */ /* rtc section */
...@@ -33,13 +35,16 @@ ...@@ -33,13 +35,16 @@
#define ISL1208_REG_SR_ARST (1<<7) /* auto reset */ #define ISL1208_REG_SR_ARST (1<<7) /* auto reset */
#define ISL1208_REG_SR_XTOSCB (1<<6) /* crystal oscillator */ #define ISL1208_REG_SR_XTOSCB (1<<6) /* crystal oscillator */
#define ISL1208_REG_SR_WRTC (1<<4) /* write rtc */ #define ISL1208_REG_SR_WRTC (1<<4) /* write rtc */
#define ISL1208_REG_SR_EVT (1<<3) /* event */
#define ISL1208_REG_SR_ALM (1<<2) /* alarm */ #define ISL1208_REG_SR_ALM (1<<2) /* alarm */
#define ISL1208_REG_SR_BAT (1<<1) /* battery */ #define ISL1208_REG_SR_BAT (1<<1) /* battery */
#define ISL1208_REG_SR_RTCF (1<<0) /* rtc fail */ #define ISL1208_REG_SR_RTCF (1<<0) /* rtc fail */
#define ISL1208_REG_INT 0x08 #define ISL1208_REG_INT 0x08
#define ISL1208_REG_INT_ALME (1<<6) /* alarm enable */ #define ISL1208_REG_INT_ALME (1<<6) /* alarm enable */
#define ISL1208_REG_INT_IM (1<<7) /* interrupt/alarm mode */ #define ISL1208_REG_INT_IM (1<<7) /* interrupt/alarm mode */
#define ISL1208_REG_09 0x09 /* reserved */ #define ISL1219_REG_EV 0x09
#define ISL1219_REG_EV_EVEN (1<<4) /* event detection enable */
#define ISL1219_REG_EV_EVIENB (1<<7) /* event in pull-up disable */
#define ISL1208_REG_ATR 0x0a #define ISL1208_REG_ATR 0x0a
#define ISL1208_REG_DTR 0x0b #define ISL1208_REG_DTR 0x0b
...@@ -57,8 +62,24 @@ ...@@ -57,8 +62,24 @@
#define ISL1208_REG_USR2 0x13 #define ISL1208_REG_USR2 0x13
#define ISL1208_USR_SECTION_LEN 2 #define ISL1208_USR_SECTION_LEN 2
/* event section */
#define ISL1219_REG_SCT 0x14
#define ISL1219_REG_MNT 0x15
#define ISL1219_REG_HRT 0x16
#define ISL1219_REG_DTT 0x17
#define ISL1219_REG_MOT 0x18
#define ISL1219_REG_YRT 0x19
#define ISL1219_EVT_SECTION_LEN 6
static struct i2c_driver isl1208_driver; static struct i2c_driver isl1208_driver;
/* ISL1208 various variants */
enum {
TYPE_ISL1208 = 0,
TYPE_ISL1218,
TYPE_ISL1219,
};
/* block read */ /* block read */
static int static int
isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[], isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[],
...@@ -80,8 +101,8 @@ isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[], ...@@ -80,8 +101,8 @@ isl1208_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[],
}; };
int ret; int ret;
BUG_ON(reg > ISL1208_REG_USR2); WARN_ON(reg > ISL1219_REG_YRT);
BUG_ON(reg + len > ISL1208_REG_USR2 + 1); WARN_ON(reg + len > ISL1219_REG_YRT + 1);
ret = i2c_transfer(client->adapter, msgs, 2); ret = i2c_transfer(client->adapter, msgs, 2);
if (ret > 0) if (ret > 0)
...@@ -104,8 +125,8 @@ isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[], ...@@ -104,8 +125,8 @@ isl1208_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[],
}; };
int ret; int ret;
BUG_ON(reg > ISL1208_REG_USR2); WARN_ON(reg > ISL1219_REG_YRT);
BUG_ON(reg + len > ISL1208_REG_USR2 + 1); WARN_ON(reg + len > ISL1219_REG_YRT + 1);
i2c_buf[0] = reg; i2c_buf[0] = reg;
memcpy(&i2c_buf[1], &buf[0], len); memcpy(&i2c_buf[1], &buf[0], len);
...@@ -493,6 +514,73 @@ isl1208_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) ...@@ -493,6 +514,73 @@ isl1208_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
return isl1208_i2c_set_alarm(to_i2c_client(dev), alarm); return isl1208_i2c_set_alarm(to_i2c_client(dev), alarm);
} }
static ssize_t timestamp0_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = dev_get_drvdata(dev);
int sr;
sr = isl1208_i2c_get_sr(client);
if (sr < 0) {
dev_err(dev, "%s: reading SR failed\n", __func__);
return sr;
}
sr &= ~ISL1208_REG_SR_EVT;
sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr);
if (sr < 0)
dev_err(dev, "%s: writing SR failed\n",
__func__);
return count;
};
static ssize_t timestamp0_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct i2c_client *client = dev_get_drvdata(dev);
u8 regs[ISL1219_EVT_SECTION_LEN] = { 0, };
struct rtc_time tm;
int sr;
sr = isl1208_i2c_get_sr(client);
if (sr < 0) {
dev_err(dev, "%s: reading SR failed\n", __func__);
return sr;
}
if (!(sr & ISL1208_REG_SR_EVT))
return 0;
sr = isl1208_i2c_read_regs(client, ISL1219_REG_SCT, regs,
ISL1219_EVT_SECTION_LEN);
if (sr < 0) {
dev_err(dev, "%s: reading event section failed\n",
__func__);
return 0;
}
/* MSB of each alarm register is an enable bit */
tm.tm_sec = bcd2bin(regs[ISL1219_REG_SCT - ISL1219_REG_SCT] & 0x7f);
tm.tm_min = bcd2bin(regs[ISL1219_REG_MNT - ISL1219_REG_SCT] & 0x7f);
tm.tm_hour = bcd2bin(regs[ISL1219_REG_HRT - ISL1219_REG_SCT] & 0x3f);
tm.tm_mday = bcd2bin(regs[ISL1219_REG_DTT - ISL1219_REG_SCT] & 0x3f);
tm.tm_mon =
bcd2bin(regs[ISL1219_REG_MOT - ISL1219_REG_SCT] & 0x1f) - 1;
tm.tm_year = bcd2bin(regs[ISL1219_REG_YRT - ISL1219_REG_SCT]) + 100;
sr = rtc_valid_tm(&tm);
if (sr)
return sr;
return sprintf(buf, "%llu\n",
(unsigned long long)rtc_tm_to_time64(&tm));
};
static DEVICE_ATTR_RW(timestamp0);
static irqreturn_t static irqreturn_t
isl1208_rtc_interrupt(int irq, void *data) isl1208_rtc_interrupt(int irq, void *data)
{ {
...@@ -538,6 +626,13 @@ isl1208_rtc_interrupt(int irq, void *data) ...@@ -538,6 +626,13 @@ isl1208_rtc_interrupt(int irq, void *data)
return err; return err;
} }
if (sr & ISL1208_REG_SR_EVT) {
sysfs_notify(&rtc->dev.kobj, NULL,
dev_attr_timestamp0.attr.name);
dev_warn(&client->dev, "event detected");
handled = 1;
}
return handled ? IRQ_HANDLED : IRQ_NONE; return handled ? IRQ_HANDLED : IRQ_NONE;
} }
...@@ -623,11 +718,39 @@ static const struct attribute_group isl1208_rtc_sysfs_files = { ...@@ -623,11 +718,39 @@ static const struct attribute_group isl1208_rtc_sysfs_files = {
.attrs = isl1208_rtc_attrs, .attrs = isl1208_rtc_attrs,
}; };
static struct attribute *isl1219_rtc_attrs[] = {
&dev_attr_timestamp0.attr,
NULL
};
static const struct attribute_group isl1219_rtc_sysfs_files = {
.attrs = isl1219_rtc_attrs,
};
static int isl1208_setup_irq(struct i2c_client *client, int irq)
{
int rc = devm_request_threaded_irq(&client->dev, irq, NULL,
isl1208_rtc_interrupt,
IRQF_SHARED | IRQF_ONESHOT,
isl1208_driver.driver.name,
client);
if (!rc) {
device_init_wakeup(&client->dev, 1);
enable_irq_wake(irq);
} else {
dev_err(&client->dev,
"Unable to request irq %d, no alarm support\n",
irq);
}
return rc;
}
static int static int
isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
{ {
int rc = 0; int rc = 0;
struct rtc_device *rtc; struct rtc_device *rtc;
int evdet_irq = -1;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV; return -ENODEV;
...@@ -642,6 +765,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -642,6 +765,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
rtc->ops = &isl1208_rtc_ops; rtc->ops = &isl1208_rtc_ops;
i2c_set_clientdata(client, rtc); i2c_set_clientdata(client, rtc);
dev_set_drvdata(&rtc->dev, client);
rc = isl1208_i2c_get_sr(client); rc = isl1208_i2c_get_sr(client);
if (rc < 0) { if (rc < 0) {
...@@ -653,26 +777,46 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -653,26 +777,46 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id)
dev_warn(&client->dev, "rtc power failure detected, " dev_warn(&client->dev, "rtc power failure detected, "
"please set clock.\n"); "please set clock.\n");
if (id->driver_data == TYPE_ISL1219) {
struct device_node *np = client->dev.of_node;
u32 evienb;
rc = i2c_smbus_read_byte_data(client, ISL1219_REG_EV);
if (rc < 0) {
dev_err(&client->dev, "failed to read EV reg\n");
return rc;
}
rc |= ISL1219_REG_EV_EVEN;
if (!of_property_read_u32(np, "isil,ev-evienb", &evienb)) {
if (evienb)
rc |= ISL1219_REG_EV_EVIENB;
else
rc &= ~ISL1219_REG_EV_EVIENB;
}
rc = i2c_smbus_write_byte_data(client, ISL1219_REG_EV, rc);
if (rc < 0) {
dev_err(&client->dev, "could not enable tamper detection\n");
return rc;
}
rc = rtc_add_group(rtc, &isl1219_rtc_sysfs_files);
if (rc)
return rc;
evdet_irq = of_irq_get_byname(np, "evdet");
}
rc = sysfs_create_group(&client->dev.kobj, &isl1208_rtc_sysfs_files); rc = sysfs_create_group(&client->dev.kobj, &isl1208_rtc_sysfs_files);
if (rc) if (rc)
return rc; return rc;
if (client->irq > 0) { if (client->irq > 0)
rc = devm_request_threaded_irq(&client->dev, client->irq, NULL, rc = isl1208_setup_irq(client, client->irq);
isl1208_rtc_interrupt, if (rc)
IRQF_SHARED | IRQF_ONESHOT, return rc;
isl1208_driver.driver.name,
client); if (evdet_irq > 0 && evdet_irq != client->irq)
if (!rc) { rc = isl1208_setup_irq(client, evdet_irq);
device_init_wakeup(&client->dev, 1); if (rc)
enable_irq_wake(client->irq); return rc;
} else {
dev_err(&client->dev,
"Unable to request irq %d, no alarm support\n",
client->irq);
client->irq = 0;
}
}
return rtc_register_device(rtc); return rtc_register_device(rtc);
} }
...@@ -686,8 +830,9 @@ isl1208_remove(struct i2c_client *client) ...@@ -686,8 +830,9 @@ isl1208_remove(struct i2c_client *client)
} }
static const struct i2c_device_id isl1208_id[] = { static const struct i2c_device_id isl1208_id[] = {
{ "isl1208", 0 }, { "isl1208", TYPE_ISL1208 },
{ "isl1218", 0 }, { "isl1218", TYPE_ISL1218 },
{ "isl1219", TYPE_ISL1219 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, isl1208_id); MODULE_DEVICE_TABLE(i2c, isl1208_id);
...@@ -695,6 +840,7 @@ MODULE_DEVICE_TABLE(i2c, isl1208_id); ...@@ -695,6 +840,7 @@ MODULE_DEVICE_TABLE(i2c, isl1208_id);
static const struct of_device_id isl1208_of_match[] = { static const struct of_device_id isl1208_of_match[] = {
{ .compatible = "isil,isl1208" }, { .compatible = "isil,isl1208" },
{ .compatible = "isil,isl1218" }, { .compatible = "isil,isl1218" },
{ .compatible = "isil,isl1219" },
{ } { }
}; };
MODULE_DEVICE_TABLE(of, isl1208_of_match); MODULE_DEVICE_TABLE(of, isl1208_of_match);
......
...@@ -373,7 +373,6 @@ static int m48t59_rtc_probe(struct platform_device *pdev) ...@@ -373,7 +373,6 @@ static int m48t59_rtc_probe(struct platform_device *pdev)
struct m48t59_private *m48t59 = NULL; struct m48t59_private *m48t59 = NULL;
struct resource *res; struct resource *res;
int ret = -ENOMEM; int ret = -ENOMEM;
char *name;
const struct rtc_class_ops *ops; const struct rtc_class_ops *ops;
struct nvmem_config nvmem_cfg = { struct nvmem_config nvmem_cfg = {
.name = "m48t59-", .name = "m48t59-",
...@@ -448,17 +447,14 @@ static int m48t59_rtc_probe(struct platform_device *pdev) ...@@ -448,17 +447,14 @@ static int m48t59_rtc_probe(struct platform_device *pdev)
} }
switch (pdata->type) { switch (pdata->type) {
case M48T59RTC_TYPE_M48T59: case M48T59RTC_TYPE_M48T59:
name = "m48t59";
ops = &m48t59_rtc_ops; ops = &m48t59_rtc_ops;
pdata->offset = 0x1ff0; pdata->offset = 0x1ff0;
break; break;
case M48T59RTC_TYPE_M48T02: case M48T59RTC_TYPE_M48T02:
name = "m48t02";
ops = &m48t02_rtc_ops; ops = &m48t02_rtc_ops;
pdata->offset = 0x7f0; pdata->offset = 0x7f0;
break; break;
case M48T59RTC_TYPE_M48T08: case M48T59RTC_TYPE_M48T08:
name = "m48t08";
ops = &m48t02_rtc_ops; ops = &m48t02_rtc_ops;
pdata->offset = 0x1ff0; pdata->offset = 0x1ff0;
break; break;
......
/* // SPDX-License-Identifier: GPL-2.0+
* RTC driver for Maxim MAX77686 and MAX77802 //
* // RTC driver for Maxim MAX77686 and MAX77802
* Copyright (C) 2012 Samsung Electronics Co.Ltd //
* // Copyright (C) 2012 Samsung Electronics Co.Ltd
* based on rtc-max8997.c //
* // based on rtc-max8997.c
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/slab.h> #include <linux/slab.h>
......
/* // SPDX-License-Identifier: GPL-2.0+
* RTC driver for Maxim MAX8997 //
* // RTC driver for Maxim MAX8997
* Copyright (C) 2013 Samsung Electronics Co.Ltd //
* // Copyright (C) 2013 Samsung Electronics Co.Ltd
* based on rtc-max8998.c //
* // based on rtc-max8998.c
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
......
/* // SPDX-License-Identifier: GPL-2.0+
* RTC driver for Maxim MAX8998 //
* // RTC driver for Maxim MAX8998
* Copyright (C) 2010 Samsung Electronics Co.Ltd //
* Author: Minkyu Kang <mk7.kang@samsung.com> // Copyright (C) 2010 Samsung Electronics Co.Ltd
* Author: Joonyoung Shim <jy0922.shim@samsung.com> // Author: Minkyu Kang <mk7.kang@samsung.com>
* // Author: Joonyoung Shim <jy0922.shim@samsung.com>
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/module.h> #include <linux/module.h>
#include <linux/i2c.h> #include <linux/i2c.h>
......
...@@ -449,6 +449,7 @@ static void omap_rtc_power_off(void) ...@@ -449,6 +449,7 @@ static void omap_rtc_power_off(void)
if (tm2bcd(&tm) < 0) { if (tm2bcd(&tm) < 0) {
dev_err(&rtc->rtc->dev, "power off failed\n"); dev_err(&rtc->rtc->dev, "power off failed\n");
rtc->type->lock(rtc);
return; return;
} }
...@@ -582,9 +583,7 @@ static int rtc_pinconf_get(struct pinctrl_dev *pctldev, ...@@ -582,9 +583,7 @@ static int rtc_pinconf_get(struct pinctrl_dev *pctldev,
u32 val; u32 val;
u16 arg = 0; u16 arg = 0;
rtc->type->unlock(rtc);
val = rtc_readl(rtc, OMAP_RTC_PMIC_REG); val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
rtc->type->lock(rtc);
switch (param) { switch (param) {
case PIN_CONFIG_INPUT_ENABLE: case PIN_CONFIG_INPUT_ENABLE:
...@@ -614,9 +613,7 @@ static int rtc_pinconf_set(struct pinctrl_dev *pctldev, ...@@ -614,9 +613,7 @@ static int rtc_pinconf_set(struct pinctrl_dev *pctldev,
u32 param_val; u32 param_val;
int i; int i;
rtc->type->unlock(rtc);
val = rtc_readl(rtc, OMAP_RTC_PMIC_REG); val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
rtc->type->lock(rtc);
/* active low by default */ /* active low by default */
val |= OMAP_RTC_PMIC_EXT_WKUP_POL(pin); val |= OMAP_RTC_PMIC_EXT_WKUP_POL(pin);
...@@ -861,13 +858,6 @@ static int omap_rtc_probe(struct platform_device *pdev) ...@@ -861,13 +858,6 @@ static int omap_rtc_probe(struct platform_device *pdev)
goto err; goto err;
} }
if (rtc->is_pmic_controller) {
if (!pm_power_off) {
omap_rtc_power_off_rtc = rtc;
pm_power_off = omap_rtc_power_off;
}
}
/* Support ext_wakeup pinconf */ /* Support ext_wakeup pinconf */
rtc_pinctrl_desc.name = dev_name(&pdev->dev); rtc_pinctrl_desc.name = dev_name(&pdev->dev);
...@@ -880,12 +870,21 @@ static int omap_rtc_probe(struct platform_device *pdev) ...@@ -880,12 +870,21 @@ static int omap_rtc_probe(struct platform_device *pdev)
ret = rtc_register_device(rtc->rtc); ret = rtc_register_device(rtc->rtc);
if (ret) if (ret)
goto err; goto err_deregister_pinctrl;
rtc_nvmem_register(rtc->rtc, &omap_rtc_nvmem_config); rtc_nvmem_register(rtc->rtc, &omap_rtc_nvmem_config);
if (rtc->is_pmic_controller) {
if (!pm_power_off) {
omap_rtc_power_off_rtc = rtc;
pm_power_off = omap_rtc_power_off;
}
}
return 0; return 0;
err_deregister_pinctrl:
pinctrl_unregister(rtc->pctldev);
err: err:
clk_disable_unprepare(rtc->clk); clk_disable_unprepare(rtc->clk);
device_init_wakeup(&pdev->dev, false); device_init_wakeup(&pdev->dev, false);
......
...@@ -36,6 +36,11 @@ ...@@ -36,6 +36,11 @@
#define PCF2127_REG_MO (0x08) #define PCF2127_REG_MO (0x08)
#define PCF2127_REG_YR (0x09) #define PCF2127_REG_YR (0x09)
/* the pcf2127 has 512 bytes nvmem, pcf2129 doesn't */
#define PCF2127_REG_RAM_addr_MSB 0x1a
#define PCF2127_REG_RAM_wrt_cmd 0x1c
#define PCF2127_REG_RAM_rd_cmd 0x1d
#define PCF2127_OSF BIT(7) /* Oscillator Fail flag */ #define PCF2127_OSF BIT(7) /* Oscillator Fail flag */
struct pcf2127 { struct pcf2127 {
...@@ -183,10 +188,47 @@ static const struct rtc_class_ops pcf2127_rtc_ops = { ...@@ -183,10 +188,47 @@ static const struct rtc_class_ops pcf2127_rtc_ops = {
.set_time = pcf2127_rtc_set_time, .set_time = pcf2127_rtc_set_time,
}; };
static int pcf2127_nvmem_read(void *priv, unsigned int offset,
void *val, size_t bytes)
{
struct pcf2127 *pcf2127 = priv;
int ret;
unsigned char offsetbuf[] = { offset >> 8, offset };
ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB,
offsetbuf, 2);
if (ret)
return ret;
ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_rd_cmd,
val, bytes);
return ret ?: bytes;
}
static int pcf2127_nvmem_write(void *priv, unsigned int offset,
void *val, size_t bytes)
{
struct pcf2127 *pcf2127 = priv;
int ret;
unsigned char offsetbuf[] = { offset >> 8, offset };
ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB,
offsetbuf, 2);
if (ret)
return ret;
ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_wrt_cmd,
val, bytes);
return ret ?: bytes;
}
static int pcf2127_probe(struct device *dev, struct regmap *regmap, static int pcf2127_probe(struct device *dev, struct regmap *regmap,
const char *name) const char *name, bool has_nvmem)
{ {
struct pcf2127 *pcf2127; struct pcf2127 *pcf2127;
int ret = 0;
dev_dbg(dev, "%s\n", __func__); dev_dbg(dev, "%s\n", __func__);
...@@ -200,8 +242,21 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, ...@@ -200,8 +242,21 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
pcf2127->rtc = devm_rtc_device_register(dev, name, &pcf2127_rtc_ops, pcf2127->rtc = devm_rtc_device_register(dev, name, &pcf2127_rtc_ops,
THIS_MODULE); THIS_MODULE);
if (IS_ERR(pcf2127->rtc))
return PTR_ERR(pcf2127->rtc);
if (has_nvmem) {
struct nvmem_config nvmem_cfg = {
.priv = pcf2127,
.reg_read = pcf2127_nvmem_read,
.reg_write = pcf2127_nvmem_write,
.size = 512,
};
return PTR_ERR_OR_ZERO(pcf2127->rtc); ret = rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg);
}
return ret;
} }
#ifdef CONFIG_OF #ifdef CONFIG_OF
...@@ -309,11 +364,11 @@ static int pcf2127_i2c_probe(struct i2c_client *client, ...@@ -309,11 +364,11 @@ static int pcf2127_i2c_probe(struct i2c_client *client,
} }
return pcf2127_probe(&client->dev, regmap, return pcf2127_probe(&client->dev, regmap,
pcf2127_i2c_driver.driver.name); pcf2127_i2c_driver.driver.name, id->driver_data);
} }
static const struct i2c_device_id pcf2127_i2c_id[] = { static const struct i2c_device_id pcf2127_i2c_id[] = {
{ "pcf2127", 0 }, { "pcf2127", 1 },
{ "pcf2129", 0 }, { "pcf2129", 0 },
{ } { }
}; };
...@@ -372,11 +427,12 @@ static int pcf2127_spi_probe(struct spi_device *spi) ...@@ -372,11 +427,12 @@ static int pcf2127_spi_probe(struct spi_device *spi)
return PTR_ERR(regmap); return PTR_ERR(regmap);
} }
return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name); return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name,
spi_get_device_id(spi)->driver_data);
} }
static const struct spi_device_id pcf2127_spi_id[] = { static const struct spi_device_id pcf2127_spi_id[] = {
{ "pcf2127", 0 }, { "pcf2127", 1 },
{ "pcf2129", 0 }, { "pcf2129", 0 },
{ } { }
}; };
......
...@@ -43,37 +43,38 @@ static struct i2c_driver pcf85063_driver; ...@@ -43,37 +43,38 @@ static struct i2c_driver pcf85063_driver;
static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1) static int pcf85063_stop_clock(struct i2c_client *client, u8 *ctrl1)
{ {
s32 ret; int rc;
u8 reg;
ret = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1); rc = i2c_smbus_read_byte_data(client, PCF85063_REG_CTRL1);
if (ret < 0) { if (rc < 0) {
dev_err(&client->dev, "Failing to stop the clock\n"); dev_err(&client->dev, "Failing to stop the clock\n");
return -EIO; return -EIO;
} }
/* stop the clock */ /* stop the clock */
ret |= PCF85063_REG_CTRL1_STOP; reg = rc | PCF85063_REG_CTRL1_STOP;
ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ret); rc = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, reg);
if (ret < 0) { if (rc < 0) {
dev_err(&client->dev, "Failing to stop the clock\n"); dev_err(&client->dev, "Failing to stop the clock\n");
return -EIO; return -EIO;
} }
*ctrl1 = ret; *ctrl1 = reg;
return 0; return 0;
} }
static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1) static int pcf85063_start_clock(struct i2c_client *client, u8 ctrl1)
{ {
s32 ret; int rc;
/* start the clock */ /* start the clock */
ctrl1 &= ~PCF85063_REG_CTRL1_STOP; ctrl1 &= ~PCF85063_REG_CTRL1_STOP;
ret = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1); rc = i2c_smbus_write_byte_data(client, PCF85063_REG_CTRL1, ctrl1);
if (ret < 0) { if (rc < 0) {
dev_err(&client->dev, "Failing to start the clock\n"); dev_err(&client->dev, "Failing to start the clock\n");
return -EIO; return -EIO;
} }
......
/* // SPDX-License-Identifier: GPL-2.0+
* Copyright (c) 2013-2014 Samsung Electronics Co., Ltd //
* http://www.samsung.com // Copyright (c) 2013-2014 Samsung Electronics Co., Ltd
* // http://www.samsung.com
* Copyright (C) 2013 Google, Inc //
* // Copyright (C) 2013 Google, Inc
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
......
...@@ -224,7 +224,6 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info) ...@@ -224,7 +224,6 @@ int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
info->rtc = rtc; info->rtc = rtc;
rtc->max_user_freq = RTC_FREQ; rtc->max_user_freq = RTC_FREQ;
rtc_irq_set_freq(rtc, NULL, RTC_FREQ);
/* Fix for a nasty initialization problem the in SA11xx RTSR register. /* Fix for a nasty initialization problem the in SA11xx RTSR register.
* See also the comments in sa1100_rtc_interrupt(). * See also the comments in sa1100_rtc_interrupt().
......
...@@ -143,8 +143,6 @@ static int __sh_rtc_alarm(struct sh_rtc *rtc) ...@@ -143,8 +143,6 @@ static int __sh_rtc_alarm(struct sh_rtc *rtc)
static int __sh_rtc_periodic(struct sh_rtc *rtc) static int __sh_rtc_periodic(struct sh_rtc *rtc)
{ {
struct rtc_device *rtc_dev = rtc->rtc_dev;
struct rtc_task *irq_task;
unsigned int tmp, pending; unsigned int tmp, pending;
tmp = readb(rtc->regbase + RCR2); tmp = readb(rtc->regbase + RCR2);
...@@ -161,13 +159,6 @@ static int __sh_rtc_periodic(struct sh_rtc *rtc) ...@@ -161,13 +159,6 @@ static int __sh_rtc_periodic(struct sh_rtc *rtc)
else { else {
if (rtc->periodic_freq & PF_HP) if (rtc->periodic_freq & PF_HP)
rtc->periodic_freq |= PF_COUNT; rtc->periodic_freq |= PF_COUNT;
if (rtc->periodic_freq & PF_KOU) {
spin_lock(&rtc_dev->irq_task_lock);
irq_task = rtc_dev->irq_task;
if (irq_task)
irq_task->func(irq_task->private_data);
spin_unlock(&rtc_dev->irq_task_lock);
} else
rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF); rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF);
} }
...@@ -224,81 +215,6 @@ static irqreturn_t sh_rtc_shared(int irq, void *dev_id) ...@@ -224,81 +215,6 @@ static irqreturn_t sh_rtc_shared(int irq, void *dev_id)
return IRQ_RETVAL(ret); return IRQ_RETVAL(ret);
} }
static int sh_rtc_irq_set_state(struct device *dev, int enable)
{
struct sh_rtc *rtc = dev_get_drvdata(dev);
unsigned int tmp;
spin_lock_irq(&rtc->lock);
tmp = readb(rtc->regbase + RCR2);
if (enable) {
rtc->periodic_freq |= PF_KOU;
tmp &= ~RCR2_PEF; /* Clear PES bit */
tmp |= (rtc->periodic_freq & ~PF_HP); /* Set PES2-0 */
} else {
rtc->periodic_freq &= ~PF_KOU;
tmp &= ~(RCR2_PESMASK | RCR2_PEF);
}
writeb(tmp, rtc->regbase + RCR2);
spin_unlock_irq(&rtc->lock);
return 0;
}
static int sh_rtc_irq_set_freq(struct device *dev, int freq)
{
struct sh_rtc *rtc = dev_get_drvdata(dev);
int tmp, ret = 0;
spin_lock_irq(&rtc->lock);
tmp = rtc->periodic_freq & PF_MASK;
switch (freq) {
case 0:
rtc->periodic_freq = 0x00;
break;
case 1:
rtc->periodic_freq = 0x60;
break;
case 2:
rtc->periodic_freq = 0x50;
break;
case 4:
rtc->periodic_freq = 0x40;
break;
case 8:
rtc->periodic_freq = 0x30 | PF_HP;
break;
case 16:
rtc->periodic_freq = 0x30;
break;
case 32:
rtc->periodic_freq = 0x20 | PF_HP;
break;
case 64:
rtc->periodic_freq = 0x20;
break;
case 128:
rtc->periodic_freq = 0x10 | PF_HP;
break;
case 256:
rtc->periodic_freq = 0x10;
break;
default:
ret = -ENOTSUPP;
}
if (ret == 0)
rtc->periodic_freq |= tmp;
spin_unlock_irq(&rtc->lock);
return ret;
}
static inline void sh_rtc_setaie(struct device *dev, unsigned int enable) static inline void sh_rtc_setaie(struct device *dev, unsigned int enable)
{ {
struct sh_rtc *rtc = dev_get_drvdata(dev); struct sh_rtc *rtc = dev_get_drvdata(dev);
...@@ -675,8 +591,6 @@ static int __init sh_rtc_probe(struct platform_device *pdev) ...@@ -675,8 +591,6 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rtc); platform_set_drvdata(pdev, rtc);
/* everything disabled by default */ /* everything disabled by default */
sh_rtc_irq_set_freq(&pdev->dev, 0);
sh_rtc_irq_set_state(&pdev->dev, 0);
sh_rtc_setaie(&pdev->dev, 0); sh_rtc_setaie(&pdev->dev, 0);
sh_rtc_setcie(&pdev->dev, 0); sh_rtc_setcie(&pdev->dev, 0);
...@@ -708,8 +622,6 @@ static int __exit sh_rtc_remove(struct platform_device *pdev) ...@@ -708,8 +622,6 @@ static int __exit sh_rtc_remove(struct platform_device *pdev)
{ {
struct sh_rtc *rtc = platform_get_drvdata(pdev); struct sh_rtc *rtc = platform_get_drvdata(pdev);
sh_rtc_irq_set_state(&pdev->dev, 0);
sh_rtc_setaie(&pdev->dev, 0); sh_rtc_setaie(&pdev->dev, 0);
sh_rtc_setcie(&pdev->dev, 0); sh_rtc_setcie(&pdev->dev, 0);
......
...@@ -40,49 +40,83 @@ struct snvs_rtc_data { ...@@ -40,49 +40,83 @@ struct snvs_rtc_data {
struct clk *clk; struct clk *clk;
}; };
/* Read 64 bit timer register, which could be in inconsistent state */
static u64 rtc_read_lpsrt(struct snvs_rtc_data *data)
{
u32 msb, lsb;
regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &msb);
regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &lsb);
return (u64)msb << 32 | lsb;
}
/* Read the secure real time counter, taking care to deal with the cases of the
* counter updating while being read.
*/
static u32 rtc_read_lp_counter(struct snvs_rtc_data *data) static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
{ {
u64 read1, read2; u64 read1, read2;
u32 val; unsigned int timeout = 100;
/* As expected, the registers might update between the read of the LSB
* reg and the MSB reg. It's also possible that one register might be
* in partially modified state as well.
*/
read1 = rtc_read_lpsrt(data);
do { do {
regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val); read2 = read1;
read1 = val; read1 = rtc_read_lpsrt(data);
read1 <<= 32; } while (read1 != read2 && --timeout);
regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val); if (!timeout)
read1 |= val; dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
read2 = val;
read2 <<= 32;
regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
read2 |= val;
} while (read1 != read2);
/* Convert 47-bit counter to 32-bit raw second count */ /* Convert 47-bit counter to 32-bit raw second count */
return (u32) (read1 >> CNTR_TO_SECS_SH); return (u32) (read1 >> CNTR_TO_SECS_SH);
} }
static void rtc_write_sync_lp(struct snvs_rtc_data *data) /* Just read the lsb from the counter, dealing with inconsistent state */
static int rtc_read_lp_counter_lsb(struct snvs_rtc_data *data, u32 *lsb)
{ {
u32 count1, count2, count3; u32 count1, count2;
int i; unsigned int timeout = 100;
/* Wait for 3 CKIL cycles */ regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
for (i = 0; i < 3; i++) {
do { do {
count2 = count1;
regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1); regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2); } while (count1 != count2 && --timeout);
} while (count1 != count2); if (!timeout) {
dev_err(&data->rtc->dev, "Timeout trying to get valid LPSRT Counter read\n");
return -ETIMEDOUT;
}
/* Now wait until counter value changes */ *lsb = count1;
do { return 0;
}
static int rtc_write_sync_lp(struct snvs_rtc_data *data)
{
u32 count1, count2;
u32 elapsed;
unsigned int timeout = 1000;
int ret;
ret = rtc_read_lp_counter_lsb(data, &count1);
if (ret)
return ret;
/* Wait for 3 CKIL cycles, about 61.0-91.5 µs */
do { do {
regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2); ret = rtc_read_lp_counter_lsb(data, &count2);
regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count3); if (ret)
} while (count2 != count3); return ret;
} while (count3 == count1); elapsed = count2 - count1; /* wrap around _is_ handled! */
} while (elapsed < 3 && --timeout);
if (!timeout) {
dev_err(&data->rtc->dev, "Timeout waiting for LPSRT Counter to change\n");
return -ETIMEDOUT;
} }
return 0;
} }
static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable) static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
...@@ -166,9 +200,7 @@ static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) ...@@ -166,9 +200,7 @@ static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN), (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN),
enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0); enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0);
rtc_write_sync_lp(data); return rtc_write_sync_lp(data);
return 0;
} }
static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
...@@ -176,11 +208,14 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -176,11 +208,14 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct snvs_rtc_data *data = dev_get_drvdata(dev); struct snvs_rtc_data *data = dev_get_drvdata(dev);
struct rtc_time *alrm_tm = &alrm->time; struct rtc_time *alrm_tm = &alrm->time;
unsigned long time; unsigned long time;
int ret;
rtc_tm_to_time(alrm_tm, &time); rtc_tm_to_time(alrm_tm, &time);
regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0); regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0);
rtc_write_sync_lp(data); ret = rtc_write_sync_lp(data);
if (ret)
return ret;
regmap_write(data->regmap, data->offset + SNVS_LPTAR, time); regmap_write(data->regmap, data->offset + SNVS_LPTAR, time);
/* Clear alarm interrupt status bit */ /* Clear alarm interrupt status bit */
......
...@@ -288,11 +288,23 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev) ...@@ -288,11 +288,23 @@ static int stmp3xxx_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rtc_data); platform_set_drvdata(pdev, rtc_data);
/*
* Resetting the rtc stops the watchdog timer that is potentially
* running. So (assuming it is running on purpose) don't reset if the
* watchdog is enabled.
*/
if (readl(rtc_data->io + STMP3XXX_RTC_CTRL) &
STMP3XXX_RTC_CTRL_WATCHDOGEN) {
dev_info(&pdev->dev,
"Watchdog is running, skip resetting rtc\n");
} else {
err = stmp_reset_block(rtc_data->io); err = stmp_reset_block(rtc_data->io);
if (err) { if (err) {
dev_err(&pdev->dev, "stmp_reset_block failed: %d\n", err); dev_err(&pdev->dev, "stmp_reset_block failed: %d\n",
err);
return err; return err;
} }
}
/* /*
* Obviously the rtc needs a clock input to be able to run. * Obviously the rtc needs a clock input to be able to run.
......
...@@ -317,3 +317,46 @@ const struct attribute_group **rtc_get_dev_attribute_groups(void) ...@@ -317,3 +317,46 @@ const struct attribute_group **rtc_get_dev_attribute_groups(void)
{ {
return rtc_attr_groups; return rtc_attr_groups;
} }
int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps)
{
size_t old_cnt = 0, add_cnt = 0, new_cnt;
const struct attribute_group **groups, **old;
if (rtc->registered)
return -EINVAL;
if (!grps)
return -EINVAL;
groups = rtc->dev.groups;
if (groups)
for (; *groups; groups++)
old_cnt++;
for (groups = grps; *groups; groups++)
add_cnt++;
new_cnt = old_cnt + add_cnt + 1;
groups = devm_kcalloc(&rtc->dev, new_cnt, sizeof(*groups), GFP_KERNEL);
if (IS_ERR_OR_NULL(groups))
return PTR_ERR(groups);
memcpy(groups, rtc->dev.groups, old_cnt * sizeof(*groups));
memcpy(groups + old_cnt, grps, add_cnt * sizeof(*groups));
groups[old_cnt + add_cnt] = NULL;
old = rtc->dev.groups;
rtc->dev.groups = groups;
if (old && old != rtc_attr_groups)
devm_kfree(&rtc->dev, old);
return 0;
}
EXPORT_SYMBOL(rtc_add_groups);
int rtc_add_group(struct rtc_device *rtc, const struct attribute_group *grp)
{
const struct attribute_group *groups[] = { grp, NULL };
return rtc_add_groups(rtc, groups);
}
EXPORT_SYMBOL(rtc_add_group);
...@@ -22,7 +22,7 @@ struct rtc_test_data { ...@@ -22,7 +22,7 @@ struct rtc_test_data {
bool alarm_en; bool alarm_en;
}; };
struct platform_device *pdev[MAX_RTC_TEST]; static struct platform_device *pdev[MAX_RTC_TEST];
static int test_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int test_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{ {
......
...@@ -87,16 +87,11 @@ struct rtc_class_ops { ...@@ -87,16 +87,11 @@ struct rtc_class_ops {
int (*set_offset)(struct device *, long offset); int (*set_offset)(struct device *, long offset);
}; };
typedef struct rtc_task {
void (*func)(void *private_data);
void *private_data;
} rtc_task_t;
struct rtc_timer { struct rtc_timer {
struct rtc_task task;
struct timerqueue_node node; struct timerqueue_node node;
ktime_t period; ktime_t period;
void (*func)(void *private_data);
void *private_data;
int enabled; int enabled;
}; };
...@@ -121,8 +116,6 @@ struct rtc_device { ...@@ -121,8 +116,6 @@ struct rtc_device {
wait_queue_head_t irq_queue; wait_queue_head_t irq_queue;
struct fasync_struct *async_queue; struct fasync_struct *async_queue;
struct rtc_task *irq_task;
spinlock_t irq_task_lock;
int irq_freq; int irq_freq;
int max_user_freq; int max_user_freq;
...@@ -204,14 +197,8 @@ extern void rtc_update_irq(struct rtc_device *rtc, ...@@ -204,14 +197,8 @@ extern void rtc_update_irq(struct rtc_device *rtc,
extern struct rtc_device *rtc_class_open(const char *name); extern struct rtc_device *rtc_class_open(const char *name);
extern void rtc_class_close(struct rtc_device *rtc); extern void rtc_class_close(struct rtc_device *rtc);
extern int rtc_irq_register(struct rtc_device *rtc, extern int rtc_irq_set_state(struct rtc_device *rtc, int enabled);
struct rtc_task *task); extern int rtc_irq_set_freq(struct rtc_device *rtc, int freq);
extern void rtc_irq_unregister(struct rtc_device *rtc,
struct rtc_task *task);
extern int rtc_irq_set_state(struct rtc_device *rtc,
struct rtc_task *task, int enabled);
extern int rtc_irq_set_freq(struct rtc_device *rtc,
struct rtc_task *task, int freq);
extern int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled); extern int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled);
extern int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled); extern int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled);
extern int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, extern int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment