You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'rtc-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
Pull RTC updates from Alexandre Belloni:
"Setting the supported range from drivers for RTCs failing soon has
started. A few fixes are developed along the way. Some drivers have
been switched to SPDX by their maintainers.
Subsystem:
- rework of the rtc-test driver which allows to test the core more
thoroughly
- rtc_set_alarm() now fails early when alarms are not supported
Drivers:
- mktime() is now replaced by mktime64()
- RTC range added for 88pm80x, ab-b5ze-s3, at91rm9200,
brcmstb-waketimer, ds1685, ftrtc010, ls1x, mxc_v2, rx8581, sprd,
st-lpc, tps6586x, tps65910 and vr41xx
- fixed a possible race condition in probe functions
- pxa: fix the probe function that is broken since v4.3
- stm32: now supports stm32mp1"
* tag 'rtc-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (78 commits)
rtc: pxa: fix probe function
rtc: cros-ec: Switch to SPDX identifier.
rtc: cros-ec: Make license text and module license match.
rtc: ensure rtc_set_alarm fails when alarms are not supported
rtc: test: remove alarm support from the first device
rtc: test: convert to devm_rtc_allocate_device
rtc: ftrtc010: let the core handle range
rtc: ftrtc010: handle dates after 2106
rtc: ftrtc010: switch to devm_rtc_allocate_device
rtc: mrst: switch to devm functions
rtc: sunxi: fix possible race condition
rtc: test: remove irq sysfs file
rtc: test: emulate alarms using timers
rtc: test: store time as an offset to system time
rtc: test: allow registering many devices
rtc: test: remove useless proc info
rtc: ds1685: Add range
rtc: ds1685: fix possible race condition
rtc: sprd: Add new RTC power down check method
rtc: sun6i: Fix bit_idx value for clk_register_gate
...
This commit is contained in:
@@ -9,7 +9,7 @@ Optional properties:
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
rtc: nxp,rtc-pcf2123@3 {
|
pcf2123: rtc@3 {
|
||||||
compatible = "nxp,rtc-pcf2123"
|
compatible = "nxp,rtc-pcf2123"
|
||||||
reg = <3>
|
reg = <3>
|
||||||
spi-cs-high;
|
spi-cs-high;
|
||||||
|
|||||||
@@ -1,23 +1,29 @@
|
|||||||
STM32 Real Time Clock
|
STM32 Real Time Clock
|
||||||
|
|
||||||
Required properties:
|
Required properties:
|
||||||
- compatible: can be either "st,stm32-rtc" or "st,stm32h7-rtc", depending on
|
- compatible: can be one of the following:
|
||||||
the device is compatible with stm32(f4/f7) or stm32h7.
|
- "st,stm32-rtc" for devices compatible with stm32(f4/f7).
|
||||||
|
- "st,stm32h7-rtc" for devices compatible with stm32h7.
|
||||||
|
- "st,stm32mp1-rtc" for devices compatible with stm32mp1.
|
||||||
- reg: address range of rtc register set.
|
- reg: address range of rtc register set.
|
||||||
- clocks: can use up to two clocks, depending on part used:
|
- clocks: can use up to two clocks, depending on part used:
|
||||||
- "rtc_ck": RTC clock source.
|
- "rtc_ck": RTC clock source.
|
||||||
It is required on stm32(f4/f7) and stm32h7.
|
|
||||||
- "pclk": RTC APB interface clock.
|
- "pclk": RTC APB interface clock.
|
||||||
It is not present on stm32(f4/f7).
|
It is not present on stm32(f4/f7).
|
||||||
It is required on stm32h7.
|
It is required on stm32(h7/mp1).
|
||||||
- clock-names: must be "rtc_ck" and "pclk".
|
- clock-names: must be "rtc_ck" and "pclk".
|
||||||
It is required only on stm32h7.
|
It is required on stm32(h7/mp1).
|
||||||
- interrupt-parent: phandle for the interrupt controller.
|
- interrupt-parent: phandle for the interrupt controller.
|
||||||
- interrupts: rtc alarm interrupt.
|
It is required on stm32(f4/f7/h7).
|
||||||
- st,syscfg: phandle for pwrcfg, mandatory to disable/enable backup domain
|
- interrupts: rtc alarm interrupt. On stm32mp1, a second interrupt is required
|
||||||
(RTC registers) write protection.
|
for rtc alarm wakeup interrupt.
|
||||||
|
- st,syscfg: phandle/offset/mask triplet. The phandle to pwrcfg used to
|
||||||
|
access control register at offset, and change the dbp (Disable Backup
|
||||||
|
Protection) bit represented by the mask, mandatory to disable/enable backup
|
||||||
|
domain (RTC registers) write protection.
|
||||||
|
It is required on stm32(f4/f7/h7).
|
||||||
|
|
||||||
Optional properties (to override default rtc_ck parent clock):
|
Optional properties (to override default rtc_ck parent clock on stm32(f4/f7/h7):
|
||||||
- assigned-clocks: reference to the rtc_ck clock entry.
|
- assigned-clocks: reference to the rtc_ck clock entry.
|
||||||
- assigned-clock-parents: phandle of the new parent clock of rtc_ck.
|
- assigned-clock-parents: phandle of the new parent clock of rtc_ck.
|
||||||
|
|
||||||
@@ -31,7 +37,7 @@ Example:
|
|||||||
assigned-clock-parents = <&rcc 1 CLK_LSE>;
|
assigned-clock-parents = <&rcc 1 CLK_LSE>;
|
||||||
interrupt-parent = <&exti>;
|
interrupt-parent = <&exti>;
|
||||||
interrupts = <17 1>;
|
interrupts = <17 1>;
|
||||||
st,syscfg = <&pwrcfg>;
|
st,syscfg = <&pwrcfg 0x00 0x100>;
|
||||||
};
|
};
|
||||||
|
|
||||||
rtc: rtc@58004000 {
|
rtc: rtc@58004000 {
|
||||||
@@ -44,5 +50,14 @@ Example:
|
|||||||
interrupt-parent = <&exti>;
|
interrupt-parent = <&exti>;
|
||||||
interrupts = <17 1>;
|
interrupts = <17 1>;
|
||||||
interrupt-names = "alarm";
|
interrupt-names = "alarm";
|
||||||
st,syscfg = <&pwrcfg>;
|
st,syscfg = <&pwrcfg 0x00 0x100>;
|
||||||
|
};
|
||||||
|
|
||||||
|
rtc: rtc@5c004000 {
|
||||||
|
compatible = "st,stm32mp1-rtc";
|
||||||
|
reg = <0x5c004000 0x400>;
|
||||||
|
clocks = <&rcc RTCAPB>, <&rcc RTC>;
|
||||||
|
clock-names = "pclk", "rtc_ck";
|
||||||
|
interrupts-extended = <&intc GIC_SPI 3 IRQ_TYPE_NONE>,
|
||||||
|
<&exti 19 1>;
|
||||||
};
|
};
|
||||||
|
|||||||
+1
-1
@@ -1613,7 +1613,7 @@ config RTC_DRV_JZ4740
|
|||||||
If you say yes here you get support for the Ingenic JZ47xx SoCs RTC
|
If you say yes here you get support for the Ingenic JZ47xx SoCs RTC
|
||||||
controllers.
|
controllers.
|
||||||
|
|
||||||
This driver can also be buillt as a module. If so, the module
|
This driver can also be built as a module. If so, the module
|
||||||
will be called rtc-jz4740.
|
will be called rtc-jz4740.
|
||||||
|
|
||||||
config RTC_DRV_LPC24XX
|
config RTC_DRV_LPC24XX
|
||||||
|
|||||||
@@ -441,6 +441,11 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
if (!rtc->ops)
|
||||||
|
return -ENODEV;
|
||||||
|
else if (!rtc->ops->set_alarm)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
err = rtc_valid_tm(&alarm->time);
|
err = rtc_valid_tm(&alarm->time);
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
+1
-1
@@ -94,7 +94,7 @@ int rtc_nvmem_register(struct rtc_device *rtc,
|
|||||||
nvmem_config->dev = rtc->dev.parent;
|
nvmem_config->dev = rtc->dev.parent;
|
||||||
nvmem_config->owner = rtc->owner;
|
nvmem_config->owner = rtc->owner;
|
||||||
rtc->nvmem = nvmem_register(nvmem_config);
|
rtc->nvmem = nvmem_register(nvmem_config);
|
||||||
if (IS_ERR_OR_NULL(rtc->nvmem))
|
if (IS_ERR(rtc->nvmem))
|
||||||
return PTR_ERR(rtc->nvmem);
|
return PTR_ERR(rtc->nvmem);
|
||||||
|
|
||||||
/* Register the old ABI */
|
/* Register the old ABI */
|
||||||
|
|||||||
+17
-41
@@ -52,10 +52,8 @@ struct pm80x_rtc_info {
|
|||||||
struct regmap *map;
|
struct regmap *map;
|
||||||
struct rtc_device *rtc_dev;
|
struct rtc_device *rtc_dev;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct delayed_work calib_work;
|
|
||||||
|
|
||||||
int irq;
|
int irq;
|
||||||
int vrtc;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static irqreturn_t rtc_update_handler(int irq, void *data)
|
static irqreturn_t rtc_update_handler(int irq, void *data)
|
||||||
@@ -100,13 +98,13 @@ static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
|
|||||||
next->tm_min = alrm->tm_min;
|
next->tm_min = alrm->tm_min;
|
||||||
next->tm_sec = alrm->tm_sec;
|
next->tm_sec = alrm->tm_sec;
|
||||||
|
|
||||||
rtc_tm_to_time(now, &now_time);
|
now_time = rtc_tm_to_time64(now);
|
||||||
rtc_tm_to_time(next, &next_time);
|
next_time = rtc_tm_to_time64(next);
|
||||||
|
|
||||||
if (next_time < now_time) {
|
if (next_time < now_time) {
|
||||||
/* Advance one day */
|
/* Advance one day */
|
||||||
next_time += 60 * 60 * 24;
|
next_time += 60 * 60 * 24;
|
||||||
rtc_time_to_tm(next_time, next);
|
rtc_time64_to_tm(next_time, next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +123,7 @@ static int pm80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||||||
ticks = base + data;
|
ticks = base + data;
|
||||||
dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
|
dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
|
||||||
base, data, ticks);
|
base, data, ticks);
|
||||||
rtc_time_to_tm(ticks, tm);
|
rtc_time64_to_tm(ticks, tm);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,13 +132,8 @@ static int pm80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
|||||||
struct pm80x_rtc_info *info = dev_get_drvdata(dev);
|
struct pm80x_rtc_info *info = dev_get_drvdata(dev);
|
||||||
unsigned char buf[4];
|
unsigned char buf[4];
|
||||||
unsigned long ticks, base, data;
|
unsigned long ticks, base, data;
|
||||||
if (tm->tm_year > 206) {
|
|
||||||
dev_dbg(info->dev,
|
ticks = rtc_tm_to_time64(tm);
|
||||||
"Set time %d out of range. Please set time between 1970 to 2106.\n",
|
|
||||||
1900 + tm->tm_year);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
rtc_tm_to_time(tm, &ticks);
|
|
||||||
|
|
||||||
/* load 32-bit read-only counter */
|
/* load 32-bit read-only counter */
|
||||||
regmap_raw_read(info->map, PM800_RTC_COUNTER1, buf, 4);
|
regmap_raw_read(info->map, PM800_RTC_COUNTER1, buf, 4);
|
||||||
@@ -174,7 +167,7 @@ static int pm80x_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|||||||
dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
|
dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
|
||||||
base, data, ticks);
|
base, data, ticks);
|
||||||
|
|
||||||
rtc_time_to_tm(ticks, &alrm->time);
|
rtc_time64_to_tm(ticks, &alrm->time);
|
||||||
regmap_read(info->map, PM800_RTC_CONTROL, &ret);
|
regmap_read(info->map, PM800_RTC_CONTROL, &ret);
|
||||||
alrm->enabled = (ret & PM800_ALARM1_EN) ? 1 : 0;
|
alrm->enabled = (ret & PM800_ALARM1_EN) ? 1 : 0;
|
||||||
alrm->pending = (ret & (PM800_ALARM | PM800_ALARM_WAKEUP)) ? 1 : 0;
|
alrm->pending = (ret & (PM800_ALARM | PM800_ALARM_WAKEUP)) ? 1 : 0;
|
||||||
@@ -202,11 +195,11 @@ static int pm80x_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|||||||
dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
|
dev_dbg(info->dev, "get base:0x%lx, RO count:0x%lx, ticks:0x%lx\n",
|
||||||
base, data, ticks);
|
base, data, ticks);
|
||||||
|
|
||||||
rtc_time_to_tm(ticks, &now_tm);
|
rtc_time64_to_tm(ticks, &now_tm);
|
||||||
dev_dbg(info->dev, "%s, now time : %lu\n", __func__, ticks);
|
dev_dbg(info->dev, "%s, now time : %lu\n", __func__, ticks);
|
||||||
rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time);
|
rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time);
|
||||||
/* get new ticks for alarm in 24 hours */
|
/* get new ticks for alarm in 24 hours */
|
||||||
rtc_tm_to_time(&alarm_tm, &ticks);
|
ticks = rtc_tm_to_time64(&alarm_tm);
|
||||||
dev_dbg(info->dev, "%s, alarm time: %lu\n", __func__, ticks);
|
dev_dbg(info->dev, "%s, alarm time: %lu\n", __func__, ticks);
|
||||||
data = ticks - base;
|
data = ticks - base;
|
||||||
|
|
||||||
@@ -254,8 +247,6 @@ static int pm80x_rtc_probe(struct platform_device *pdev)
|
|||||||
struct pm80x_rtc_pdata *pdata = dev_get_platdata(&pdev->dev);
|
struct pm80x_rtc_pdata *pdata = dev_get_platdata(&pdev->dev);
|
||||||
struct pm80x_rtc_info *info;
|
struct pm80x_rtc_info *info;
|
||||||
struct device_node *node = pdev->dev.of_node;
|
struct device_node *node = pdev->dev.of_node;
|
||||||
struct rtc_time tm;
|
|
||||||
unsigned long ticks = 0;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!pdata && !node) {
|
if (!pdata && !node) {
|
||||||
@@ -294,6 +285,10 @@ static int pm80x_rtc_probe(struct platform_device *pdev)
|
|||||||
info->dev = &pdev->dev;
|
info->dev = &pdev->dev;
|
||||||
dev_set_drvdata(&pdev->dev, info);
|
dev_set_drvdata(&pdev->dev, info);
|
||||||
|
|
||||||
|
info->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
|
||||||
|
if (IS_ERR(info->rtc_dev))
|
||||||
|
return PTR_ERR(info->rtc_dev);
|
||||||
|
|
||||||
ret = pm80x_request_irq(chip, info->irq, rtc_update_handler,
|
ret = pm80x_request_irq(chip, info->irq, rtc_update_handler,
|
||||||
IRQF_ONESHOT, "rtc", info);
|
IRQF_ONESHOT, "rtc", info);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@@ -302,30 +297,11 @@ static int pm80x_rtc_probe(struct platform_device *pdev)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = pm80x_rtc_read_time(&pdev->dev, &tm);
|
info->rtc_dev->ops = &pm80x_rtc_ops;
|
||||||
if (ret < 0) {
|
info->rtc_dev->range_max = U32_MAX;
|
||||||
dev_err(&pdev->dev, "Failed to read initial time.\n");
|
|
||||||
goto out_rtc;
|
|
||||||
}
|
|
||||||
if ((tm.tm_year < 70) || (tm.tm_year > 138)) {
|
|
||||||
tm.tm_year = 70;
|
|
||||||
tm.tm_mon = 0;
|
|
||||||
tm.tm_mday = 1;
|
|
||||||
tm.tm_hour = 0;
|
|
||||||
tm.tm_min = 0;
|
|
||||||
tm.tm_sec = 0;
|
|
||||||
ret = pm80x_rtc_set_time(&pdev->dev, &tm);
|
|
||||||
if (ret < 0) {
|
|
||||||
dev_err(&pdev->dev, "Failed to set initial time.\n");
|
|
||||||
goto out_rtc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rtc_tm_to_time(&tm, &ticks);
|
|
||||||
|
|
||||||
info->rtc_dev = devm_rtc_device_register(&pdev->dev, "88pm80x-rtc",
|
ret = rtc_register_device(info->rtc_dev);
|
||||||
&pm80x_rtc_ops, THIS_MODULE);
|
if (ret) {
|
||||||
if (IS_ERR(info->rtc_dev)) {
|
|
||||||
ret = PTR_ERR(info->rtc_dev);
|
|
||||||
dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
|
dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
|
||||||
goto out_rtc;
|
goto out_rtc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -265,15 +265,6 @@ static int abb5zes3_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
|||||||
u8 regs[ABB5ZES3_REG_RTC_SC + ABB5ZES3_RTC_SEC_LEN];
|
u8 regs[ABB5ZES3_REG_RTC_SC + ABB5ZES3_RTC_SEC_LEN];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/*
|
|
||||||
* Year register is 8-bit wide and bcd-coded, i.e records values
|
|
||||||
* between 0 and 99. tm_year is an offset from 1900 and we are
|
|
||||||
* interested in the 2000-2099 range, so any value less than 100
|
|
||||||
* is invalid.
|
|
||||||
*/
|
|
||||||
if (tm->tm_year < 100)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
regs[ABB5ZES3_REG_RTC_SC] = bin2bcd(tm->tm_sec); /* MSB=0 clears OSC */
|
regs[ABB5ZES3_REG_RTC_SC] = bin2bcd(tm->tm_sec); /* MSB=0 clears OSC */
|
||||||
regs[ABB5ZES3_REG_RTC_MN] = bin2bcd(tm->tm_min);
|
regs[ABB5ZES3_REG_RTC_MN] = bin2bcd(tm->tm_min);
|
||||||
regs[ABB5ZES3_REG_RTC_HR] = bin2bcd(tm->tm_hour); /* 24-hour format */
|
regs[ABB5ZES3_REG_RTC_HR] = bin2bcd(tm->tm_hour); /* 24-hour format */
|
||||||
@@ -925,6 +916,14 @@ static int abb5zes3_probe(struct i2c_client *client,
|
|||||||
if (ret)
|
if (ret)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
|
data->rtc = devm_rtc_allocate_device(dev);
|
||||||
|
ret = PTR_ERR_OR_ZERO(data->rtc);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "%s: unable to allocate RTC device (%d)\n",
|
||||||
|
__func__, ret);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (client->irq > 0) {
|
if (client->irq > 0) {
|
||||||
ret = devm_request_threaded_irq(dev, client->irq, NULL,
|
ret = devm_request_threaded_irq(dev, client->irq, NULL,
|
||||||
_abb5zes3_rtc_interrupt,
|
_abb5zes3_rtc_interrupt,
|
||||||
@@ -942,14 +941,9 @@ static int abb5zes3_probe(struct i2c_client *client,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data->rtc = devm_rtc_device_register(dev, DRV_NAME, &rtc_ops,
|
data->rtc->ops = &rtc_ops;
|
||||||
THIS_MODULE);
|
data->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||||
ret = PTR_ERR_OR_ZERO(data->rtc);
|
data->rtc->range_max = RTC_TIMESTAMP_END_2099;
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "%s: unable to register RTC device (%d)\n",
|
|
||||||
__func__, ret);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Enable battery low detection interrupt if battery not already low */
|
/* Enable battery low detection interrupt if battery not already low */
|
||||||
if (!data->battery_low && data->irq) {
|
if (!data->battery_low && data->irq) {
|
||||||
@@ -961,6 +955,8 @@ static int abb5zes3_probe(struct i2c_client *client,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = rtc_register_device(data->rtc);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (ret && data && data->irq)
|
if (ret && data && data->irq)
|
||||||
device_init_wakeup(dev, false);
|
device_init_wakeup(dev, false);
|
||||||
|
|||||||
@@ -440,6 +440,8 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
|
|||||||
device_init_wakeup(&pdev->dev, 1);
|
device_init_wakeup(&pdev->dev, 1);
|
||||||
|
|
||||||
rtc->ops = &at91_rtc_ops;
|
rtc->ops = &at91_rtc_ops;
|
||||||
|
rtc->range_min = RTC_TIMESTAMP_BEGIN_1900;
|
||||||
|
rtc->range_max = RTC_TIMESTAMP_END_2099;
|
||||||
ret = rtc_register_device(rtc);
|
ret = rtc_register_device(rtc);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto err_clk;
|
goto err_clk;
|
||||||
|
|||||||
@@ -48,8 +48,7 @@ static void bq4802_write_mem(struct bq4802 *p, int off, u8 val)
|
|||||||
|
|
||||||
static int bq4802_read_time(struct device *dev, struct rtc_time *tm)
|
static int bq4802_read_time(struct device *dev, struct rtc_time *tm)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct bq4802 *p = dev_get_drvdata(dev);
|
||||||
struct bq4802 *p = platform_get_drvdata(pdev);
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int century;
|
unsigned int century;
|
||||||
u8 val;
|
u8 val;
|
||||||
@@ -91,8 +90,7 @@ static int bq4802_read_time(struct device *dev, struct rtc_time *tm)
|
|||||||
|
|
||||||
static int bq4802_set_time(struct device *dev, struct rtc_time *tm)
|
static int bq4802_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct bq4802 *p = dev_get_drvdata(dev);
|
||||||
struct bq4802 *p = platform_get_drvdata(pdev);
|
|
||||||
u8 sec, min, hrs, day, mon, yrs, century, val;
|
u8 sec, min, hrs, day, mon, yrs, century, val;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
unsigned int year;
|
unsigned int year;
|
||||||
|
|||||||
@@ -145,9 +145,6 @@ static int brcmstb_waketmr_settime(struct device *dev,
|
|||||||
|
|
||||||
sec = rtc_tm_to_time64(tm);
|
sec = rtc_tm_to_time64(tm);
|
||||||
|
|
||||||
if (sec > U32_MAX || sec < 0)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
writel_relaxed(sec, timer->base + BRCMSTB_WKTMR_COUNTER);
|
writel_relaxed(sec, timer->base + BRCMSTB_WKTMR_COUNTER);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -184,9 +181,6 @@ static int brcmstb_waketmr_setalarm(struct device *dev,
|
|||||||
else
|
else
|
||||||
sec = 0;
|
sec = 0;
|
||||||
|
|
||||||
if (sec > U32_MAX || sec < 0)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
brcmstb_waketmr_set_alarm(timer, sec);
|
brcmstb_waketmr_set_alarm(timer, sec);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -229,6 +223,10 @@ static int brcmstb_waketmr_probe(struct platform_device *pdev)
|
|||||||
if (IS_ERR(timer->base))
|
if (IS_ERR(timer->base))
|
||||||
return PTR_ERR(timer->base);
|
return PTR_ERR(timer->base);
|
||||||
|
|
||||||
|
timer->rtc = devm_rtc_allocate_device(dev);
|
||||||
|
if (IS_ERR(timer->rtc))
|
||||||
|
return PTR_ERR(timer->rtc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set wakeup capability before requesting wakeup interrupt, so we can
|
* Set wakeup capability before requesting wakeup interrupt, so we can
|
||||||
* process boot-time "wakeups" (e.g., from S5 soft-off)
|
* process boot-time "wakeups" (e.g., from S5 soft-off)
|
||||||
@@ -261,11 +259,12 @@ static int brcmstb_waketmr_probe(struct platform_device *pdev)
|
|||||||
timer->reboot_notifier.notifier_call = brcmstb_waketmr_reboot;
|
timer->reboot_notifier.notifier_call = brcmstb_waketmr_reboot;
|
||||||
register_reboot_notifier(&timer->reboot_notifier);
|
register_reboot_notifier(&timer->reboot_notifier);
|
||||||
|
|
||||||
timer->rtc = rtc_device_register("brcmstb-waketmr", dev,
|
timer->rtc->ops = &brcmstb_waketmr_ops;
|
||||||
&brcmstb_waketmr_ops, THIS_MODULE);
|
timer->rtc->range_max = U32_MAX;
|
||||||
if (IS_ERR(timer->rtc)) {
|
|
||||||
|
ret = rtc_register_device(timer->rtc);
|
||||||
|
if (ret) {
|
||||||
dev_err(dev, "unable to register device\n");
|
dev_err(dev, "unable to register device\n");
|
||||||
ret = PTR_ERR(timer->rtc);
|
|
||||||
goto err_notifier;
|
goto err_notifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,7 +287,6 @@ static int brcmstb_waketmr_remove(struct platform_device *pdev)
|
|||||||
struct brcmstb_waketmr *timer = dev_get_drvdata(&pdev->dev);
|
struct brcmstb_waketmr *timer = dev_get_drvdata(&pdev->dev);
|
||||||
|
|
||||||
unregister_reboot_notifier(&timer->reboot_notifier);
|
unregister_reboot_notifier(&timer->reboot_notifier);
|
||||||
rtc_device_unregister(timer->rtc);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+105
-12
@@ -43,11 +43,24 @@
|
|||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#ifdef CONFIG_X86
|
#ifdef CONFIG_X86
|
||||||
#include <asm/i8259.h>
|
#include <asm/i8259.h>
|
||||||
|
#include <asm/processor.h>
|
||||||
|
#include <linux/dmi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
|
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
|
||||||
#include <linux/mc146818rtc.h>
|
#include <linux/mc146818rtc.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use ACPI SCI to replace HPET interrupt for RTC Alarm event
|
||||||
|
*
|
||||||
|
* If cleared, ACPI SCI is only used to wake up the system from suspend
|
||||||
|
*
|
||||||
|
* If set, ACPI SCI is used to handle UIE/AIE and system wakeup
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool use_acpi_alarm;
|
||||||
|
module_param(use_acpi_alarm, bool, 0444);
|
||||||
|
|
||||||
struct cmos_rtc {
|
struct cmos_rtc {
|
||||||
struct rtc_device *rtc;
|
struct rtc_device *rtc;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
@@ -153,6 +166,12 @@ static inline int hpet_unregister_irq_handler(irq_handler_t handler)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Don't use HPET for RTC Alarm event if ACPI Fixed event is used */
|
||||||
|
static int use_hpet_alarm(void)
|
||||||
|
{
|
||||||
|
return is_hpet_enabled() && !use_acpi_alarm;
|
||||||
|
}
|
||||||
|
|
||||||
/*----------------------------------------------------------------*/
|
/*----------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifdef RTC_PORT
|
#ifdef RTC_PORT
|
||||||
@@ -298,7 +317,7 @@ static void cmos_checkintr(struct cmos_rtc *cmos, unsigned char rtc_control)
|
|||||||
*/
|
*/
|
||||||
rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
|
rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
|
||||||
|
|
||||||
if (is_hpet_enabled())
|
if (use_hpet_alarm())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
|
rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF;
|
||||||
@@ -318,8 +337,14 @@ static void cmos_irq_enable(struct cmos_rtc *cmos, unsigned char mask)
|
|||||||
|
|
||||||
rtc_control |= mask;
|
rtc_control |= mask;
|
||||||
CMOS_WRITE(rtc_control, RTC_CONTROL);
|
CMOS_WRITE(rtc_control, RTC_CONTROL);
|
||||||
|
if (use_hpet_alarm())
|
||||||
hpet_set_rtc_irq_bit(mask);
|
hpet_set_rtc_irq_bit(mask);
|
||||||
|
|
||||||
|
if ((mask & RTC_AIE) && use_acpi_alarm) {
|
||||||
|
if (cmos->wake_on)
|
||||||
|
cmos->wake_on(cmos->dev);
|
||||||
|
}
|
||||||
|
|
||||||
cmos_checkintr(cmos, rtc_control);
|
cmos_checkintr(cmos, rtc_control);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,8 +355,14 @@ static void cmos_irq_disable(struct cmos_rtc *cmos, unsigned char mask)
|
|||||||
rtc_control = CMOS_READ(RTC_CONTROL);
|
rtc_control = CMOS_READ(RTC_CONTROL);
|
||||||
rtc_control &= ~mask;
|
rtc_control &= ~mask;
|
||||||
CMOS_WRITE(rtc_control, RTC_CONTROL);
|
CMOS_WRITE(rtc_control, RTC_CONTROL);
|
||||||
|
if (use_hpet_alarm())
|
||||||
hpet_mask_rtc_irq_bit(mask);
|
hpet_mask_rtc_irq_bit(mask);
|
||||||
|
|
||||||
|
if ((mask & RTC_AIE) && use_acpi_alarm) {
|
||||||
|
if (cmos->wake_off)
|
||||||
|
cmos->wake_off(cmos->dev);
|
||||||
|
}
|
||||||
|
|
||||||
cmos_checkintr(cmos, rtc_control);
|
cmos_checkintr(cmos, rtc_control);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -448,10 +479,14 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
|
|||||||
CMOS_WRITE(mon, cmos->mon_alrm);
|
CMOS_WRITE(mon, cmos->mon_alrm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME the HPET alarm glue currently ignores day_alrm
|
if (use_hpet_alarm()) {
|
||||||
|
/*
|
||||||
|
* FIXME the HPET alarm glue currently ignores day_alrm
|
||||||
* and mon_alrm ...
|
* and mon_alrm ...
|
||||||
*/
|
*/
|
||||||
hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min, t->time.tm_sec);
|
hpet_set_alarm_time(t->time.tm_hour, t->time.tm_min,
|
||||||
|
t->time.tm_sec);
|
||||||
|
}
|
||||||
|
|
||||||
if (t->enabled)
|
if (t->enabled)
|
||||||
cmos_irq_enable(cmos, RTC_AIE);
|
cmos_irq_enable(cmos, RTC_AIE);
|
||||||
@@ -508,7 +543,7 @@ static int cmos_procfs(struct device *dev, struct seq_file *seq)
|
|||||||
"batt_status\t: %s\n",
|
"batt_status\t: %s\n",
|
||||||
(rtc_control & RTC_PIE) ? "yes" : "no",
|
(rtc_control & RTC_PIE) ? "yes" : "no",
|
||||||
(rtc_control & RTC_UIE) ? "yes" : "no",
|
(rtc_control & RTC_UIE) ? "yes" : "no",
|
||||||
is_hpet_enabled() ? "yes" : "no",
|
use_hpet_alarm() ? "yes" : "no",
|
||||||
// (rtc_control & RTC_SQWE) ? "yes" : "no",
|
// (rtc_control & RTC_SQWE) ? "yes" : "no",
|
||||||
(rtc_control & RTC_DM_BINARY) ? "no" : "yes",
|
(rtc_control & RTC_DM_BINARY) ? "no" : "yes",
|
||||||
(rtc_control & RTC_DST_EN) ? "yes" : "no",
|
(rtc_control & RTC_DST_EN) ? "yes" : "no",
|
||||||
@@ -614,7 +649,7 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
|
|||||||
*/
|
*/
|
||||||
irqstat = CMOS_READ(RTC_INTR_FLAGS);
|
irqstat = CMOS_READ(RTC_INTR_FLAGS);
|
||||||
rtc_control = CMOS_READ(RTC_CONTROL);
|
rtc_control = CMOS_READ(RTC_CONTROL);
|
||||||
if (is_hpet_enabled())
|
if (use_hpet_alarm())
|
||||||
irqstat = (unsigned long)irq & 0xF0;
|
irqstat = (unsigned long)irq & 0xF0;
|
||||||
|
|
||||||
/* If we were suspended, RTC_CONTROL may not be accurate since the
|
/* If we were suspended, RTC_CONTROL may not be accurate since the
|
||||||
@@ -633,6 +668,7 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
|
|||||||
cmos_rtc.suspend_ctrl &= ~RTC_AIE;
|
cmos_rtc.suspend_ctrl &= ~RTC_AIE;
|
||||||
rtc_control &= ~RTC_AIE;
|
rtc_control &= ~RTC_AIE;
|
||||||
CMOS_WRITE(rtc_control, RTC_CONTROL);
|
CMOS_WRITE(rtc_control, RTC_CONTROL);
|
||||||
|
if (use_hpet_alarm())
|
||||||
hpet_mask_rtc_irq_bit(RTC_AIE);
|
hpet_mask_rtc_irq_bit(RTC_AIE);
|
||||||
CMOS_READ(RTC_INTR_FLAGS);
|
CMOS_READ(RTC_INTR_FLAGS);
|
||||||
}
|
}
|
||||||
@@ -762,6 +798,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
|||||||
* need to do something about other clock frequencies.
|
* need to do something about other clock frequencies.
|
||||||
*/
|
*/
|
||||||
cmos_rtc.rtc->irq_freq = 1024;
|
cmos_rtc.rtc->irq_freq = 1024;
|
||||||
|
if (use_hpet_alarm())
|
||||||
hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq);
|
hpet_set_periodic_freq(cmos_rtc.rtc->irq_freq);
|
||||||
CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
|
CMOS_WRITE(RTC_REF_CLCK_32KHZ | 0x06, RTC_FREQ_SELECT);
|
||||||
}
|
}
|
||||||
@@ -780,12 +817,13 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
|||||||
goto cleanup1;
|
goto cleanup1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (use_hpet_alarm())
|
||||||
hpet_rtc_timer_init();
|
hpet_rtc_timer_init();
|
||||||
|
|
||||||
if (is_valid_irq(rtc_irq)) {
|
if (is_valid_irq(rtc_irq)) {
|
||||||
irq_handler_t rtc_cmos_int_handler;
|
irq_handler_t rtc_cmos_int_handler;
|
||||||
|
|
||||||
if (is_hpet_enabled()) {
|
if (use_hpet_alarm()) {
|
||||||
rtc_cmos_int_handler = hpet_rtc_interrupt;
|
rtc_cmos_int_handler = hpet_rtc_interrupt;
|
||||||
retval = hpet_register_irq_handler(cmos_interrupt);
|
retval = hpet_register_irq_handler(cmos_interrupt);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
@@ -824,7 +862,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
|||||||
"alarms up to one day",
|
"alarms up to one day",
|
||||||
cmos_rtc.century ? ", y3k" : "",
|
cmos_rtc.century ? ", y3k" : "",
|
||||||
nvmem_cfg.size,
|
nvmem_cfg.size,
|
||||||
is_hpet_enabled() ? ", hpet irqs" : "");
|
use_hpet_alarm() ? ", hpet irqs" : "");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -858,6 +896,7 @@ static void cmos_do_remove(struct device *dev)
|
|||||||
|
|
||||||
if (is_valid_irq(cmos->irq)) {
|
if (is_valid_irq(cmos->irq)) {
|
||||||
free_irq(cmos->irq, cmos->rtc);
|
free_irq(cmos->irq, cmos->rtc);
|
||||||
|
if (use_hpet_alarm())
|
||||||
hpet_unregister_irq_handler(cmos_interrupt);
|
hpet_unregister_irq_handler(cmos_interrupt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -935,13 +974,13 @@ static int cmos_suspend(struct device *dev)
|
|||||||
mask = RTC_IRQMASK;
|
mask = RTC_IRQMASK;
|
||||||
tmp &= ~mask;
|
tmp &= ~mask;
|
||||||
CMOS_WRITE(tmp, RTC_CONTROL);
|
CMOS_WRITE(tmp, RTC_CONTROL);
|
||||||
|
if (use_hpet_alarm())
|
||||||
hpet_mask_rtc_irq_bit(mask);
|
hpet_mask_rtc_irq_bit(mask);
|
||||||
|
|
||||||
cmos_checkintr(cmos, tmp);
|
cmos_checkintr(cmos, tmp);
|
||||||
}
|
}
|
||||||
spin_unlock_irq(&rtc_lock);
|
spin_unlock_irq(&rtc_lock);
|
||||||
|
|
||||||
if (tmp & RTC_AIE) {
|
if ((tmp & RTC_AIE) && !use_acpi_alarm) {
|
||||||
cmos->enabled_wake = 1;
|
cmos->enabled_wake = 1;
|
||||||
if (cmos->wake_on)
|
if (cmos->wake_on)
|
||||||
cmos->wake_on(dev);
|
cmos->wake_on(dev);
|
||||||
@@ -976,8 +1015,26 @@ static void cmos_check_wkalrm(struct device *dev)
|
|||||||
{
|
{
|
||||||
struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
||||||
struct rtc_wkalrm current_alarm;
|
struct rtc_wkalrm current_alarm;
|
||||||
|
time64_t t_now;
|
||||||
time64_t t_current_expires;
|
time64_t t_current_expires;
|
||||||
time64_t t_saved_expires;
|
time64_t t_saved_expires;
|
||||||
|
struct rtc_time now;
|
||||||
|
|
||||||
|
/* Check if we have RTC Alarm armed */
|
||||||
|
if (!(cmos->suspend_ctrl & RTC_AIE))
|
||||||
|
return;
|
||||||
|
|
||||||
|
cmos_read_time(dev, &now);
|
||||||
|
t_now = rtc_tm_to_time64(&now);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ACPI RTC wake event is cleared after resume from STR,
|
||||||
|
* ACK the rtc irq here
|
||||||
|
*/
|
||||||
|
if (t_now >= cmos->alarm_expires && use_acpi_alarm) {
|
||||||
|
cmos_interrupt(0, (void *)cmos->rtc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
cmos_read_alarm(dev, ¤t_alarm);
|
cmos_read_alarm(dev, ¤t_alarm);
|
||||||
t_current_expires = rtc_tm_to_time64(¤t_alarm.time);
|
t_current_expires = rtc_tm_to_time64(¤t_alarm.time);
|
||||||
@@ -996,7 +1053,7 @@ static int __maybe_unused cmos_resume(struct device *dev)
|
|||||||
struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
||||||
unsigned char tmp;
|
unsigned char tmp;
|
||||||
|
|
||||||
if (cmos->enabled_wake) {
|
if (cmos->enabled_wake && !use_acpi_alarm) {
|
||||||
if (cmos->wake_off)
|
if (cmos->wake_off)
|
||||||
cmos->wake_off(dev);
|
cmos->wake_off(dev);
|
||||||
else
|
else
|
||||||
@@ -1014,16 +1071,17 @@ static int __maybe_unused cmos_resume(struct device *dev)
|
|||||||
if (tmp & RTC_IRQMASK) {
|
if (tmp & RTC_IRQMASK) {
|
||||||
unsigned char mask;
|
unsigned char mask;
|
||||||
|
|
||||||
if (device_may_wakeup(dev))
|
if (device_may_wakeup(dev) && use_hpet_alarm())
|
||||||
hpet_rtc_timer_init();
|
hpet_rtc_timer_init();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
CMOS_WRITE(tmp, RTC_CONTROL);
|
CMOS_WRITE(tmp, RTC_CONTROL);
|
||||||
|
if (use_hpet_alarm())
|
||||||
hpet_set_rtc_irq_bit(tmp & RTC_IRQMASK);
|
hpet_set_rtc_irq_bit(tmp & RTC_IRQMASK);
|
||||||
|
|
||||||
mask = CMOS_READ(RTC_INTR_FLAGS);
|
mask = CMOS_READ(RTC_INTR_FLAGS);
|
||||||
mask &= (tmp & RTC_IRQMASK) | RTC_IRQF;
|
mask &= (tmp & RTC_IRQMASK) | RTC_IRQF;
|
||||||
if (!is_hpet_enabled() || !is_intr(mask))
|
if (!use_hpet_alarm() || !is_intr(mask))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* force one-shot behavior if HPET blocked
|
/* force one-shot behavior if HPET blocked
|
||||||
@@ -1068,6 +1126,16 @@ static u32 rtc_handler(void *context)
|
|||||||
unsigned char rtc_intr;
|
unsigned char rtc_intr;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Always update rtc irq when ACPI is used as RTC Alarm.
|
||||||
|
* Or else, ACPI SCI is enabled during suspend/resume only,
|
||||||
|
* update rtc irq in that case.
|
||||||
|
*/
|
||||||
|
if (use_acpi_alarm)
|
||||||
|
cmos_interrupt(0, (void *)cmos->rtc);
|
||||||
|
else {
|
||||||
|
/* Fix me: can we use cmos_interrupt() here as well? */
|
||||||
spin_lock_irqsave(&rtc_lock, flags);
|
spin_lock_irqsave(&rtc_lock, flags);
|
||||||
if (cmos_rtc.suspend_ctrl)
|
if (cmos_rtc.suspend_ctrl)
|
||||||
rtc_control = CMOS_READ(RTC_CONTROL);
|
rtc_control = CMOS_READ(RTC_CONTROL);
|
||||||
@@ -1078,6 +1146,7 @@ static u32 rtc_handler(void *context)
|
|||||||
rtc_update_irq(cmos->rtc, 1, rtc_intr);
|
rtc_update_irq(cmos->rtc, 1, rtc_intr);
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&rtc_lock, flags);
|
spin_unlock_irqrestore(&rtc_lock, flags);
|
||||||
|
}
|
||||||
|
|
||||||
pm_wakeup_hard_event(dev);
|
pm_wakeup_hard_event(dev);
|
||||||
acpi_clear_event(ACPI_EVENT_RTC);
|
acpi_clear_event(ACPI_EVENT_RTC);
|
||||||
@@ -1107,6 +1176,28 @@ static void rtc_wake_off(struct device *dev)
|
|||||||
acpi_disable_event(ACPI_EVENT_RTC, 0);
|
acpi_disable_event(ACPI_EVENT_RTC, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_X86
|
||||||
|
/* Enable use_acpi_alarm mode for Intel platforms no earlier than 2015 */
|
||||||
|
static void use_acpi_alarm_quirks(void)
|
||||||
|
{
|
||||||
|
int year;
|
||||||
|
|
||||||
|
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!is_hpet_enabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (dmi_get_date(DMI_BIOS_DATE, &year, NULL, NULL) && year >= 2015)
|
||||||
|
use_acpi_alarm = true;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline void use_acpi_alarm_quirks(void) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find
|
/* Every ACPI platform has a mc146818 compatible "cmos rtc". Here we find
|
||||||
* its device node and pass extra config data. This helps its driver use
|
* its device node and pass extra config data. This helps its driver use
|
||||||
* capabilities that the now-obsolete mc146818 didn't have, and informs it
|
* capabilities that the now-obsolete mc146818 didn't have, and informs it
|
||||||
@@ -1119,6 +1210,8 @@ static void cmos_wake_setup(struct device *dev)
|
|||||||
if (acpi_disabled)
|
if (acpi_disabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
use_acpi_alarm_quirks();
|
||||||
|
|
||||||
rtc_wake_setup(dev);
|
rtc_wake_setup(dev);
|
||||||
acpi_rtc_info.wake_on = rtc_wake_on;
|
acpi_rtc_info.wake_on = rtc_wake_on;
|
||||||
acpi_rtc_info.wake_off = rtc_wake_off;
|
acpi_rtc_info.wake_off = rtc_wake_off;
|
||||||
|
|||||||
@@ -1,19 +1,8 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
* RTC driver for Chrome OS Embedded Controller
|
// RTC driver for ChromeOS Embedded Controller.
|
||||||
*
|
//
|
||||||
* Copyright (c) 2017, Google, Inc
|
// Copyright (C) 2017 Google, Inc.
|
||||||
*
|
// Author: Stephen Barber <smbarber@chromium.org>
|
||||||
* Author: Stephen Barber <smbarber@chromium.org>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms and conditions of the GNU General Public License,
|
|
||||||
* version 2, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/mfd/cros_ec.h>
|
#include <linux/mfd/cros_ec.h>
|
||||||
@@ -409,5 +398,5 @@ module_platform_driver(cros_ec_rtc_driver);
|
|||||||
|
|
||||||
MODULE_DESCRIPTION("RTC driver for Chrome OS ECs");
|
MODULE_DESCRIPTION("RTC driver for Chrome OS ECs");
|
||||||
MODULE_AUTHOR("Stephen Barber <smbarber@chromium.org>");
|
MODULE_AUTHOR("Stephen Barber <smbarber@chromium.org>");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL v2");
|
||||||
MODULE_ALIAS("platform:" DRV_NAME);
|
MODULE_ALIAS("platform:" DRV_NAME);
|
||||||
|
|||||||
@@ -76,8 +76,7 @@ static void ds1216_switch_ds_to_clock(u8 __iomem *ioaddr)
|
|||||||
|
|
||||||
static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct ds1216_priv *priv = dev_get_drvdata(dev);
|
||||||
struct ds1216_priv *priv = platform_get_drvdata(pdev);
|
|
||||||
struct ds1216_regs regs;
|
struct ds1216_regs regs;
|
||||||
|
|
||||||
ds1216_switch_ds_to_clock(priv->ioaddr);
|
ds1216_switch_ds_to_clock(priv->ioaddr);
|
||||||
@@ -104,8 +103,7 @@ static int ds1216_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||||||
|
|
||||||
static int ds1216_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
static int ds1216_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct ds1216_priv *priv = dev_get_drvdata(dev);
|
||||||
struct ds1216_priv *priv = platform_get_drvdata(pdev);
|
|
||||||
struct ds1216_regs regs;
|
struct ds1216_regs regs;
|
||||||
|
|
||||||
ds1216_switch_ds_to_clock(priv->ioaddr);
|
ds1216_switch_ds_to_clock(priv->ioaddr);
|
||||||
|
|||||||
@@ -201,6 +201,7 @@ static const struct chip_desc chips[last_ds_type] = {
|
|||||||
.century_reg = DS1307_REG_HOUR,
|
.century_reg = DS1307_REG_HOUR,
|
||||||
.century_enable_bit = DS1340_BIT_CENTURY_EN,
|
.century_enable_bit = DS1340_BIT_CENTURY_EN,
|
||||||
.century_bit = DS1340_BIT_CENTURY,
|
.century_bit = DS1340_BIT_CENTURY,
|
||||||
|
.do_trickle_setup = &do_trickle_setup_ds1339,
|
||||||
.trickle_charger_reg = 0x08,
|
.trickle_charger_reg = 0x08,
|
||||||
},
|
},
|
||||||
[ds_1341] = {
|
[ds_1341] = {
|
||||||
@@ -1371,6 +1372,7 @@ static void ds1307_clks_register(struct ds1307 *ds1307)
|
|||||||
static const struct regmap_config regmap_config = {
|
static const struct regmap_config regmap_config = {
|
||||||
.reg_bits = 8,
|
.reg_bits = 8,
|
||||||
.val_bits = 8,
|
.val_bits = 8,
|
||||||
|
.max_register = 0x9,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ds1307_probe(struct i2c_client *client,
|
static int ds1307_probe(struct i2c_client *client,
|
||||||
|
|||||||
@@ -314,8 +314,7 @@ ds1511_rtc_update_alarm(struct rtc_plat_data *pdata)
|
|||||||
static int
|
static int
|
||||||
ds1511_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
ds1511_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct rtc_plat_data *pdata = dev_get_drvdata(dev);
|
||||||
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
|
|
||||||
|
|
||||||
if (pdata->irq <= 0)
|
if (pdata->irq <= 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -334,8 +333,7 @@ ds1511_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|||||||
static int
|
static int
|
||||||
ds1511_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
ds1511_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct rtc_plat_data *pdata = dev_get_drvdata(dev);
|
||||||
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
|
|
||||||
|
|
||||||
if (pdata->irq <= 0)
|
if (pdata->irq <= 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -373,8 +371,7 @@ ds1511_interrupt(int irq, void *dev_id)
|
|||||||
|
|
||||||
static int ds1511_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
static int ds1511_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct rtc_plat_data *pdata = dev_get_drvdata(dev);
|
||||||
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
|
|
||||||
|
|
||||||
if (pdata->irq <= 0)
|
if (pdata->irq <= 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|||||||
@@ -73,8 +73,7 @@ struct rtc_plat_data {
|
|||||||
|
|
||||||
static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct rtc_plat_data *pdata = dev_get_drvdata(dev);
|
||||||
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
|
|
||||||
void __iomem *ioaddr = pdata->ioaddr;
|
void __iomem *ioaddr = pdata->ioaddr;
|
||||||
u8 century;
|
u8 century;
|
||||||
|
|
||||||
@@ -98,8 +97,7 @@ static int ds1553_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
|||||||
|
|
||||||
static int ds1553_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
static int ds1553_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct rtc_plat_data *pdata = dev_get_drvdata(dev);
|
||||||
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
|
|
||||||
void __iomem *ioaddr = pdata->ioaddr;
|
void __iomem *ioaddr = pdata->ioaddr;
|
||||||
unsigned int year, month, day, hour, minute, second, week;
|
unsigned int year, month, day, hour, minute, second, week;
|
||||||
unsigned int century;
|
unsigned int century;
|
||||||
@@ -155,8 +153,7 @@ static void ds1553_rtc_update_alarm(struct rtc_plat_data *pdata)
|
|||||||
|
|
||||||
static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct rtc_plat_data *pdata = dev_get_drvdata(dev);
|
||||||
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
|
|
||||||
|
|
||||||
if (pdata->irq <= 0)
|
if (pdata->irq <= 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -172,8 +169,7 @@ static int ds1553_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|||||||
|
|
||||||
static int ds1553_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
static int ds1553_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct rtc_plat_data *pdata = dev_get_drvdata(dev);
|
||||||
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
|
|
||||||
|
|
||||||
if (pdata->irq <= 0)
|
if (pdata->irq <= 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -208,8 +204,7 @@ static irqreturn_t ds1553_rtc_interrupt(int irq, void *dev_id)
|
|||||||
|
|
||||||
static int ds1553_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
static int ds1553_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct rtc_plat_data *pdata = dev_get_drvdata(dev);
|
||||||
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
|
|
||||||
|
|
||||||
if (pdata->irq <= 0)
|
if (pdata->irq <= 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|||||||
+29
-37
@@ -267,8 +267,7 @@ ds1685_rtc_get_ssn(struct ds1685_priv *rtc, u8 *ssn)
|
|||||||
static int
|
static int
|
||||||
ds1685_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
ds1685_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct ds1685_priv *rtc = dev_get_drvdata(dev);
|
||||||
struct ds1685_priv *rtc = platform_get_drvdata(pdev);
|
|
||||||
u8 ctrlb, century;
|
u8 ctrlb, century;
|
||||||
u8 seconds, minutes, hours, wday, mday, month, years;
|
u8 seconds, minutes, hours, wday, mday, month, years;
|
||||||
|
|
||||||
@@ -317,8 +316,7 @@ ds1685_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||||||
static int
|
static int
|
||||||
ds1685_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
ds1685_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct ds1685_priv *rtc = dev_get_drvdata(dev);
|
||||||
struct ds1685_priv *rtc = platform_get_drvdata(pdev);
|
|
||||||
u8 ctrlb, seconds, minutes, hours, wday, mday, month, years, century;
|
u8 ctrlb, seconds, minutes, hours, wday, mday, month, years, century;
|
||||||
|
|
||||||
/* Fetch the time info from rtc_time. */
|
/* Fetch the time info from rtc_time. */
|
||||||
@@ -394,8 +392,7 @@ ds1685_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
|||||||
static int
|
static int
|
||||||
ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct ds1685_priv *rtc = dev_get_drvdata(dev);
|
||||||
struct ds1685_priv *rtc = platform_get_drvdata(pdev);
|
|
||||||
u8 seconds, minutes, hours, mday, ctrlb, ctrlc;
|
u8 seconds, minutes, hours, mday, ctrlb, ctrlc;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -453,8 +450,7 @@ ds1685_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|||||||
static int
|
static int
|
||||||
ds1685_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
ds1685_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct ds1685_priv *rtc = dev_get_drvdata(dev);
|
||||||
struct ds1685_priv *rtc = platform_get_drvdata(pdev);
|
|
||||||
u8 ctrlb, seconds, minutes, hours, mday;
|
u8 ctrlb, seconds, minutes, hours, mday;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -1119,8 +1115,7 @@ static ssize_t
|
|||||||
ds1685_rtc_sysfs_battery_show(struct device *dev,
|
ds1685_rtc_sysfs_battery_show(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct ds1685_priv *rtc = dev_get_drvdata(dev);
|
||||||
struct ds1685_priv *rtc = platform_get_drvdata(pdev);
|
|
||||||
u8 ctrld;
|
u8 ctrld;
|
||||||
|
|
||||||
ctrld = rtc->read(rtc, RTC_CTRL_D);
|
ctrld = rtc->read(rtc, RTC_CTRL_D);
|
||||||
@@ -1140,8 +1135,7 @@ static ssize_t
|
|||||||
ds1685_rtc_sysfs_auxbatt_show(struct device *dev,
|
ds1685_rtc_sysfs_auxbatt_show(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct ds1685_priv *rtc = dev_get_drvdata(dev);
|
||||||
struct ds1685_priv *rtc = platform_get_drvdata(pdev);
|
|
||||||
u8 ctrl4a;
|
u8 ctrl4a;
|
||||||
|
|
||||||
ds1685_rtc_switch_to_bank1(rtc);
|
ds1685_rtc_switch_to_bank1(rtc);
|
||||||
@@ -1163,8 +1157,7 @@ static ssize_t
|
|||||||
ds1685_rtc_sysfs_serial_show(struct device *dev,
|
ds1685_rtc_sysfs_serial_show(struct device *dev,
|
||||||
struct device_attribute *attr, char *buf)
|
struct device_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct ds1685_priv *rtc = dev_get_drvdata(dev);
|
||||||
struct ds1685_priv *rtc = platform_get_drvdata(pdev);
|
|
||||||
u8 ssn[8];
|
u8 ssn[8];
|
||||||
|
|
||||||
ds1685_rtc_switch_to_bank1(rtc);
|
ds1685_rtc_switch_to_bank1(rtc);
|
||||||
@@ -2044,6 +2037,26 @@ ds1685_rtc_probe(struct platform_device *pdev)
|
|||||||
rtc->write(rtc, RTC_EXT_CTRL_4B,
|
rtc->write(rtc, RTC_EXT_CTRL_4B,
|
||||||
(rtc->read(rtc, RTC_EXT_CTRL_4B) | RTC_CTRL_4B_KSE));
|
(rtc->read(rtc, RTC_EXT_CTRL_4B) | RTC_CTRL_4B_KSE));
|
||||||
|
|
||||||
|
rtc_dev = devm_rtc_allocate_device(&pdev->dev);
|
||||||
|
if (IS_ERR(rtc_dev))
|
||||||
|
return PTR_ERR(rtc_dev);
|
||||||
|
|
||||||
|
rtc_dev->ops = &ds1685_rtc_ops;
|
||||||
|
|
||||||
|
/* Century bit is useless because leap year fails in 1900 and 2100 */
|
||||||
|
rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||||
|
rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
|
||||||
|
|
||||||
|
/* Maximum periodic rate is 8192Hz (0.122070ms). */
|
||||||
|
rtc_dev->max_user_freq = RTC_MAX_USER_FREQ;
|
||||||
|
|
||||||
|
/* See if the platform doesn't support UIE. */
|
||||||
|
if (pdata->uie_unsupported)
|
||||||
|
rtc_dev->uie_unsupported = 1;
|
||||||
|
rtc->uie_unsupported = pdata->uie_unsupported;
|
||||||
|
|
||||||
|
rtc->dev = rtc_dev;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fetch the IRQ and setup the interrupt handler.
|
* Fetch the IRQ and setup the interrupt handler.
|
||||||
*
|
*
|
||||||
@@ -2076,32 +2089,13 @@ ds1685_rtc_probe(struct platform_device *pdev)
|
|||||||
/* Setup complete. */
|
/* Setup complete. */
|
||||||
ds1685_rtc_switch_to_bank0(rtc);
|
ds1685_rtc_switch_to_bank0(rtc);
|
||||||
|
|
||||||
/* Register the device as an RTC. */
|
|
||||||
rtc_dev = rtc_device_register(pdev->name, &pdev->dev,
|
|
||||||
&ds1685_rtc_ops, THIS_MODULE);
|
|
||||||
|
|
||||||
/* Success? */
|
|
||||||
if (IS_ERR(rtc_dev))
|
|
||||||
return PTR_ERR(rtc_dev);
|
|
||||||
|
|
||||||
/* Maximum periodic rate is 8192Hz (0.122070ms). */
|
|
||||||
rtc_dev->max_user_freq = RTC_MAX_USER_FREQ;
|
|
||||||
|
|
||||||
/* See if the platform doesn't support UIE. */
|
|
||||||
if (pdata->uie_unsupported)
|
|
||||||
rtc_dev->uie_unsupported = 1;
|
|
||||||
rtc->uie_unsupported = pdata->uie_unsupported;
|
|
||||||
|
|
||||||
rtc->dev = rtc_dev;
|
|
||||||
|
|
||||||
#ifdef CONFIG_SYSFS
|
#ifdef CONFIG_SYSFS
|
||||||
ret = ds1685_rtc_sysfs_register(&pdev->dev);
|
ret = ds1685_rtc_sysfs_register(&pdev->dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
rtc_device_unregister(rtc->dev);
|
return ret;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Done! */
|
return rtc_register_device(rtc_dev);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2117,8 +2111,6 @@ ds1685_rtc_remove(struct platform_device *pdev)
|
|||||||
ds1685_rtc_sysfs_unregister(&pdev->dev);
|
ds1685_rtc_sysfs_unregister(&pdev->dev);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rtc_device_unregister(rtc->dev);
|
|
||||||
|
|
||||||
/* Read Ctrl B and clear PIE/AIE/UIE. */
|
/* Read Ctrl B and clear PIE/AIE/UIE. */
|
||||||
rtc->write(rtc, RTC_CTRL_B,
|
rtc->write(rtc, RTC_CTRL_B,
|
||||||
(rtc->read(rtc, RTC_CTRL_B) &
|
(rtc->read(rtc, RTC_CTRL_B) &
|
||||||
|
|||||||
@@ -58,8 +58,7 @@ struct rtc_plat_data {
|
|||||||
|
|
||||||
static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct rtc_plat_data *pdata = dev_get_drvdata(dev);
|
||||||
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
|
|
||||||
void __iomem *ioaddr = pdata->ioaddr_rtc;
|
void __iomem *ioaddr = pdata->ioaddr_rtc;
|
||||||
u8 century;
|
u8 century;
|
||||||
|
|
||||||
@@ -83,8 +82,7 @@ static int ds1742_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
|||||||
|
|
||||||
static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
static int ds1742_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct rtc_plat_data *pdata = dev_get_drvdata(dev);
|
||||||
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
|
|
||||||
void __iomem *ioaddr = pdata->ioaddr_rtc;
|
void __iomem *ioaddr = pdata->ioaddr_rtc;
|
||||||
unsigned int year, month, day, hour, minute, second, week;
|
unsigned int year, month, day, hour, minute, second, week;
|
||||||
unsigned int century;
|
unsigned int century;
|
||||||
@@ -154,8 +152,6 @@ static int ds1742_rtc_probe(struct platform_device *pdev)
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct nvmem_config nvmem_cfg = {
|
struct nvmem_config nvmem_cfg = {
|
||||||
.name = "ds1742_nvram",
|
.name = "ds1742_nvram",
|
||||||
.word_size = 1,
|
|
||||||
.stride = 1,
|
|
||||||
.reg_read = ds1742_nvram_read,
|
.reg_read = ds1742_nvram_read,
|
||||||
.reg_write = ds1742_nvram_write,
|
.reg_write = ds1742_nvram_write,
|
||||||
};
|
};
|
||||||
|
|||||||
+23
-13
@@ -73,8 +73,8 @@ static int ftrtc010_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||||||
{
|
{
|
||||||
struct ftrtc010_rtc *rtc = dev_get_drvdata(dev);
|
struct ftrtc010_rtc *rtc = dev_get_drvdata(dev);
|
||||||
|
|
||||||
unsigned int days, hour, min, sec;
|
u32 days, hour, min, sec, offset;
|
||||||
unsigned long offset, time;
|
timeu64_t time;
|
||||||
|
|
||||||
sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND);
|
sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND);
|
||||||
min = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE);
|
min = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE);
|
||||||
@@ -84,7 +84,7 @@ static int ftrtc010_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||||||
|
|
||||||
time = offset + days * 86400 + hour * 3600 + min * 60 + sec;
|
time = offset + days * 86400 + hour * 3600 + min * 60 + sec;
|
||||||
|
|
||||||
rtc_time_to_tm(time, tm);
|
rtc_time64_to_tm(time, tm);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -92,13 +92,10 @@ static int ftrtc010_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||||||
static int ftrtc010_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
static int ftrtc010_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
{
|
{
|
||||||
struct ftrtc010_rtc *rtc = dev_get_drvdata(dev);
|
struct ftrtc010_rtc *rtc = dev_get_drvdata(dev);
|
||||||
unsigned int sec, min, hour, day;
|
u32 sec, min, hour, day, offset;
|
||||||
unsigned long offset, time;
|
timeu64_t time;
|
||||||
|
|
||||||
if (tm->tm_year >= 2148) /* EPOCH Year + 179 */
|
time = rtc_tm_to_time64(tm);
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
rtc_tm_to_time(tm, &time);
|
|
||||||
|
|
||||||
sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND);
|
sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND);
|
||||||
min = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE);
|
min = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE);
|
||||||
@@ -120,6 +117,7 @@ static const struct rtc_class_ops ftrtc010_rtc_ops = {
|
|||||||
|
|
||||||
static int ftrtc010_rtc_probe(struct platform_device *pdev)
|
static int ftrtc010_rtc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
u32 days, hour, min, sec;
|
||||||
struct ftrtc010_rtc *rtc;
|
struct ftrtc010_rtc *rtc;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct resource *res;
|
struct resource *res;
|
||||||
@@ -166,14 +164,27 @@ static int ftrtc010_rtc_probe(struct platform_device *pdev)
|
|||||||
if (!rtc->rtc_base)
|
if (!rtc->rtc_base)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
rtc->rtc_dev = devm_rtc_allocate_device(dev);
|
||||||
|
if (IS_ERR(rtc->rtc_dev))
|
||||||
|
return PTR_ERR(rtc->rtc_dev);
|
||||||
|
|
||||||
|
rtc->rtc_dev->ops = &ftrtc010_rtc_ops;
|
||||||
|
|
||||||
|
sec = readl(rtc->rtc_base + FTRTC010_RTC_SECOND);
|
||||||
|
min = readl(rtc->rtc_base + FTRTC010_RTC_MINUTE);
|
||||||
|
hour = readl(rtc->rtc_base + FTRTC010_RTC_HOUR);
|
||||||
|
days = readl(rtc->rtc_base + FTRTC010_RTC_DAYS);
|
||||||
|
|
||||||
|
rtc->rtc_dev->range_min = (u64)days * 86400 + hour * 3600 +
|
||||||
|
min * 60 + sec;
|
||||||
|
rtc->rtc_dev->range_max = U32_MAX + rtc->rtc_dev->range_min;
|
||||||
|
|
||||||
ret = devm_request_irq(dev, rtc->rtc_irq, ftrtc010_rtc_interrupt,
|
ret = devm_request_irq(dev, rtc->rtc_irq, ftrtc010_rtc_interrupt,
|
||||||
IRQF_SHARED, pdev->name, dev);
|
IRQF_SHARED, pdev->name, dev);
|
||||||
if (unlikely(ret))
|
if (unlikely(ret))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
rtc->rtc_dev = rtc_device_register(pdev->name, dev,
|
return rtc_register_device(rtc->rtc_dev);
|
||||||
&ftrtc010_rtc_ops, THIS_MODULE);
|
|
||||||
return PTR_ERR_OR_ZERO(rtc->rtc_dev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ftrtc010_rtc_remove(struct platform_device *pdev)
|
static int ftrtc010_rtc_remove(struct platform_device *pdev)
|
||||||
@@ -184,7 +195,6 @@ static int ftrtc010_rtc_remove(struct platform_device *pdev)
|
|||||||
clk_disable_unprepare(rtc->extclk);
|
clk_disable_unprepare(rtc->extclk);
|
||||||
if (!IS_ERR(rtc->pclk))
|
if (!IS_ERR(rtc->pclk))
|
||||||
clk_disable_unprepare(rtc->pclk);
|
clk_disable_unprepare(rtc->pclk);
|
||||||
rtc_device_unregister(rtc->rtc_dev);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -294,11 +294,10 @@ static int lpc32xx_rtc_remove(struct platform_device *pdev)
|
|||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
static int lpc32xx_rtc_suspend(struct device *dev)
|
static int lpc32xx_rtc_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
|
||||||
struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev);
|
|
||||||
|
|
||||||
if (rtc->irq >= 0) {
|
if (rtc->irq >= 0) {
|
||||||
if (device_may_wakeup(&pdev->dev))
|
if (device_may_wakeup(dev))
|
||||||
enable_irq_wake(rtc->irq);
|
enable_irq_wake(rtc->irq);
|
||||||
else
|
else
|
||||||
disable_irq_wake(rtc->irq);
|
disable_irq_wake(rtc->irq);
|
||||||
@@ -309,10 +308,9 @@ static int lpc32xx_rtc_suspend(struct device *dev)
|
|||||||
|
|
||||||
static int lpc32xx_rtc_resume(struct device *dev)
|
static int lpc32xx_rtc_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
|
||||||
struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev);
|
|
||||||
|
|
||||||
if (rtc->irq >= 0 && device_may_wakeup(&pdev->dev))
|
if (rtc->irq >= 0 && device_may_wakeup(dev))
|
||||||
disable_irq_wake(rtc->irq);
|
disable_irq_wake(rtc->irq);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -321,8 +319,7 @@ static int lpc32xx_rtc_resume(struct device *dev)
|
|||||||
/* Unconditionally disable the alarm */
|
/* Unconditionally disable the alarm */
|
||||||
static int lpc32xx_rtc_freeze(struct device *dev)
|
static int lpc32xx_rtc_freeze(struct device *dev)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
|
||||||
struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev);
|
|
||||||
|
|
||||||
spin_lock_irq(&rtc->lock);
|
spin_lock_irq(&rtc->lock);
|
||||||
|
|
||||||
@@ -337,8 +334,7 @@ static int lpc32xx_rtc_freeze(struct device *dev)
|
|||||||
|
|
||||||
static int lpc32xx_rtc_thaw(struct device *dev)
|
static int lpc32xx_rtc_thaw(struct device *dev)
|
||||||
{
|
{
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct lpc32xx_rtc *rtc = dev_get_drvdata(dev);
|
||||||
struct lpc32xx_rtc *rtc = platform_get_drvdata(pdev);
|
|
||||||
|
|
||||||
if (rtc->alarm_enabled) {
|
if (rtc->alarm_enabled) {
|
||||||
spin_lock_irq(&rtc->lock);
|
spin_lock_irq(&rtc->lock);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user