RTC for 5.8
Subsystem: - new VL flag for backup switch over Drivers: - ingenic: only support device tree - pcf2127: report battery switch over, handle nowayout -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEycoQi/giopmpPgB12wIijOdRNOUFAl7dWSkACgkQ2wIijOdR NOXGbQ//cSTxUJbuYBNi/VCV7J3/khGlyoQQqDsru/tzuEwXHGBoG2LRNQMOauWd 2Osg61VQj4IY+WCqp4+ivn5H0K26y1PPKkt+UmrlRgkl0eeDFWmY4ejpziZ85D7Z kDlzcUi3YWkd6m4YSJJrtdCcKljBMIEXb/PEKKK9y6dkrcG5990N8JchpmkCzrjx fTPVIOfxu43msDc5b8egUDzPYnNbFw3ERAeasr6/EGTz+ksCspXtvWDk/mJzum0G FiermTkO499Dr66Nf0AS3ex9SvEoqH+kd9KA1CKii5OlYEl7K9sI+eSmTQ1EutZO L5WAvvQdW8UkARo6R4HAobhwK27pL+wpzUljbyXxt940/RTeqp82kl7rnH+0ihU7 tTbR2Vu+uwWrfQbPkCCj0TJmqIHgam5/Vhn1+ZR2f4U2JIlPvvHoLRVKO0oP7XKK 1ZDcP8zc9V2LQ2G2M1/ec6eOmoGW3EZDnKp4hcv9mnEiePSvVn04t5sa83NjNs4R e+awVY1x5pFwoXu99gjlfQTV2kTyaA7Jywp6gIO7BKaw/Ci3+d3tlpowfsDH+UVI WwKxNNqmuNXqoIep0zqUhqXHNIizKxGEk8wE4mr8HP2SlGJ+lUHAyrTTdpLeinN1 5qTEPT3BhjExSFfDZQyWV3+CzKMvxtfFA4/Ca/0iSoaqzMZpm1E= =dsKr -----END PGP SIGNATURE----- Merge tag 'rtc-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux Pull RTC updates from Alexandre Belloni: "Not much this cycle apart from the ingenic rtc driver rework. The fixes are mainly minor issues reported by coccinelle rather than real world issues. Subsystem: - new VL flag for backup switch over Drivers: - ingenic: only support device tree - pcf2127: report battery switch over, handle nowayout" * tag 'rtc-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (29 commits) rtc: pcf2127: watchdog: handle nowayout feature rtc: fsl-ftm-alarm: fix freeze(s2idle) failed to wake rtc: abx80x: Provide debug feedback for invalid dt properties rtc: abx80x: Add Device Tree matching table rtc: rv3028: Add missed check for devm_regmap_init_i2c() rtc: mpc5121: Use correct return value for mpc5121_rtc_probe() rtc: goldfish: Use correct return value for goldfish_rtc_probe() rtc: snvs: Add necessary clock operations for RTC APIs rtc: snvs: Make SNVS clock always prepared rtc: ingenic: Reset regulator register in probe rtc: ingenic: Fix masking of error code rtc: ingenic: Remove unused fields from private structure rtc: ingenic: Set wakeup params in probe rtc: ingenic: Enable clock in probe rtc: ingenic: Use local 'dev' variable in probe rtc: ingenic: Only support probing from devicetree rtc: mc13xxx: fix a double-unlock issue rtc: stmp3xxx: update contact email rtc: max77686: Use single-byte writes on MAX77620 rtc: pcf2127: report battery switch over ...
This commit is contained in:
Коммит
e8dff03aef
|
@ -1680,6 +1680,7 @@ config RTC_DRV_MPC5121
|
||||||
config RTC_DRV_JZ4740
|
config RTC_DRV_JZ4740
|
||||||
tristate "Ingenic JZ4740 SoC"
|
tristate "Ingenic JZ4740 SoC"
|
||||||
depends on MIPS || COMPILE_TEST
|
depends on MIPS || COMPILE_TEST
|
||||||
|
depends on OF
|
||||||
help
|
help
|
||||||
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.
|
||||||
|
|
|
@ -106,12 +106,6 @@ static int pm860x_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
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, "Set time %d out of range. "
|
|
||||||
"Please set time between 1970 to 2106.\n",
|
|
||||||
1900 + tm->tm_year);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
ticks = rtc_tm_to_time64(tm);
|
ticks = rtc_tm_to_time64(tm);
|
||||||
|
|
||||||
/* load 32-bit read-only counter */
|
/* load 32-bit read-only counter */
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <linux/bcd.h>
|
#include <linux/bcd.h>
|
||||||
#include <linux/i2c.h>
|
#include <linux/i2c.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
#include <linux/rtc.h>
|
#include <linux/rtc.h>
|
||||||
#include <linux/watchdog.h>
|
#include <linux/watchdog.h>
|
||||||
|
|
||||||
|
@ -554,8 +555,9 @@ static const struct rtc_class_ops abx80x_rtc_ops = {
|
||||||
.ioctl = abx80x_ioctl,
|
.ioctl = abx80x_ioctl,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int abx80x_dt_trickle_cfg(struct device_node *np)
|
static int abx80x_dt_trickle_cfg(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
|
struct device_node *np = client->dev.of_node;
|
||||||
const char *diode;
|
const char *diode;
|
||||||
int trickle_cfg = 0;
|
int trickle_cfg = 0;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
@ -565,12 +567,14 @@ static int abx80x_dt_trickle_cfg(struct device_node *np)
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (!strcmp(diode, "standard"))
|
if (!strcmp(diode, "standard")) {
|
||||||
trickle_cfg |= ABX8XX_TRICKLE_STANDARD_DIODE;
|
trickle_cfg |= ABX8XX_TRICKLE_STANDARD_DIODE;
|
||||||
else if (!strcmp(diode, "schottky"))
|
} else if (!strcmp(diode, "schottky")) {
|
||||||
trickle_cfg |= ABX8XX_TRICKLE_SCHOTTKY_DIODE;
|
trickle_cfg |= ABX8XX_TRICKLE_SCHOTTKY_DIODE;
|
||||||
else
|
} else {
|
||||||
|
dev_dbg(&client->dev, "Invalid tc-diode value: %s\n", diode);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
ret = of_property_read_u32(np, "abracon,tc-resistor", &tmp);
|
ret = of_property_read_u32(np, "abracon,tc-resistor", &tmp);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -580,8 +584,10 @@ static int abx80x_dt_trickle_cfg(struct device_node *np)
|
||||||
if (trickle_resistors[i] == tmp)
|
if (trickle_resistors[i] == tmp)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (i == sizeof(trickle_resistors))
|
if (i == sizeof(trickle_resistors)) {
|
||||||
|
dev_dbg(&client->dev, "Invalid tc-resistor value: %u\n", tmp);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
return (trickle_cfg | i);
|
return (trickle_cfg | i);
|
||||||
}
|
}
|
||||||
|
@ -793,7 +799,7 @@ static int abx80x_probe(struct i2c_client *client,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (np && abx80x_caps[part].has_tc)
|
if (np && abx80x_caps[part].has_tc)
|
||||||
trickle_cfg = abx80x_dt_trickle_cfg(np);
|
trickle_cfg = abx80x_dt_trickle_cfg(client);
|
||||||
|
|
||||||
if (trickle_cfg > 0) {
|
if (trickle_cfg > 0) {
|
||||||
dev_info(&client->dev, "Enabling trickle charger: %02x\n",
|
dev_info(&client->dev, "Enabling trickle charger: %02x\n",
|
||||||
|
@ -863,9 +869,57 @@ static const struct i2c_device_id abx80x_id[] = {
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, abx80x_id);
|
MODULE_DEVICE_TABLE(i2c, abx80x_id);
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
|
static const struct of_device_id abx80x_of_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "abracon,abx80x",
|
||||||
|
.data = (void *)ABX80X
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "abracon,ab0801",
|
||||||
|
.data = (void *)AB0801
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "abracon,ab0803",
|
||||||
|
.data = (void *)AB0803
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "abracon,ab0804",
|
||||||
|
.data = (void *)AB0804
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "abracon,ab0805",
|
||||||
|
.data = (void *)AB0805
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "abracon,ab1801",
|
||||||
|
.data = (void *)AB1801
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "abracon,ab1803",
|
||||||
|
.data = (void *)AB1803
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "abracon,ab1804",
|
||||||
|
.data = (void *)AB1804
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "abracon,ab1805",
|
||||||
|
.data = (void *)AB1805
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "microcrystal,rv1805",
|
||||||
|
.data = (void *)RV1805
|
||||||
|
},
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, abx80x_of_match);
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct i2c_driver abx80x_driver = {
|
static struct i2c_driver abx80x_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "rtc-abx80x",
|
.name = "rtc-abx80x",
|
||||||
|
.of_match_table = of_match_ptr(abx80x_of_match),
|
||||||
},
|
},
|
||||||
.probe = abx80x_probe,
|
.probe = abx80x_probe,
|
||||||
.id_table = abx80x_id,
|
.id_table = abx80x_id,
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <linux/rtc.h>
|
#include <linux/rtc.h>
|
||||||
#include <linux/time.h>
|
#include <linux/time.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
|
#include <linux/pm_wakeirq.h>
|
||||||
|
|
||||||
#define FTM_SC_CLK(c) ((c) << FTM_SC_CLK_MASK_SHIFT)
|
#define FTM_SC_CLK(c) ((c) << FTM_SC_CLK_MASK_SHIFT)
|
||||||
|
|
||||||
|
@ -268,13 +269,11 @@ static int ftm_rtc_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0) {
|
if (irq < 0)
|
||||||
dev_err(&pdev->dev, "can't get irq number\n");
|
|
||||||
return irq;
|
return irq;
|
||||||
}
|
|
||||||
|
|
||||||
ret = devm_request_irq(&pdev->dev, irq, ftm_rtc_alarm_interrupt,
|
ret = devm_request_irq(&pdev->dev, irq, ftm_rtc_alarm_interrupt,
|
||||||
IRQF_NO_SUSPEND, dev_name(&pdev->dev), rtc);
|
0, dev_name(&pdev->dev), rtc);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(&pdev->dev, "failed to request irq\n");
|
dev_err(&pdev->dev, "failed to request irq\n");
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -287,6 +286,9 @@ static int ftm_rtc_probe(struct platform_device *pdev)
|
||||||
rtc->rtc_dev->ops = &ftm_rtc_ops;
|
rtc->rtc_dev->ops = &ftm_rtc_ops;
|
||||||
|
|
||||||
device_init_wakeup(&pdev->dev, true);
|
device_init_wakeup(&pdev->dev, true);
|
||||||
|
ret = dev_pm_set_wake_irq(&pdev->dev, irq);
|
||||||
|
if (ret)
|
||||||
|
dev_err(&pdev->dev, "failed to enable irq wake\n");
|
||||||
|
|
||||||
ret = rtc_register_device(rtc->rtc_dev);
|
ret = rtc_register_device(rtc->rtc_dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|
|
@ -174,7 +174,7 @@ static int goldfish_rtc_probe(struct platform_device *pdev)
|
||||||
platform_set_drvdata(pdev, rtcdrv);
|
platform_set_drvdata(pdev, rtcdrv);
|
||||||
rtcdrv->base = devm_platform_ioremap_resource(pdev, 0);
|
rtcdrv->base = devm_platform_ioremap_resource(pdev, 0);
|
||||||
if (IS_ERR(rtcdrv->base))
|
if (IS_ERR(rtcdrv->base))
|
||||||
return -ENODEV;
|
return PTR_ERR(rtcdrv->base);
|
||||||
|
|
||||||
rtcdrv->irq = platform_get_irq(pdev, 0);
|
rtcdrv->irq = platform_get_irq(pdev, 0);
|
||||||
if (rtcdrv->irq < 0)
|
if (rtcdrv->irq < 0)
|
||||||
|
|
|
@ -55,14 +55,8 @@ struct jz4740_rtc {
|
||||||
enum jz4740_rtc_type type;
|
enum jz4740_rtc_type type;
|
||||||
|
|
||||||
struct rtc_device *rtc;
|
struct rtc_device *rtc;
|
||||||
struct clk *clk;
|
|
||||||
|
|
||||||
int irq;
|
|
||||||
|
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
|
||||||
unsigned int min_wakeup_pin_assert_time;
|
|
||||||
unsigned int reset_pin_assert_time;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct device *dev_for_power_off;
|
static struct device *dev_for_power_off;
|
||||||
|
@ -259,44 +253,15 @@ static void jz4740_rtc_poweroff(struct device *dev)
|
||||||
|
|
||||||
static void jz4740_rtc_power_off(void)
|
static void jz4740_rtc_power_off(void)
|
||||||
{
|
{
|
||||||
struct jz4740_rtc *rtc = dev_get_drvdata(dev_for_power_off);
|
|
||||||
unsigned long rtc_rate;
|
|
||||||
unsigned long wakeup_filter_ticks;
|
|
||||||
unsigned long reset_counter_ticks;
|
|
||||||
|
|
||||||
clk_prepare_enable(rtc->clk);
|
|
||||||
|
|
||||||
rtc_rate = clk_get_rate(rtc->clk);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set minimum wakeup pin assertion time: 100 ms.
|
|
||||||
* Range is 0 to 2 sec if RTC is clocked at 32 kHz.
|
|
||||||
*/
|
|
||||||
wakeup_filter_ticks =
|
|
||||||
(rtc->min_wakeup_pin_assert_time * rtc_rate) / 1000;
|
|
||||||
if (wakeup_filter_ticks < JZ_RTC_WAKEUP_FILTER_MASK)
|
|
||||||
wakeup_filter_ticks &= JZ_RTC_WAKEUP_FILTER_MASK;
|
|
||||||
else
|
|
||||||
wakeup_filter_ticks = JZ_RTC_WAKEUP_FILTER_MASK;
|
|
||||||
jz4740_rtc_reg_write(rtc,
|
|
||||||
JZ_REG_RTC_WAKEUP_FILTER, wakeup_filter_ticks);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set reset pin low-level assertion time after wakeup: 60 ms.
|
|
||||||
* Range is 0 to 125 ms if RTC is clocked at 32 kHz.
|
|
||||||
*/
|
|
||||||
reset_counter_ticks = (rtc->reset_pin_assert_time * rtc_rate) / 1000;
|
|
||||||
if (reset_counter_ticks < JZ_RTC_RESET_COUNTER_MASK)
|
|
||||||
reset_counter_ticks &= JZ_RTC_RESET_COUNTER_MASK;
|
|
||||||
else
|
|
||||||
reset_counter_ticks = JZ_RTC_RESET_COUNTER_MASK;
|
|
||||||
jz4740_rtc_reg_write(rtc,
|
|
||||||
JZ_REG_RTC_RESET_COUNTER, reset_counter_ticks);
|
|
||||||
|
|
||||||
jz4740_rtc_poweroff(dev_for_power_off);
|
jz4740_rtc_poweroff(dev_for_power_off);
|
||||||
kernel_halt();
|
kernel_halt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void jz4740_rtc_clk_disable(void *data)
|
||||||
|
{
|
||||||
|
clk_disable_unprepare(data);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct of_device_id jz4740_rtc_of_match[] = {
|
static const struct of_device_id jz4740_rtc_of_match[] = {
|
||||||
{ .compatible = "ingenic,jz4740-rtc", .data = (void *)ID_JZ4740 },
|
{ .compatible = "ingenic,jz4740-rtc", .data = (void *)ID_JZ4740 },
|
||||||
{ .compatible = "ingenic,jz4760-rtc", .data = (void *)ID_JZ4760 },
|
{ .compatible = "ingenic,jz4760-rtc", .data = (void *)ID_JZ4760 },
|
||||||
|
@ -305,110 +270,140 @@ static const struct of_device_id jz4740_rtc_of_match[] = {
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, jz4740_rtc_of_match);
|
MODULE_DEVICE_TABLE(of, jz4740_rtc_of_match);
|
||||||
|
|
||||||
|
static void jz4740_rtc_set_wakeup_params(struct jz4740_rtc *rtc,
|
||||||
|
struct device_node *np,
|
||||||
|
unsigned long rate)
|
||||||
|
{
|
||||||
|
unsigned long wakeup_ticks, reset_ticks;
|
||||||
|
unsigned int min_wakeup_pin_assert_time = 60; /* Default: 60ms */
|
||||||
|
unsigned int reset_pin_assert_time = 100; /* Default: 100ms */
|
||||||
|
|
||||||
|
of_property_read_u32(np, "ingenic,reset-pin-assert-time-ms",
|
||||||
|
&reset_pin_assert_time);
|
||||||
|
of_property_read_u32(np, "ingenic,min-wakeup-pin-assert-time-ms",
|
||||||
|
&min_wakeup_pin_assert_time);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set minimum wakeup pin assertion time: 100 ms.
|
||||||
|
* Range is 0 to 2 sec if RTC is clocked at 32 kHz.
|
||||||
|
*/
|
||||||
|
wakeup_ticks = (min_wakeup_pin_assert_time * rate) / 1000;
|
||||||
|
if (wakeup_ticks < JZ_RTC_WAKEUP_FILTER_MASK)
|
||||||
|
wakeup_ticks &= JZ_RTC_WAKEUP_FILTER_MASK;
|
||||||
|
else
|
||||||
|
wakeup_ticks = JZ_RTC_WAKEUP_FILTER_MASK;
|
||||||
|
jz4740_rtc_reg_write(rtc, JZ_REG_RTC_WAKEUP_FILTER, wakeup_ticks);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set reset pin low-level assertion time after wakeup: 60 ms.
|
||||||
|
* Range is 0 to 125 ms if RTC is clocked at 32 kHz.
|
||||||
|
*/
|
||||||
|
reset_ticks = (reset_pin_assert_time * rate) / 1000;
|
||||||
|
if (reset_ticks < JZ_RTC_RESET_COUNTER_MASK)
|
||||||
|
reset_ticks &= JZ_RTC_RESET_COUNTER_MASK;
|
||||||
|
else
|
||||||
|
reset_ticks = JZ_RTC_RESET_COUNTER_MASK;
|
||||||
|
jz4740_rtc_reg_write(rtc, JZ_REG_RTC_RESET_COUNTER, reset_ticks);
|
||||||
|
}
|
||||||
|
|
||||||
static int jz4740_rtc_probe(struct platform_device *pdev)
|
static int jz4740_rtc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int ret;
|
struct device *dev = &pdev->dev;
|
||||||
|
struct device_node *np = dev->of_node;
|
||||||
struct jz4740_rtc *rtc;
|
struct jz4740_rtc *rtc;
|
||||||
const struct platform_device_id *id = platform_get_device_id(pdev);
|
unsigned long rate;
|
||||||
const struct of_device_id *of_id = of_match_device(
|
struct clk *clk;
|
||||||
jz4740_rtc_of_match, &pdev->dev);
|
int ret, irq;
|
||||||
struct device_node *np = pdev->dev.of_node;
|
|
||||||
|
|
||||||
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
|
rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
|
||||||
if (!rtc)
|
if (!rtc)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
if (of_id)
|
rtc->type = (enum jz4740_rtc_type)device_get_match_data(dev);
|
||||||
rtc->type = (enum jz4740_rtc_type)of_id->data;
|
|
||||||
else
|
|
||||||
rtc->type = id->driver_data;
|
|
||||||
|
|
||||||
rtc->irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (rtc->irq < 0)
|
if (irq < 0)
|
||||||
return -ENOENT;
|
return irq;
|
||||||
|
|
||||||
rtc->base = devm_platform_ioremap_resource(pdev, 0);
|
rtc->base = devm_platform_ioremap_resource(pdev, 0);
|
||||||
if (IS_ERR(rtc->base))
|
if (IS_ERR(rtc->base))
|
||||||
return PTR_ERR(rtc->base);
|
return PTR_ERR(rtc->base);
|
||||||
|
|
||||||
rtc->clk = devm_clk_get(&pdev->dev, "rtc");
|
clk = devm_clk_get(dev, "rtc");
|
||||||
if (IS_ERR(rtc->clk)) {
|
if (IS_ERR(clk)) {
|
||||||
dev_err(&pdev->dev, "Failed to get RTC clock\n");
|
dev_err(dev, "Failed to get RTC clock\n");
|
||||||
return PTR_ERR(rtc->clk);
|
return PTR_ERR(clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_prepare_enable(clk);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "Failed to enable clock\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = devm_add_action_or_reset(dev, jz4740_rtc_clk_disable, clk);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "Failed to register devm action\n");
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_init(&rtc->lock);
|
spin_lock_init(&rtc->lock);
|
||||||
|
|
||||||
platform_set_drvdata(pdev, rtc);
|
platform_set_drvdata(pdev, rtc);
|
||||||
|
|
||||||
device_init_wakeup(&pdev->dev, 1);
|
device_init_wakeup(dev, 1);
|
||||||
|
|
||||||
ret = dev_pm_set_wake_irq(&pdev->dev, rtc->irq);
|
ret = dev_pm_set_wake_irq(dev, irq);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "Failed to set wake irq: %d\n", ret);
|
dev_err(dev, "Failed to set wake irq: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
|
rtc->rtc = devm_rtc_allocate_device(dev);
|
||||||
if (IS_ERR(rtc->rtc)) {
|
if (IS_ERR(rtc->rtc)) {
|
||||||
ret = PTR_ERR(rtc->rtc);
|
ret = PTR_ERR(rtc->rtc);
|
||||||
dev_err(&pdev->dev, "Failed to allocate rtc device: %d\n", ret);
|
dev_err(dev, "Failed to allocate rtc device: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtc->rtc->ops = &jz4740_rtc_ops;
|
rtc->rtc->ops = &jz4740_rtc_ops;
|
||||||
rtc->rtc->range_max = U32_MAX;
|
rtc->rtc->range_max = U32_MAX;
|
||||||
|
|
||||||
|
rate = clk_get_rate(clk);
|
||||||
|
jz4740_rtc_set_wakeup_params(rtc, np, rate);
|
||||||
|
|
||||||
|
/* Each 1 Hz pulse should happen after (rate) ticks */
|
||||||
|
jz4740_rtc_reg_write(rtc, JZ_REG_RTC_REGULATOR, rate - 1);
|
||||||
|
|
||||||
ret = rtc_register_device(rtc->rtc);
|
ret = rtc_register_device(rtc->rtc);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = devm_request_irq(&pdev->dev, rtc->irq, jz4740_rtc_irq, 0,
|
ret = devm_request_irq(dev, irq, jz4740_rtc_irq, 0,
|
||||||
pdev->name, rtc);
|
pdev->name, rtc);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&pdev->dev, "Failed to request rtc irq: %d\n", ret);
|
dev_err(dev, "Failed to request rtc irq: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (np && of_device_is_system_power_controller(np)) {
|
if (of_device_is_system_power_controller(np)) {
|
||||||
if (!pm_power_off) {
|
dev_for_power_off = dev;
|
||||||
/* Default: 60ms */
|
|
||||||
rtc->reset_pin_assert_time = 60;
|
|
||||||
of_property_read_u32(np,
|
|
||||||
"ingenic,reset-pin-assert-time-ms",
|
|
||||||
&rtc->reset_pin_assert_time);
|
|
||||||
|
|
||||||
/* Default: 100ms */
|
if (!pm_power_off)
|
||||||
rtc->min_wakeup_pin_assert_time = 100;
|
|
||||||
of_property_read_u32(np,
|
|
||||||
"ingenic,min-wakeup-pin-assert-time-ms",
|
|
||||||
&rtc->min_wakeup_pin_assert_time);
|
|
||||||
|
|
||||||
dev_for_power_off = &pdev->dev;
|
|
||||||
pm_power_off = jz4740_rtc_power_off;
|
pm_power_off = jz4740_rtc_power_off;
|
||||||
} else {
|
else
|
||||||
dev_warn(&pdev->dev,
|
dev_warn(dev, "Poweroff handler already present!\n");
|
||||||
"Poweroff handler already present!\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct platform_device_id jz4740_rtc_ids[] = {
|
|
||||||
{ "jz4740-rtc", ID_JZ4740 },
|
|
||||||
{ "jz4780-rtc", ID_JZ4780 },
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
MODULE_DEVICE_TABLE(platform, jz4740_rtc_ids);
|
|
||||||
|
|
||||||
static struct platform_driver jz4740_rtc_driver = {
|
static struct platform_driver jz4740_rtc_driver = {
|
||||||
.probe = jz4740_rtc_probe,
|
.probe = jz4740_rtc_probe,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "jz4740-rtc",
|
.name = "jz4740-rtc",
|
||||||
.of_match_table = of_match_ptr(jz4740_rtc_of_match),
|
.of_match_table = jz4740_rtc_of_match,
|
||||||
},
|
},
|
||||||
.id_table = jz4740_rtc_ids,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module_platform_driver(jz4740_rtc_driver);
|
module_platform_driver(jz4740_rtc_driver);
|
||||||
|
|
|
@ -205,10 +205,8 @@ static int lpc24xx_rtc_probe(struct platform_device *pdev)
|
||||||
return PTR_ERR(rtc->rtc_base);
|
return PTR_ERR(rtc->rtc_base);
|
||||||
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (irq < 0) {
|
if (irq < 0)
|
||||||
dev_warn(&pdev->dev, "can't get interrupt resource\n");
|
|
||||||
return irq;
|
return irq;
|
||||||
}
|
|
||||||
|
|
||||||
rtc->clk_rtc = devm_clk_get(&pdev->dev, "rtc");
|
rtc->clk_rtc = devm_clk_get(&pdev->dev, "rtc");
|
||||||
if (IS_ERR(rtc->clk_rtc)) {
|
if (IS_ERR(rtc->clk_rtc)) {
|
||||||
|
|
|
@ -78,6 +78,8 @@ struct max77686_rtc_driver_data {
|
||||||
int alarm_pending_status_reg;
|
int alarm_pending_status_reg;
|
||||||
/* RTC IRQ CHIP for regmap */
|
/* RTC IRQ CHIP for regmap */
|
||||||
const struct regmap_irq_chip *rtc_irq_chip;
|
const struct regmap_irq_chip *rtc_irq_chip;
|
||||||
|
/* regmap configuration for the chip */
|
||||||
|
const struct regmap_config *regmap_config;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct max77686_rtc_info {
|
struct max77686_rtc_info {
|
||||||
|
@ -182,6 +184,11 @@ static const struct regmap_irq_chip max77686_rtc_irq_chip = {
|
||||||
.num_irqs = ARRAY_SIZE(max77686_rtc_irqs),
|
.num_irqs = ARRAY_SIZE(max77686_rtc_irqs),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct regmap_config max77686_rtc_regmap_config = {
|
||||||
|
.reg_bits = 8,
|
||||||
|
.val_bits = 8,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct max77686_rtc_driver_data max77686_drv_data = {
|
static const struct max77686_rtc_driver_data max77686_drv_data = {
|
||||||
.delay = 16000,
|
.delay = 16000,
|
||||||
.mask = 0x7f,
|
.mask = 0x7f,
|
||||||
|
@ -191,6 +198,13 @@ static const struct max77686_rtc_driver_data max77686_drv_data = {
|
||||||
.alarm_pending_status_reg = MAX77686_REG_STATUS2,
|
.alarm_pending_status_reg = MAX77686_REG_STATUS2,
|
||||||
.rtc_i2c_addr = MAX77686_I2C_ADDR_RTC,
|
.rtc_i2c_addr = MAX77686_I2C_ADDR_RTC,
|
||||||
.rtc_irq_chip = &max77686_rtc_irq_chip,
|
.rtc_irq_chip = &max77686_rtc_irq_chip,
|
||||||
|
.regmap_config = &max77686_rtc_regmap_config,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_config max77620_rtc_regmap_config = {
|
||||||
|
.reg_bits = 8,
|
||||||
|
.val_bits = 8,
|
||||||
|
.use_single_write = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct max77686_rtc_driver_data max77620_drv_data = {
|
static const struct max77686_rtc_driver_data max77620_drv_data = {
|
||||||
|
@ -202,6 +216,7 @@ static const struct max77686_rtc_driver_data max77620_drv_data = {
|
||||||
.alarm_pending_status_reg = MAX77686_INVALID_REG,
|
.alarm_pending_status_reg = MAX77686_INVALID_REG,
|
||||||
.rtc_i2c_addr = MAX77620_I2C_ADDR_RTC,
|
.rtc_i2c_addr = MAX77620_I2C_ADDR_RTC,
|
||||||
.rtc_irq_chip = &max77686_rtc_irq_chip,
|
.rtc_irq_chip = &max77686_rtc_irq_chip,
|
||||||
|
.regmap_config = &max77620_rtc_regmap_config,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const unsigned int max77802_map[REG_RTC_END] = {
|
static const unsigned int max77802_map[REG_RTC_END] = {
|
||||||
|
@ -658,11 +673,6 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct regmap_config max77686_rtc_regmap_config = {
|
|
||||||
.reg_bits = 8,
|
|
||||||
.val_bits = 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
|
static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
|
||||||
{
|
{
|
||||||
struct device *parent = info->dev->parent;
|
struct device *parent = info->dev->parent;
|
||||||
|
@ -698,7 +708,7 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
|
||||||
}
|
}
|
||||||
|
|
||||||
info->rtc_regmap = devm_regmap_init_i2c(info->rtc,
|
info->rtc_regmap = devm_regmap_init_i2c(info->rtc,
|
||||||
&max77686_rtc_regmap_config);
|
info->drv_data->regmap_config);
|
||||||
if (IS_ERR(info->rtc_regmap)) {
|
if (IS_ERR(info->rtc_regmap)) {
|
||||||
ret = PTR_ERR(info->rtc_regmap);
|
ret = PTR_ERR(info->rtc_regmap);
|
||||||
dev_err(info->dev, "Failed to allocate RTC regmap: %d\n", ret);
|
dev_err(info->dev, "Failed to allocate RTC regmap: %d\n", ret);
|
||||||
|
|
|
@ -308,8 +308,10 @@ static int __init mc13xxx_rtc_probe(struct platform_device *pdev)
|
||||||
mc13xxx_unlock(mc13xxx);
|
mc13xxx_unlock(mc13xxx);
|
||||||
|
|
||||||
ret = rtc_register_device(priv->rtc);
|
ret = rtc_register_device(priv->rtc);
|
||||||
if (ret)
|
if (ret) {
|
||||||
|
mc13xxx_lock(mc13xxx);
|
||||||
goto err_irq_request;
|
goto err_irq_request;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -316,7 +316,7 @@ static int mpc5121_rtc_probe(struct platform_device *op)
|
||||||
rtc->regs = devm_platform_ioremap_resource(op, 0);
|
rtc->regs = devm_platform_ioremap_resource(op, 0);
|
||||||
if (IS_ERR(rtc->regs)) {
|
if (IS_ERR(rtc->regs)) {
|
||||||
dev_err(&op->dev, "%s: couldn't map io space\n", __func__);
|
dev_err(&op->dev, "%s: couldn't map io space\n", __func__);
|
||||||
return -ENOSYS;
|
return PTR_ERR(rtc->regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
device_init_wakeup(&op->dev, 1);
|
device_init_wakeup(&op->dev, 1);
|
||||||
|
|
|
@ -310,7 +310,6 @@ static const struct rtc_class_ops mt2712_rtc_ops = {
|
||||||
|
|
||||||
static int mt2712_rtc_probe(struct platform_device *pdev)
|
static int mt2712_rtc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct resource *res;
|
|
||||||
struct mt2712_rtc *mt2712_rtc;
|
struct mt2712_rtc *mt2712_rtc;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -319,8 +318,7 @@ static int mt2712_rtc_probe(struct platform_device *pdev)
|
||||||
if (!mt2712_rtc)
|
if (!mt2712_rtc)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
mt2712_rtc->base = devm_platform_ioremap_resource(pdev, 0);
|
||||||
mt2712_rtc->base = devm_ioremap_resource(&pdev->dev, res);
|
|
||||||
if (IS_ERR(mt2712_rtc->base))
|
if (IS_ERR(mt2712_rtc->base))
|
||||||
return PTR_ERR(mt2712_rtc->base);
|
return PTR_ERR(mt2712_rtc->base);
|
||||||
|
|
||||||
|
@ -328,10 +326,8 @@ static int mt2712_rtc_probe(struct platform_device *pdev)
|
||||||
mt2712_rtc_hw_init(mt2712_rtc);
|
mt2712_rtc_hw_init(mt2712_rtc);
|
||||||
|
|
||||||
mt2712_rtc->irq = platform_get_irq(pdev, 0);
|
mt2712_rtc->irq = platform_get_irq(pdev, 0);
|
||||||
if (mt2712_rtc->irq < 0) {
|
if (mt2712_rtc->irq < 0)
|
||||||
dev_err(&pdev->dev, "No IRQ resource\n");
|
|
||||||
return mt2712_rtc->irq;
|
return mt2712_rtc->irq;
|
||||||
}
|
|
||||||
|
|
||||||
platform_set_drvdata(pdev, mt2712_rtc);
|
platform_set_drvdata(pdev, mt2712_rtc);
|
||||||
|
|
||||||
|
@ -356,13 +352,7 @@ static int mt2712_rtc_probe(struct platform_device *pdev)
|
||||||
mt2712_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
mt2712_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||||
mt2712_rtc->rtc->range_max = MT2712_RTC_TIMESTAMP_END_2127;
|
mt2712_rtc->rtc->range_max = MT2712_RTC_TIMESTAMP_END_2127;
|
||||||
|
|
||||||
ret = rtc_register_device(mt2712_rtc->rtc);
|
return rtc_register_device(mt2712_rtc->rtc);
|
||||||
if (ret) {
|
|
||||||
dev_err(&pdev->dev, "register rtc device failed\n");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
|
|
|
@ -137,8 +137,7 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||||
tm->tm_wday = buf[PCF2127_REG_DW] & 0x07;
|
tm->tm_wday = buf[PCF2127_REG_DW] & 0x07;
|
||||||
tm->tm_mon = bcd2bin(buf[PCF2127_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
|
tm->tm_mon = bcd2bin(buf[PCF2127_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */
|
||||||
tm->tm_year = bcd2bin(buf[PCF2127_REG_YR]);
|
tm->tm_year = bcd2bin(buf[PCF2127_REG_YR]);
|
||||||
if (tm->tm_year < 70)
|
tm->tm_year += 100;
|
||||||
tm->tm_year += 100; /* assume we are in 1970...2069 */
|
|
||||||
|
|
||||||
dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
|
dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
|
||||||
"mday=%d, mon=%d, year=%d, wday=%d\n",
|
"mday=%d, mon=%d, year=%d, wday=%d\n",
|
||||||
|
@ -172,7 +171,7 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
buf[i++] = bin2bcd(tm->tm_mon + 1);
|
buf[i++] = bin2bcd(tm->tm_mon + 1);
|
||||||
|
|
||||||
/* year */
|
/* year */
|
||||||
buf[i++] = bin2bcd(tm->tm_year % 100);
|
buf[i++] = bin2bcd(tm->tm_year - 100);
|
||||||
|
|
||||||
/* write register's data */
|
/* write register's data */
|
||||||
err = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_SC, buf, i);
|
err = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_SC, buf, i);
|
||||||
|
@ -185,30 +184,35 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_RTC_INTF_DEV
|
|
||||||
static int pcf2127_rtc_ioctl(struct device *dev,
|
static int pcf2127_rtc_ioctl(struct device *dev,
|
||||||
unsigned int cmd, unsigned long arg)
|
unsigned int cmd, unsigned long arg)
|
||||||
{
|
{
|
||||||
struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
|
struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
|
||||||
int touser;
|
int val, touser = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case RTC_VL_READ:
|
case RTC_VL_READ:
|
||||||
ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &touser);
|
ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &val);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
touser = touser & PCF2127_BIT_CTRL3_BLF ? RTC_VL_BACKUP_LOW : 0;
|
if (val & PCF2127_BIT_CTRL3_BLF)
|
||||||
|
touser |= RTC_VL_BACKUP_LOW;
|
||||||
|
|
||||||
|
if (val & PCF2127_BIT_CTRL3_BF)
|
||||||
|
touser |= RTC_VL_BACKUP_SWITCH;
|
||||||
|
|
||||||
return put_user(touser, (unsigned int __user *)arg);
|
return put_user(touser, (unsigned int __user *)arg);
|
||||||
|
|
||||||
|
case RTC_VL_CLR:
|
||||||
|
return regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3,
|
||||||
|
PCF2127_BIT_CTRL3_BF, 0);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return -ENOIOCTLCMD;
|
return -ENOIOCTLCMD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
#define pcf2127_rtc_ioctl NULL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const struct rtc_class_ops pcf2127_rtc_ops = {
|
static const struct rtc_class_ops pcf2127_rtc_ops = {
|
||||||
.ioctl = pcf2127_rtc_ioctl,
|
.ioctl = pcf2127_rtc_ioctl,
|
||||||
|
@ -433,6 +437,9 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
|
||||||
return PTR_ERR(pcf2127->rtc);
|
return PTR_ERR(pcf2127->rtc);
|
||||||
|
|
||||||
pcf2127->rtc->ops = &pcf2127_rtc_ops;
|
pcf2127->rtc->ops = &pcf2127_rtc_ops;
|
||||||
|
pcf2127->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
|
||||||
|
pcf2127->rtc->range_max = RTC_TIMESTAMP_END_2099;
|
||||||
|
pcf2127->rtc->set_start_time = true; /* Sets actual start to 1970 */
|
||||||
|
|
||||||
pcf2127->wdd.parent = dev;
|
pcf2127->wdd.parent = dev;
|
||||||
pcf2127->wdd.info = &pcf2127_wdt_info;
|
pcf2127->wdd.info = &pcf2127_wdt_info;
|
||||||
|
@ -441,6 +448,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
|
||||||
pcf2127->wdd.max_timeout = PCF2127_WD_VAL_MAX;
|
pcf2127->wdd.max_timeout = PCF2127_WD_VAL_MAX;
|
||||||
pcf2127->wdd.timeout = PCF2127_WD_VAL_DEFAULT;
|
pcf2127->wdd.timeout = PCF2127_WD_VAL_DEFAULT;
|
||||||
pcf2127->wdd.min_hw_heartbeat_ms = 500;
|
pcf2127->wdd.min_hw_heartbeat_ms = 500;
|
||||||
|
pcf2127->wdd.status = WATCHDOG_NOWAYOUT_INIT_STATUS;
|
||||||
|
|
||||||
watchdog_set_drvdata(&pcf2127->wdd, pcf2127);
|
watchdog_set_drvdata(&pcf2127->wdd, pcf2127);
|
||||||
|
|
||||||
|
@ -495,7 +503,6 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
|
||||||
*/
|
*/
|
||||||
ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3,
|
ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3,
|
||||||
PCF2127_BIT_CTRL3_BTSE |
|
PCF2127_BIT_CTRL3_BTSE |
|
||||||
PCF2127_BIT_CTRL3_BF |
|
|
||||||
PCF2127_BIT_CTRL3_BIE |
|
PCF2127_BIT_CTRL3_BIE |
|
||||||
PCF2127_BIT_CTRL3_BLIE, 0);
|
PCF2127_BIT_CTRL3_BLIE, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -636,6 +643,7 @@ static int pcf2127_i2c_probe(struct i2c_client *client,
|
||||||
static const struct regmap_config config = {
|
static const struct regmap_config config = {
|
||||||
.reg_bits = 8,
|
.reg_bits = 8,
|
||||||
.val_bits = 8,
|
.val_bits = 8,
|
||||||
|
.max_register = 0x1d,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
|
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
|
||||||
|
@ -703,6 +711,7 @@ static int pcf2127_spi_probe(struct spi_device *spi)
|
||||||
.val_bits = 8,
|
.val_bits = 8,
|
||||||
.read_flag_mask = 0xa0,
|
.read_flag_mask = 0xa0,
|
||||||
.write_flag_mask = 0x20,
|
.write_flag_mask = 0x20,
|
||||||
|
.max_register = 0x1d,
|
||||||
};
|
};
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
|
|
||||||
|
|
|
@ -356,10 +356,8 @@ static int rc5t619_rtc_probe(struct platform_device *pdev)
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
|
rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
|
||||||
if (IS_ERR(rtc)) {
|
if (!rtc)
|
||||||
err = PTR_ERR(rtc);
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
|
||||||
|
|
||||||
rtc->rn5t618 = rn5t618;
|
rtc->rn5t618 = rn5t618;
|
||||||
|
|
||||||
|
|
|
@ -755,6 +755,8 @@ static int rv3028_probe(struct i2c_client *client)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
rv3028->regmap = devm_regmap_init_i2c(client, ®map_config);
|
rv3028->regmap = devm_regmap_init_i2c(client, ®map_config);
|
||||||
|
if (IS_ERR(rv3028->regmap))
|
||||||
|
return PTR_ERR(rv3028->regmap);
|
||||||
|
|
||||||
i2c_set_clientdata(client, rv3028);
|
i2c_set_clientdata(client, rv3028);
|
||||||
|
|
||||||
|
|
|
@ -148,10 +148,21 @@ static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
|
||||||
static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||||
{
|
{
|
||||||
struct snvs_rtc_data *data = dev_get_drvdata(dev);
|
struct snvs_rtc_data *data = dev_get_drvdata(dev);
|
||||||
unsigned long time = rtc_read_lp_counter(data);
|
unsigned long time;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (data->clk) {
|
||||||
|
ret = clk_enable(data->clk);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
time = rtc_read_lp_counter(data);
|
||||||
rtc_time64_to_tm(time, tm);
|
rtc_time64_to_tm(time, tm);
|
||||||
|
|
||||||
|
if (data->clk)
|
||||||
|
clk_disable(data->clk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,6 +172,12 @@ static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
unsigned long time = rtc_tm_to_time64(tm);
|
unsigned long time = rtc_tm_to_time64(tm);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (data->clk) {
|
||||||
|
ret = clk_enable(data->clk);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* Disable RTC first */
|
/* Disable RTC first */
|
||||||
ret = snvs_rtc_enable(data, false);
|
ret = snvs_rtc_enable(data, false);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -173,6 +190,9 @@ static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||||
/* Enable RTC again */
|
/* Enable RTC again */
|
||||||
ret = snvs_rtc_enable(data, true);
|
ret = snvs_rtc_enable(data, true);
|
||||||
|
|
||||||
|
if (data->clk)
|
||||||
|
clk_disable(data->clk);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,6 +200,13 @@ static int snvs_rtc_read_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);
|
||||||
u32 lptar, lpsr;
|
u32 lptar, lpsr;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (data->clk) {
|
||||||
|
ret = clk_enable(data->clk);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
regmap_read(data->regmap, data->offset + SNVS_LPTAR, &lptar);
|
regmap_read(data->regmap, data->offset + SNVS_LPTAR, &lptar);
|
||||||
rtc_time64_to_tm(lptar, &alrm->time);
|
rtc_time64_to_tm(lptar, &alrm->time);
|
||||||
|
@ -187,18 +214,33 @@ static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);
|
regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);
|
||||||
alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0;
|
alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0;
|
||||||
|
|
||||||
|
if (data->clk)
|
||||||
|
clk_disable(data->clk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
|
static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
|
||||||
{
|
{
|
||||||
struct snvs_rtc_data *data = dev_get_drvdata(dev);
|
struct snvs_rtc_data *data = dev_get_drvdata(dev);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (data->clk) {
|
||||||
|
ret = clk_enable(data->clk);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
regmap_update_bits(data->regmap, data->offset + SNVS_LPCR,
|
regmap_update_bits(data->regmap, data->offset + SNVS_LPCR,
|
||||||
(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);
|
||||||
|
|
||||||
return rtc_write_sync_lp(data);
|
ret = rtc_write_sync_lp(data);
|
||||||
|
|
||||||
|
if (data->clk)
|
||||||
|
clk_disable(data->clk);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
@ -207,6 +249,12 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
unsigned long time = rtc_tm_to_time64(&alrm->time);
|
unsigned long time = rtc_tm_to_time64(&alrm->time);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (data->clk) {
|
||||||
|
ret = clk_enable(data->clk);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
ret = rtc_write_sync_lp(data);
|
ret = rtc_write_sync_lp(data);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -216,6 +264,9 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||||
/* Clear alarm interrupt status bit */
|
/* Clear alarm interrupt status bit */
|
||||||
regmap_write(data->regmap, data->offset + SNVS_LPSR, SNVS_LPSR_LPTA);
|
regmap_write(data->regmap, data->offset + SNVS_LPSR, SNVS_LPSR_LPTA);
|
||||||
|
|
||||||
|
if (data->clk)
|
||||||
|
clk_disable(data->clk);
|
||||||
|
|
||||||
return snvs_rtc_alarm_irq_enable(dev, alrm->enabled);
|
return snvs_rtc_alarm_irq_enable(dev, alrm->enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -362,7 +413,7 @@ static int __maybe_unused snvs_rtc_suspend_noirq(struct device *dev)
|
||||||
struct snvs_rtc_data *data = dev_get_drvdata(dev);
|
struct snvs_rtc_data *data = dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (data->clk)
|
if (data->clk)
|
||||||
clk_disable_unprepare(data->clk);
|
clk_disable(data->clk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -372,7 +423,7 @@ static int __maybe_unused snvs_rtc_resume_noirq(struct device *dev)
|
||||||
struct snvs_rtc_data *data = dev_get_drvdata(dev);
|
struct snvs_rtc_data *data = dev_get_drvdata(dev);
|
||||||
|
|
||||||
if (data->clk)
|
if (data->clk)
|
||||||
return clk_prepare_enable(data->clk);
|
return clk_enable(data->clk);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -416,5 +416,5 @@ module_platform_driver(stmp3xxx_rtcdrv);
|
||||||
|
|
||||||
MODULE_DESCRIPTION("STMP3xxx RTC Driver");
|
MODULE_DESCRIPTION("STMP3xxx RTC Driver");
|
||||||
MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and "
|
MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and "
|
||||||
"Wolfram Sang <w.sang@pengutronix.de>");
|
"Wolfram Sang <kernel@pengutronix.de>");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -99,6 +99,7 @@ struct rtc_pll_info {
|
||||||
#define RTC_VL_BACKUP_LOW _BITUL(1) /* Backup voltage is low */
|
#define RTC_VL_BACKUP_LOW _BITUL(1) /* Backup voltage is low */
|
||||||
#define RTC_VL_BACKUP_EMPTY _BITUL(2) /* Backup empty or not present */
|
#define RTC_VL_BACKUP_EMPTY _BITUL(2) /* Backup empty or not present */
|
||||||
#define RTC_VL_ACCURACY_LOW _BITUL(3) /* Voltage is low, RTC accuracy is reduced */
|
#define RTC_VL_ACCURACY_LOW _BITUL(3) /* Voltage is low, RTC accuracy is reduced */
|
||||||
|
#define RTC_VL_BACKUP_SWITCH _BITUL(4) /* Backup switchover happened */
|
||||||
|
|
||||||
#define RTC_VL_READ _IOR('p', 0x13, unsigned int) /* Voltage low detection */
|
#define RTC_VL_READ _IOR('p', 0x13, unsigned int) /* Voltage low detection */
|
||||||
#define RTC_VL_CLR _IO('p', 0x14) /* Clear voltage low information */
|
#define RTC_VL_CLR _IO('p', 0x14) /* Clear voltage low information */
|
||||||
|
|
Загрузка…
Ссылка в новой задаче