RTC for 6.15

Core:
  - setdate is removed as it has better replacements
  - skip alarms with a second resolution when we know the RTC doesn't support
    those.
 
 Subsystem:
  - remove unnecessary private struct members
  - use devm_pm_set_wake_irq were relevant
 
 Drivers:
  - ds1307: stop disabling alarms on probe for DS1337, DS1339, DS1341 and DS3231
  - max31335: add max31331 support
  - pcf50633 is removed as support for the related SoC has been removed
  - pcf85063: properly handle POR failures
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEBqsFVZXh8s/0O5JiY6TcMGxwOjIFAmftwMgACgkQY6TcMGxw
 OjKk1g//dwDeinPyXC8+isDYCf07U6xy1OmvZcQSqG1qL64rONY1KoUKVq92mQUs
 1+rijwIJMi4MNJqaCwYHAEhvXxYJNoQLcV3uHkqVjrRfGQY0Mgl4/pLALGNp6P4U
 QixG8qJiVzAMolTVUozqp/amTc0zztFT6Fnr1EbrLkx0JZX5D09Na5pgdbvoBFX3
 pH5kxYQotpBD8x8CUHFU0oz8dEeSAbISEVJKX1Ct9xTqhYX9/OB92jQvvg46STPU
 2J6n9Yl9eH77itX8GmaDyNyKIIzAZktWuZofiPkni090W/H+uVIdSo0/pHRinvsA
 hoZBLc9CjUDFfqK9uuFOszl1lW/zpVkLdz3VR9OYxjIFzDk5KKnAK9g669VIBm3P
 yPlYQL9TzW+uacpzdN7YhUW0Oy5opRcYjjCrTg5znTtFFplxrMucveyXb8wAP3DG
 m68C1LJzCOxzYAqnfzh59UYSr+JexDJgEH1u79d0GYFrTXZ4mY6i94yva4lIOofX
 uaUuTOsUyQY4ZxMEXw2FlUzvSmQBaALj7ycMFmSBWYa5efI7UWZ2r2HZ0jX30HQU
 m+bG/+eMMZq9gYsiCrYxo0J+afpZ0lTRmyecnuCqP79rYPTCrOui/2n3fZryGfjV
 cDUYbFl5VbsYpwT/sBUrsKU8e9YYb85ACep3WbRlnS7YI5qkM+Y=
 =QJeg
 -----END PGP SIGNATURE-----

Merge tag 'rtc-6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux

Pull RTC updates from Alexandre Belloni:
 "We see a net reduction of the number of lines of code thanks to the
  removal of a now unused driver and a testing tool that is not used
  anymore. Apart from this, the max31335 driver gets support for a new
  part number and pm8xxx gets UEFI support.

  Core:

   - setdate is removed as it has better replacements

   - skip alarms with a second resolution when we know the RTC doesn't
     support those.

  Subsystem:

   - remove unnecessary private struct members

   - use devm_pm_set_wake_irq were relevant

  Drivers:

   - ds1307: stop disabling alarms on probe for DS1337, DS1339, DS1341
     and DS3231

   - max31335: add max31331 support

   - pcf50633 is removed as support for the related SoC has been removed

   - pcf85063: properly handle POR failures"

* tag 'rtc-6.15' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (50 commits)
  rtc: remove 'setdate' test program
  selftest: rtc: skip some tests if the alarm only supports minutes
  rtc: mt6397: drop unused defines
  rtc: pcf85063: replace dev_err+return with return dev_err_probe
  rtc: pcf85063: do a SW reset if POR failed
  rtc: max31335: Add driver support for max31331
  dt-bindings: rtc: max31335: Add max31331 support
  rtc: cros-ec: Avoid a couple of -Wflex-array-member-not-at-end warnings
  dt-bindings: rtc: pcf2127: Reference spi-peripheral-props.yaml
  rtc: rzn1: implement one-second accuracy for alarms
  rtc: pcf50633: Remove
  rtc: pm8xxx: implement qcom,no-alarm flag for non-HLOS owned alarm
  rtc: pm8xxx: mitigate flash wear
  rtc: pm8xxx: add support for uefi offset
  dt-bindings: rtc: qcom-pm8xxx: document qcom,no-alarm flag
  rtc: rv3032: drop WADA
  rtc: rv3032: fix EERD location
  rtc: pm8xxx: switch to devm_device_init_wakeup
  rtc: pm8xxx: fix possible race condition
  rtc: mpfs: switch to devm_device_init_wakeup
  ...
This commit is contained in:
Linus Torvalds 2025-04-03 15:31:14 -07:00
commit 5916a6fbc0
43 changed files with 662 additions and 858 deletions

View File

@ -18,7 +18,9 @@ allOf:
properties:
compatible:
const: adi,max31335
enum:
- adi,max31331
- adi,max31335
reg:
maxItems: 1

View File

@ -8,6 +8,7 @@ title: NXP PCF2127 Real Time Clock
allOf:
- $ref: rtc.yaml#
- $ref: /schemas/spi/spi-peripheral-props.yaml#
maintainers:
- Alexandre Belloni <alexandre.belloni@bootlin.com>
@ -34,7 +35,7 @@ required:
- compatible
- reg
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View File

@ -50,6 +50,11 @@ properties:
items:
- const: offset
qcom,no-alarm:
type: boolean
description:
RTC alarm is not owned by the OS
wakeup-source: true
required:

View File

@ -1321,13 +1321,6 @@ config RTC_DRV_SPEAR
If you say Y here you will get support for the RTC found on
spear
config RTC_DRV_PCF50633
depends on MFD_PCF50633
tristate "NXP PCF50633 RTC"
help
If you say yes here you get support for the RTC subsystem of the
NXP PCF50633 used in embedded systems.
config RTC_DRV_AB8500
tristate "ST-Ericsson AB8500 RTC"
depends on AB8500_CORE

View File

@ -126,7 +126,6 @@ obj-$(CONFIG_RTC_DRV_PALMAS) += rtc-palmas.o
obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o
obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o
obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o
obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o
obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o
obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o
obj-$(CONFIG_RTC_DRV_PCF85363) += rtc-pcf85363.o

View File

@ -426,29 +426,9 @@ static umode_t abeoz9_is_visible(const void *data,
}
}
static const u32 abeoz9_chip_config[] = {
HWMON_C_REGISTER_TZ,
0
};
static const struct hwmon_channel_info abeoz9_chip = {
.type = hwmon_chip,
.config = abeoz9_chip_config,
};
static const u32 abeoz9_temp_config[] = {
HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN,
0
};
static const struct hwmon_channel_info abeoz9_temp = {
.type = hwmon_temp,
.config = abeoz9_temp_config,
};
static const struct hwmon_channel_info * const abeoz9_info[] = {
&abeoz9_chip,
&abeoz9_temp,
HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN),
NULL
};

View File

@ -361,7 +361,7 @@ static int ab8500_rtc_probe(struct platform_device *pdev)
return -ENODEV;
}
device_init_wakeup(&pdev->dev, true);
devm_device_init_wakeup(&pdev->dev);
rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc))
@ -375,7 +375,7 @@ static int ab8500_rtc_probe(struct platform_device *pdev)
if (err < 0)
return err;
dev_pm_set_wake_irq(&pdev->dev, irq);
devm_pm_set_wake_irq(&pdev->dev, irq);
platform_set_drvdata(pdev, rtc);
set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features);
@ -392,18 +392,11 @@ static int ab8500_rtc_probe(struct platform_device *pdev)
return devm_rtc_register_device(rtc);
}
static void ab8500_rtc_remove(struct platform_device *pdev)
{
dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
}
static struct platform_driver ab8500_rtc_driver = {
.driver = {
.name = "ab8500-rtc",
},
.probe = ab8500_rtc_probe,
.remove = ab8500_rtc_remove,
.id_table = ab85xx_rtc_ids,
};

View File

@ -8,7 +8,6 @@
#include <linux/io.h>
struct aspeed_rtc {
struct rtc_device *rtc_dev;
void __iomem *base;
};
@ -85,6 +84,7 @@ static const struct rtc_class_ops aspeed_rtc_ops = {
static int aspeed_rtc_probe(struct platform_device *pdev)
{
struct aspeed_rtc *rtc;
struct rtc_device *rtc_dev;
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
if (!rtc)
@ -94,17 +94,17 @@ static int aspeed_rtc_probe(struct platform_device *pdev)
if (IS_ERR(rtc->base))
return PTR_ERR(rtc->base);
rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc->rtc_dev))
return PTR_ERR(rtc->rtc_dev);
rtc_dev = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc_dev))
return PTR_ERR(rtc_dev);
platform_set_drvdata(pdev, rtc);
rtc->rtc_dev->ops = &aspeed_rtc_ops;
rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900;
rtc->rtc_dev->range_max = 38814989399LL; /* 3199-12-31 23:59:59 */
rtc_dev->ops = &aspeed_rtc_ops;
rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900;
rtc_dev->range_max = 38814989399LL; /* 3199-12-31 23:59:59 */
return devm_rtc_register_device(rtc->rtc_dev);
return devm_rtc_register_device(rtc_dev);
}
static const struct of_device_id aspeed_rtc_match[] = {

View File

@ -35,21 +35,18 @@ struct cros_ec_rtc {
static int cros_ec_rtc_get(struct cros_ec_device *cros_ec, u32 command,
u32 *response)
{
DEFINE_RAW_FLEX(struct cros_ec_command, msg, data,
sizeof(struct ec_response_rtc));
int ret;
struct {
struct cros_ec_command msg;
struct ec_response_rtc data;
} __packed msg;
memset(&msg, 0, sizeof(msg));
msg.msg.command = command;
msg.msg.insize = sizeof(msg.data);
msg->command = command;
msg->insize = sizeof(struct ec_response_rtc);
ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
ret = cros_ec_cmd_xfer_status(cros_ec, msg);
if (ret < 0)
return ret;
*response = msg.data.time;
*response = ((struct ec_response_rtc *)msg->data)->time;
return 0;
}
@ -57,18 +54,15 @@ static int cros_ec_rtc_get(struct cros_ec_device *cros_ec, u32 command,
static int cros_ec_rtc_set(struct cros_ec_device *cros_ec, u32 command,
u32 param)
{
DEFINE_RAW_FLEX(struct cros_ec_command, msg, data,
sizeof(struct ec_response_rtc));
int ret;
struct {
struct cros_ec_command msg;
struct ec_response_rtc data;
} __packed msg;
memset(&msg, 0, sizeof(msg));
msg.msg.command = command;
msg.msg.outsize = sizeof(msg.data);
msg.data.time = param;
msg->command = command;
msg->outsize = sizeof(struct ec_response_rtc);
((struct ec_response_rtc *)msg->data)->time = param;
ret = cros_ec_cmd_xfer_status(cros_ec, &msg.msg);
ret = cros_ec_cmd_xfer_status(cros_ec, msg);
if (ret < 0)
return ret;
return 0;

View File

@ -1807,10 +1807,8 @@ static int ds1307_probe(struct i2c_client *client)
* For some variants, be sure alarms can trigger when we're
* running on Vbackup (BBSQI/BBSQW)
*/
if (want_irq || ds1307_can_wakeup_device) {
if (want_irq || ds1307_can_wakeup_device)
regs[0] |= DS1337_BIT_INTCN | chip->bbsqi_bit;
regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE);
}
regmap_write(ds1307->regmap, DS1337_REG_CONTROL,
regs[0]);

View File

@ -427,18 +427,13 @@ static int ds1343_probe(struct spi_device *spi)
"unable to request irq for rtc ds1343\n");
} else {
device_init_wakeup(&spi->dev, true);
dev_pm_set_wake_irq(&spi->dev, spi->irq);
devm_pm_set_wake_irq(&spi->dev, spi->irq);
}
}
return 0;
}
static void ds1343_remove(struct spi_device *spi)
{
dev_pm_clear_wake_irq(&spi->dev);
}
#ifdef CONFIG_PM_SLEEP
static int ds1343_suspend(struct device *dev)
@ -471,7 +466,6 @@ static struct spi_driver ds1343_driver = {
.pm = &ds1343_pm,
},
.probe = ds1343_probe,
.remove = ds1343_remove,
.id_table = ds1343_id,
};

View File

@ -31,7 +31,6 @@ struct ds2404 {
struct gpio_desc *rst_gpiod;
struct gpio_desc *clk_gpiod;
struct gpio_desc *dq_gpiod;
struct rtc_device *rtc;
};
static int ds2404_gpio_map(struct ds2404 *chip, struct platform_device *pdev)
@ -182,6 +181,7 @@ static const struct rtc_class_ops ds2404_rtc_ops = {
static int rtc_probe(struct platform_device *pdev)
{
struct ds2404 *chip;
struct rtc_device *rtc;
int retval = -EBUSY;
chip = devm_kzalloc(&pdev->dev, sizeof(struct ds2404), GFP_KERNEL);
@ -190,9 +190,9 @@ static int rtc_probe(struct platform_device *pdev)
chip->dev = &pdev->dev;
chip->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(chip->rtc))
return PTR_ERR(chip->rtc);
rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
retval = ds2404_gpio_map(chip, pdev);
if (retval)
@ -200,10 +200,10 @@ static int rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, chip);
chip->rtc->ops = &ds2404_rtc_ops;
chip->rtc->range_max = U32_MAX;
rtc->ops = &ds2404_rtc_ops;
rtc->range_max = U32_MAX;
retval = devm_rtc_register_device(chip->rtc);
retval = devm_rtc_register_device(rtc);
if (retval)
return retval;

View File

@ -339,29 +339,9 @@ static int ds3232_hwmon_read(struct device *dev,
return err;
}
static u32 ds3232_hwmon_chip_config[] = {
HWMON_C_REGISTER_TZ,
0
};
static const struct hwmon_channel_info ds3232_hwmon_chip = {
.type = hwmon_chip,
.config = ds3232_hwmon_chip_config,
};
static u32 ds3232_hwmon_temp_config[] = {
HWMON_T_INPUT,
0
};
static const struct hwmon_channel_info ds3232_hwmon_temp = {
.type = hwmon_temp,
.config = ds3232_hwmon_temp_config,
};
static const struct hwmon_channel_info * const ds3232_hwmon_info[] = {
&ds3232_hwmon_chip,
&ds3232_hwmon_temp,
HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
NULL
};

View File

@ -28,7 +28,6 @@
struct ep93xx_rtc {
void __iomem *mmio_base;
struct rtc_device *rtc;
};
static int ep93xx_rtc_get_swcomp(struct device *dev, unsigned short *preload,
@ -123,6 +122,7 @@ static const struct attribute_group ep93xx_rtc_sysfs_files = {
static int ep93xx_rtc_probe(struct platform_device *pdev)
{
struct ep93xx_rtc *ep93xx_rtc;
struct rtc_device *rtc;
int err;
ep93xx_rtc = devm_kzalloc(&pdev->dev, sizeof(*ep93xx_rtc), GFP_KERNEL);
@ -135,18 +135,18 @@ static int ep93xx_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ep93xx_rtc);
ep93xx_rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(ep93xx_rtc->rtc))
return PTR_ERR(ep93xx_rtc->rtc);
rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
ep93xx_rtc->rtc->ops = &ep93xx_rtc_ops;
ep93xx_rtc->rtc->range_max = U32_MAX;
rtc->ops = &ep93xx_rtc_ops;
rtc->range_max = U32_MAX;
err = rtc_add_group(ep93xx_rtc->rtc, &ep93xx_rtc_sysfs_files);
err = rtc_add_group(rtc, &ep93xx_rtc_sysfs_files);
if (err)
return err;
return devm_rtc_register_device(ep93xx_rtc->rtc);
return devm_rtc_register_device(rtc);
}
static const struct of_device_id ep93xx_rtc_of_ids[] = {

View File

@ -309,7 +309,7 @@ static const struct of_device_id ftm_rtc_match[] = {
};
MODULE_DEVICE_TABLE(of, ftm_rtc_match);
static const struct acpi_device_id ftm_imx_acpi_ids[] = {
static const struct acpi_device_id ftm_imx_acpi_ids[] __maybe_unused = {
{"NXP0014",},
{ }
};

View File

@ -28,7 +28,6 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
struct ftrtc010_rtc {
struct rtc_device *rtc_dev;
void __iomem *rtc_base;
int rtc_irq;
struct clk *pclk;
@ -113,6 +112,7 @@ static int ftrtc010_rtc_probe(struct platform_device *pdev)
struct ftrtc010_rtc *rtc;
struct device *dev = &pdev->dev;
struct resource *res;
struct rtc_device *rtc_dev;
int ret;
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
@ -160,29 +160,28 @@ static int ftrtc010_rtc_probe(struct platform_device *pdev)
goto err_disable_extclk;
}
rtc->rtc_dev = devm_rtc_allocate_device(dev);
if (IS_ERR(rtc->rtc_dev)) {
ret = PTR_ERR(rtc->rtc_dev);
rtc_dev = devm_rtc_allocate_device(dev);
if (IS_ERR(rtc_dev)) {
ret = PTR_ERR(rtc_dev);
goto err_disable_extclk;
}
rtc->rtc_dev->ops = &ftrtc010_rtc_ops;
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;
rtc_dev->range_min = (u64)days * 86400 + hour * 3600 + min * 60 + sec;
rtc_dev->range_max = U32_MAX + rtc_dev->range_min;
ret = devm_request_irq(dev, rtc->rtc_irq, ftrtc010_rtc_interrupt,
IRQF_SHARED, pdev->name, dev);
if (unlikely(ret))
goto err_disable_extclk;
return devm_rtc_register_device(rtc->rtc_dev);
return devm_rtc_register_device(rtc_dev);
err_disable_extclk:
clk_disable_unprepare(rtc->extclk);

View File

@ -41,7 +41,6 @@
struct m48t86_rtc_info {
void __iomem *index_reg;
void __iomem *data_reg;
struct rtc_device *rtc;
};
static unsigned char m48t86_readb(struct device *dev, unsigned long addr)
@ -219,6 +218,7 @@ static bool m48t86_verify_chip(struct platform_device *pdev)
static int m48t86_rtc_probe(struct platform_device *pdev)
{
struct m48t86_rtc_info *info;
struct rtc_device *rtc;
unsigned char reg;
int err;
struct nvmem_config m48t86_nvmem_cfg = {
@ -250,17 +250,17 @@ static int m48t86_rtc_probe(struct platform_device *pdev)
return -ENODEV;
}
info->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(info->rtc))
return PTR_ERR(info->rtc);
rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
info->rtc->ops = &m48t86_rtc_ops;
rtc->ops = &m48t86_rtc_ops;
err = devm_rtc_register_device(info->rtc);
err = devm_rtc_register_device(rtc);
if (err)
return err;
devm_rtc_nvmem_register(info->rtc, &m48t86_nvmem_cfg);
devm_rtc_nvmem_register(rtc, &m48t86_nvmem_cfg);
/* read battery status */
reg = m48t86_readb(&pdev->dev, M48T86_D);

View File

@ -184,31 +184,91 @@
#define MAX31335_RAM_SIZE 32
#define MAX31335_TIME_SIZE 0x07
/* MAX31331 Register Map */
#define MAX31331_RTC_CONFIG2 0x04
#define clk_hw_to_max31335(_hw) container_of(_hw, struct max31335_data, clkout)
/* Supported Maxim RTC */
enum max_rtc_ids {
ID_MAX31331,
ID_MAX31335,
MAX_RTC_ID_NR
};
struct chip_desc {
u8 sec_reg;
u8 alarm1_sec_reg;
u8 int_en_reg;
u8 int_status_reg;
u8 ram_reg;
u8 ram_size;
u8 temp_reg;
u8 trickle_reg;
u8 clkout_reg;
enum max_rtc_ids id;
};
struct max31335_data {
struct regmap *regmap;
struct rtc_device *rtc;
struct clk_hw clkout;
struct clk *clkin;
const struct chip_desc *chip;
int irq;
};
static const int max31335_clkout_freq[] = { 1, 64, 1024, 32768 };
static const struct chip_desc chip[MAX_RTC_ID_NR] = {
[ID_MAX31331] = {
.id = ID_MAX31331,
.int_en_reg = 0x01,
.int_status_reg = 0x00,
.sec_reg = 0x08,
.alarm1_sec_reg = 0x0F,
.ram_reg = 0x20,
.ram_size = 32,
.trickle_reg = 0x1B,
.clkout_reg = 0x04,
},
[ID_MAX31335] = {
.id = ID_MAX31335,
.int_en_reg = 0x01,
.int_status_reg = 0x00,
.sec_reg = 0x0A,
.alarm1_sec_reg = 0x11,
.ram_reg = 0x40,
.ram_size = 32,
.temp_reg = 0x35,
.trickle_reg = 0x1D,
.clkout_reg = 0x06,
},
};
static const u16 max31335_trickle_resistors[] = {3000, 6000, 11000};
static bool max31335_volatile_reg(struct device *dev, unsigned int reg)
{
struct max31335_data *max31335 = dev_get_drvdata(dev);
const struct chip_desc *chip = max31335->chip;
/* time keeping registers */
if (reg >= MAX31335_SECONDS &&
reg < MAX31335_SECONDS + MAX31335_TIME_SIZE)
if (reg >= chip->sec_reg && reg < chip->sec_reg + MAX31335_TIME_SIZE)
return true;
/* interrupt status register */
if (reg == MAX31335_STATUS1)
if (reg == chip->int_status_reg)
return true;
/* temperature registers */
if (reg == MAX31335_TEMP_DATA_MSB || reg == MAX31335_TEMP_DATA_LSB)
/* temperature registers if valid */
if (chip->temp_reg && (reg == chip->temp_reg || reg == chip->temp_reg + 1))
return true;
return false;
@ -227,7 +287,7 @@ static int max31335_read_time(struct device *dev, struct rtc_time *tm)
u8 date[7];
int ret;
ret = regmap_bulk_read(max31335->regmap, MAX31335_SECONDS, date,
ret = regmap_bulk_read(max31335->regmap, max31335->chip->sec_reg, date,
sizeof(date));
if (ret)
return ret;
@ -262,7 +322,7 @@ static int max31335_set_time(struct device *dev, struct rtc_time *tm)
if (tm->tm_year >= 200)
date[5] |= FIELD_PREP(MAX31335_MONTH_CENTURY, 1);
return regmap_bulk_write(max31335->regmap, MAX31335_SECONDS, date,
return regmap_bulk_write(max31335->regmap, max31335->chip->sec_reg, date,
sizeof(date));
}
@ -273,7 +333,7 @@ static int max31335_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct rtc_time time;
u8 regs[6];
ret = regmap_bulk_read(max31335->regmap, MAX31335_ALM1_SEC, regs,
ret = regmap_bulk_read(max31335->regmap, max31335->chip->alarm1_sec_reg, regs,
sizeof(regs));
if (ret)
return ret;
@ -292,11 +352,11 @@ static int max31335_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
if (time.tm_year >= 200)
alrm->time.tm_year += 100;
ret = regmap_read(max31335->regmap, MAX31335_INT_EN1, &ctrl);
ret = regmap_read(max31335->regmap, max31335->chip->int_en_reg, &ctrl);
if (ret)
return ret;
ret = regmap_read(max31335->regmap, MAX31335_STATUS1, &status);
ret = regmap_read(max31335->regmap, max31335->chip->int_status_reg, &status);
if (ret)
return ret;
@ -320,18 +380,18 @@ static int max31335_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
regs[4] = bin2bcd(alrm->time.tm_mon + 1);
regs[5] = bin2bcd(alrm->time.tm_year % 100);
ret = regmap_bulk_write(max31335->regmap, MAX31335_ALM1_SEC,
ret = regmap_bulk_write(max31335->regmap, max31335->chip->alarm1_sec_reg,
regs, sizeof(regs));
if (ret)
return ret;
reg = FIELD_PREP(MAX31335_INT_EN1_A1IE, alrm->enabled);
ret = regmap_update_bits(max31335->regmap, MAX31335_INT_EN1,
ret = regmap_update_bits(max31335->regmap, max31335->chip->int_en_reg,
MAX31335_INT_EN1_A1IE, reg);
if (ret)
return ret;
ret = regmap_update_bits(max31335->regmap, MAX31335_STATUS1,
ret = regmap_update_bits(max31335->regmap, max31335->chip->int_status_reg,
MAX31335_STATUS1_A1F, 0);
return 0;
@ -341,23 +401,33 @@ static int max31335_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
struct max31335_data *max31335 = dev_get_drvdata(dev);
return regmap_update_bits(max31335->regmap, MAX31335_INT_EN1,
return regmap_update_bits(max31335->regmap, max31335->chip->int_en_reg,
MAX31335_INT_EN1_A1IE, enabled);
}
static irqreturn_t max31335_handle_irq(int irq, void *dev_id)
{
struct max31335_data *max31335 = dev_id;
bool status;
int ret;
struct mutex *lock = &max31335->rtc->ops_lock;
int ret, status;
ret = regmap_update_bits_check(max31335->regmap, MAX31335_STATUS1,
MAX31335_STATUS1_A1F, 0, &status);
mutex_lock(lock);
ret = regmap_read(max31335->regmap, max31335->chip->int_status_reg, &status);
if (ret)
return IRQ_HANDLED;
goto exit;
if (FIELD_GET(MAX31335_STATUS1_A1F, status)) {
ret = regmap_update_bits(max31335->regmap, max31335->chip->int_status_reg,
MAX31335_STATUS1_A1F, 0);
if (ret)
goto exit;
if (status)
rtc_update_irq(max31335->rtc, 1, RTC_AF | RTC_IRQF);
}
exit:
mutex_unlock(lock);
return IRQ_HANDLED;
}
@ -404,7 +474,7 @@ static int max31335_trickle_charger_setup(struct device *dev,
i = i + trickle_cfg;
return regmap_write(max31335->regmap, MAX31335_TRICKLE_REG,
return regmap_write(max31335->regmap, max31335->chip->trickle_reg,
FIELD_PREP(MAX31335_TRICKLE_REG_TRICKLE, i) |
FIELD_PREP(MAX31335_TRICKLE_REG_EN_TRICKLE,
chargeable));
@ -418,7 +488,7 @@ static unsigned long max31335_clkout_recalc_rate(struct clk_hw *hw,
unsigned int reg;
int ret;
ret = regmap_read(max31335->regmap, MAX31335_RTC_CONFIG2, &reg);
ret = regmap_read(max31335->regmap, max31335->chip->clkout_reg, &reg);
if (ret)
return 0;
@ -449,23 +519,23 @@ static int max31335_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
ARRAY_SIZE(max31335_clkout_freq));
freq_mask = __roundup_pow_of_two(ARRAY_SIZE(max31335_clkout_freq)) - 1;
return regmap_update_bits(max31335->regmap, MAX31335_RTC_CONFIG2,
freq_mask, index);
return regmap_update_bits(max31335->regmap, max31335->chip->clkout_reg,
freq_mask, index);
}
static int max31335_clkout_enable(struct clk_hw *hw)
{
struct max31335_data *max31335 = clk_hw_to_max31335(hw);
return regmap_set_bits(max31335->regmap, MAX31335_RTC_CONFIG2,
MAX31335_RTC_CONFIG2_ENCLKO);
return regmap_set_bits(max31335->regmap, max31335->chip->clkout_reg,
MAX31335_RTC_CONFIG2_ENCLKO);
}
static void max31335_clkout_disable(struct clk_hw *hw)
{
struct max31335_data *max31335 = clk_hw_to_max31335(hw);
regmap_clear_bits(max31335->regmap, MAX31335_RTC_CONFIG2,
regmap_clear_bits(max31335->regmap, max31335->chip->clkout_reg,
MAX31335_RTC_CONFIG2_ENCLKO);
}
@ -475,7 +545,7 @@ static int max31335_clkout_is_enabled(struct clk_hw *hw)
unsigned int reg;
int ret;
ret = regmap_read(max31335->regmap, MAX31335_RTC_CONFIG2, &reg);
ret = regmap_read(max31335->regmap, max31335->chip->clkout_reg, &reg);
if (ret)
return ret;
@ -500,7 +570,7 @@ static int max31335_nvmem_reg_read(void *priv, unsigned int offset,
void *val, size_t bytes)
{
struct max31335_data *max31335 = priv;
unsigned int reg = MAX31335_TS0_SEC_1_128 + offset;
unsigned int reg = max31335->chip->ram_reg + offset;
return regmap_bulk_read(max31335->regmap, reg, val, bytes);
}
@ -509,7 +579,7 @@ static int max31335_nvmem_reg_write(void *priv, unsigned int offset,
void *val, size_t bytes)
{
struct max31335_data *max31335 = priv;
unsigned int reg = MAX31335_TS0_SEC_1_128 + offset;
unsigned int reg = max31335->chip->ram_reg + offset;
return regmap_bulk_write(max31335->regmap, reg, val, bytes);
}
@ -533,7 +603,7 @@ static int max31335_read_temp(struct device *dev, enum hwmon_sensor_types type,
if (type != hwmon_temp || attr != hwmon_temp_input)
return -EOPNOTSUPP;
ret = regmap_bulk_read(max31335->regmap, MAX31335_TEMP_DATA_MSB,
ret = regmap_bulk_read(max31335->regmap, max31335->chip->temp_reg,
reg, 2);
if (ret)
return ret;
@ -577,8 +647,8 @@ static int max31335_clkout_register(struct device *dev)
int ret;
if (!device_property_present(dev, "#clock-cells"))
return regmap_clear_bits(max31335->regmap, MAX31335_RTC_CONFIG2,
MAX31335_RTC_CONFIG2_ENCLKO);
return regmap_clear_bits(max31335->regmap, max31335->chip->clkout_reg,
MAX31335_RTC_CONFIG2_ENCLKO);
max31335->clkout.init = &max31335_clk_init;
@ -605,6 +675,7 @@ static int max31335_probe(struct i2c_client *client)
#if IS_REACHABLE(HWMON)
struct device *hwmon;
#endif
const struct chip_desc *match;
int ret;
max31335 = devm_kzalloc(&client->dev, sizeof(*max31335), GFP_KERNEL);
@ -616,7 +687,10 @@ static int max31335_probe(struct i2c_client *client)
return PTR_ERR(max31335->regmap);
i2c_set_clientdata(client, max31335);
match = i2c_get_match_data(client);
if (!match)
return -ENODEV;
max31335->chip = match;
max31335->rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(max31335->rtc))
return PTR_ERR(max31335->rtc);
@ -639,6 +713,8 @@ static int max31335_probe(struct i2c_client *client)
dev_warn(&client->dev,
"unable to request IRQ, alarm max31335 disabled\n");
client->irq = 0;
} else {
max31335->irq = client->irq;
}
}
@ -652,13 +728,13 @@ static int max31335_probe(struct i2c_client *client)
"cannot register rtc nvmem\n");
#if IS_REACHABLE(HWMON)
hwmon = devm_hwmon_device_register_with_info(&client->dev, client->name,
max31335,
&max31335_chip_info,
NULL);
if (IS_ERR(hwmon))
return dev_err_probe(&client->dev, PTR_ERR(hwmon),
"cannot register hwmon device\n");
if (max31335->chip->temp_reg) {
hwmon = devm_hwmon_device_register_with_info(&client->dev, client->name, max31335,
&max31335_chip_info, NULL);
if (IS_ERR(hwmon))
return dev_err_probe(&client->dev, PTR_ERR(hwmon),
"cannot register hwmon device\n");
}
#endif
ret = max31335_trickle_charger_setup(&client->dev, max31335);
@ -669,14 +745,16 @@ static int max31335_probe(struct i2c_client *client)
}
static const struct i2c_device_id max31335_id[] = {
{ "max31335" },
{ "max31331", (kernel_ulong_t)&chip[ID_MAX31331] },
{ "max31335", (kernel_ulong_t)&chip[ID_MAX31335] },
{ }
};
MODULE_DEVICE_TABLE(i2c, max31335_id);
static const struct of_device_id max31335_of_match[] = {
{ .compatible = "adi,max31335" },
{ .compatible = "adi,max31331", .data = &chip[ID_MAX31331] },
{ .compatible = "adi,max31335", .data = &chip[ID_MAX31335] },
{ }
};
@ -693,5 +771,6 @@ static struct i2c_driver max31335_driver = {
module_i2c_driver(max31335_driver);
MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com>");
MODULE_AUTHOR("Saket Kumar Purwar <Saket.Kumarpurwar@analog.com>");
MODULE_DESCRIPTION("MAX31335 RTC driver");
MODULE_LICENSE("GPL");

View File

@ -85,7 +85,6 @@ struct max77686_rtc_driver_data {
struct max77686_rtc_info {
struct device *dev;
struct i2c_client *rtc;
struct rtc_device *rtc_dev;
struct mutex lock;
@ -691,6 +690,7 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
{
struct device *parent = info->dev->parent;
struct i2c_client *parent_i2c = to_i2c_client(parent);
struct i2c_client *client;
int ret;
if (info->drv_data->rtc_irq_from_platform) {
@ -704,40 +704,35 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
}
info->regmap = dev_get_regmap(parent, NULL);
if (!info->regmap) {
dev_err(info->dev, "Failed to get rtc regmap\n");
return -ENODEV;
}
if (!info->regmap)
return dev_err_probe(info->dev, -ENODEV,
"Failed to get rtc regmap\n");
if (info->drv_data->rtc_i2c_addr == MAX77686_INVALID_I2C_ADDR) {
info->rtc_regmap = info->regmap;
goto add_rtc_irq;
}
info->rtc = devm_i2c_new_dummy_device(info->dev, parent_i2c->adapter,
info->drv_data->rtc_i2c_addr);
if (IS_ERR(info->rtc)) {
dev_err(info->dev, "Failed to allocate I2C device for RTC\n");
return PTR_ERR(info->rtc);
}
client = devm_i2c_new_dummy_device(info->dev, parent_i2c->adapter,
info->drv_data->rtc_i2c_addr);
if (IS_ERR(client))
return dev_err_probe(info->dev, PTR_ERR(client),
"Failed to allocate I2C device for RTC\n");
info->rtc_regmap = devm_regmap_init_i2c(info->rtc,
info->rtc_regmap = devm_regmap_init_i2c(client,
info->drv_data->regmap_config);
if (IS_ERR(info->rtc_regmap)) {
ret = PTR_ERR(info->rtc_regmap);
dev_err(info->dev, "Failed to allocate RTC regmap: %d\n", ret);
return ret;
}
if (IS_ERR(info->rtc_regmap))
return dev_err_probe(info->dev, PTR_ERR(info->rtc_regmap),
"Failed to allocate RTC regmap\n");
add_rtc_irq:
ret = regmap_add_irq_chip(info->rtc_regmap, info->rtc_irq,
IRQF_ONESHOT | IRQF_SHARED,
0, info->drv_data->rtc_irq_chip,
&info->rtc_irq_data);
if (ret < 0) {
dev_err(info->dev, "Failed to add RTC irq chip: %d\n", ret);
return ret;
}
if (ret < 0)
return dev_err_probe(info->dev, ret,
"Failed to add RTC irq chip\n");
return 0;
}

View File

@ -13,7 +13,6 @@
struct meson_vrtc_data {
void __iomem *io_alarm;
struct rtc_device *rtc;
unsigned long alarm_time;
bool enabled;
};
@ -65,6 +64,7 @@ static const struct rtc_class_ops meson_vrtc_ops = {
static int meson_vrtc_probe(struct platform_device *pdev)
{
struct meson_vrtc_data *vrtc;
struct rtc_device *rtc;
vrtc = devm_kzalloc(&pdev->dev, sizeof(*vrtc), GFP_KERNEL);
if (!vrtc)
@ -78,12 +78,12 @@ static int meson_vrtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, vrtc);
vrtc->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(vrtc->rtc))
return PTR_ERR(vrtc->rtc);
rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
vrtc->rtc->ops = &meson_vrtc_ops;
return devm_rtc_register_device(vrtc->rtc);
rtc->ops = &meson_vrtc_ops;
return devm_rtc_register_device(rtc);
}
static int __maybe_unused meson_vrtc_suspend(struct device *dev)

View File

@ -59,7 +59,6 @@
#define MESON_STATIC_DEFAULT (MESON_STATIC_BIAS_CUR | MESON_STATIC_VOLTAGE)
struct meson_rtc {
struct rtc_device *rtc; /* rtc device we created */
struct device *dev; /* device we bound from */
struct reset_control *reset; /* reset source */
struct regulator *vdd; /* voltage input */
@ -292,6 +291,7 @@ static int meson_rtc_probe(struct platform_device *pdev)
};
struct device *dev = &pdev->dev;
struct meson_rtc *rtc;
struct rtc_device *rtc_dev;
void __iomem *base;
int ret;
u32 tm;
@ -300,16 +300,16 @@ static int meson_rtc_probe(struct platform_device *pdev)
if (!rtc)
return -ENOMEM;
rtc->rtc = devm_rtc_allocate_device(dev);
if (IS_ERR(rtc->rtc))
return PTR_ERR(rtc->rtc);
rtc_dev = devm_rtc_allocate_device(dev);
if (IS_ERR(rtc_dev))
return PTR_ERR(rtc_dev);
platform_set_drvdata(pdev, rtc);
rtc->dev = dev;
rtc->rtc->ops = &meson_rtc_ops;
rtc->rtc->range_max = U32_MAX;
rtc_dev->ops = &meson_rtc_ops;
rtc_dev->range_max = U32_MAX;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
@ -365,11 +365,11 @@ static int meson_rtc_probe(struct platform_device *pdev)
}
meson_rtc_nvmem_config.priv = rtc;
ret = devm_rtc_nvmem_register(rtc->rtc, &meson_rtc_nvmem_config);
ret = devm_rtc_nvmem_register(rtc_dev, &meson_rtc_nvmem_config);
if (ret)
goto out_disable_vdd;
ret = devm_rtc_register_device(rtc->rtc);
ret = devm_rtc_register_device(rtc_dev);
if (ret)
goto out_disable_vdd;

View File

@ -266,19 +266,14 @@ static int mpfs_rtc_probe(struct platform_device *pdev)
writel(prescaler, rtcdev->base + PRESCALER_REG);
dev_info(&pdev->dev, "prescaler set to: %lu\n", prescaler);
device_init_wakeup(&pdev->dev, true);
ret = dev_pm_set_wake_irq(&pdev->dev, wakeup_irq);
devm_device_init_wakeup(&pdev->dev);
ret = devm_pm_set_wake_irq(&pdev->dev, wakeup_irq);
if (ret)
dev_err(&pdev->dev, "failed to enable irq wake\n");
return devm_rtc_register_device(rtcdev->rtc);
}
static void mpfs_rtc_remove(struct platform_device *pdev)
{
dev_pm_clear_wake_irq(&pdev->dev);
}
static const struct of_device_id mpfs_rtc_of_match[] = {
{ .compatible = "microchip,mpfs-rtc" },
{ }
@ -288,7 +283,6 @@ MODULE_DEVICE_TABLE(of, mpfs_rtc_of_match);
static struct platform_driver mpfs_rtc_driver = {
.probe = mpfs_rtc_probe,
.remove = mpfs_rtc_remove,
.driver = {
.name = "mpfs_rtc",
.of_match_table = mpfs_rtc_of_match,

View File

@ -189,36 +189,26 @@ static int bbnsm_rtc_probe(struct platform_device *pdev)
/* clear all the pending events */
regmap_write(bbnsm->regmap, BBNSM_EVENTS, 0x7A);
device_init_wakeup(&pdev->dev, true);
dev_pm_set_wake_irq(&pdev->dev, bbnsm->irq);
ret = devm_device_init_wakeup(&pdev->dev);
if (ret)
dev_err(&pdev->dev, "failed to init wakeup, %d\n", ret);
ret = devm_pm_set_wake_irq(&pdev->dev, bbnsm->irq);
if (ret)
dev_err(&pdev->dev, "failed to set wake irq, %d\n", ret);
ret = devm_request_irq(&pdev->dev, bbnsm->irq, bbnsm_rtc_irq_handler,
IRQF_SHARED, "rtc alarm", &pdev->dev);
if (ret) {
dev_err(&pdev->dev, "failed to request irq %d: %d\n",
bbnsm->irq, ret);
goto err;
return ret;
}
bbnsm->rtc->ops = &bbnsm_rtc_ops;
bbnsm->rtc->range_max = U32_MAX;
ret = devm_rtc_register_device(bbnsm->rtc);
if (ret)
goto err;
return 0;
err:
dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
return ret;
}
static void bbnsm_rtc_remove(struct platform_device *pdev)
{
dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
return devm_rtc_register_device(bbnsm->rtc);
}
static const struct of_device_id bbnsm_dt_ids[] = {
@ -233,7 +223,6 @@ static struct platform_driver bbnsm_rtc_driver = {
.of_match_table = bbnsm_dt_ids,
},
.probe = bbnsm_rtc_probe,
.remove = bbnsm_rtc_remove,
};
module_platform_driver(bbnsm_rtc_driver);

View File

@ -1,284 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/* NXP PCF50633 RTC Driver
*
* (C) 2006-2008 by Openmoko, Inc.
* Author: Balaji Rao <balajirrao@openmoko.org>
* All rights reserved.
*
* Broken down from monstrous PCF50633 driver mainly by
* Harald Welte, Andy Green and Werner Almesberger
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/err.h>
#include <linux/mfd/pcf50633/core.h>
#define PCF50633_REG_RTCSC 0x59 /* Second */
#define PCF50633_REG_RTCMN 0x5a /* Minute */
#define PCF50633_REG_RTCHR 0x5b /* Hour */
#define PCF50633_REG_RTCWD 0x5c /* Weekday */
#define PCF50633_REG_RTCDT 0x5d /* Day */
#define PCF50633_REG_RTCMT 0x5e /* Month */
#define PCF50633_REG_RTCYR 0x5f /* Year */
#define PCF50633_REG_RTCSCA 0x60 /* Alarm Second */
#define PCF50633_REG_RTCMNA 0x61 /* Alarm Minute */
#define PCF50633_REG_RTCHRA 0x62 /* Alarm Hour */
#define PCF50633_REG_RTCWDA 0x63 /* Alarm Weekday */
#define PCF50633_REG_RTCDTA 0x64 /* Alarm Day */
#define PCF50633_REG_RTCMTA 0x65 /* Alarm Month */
#define PCF50633_REG_RTCYRA 0x66 /* Alarm Year */
enum pcf50633_time_indexes {
PCF50633_TI_SEC,
PCF50633_TI_MIN,
PCF50633_TI_HOUR,
PCF50633_TI_WKDAY,
PCF50633_TI_DAY,
PCF50633_TI_MONTH,
PCF50633_TI_YEAR,
PCF50633_TI_EXTENT /* always last */
};
struct pcf50633_time {
u_int8_t time[PCF50633_TI_EXTENT];
};
struct pcf50633_rtc {
int alarm_enabled;
int alarm_pending;
struct pcf50633 *pcf;
struct rtc_device *rtc_dev;
};
static void pcf2rtc_time(struct rtc_time *rtc, struct pcf50633_time *pcf)
{
rtc->tm_sec = bcd2bin(pcf->time[PCF50633_TI_SEC]);
rtc->tm_min = bcd2bin(pcf->time[PCF50633_TI_MIN]);
rtc->tm_hour = bcd2bin(pcf->time[PCF50633_TI_HOUR]);
rtc->tm_wday = bcd2bin(pcf->time[PCF50633_TI_WKDAY]);
rtc->tm_mday = bcd2bin(pcf->time[PCF50633_TI_DAY]);
rtc->tm_mon = bcd2bin(pcf->time[PCF50633_TI_MONTH]) - 1;
rtc->tm_year = bcd2bin(pcf->time[PCF50633_TI_YEAR]) + 100;
}
static void rtc2pcf_time(struct pcf50633_time *pcf, struct rtc_time *rtc)
{
pcf->time[PCF50633_TI_SEC] = bin2bcd(rtc->tm_sec);
pcf->time[PCF50633_TI_MIN] = bin2bcd(rtc->tm_min);
pcf->time[PCF50633_TI_HOUR] = bin2bcd(rtc->tm_hour);
pcf->time[PCF50633_TI_WKDAY] = bin2bcd(rtc->tm_wday);
pcf->time[PCF50633_TI_DAY] = bin2bcd(rtc->tm_mday);
pcf->time[PCF50633_TI_MONTH] = bin2bcd(rtc->tm_mon + 1);
pcf->time[PCF50633_TI_YEAR] = bin2bcd(rtc->tm_year % 100);
}
static int
pcf50633_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
struct pcf50633_rtc *rtc = dev_get_drvdata(dev);
int err;
if (enabled)
err = pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
else
err = pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM);
if (err < 0)
return err;
rtc->alarm_enabled = enabled;
return 0;
}
static int pcf50633_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct pcf50633_rtc *rtc;
struct pcf50633_time pcf_tm;
int ret;
rtc = dev_get_drvdata(dev);
ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSC,
PCF50633_TI_EXTENT,
&pcf_tm.time[0]);
if (ret != PCF50633_TI_EXTENT) {
dev_err(dev, "Failed to read time\n");
return -EIO;
}
dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n",
pcf_tm.time[PCF50633_TI_DAY],
pcf_tm.time[PCF50633_TI_MONTH],
pcf_tm.time[PCF50633_TI_YEAR],
pcf_tm.time[PCF50633_TI_HOUR],
pcf_tm.time[PCF50633_TI_MIN],
pcf_tm.time[PCF50633_TI_SEC]);
pcf2rtc_time(tm, &pcf_tm);
dev_dbg(dev, "RTC_TIME: %ptRr\n", tm);
return 0;
}
static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct pcf50633_rtc *rtc;
struct pcf50633_time pcf_tm;
int alarm_masked, ret = 0;
rtc = dev_get_drvdata(dev);
dev_dbg(dev, "RTC_TIME: %ptRr\n", tm);
rtc2pcf_time(&pcf_tm, tm);
dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n",
pcf_tm.time[PCF50633_TI_DAY],
pcf_tm.time[PCF50633_TI_MONTH],
pcf_tm.time[PCF50633_TI_YEAR],
pcf_tm.time[PCF50633_TI_HOUR],
pcf_tm.time[PCF50633_TI_MIN],
pcf_tm.time[PCF50633_TI_SEC]);
alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM);
if (!alarm_masked)
pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM);
/* Returns 0 on success */
ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSC,
PCF50633_TI_EXTENT,
&pcf_tm.time[0]);
if (!alarm_masked)
pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
return ret;
}
static int pcf50633_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct pcf50633_rtc *rtc;
struct pcf50633_time pcf_tm;
int ret = 0;
rtc = dev_get_drvdata(dev);
alrm->enabled = rtc->alarm_enabled;
alrm->pending = rtc->alarm_pending;
ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSCA,
PCF50633_TI_EXTENT, &pcf_tm.time[0]);
if (ret != PCF50633_TI_EXTENT) {
dev_err(dev, "Failed to read time\n");
return -EIO;
}
pcf2rtc_time(&alrm->time, &pcf_tm);
return rtc_valid_tm(&alrm->time);
}
static int pcf50633_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct pcf50633_rtc *rtc;
struct pcf50633_time pcf_tm;
int alarm_masked, ret = 0;
rtc = dev_get_drvdata(dev);
rtc2pcf_time(&pcf_tm, &alrm->time);
/* do like mktime does and ignore tm_wday */
pcf_tm.time[PCF50633_TI_WKDAY] = 7;
alarm_masked = pcf50633_irq_mask_get(rtc->pcf, PCF50633_IRQ_ALARM);
/* disable alarm interrupt */
if (!alarm_masked)
pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_ALARM);
/* Returns 0 on success */
ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA,
PCF50633_TI_EXTENT, &pcf_tm.time[0]);
if (!alrm->enabled)
rtc->alarm_pending = 0;
if (!alarm_masked || alrm->enabled)
pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
rtc->alarm_enabled = alrm->enabled;
return ret;
}
static const struct rtc_class_ops pcf50633_rtc_ops = {
.read_time = pcf50633_rtc_read_time,
.set_time = pcf50633_rtc_set_time,
.read_alarm = pcf50633_rtc_read_alarm,
.set_alarm = pcf50633_rtc_set_alarm,
.alarm_irq_enable = pcf50633_rtc_alarm_irq_enable,
};
static void pcf50633_rtc_irq(int irq, void *data)
{
struct pcf50633_rtc *rtc = data;
rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
rtc->alarm_pending = 1;
}
static int pcf50633_rtc_probe(struct platform_device *pdev)
{
struct pcf50633_rtc *rtc;
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
if (!rtc)
return -ENOMEM;
rtc->pcf = dev_to_pcf50633(pdev->dev.parent);
platform_set_drvdata(pdev, rtc);
rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, "pcf50633-rtc",
&pcf50633_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc_dev))
return PTR_ERR(rtc->rtc_dev);
pcf50633_register_irq(rtc->pcf, PCF50633_IRQ_ALARM,
pcf50633_rtc_irq, rtc);
return 0;
}
static void pcf50633_rtc_remove(struct platform_device *pdev)
{
struct pcf50633_rtc *rtc;
rtc = platform_get_drvdata(pdev);
pcf50633_free_irq(rtc->pcf, PCF50633_IRQ_ALARM);
}
static struct platform_driver pcf50633_rtc_driver = {
.driver = {
.name = "pcf50633-rtc",
},
.probe = pcf50633_rtc_probe,
.remove = pcf50633_rtc_remove,
};
module_platform_driver(pcf50633_rtc_driver);
MODULE_DESCRIPTION("PCF50633 RTC driver");
MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
MODULE_LICENSE("GPL");

View File

@ -35,6 +35,7 @@
#define PCF85063_REG_CTRL1_CAP_SEL BIT(0)
#define PCF85063_REG_CTRL1_STOP BIT(5)
#define PCF85063_REG_CTRL1_EXT_TEST BIT(7)
#define PCF85063_REG_CTRL1_SWR 0x58
#define PCF85063_REG_CTRL2 0x01
#define PCF85063_CTRL2_AF BIT(6)
@ -589,16 +590,30 @@ static int pcf85063_probe(struct i2c_client *client)
i2c_set_clientdata(client, pcf85063);
err = regmap_read(pcf85063->regmap, PCF85063_REG_CTRL1, &tmp);
if (err) {
dev_err(&client->dev, "RTC chip is not present\n");
return err;
}
err = regmap_read(pcf85063->regmap, PCF85063_REG_SC, &tmp);
if (err)
return dev_err_probe(&client->dev, err, "RTC chip is not present\n");
pcf85063->rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(pcf85063->rtc))
return PTR_ERR(pcf85063->rtc);
/*
* If a Power loss is detected, SW reset the device.
* From PCF85063A datasheet:
* There is a low probability that some devices will have corruption
* of the registers after the automatic power-on reset...
*/
if (tmp & PCF85063_REG_SC_OS) {
dev_warn(&client->dev,
"POR issue detected, sending a SW reset\n");
err = regmap_write(pcf85063->regmap, PCF85063_REG_CTRL1,
PCF85063_REG_CTRL1_SWR);
if (err < 0)
dev_warn(&client->dev,
"SW reset failed, trying to continue\n");
}
err = pcf85063_load_capacitance(pcf85063, client->dev.of_node,
config->force_cap_7000 ? 7000 : 0);
if (err < 0)

View File

@ -21,7 +21,6 @@
#define RTC_CR_MIE (1 << 0)
struct pl030_rtc {
struct rtc_device *rtc;
void __iomem *base;
};
@ -86,6 +85,7 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id)
{
struct pl030_rtc *rtc;
int ret;
struct rtc_device *rtc_dev;
ret = amba_request_regions(dev, NULL);
if (ret)
@ -97,14 +97,14 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id)
goto err_rtc;
}
rtc->rtc = devm_rtc_allocate_device(&dev->dev);
if (IS_ERR(rtc->rtc)) {
ret = PTR_ERR(rtc->rtc);
rtc_dev = devm_rtc_allocate_device(&dev->dev);
if (IS_ERR(rtc_dev)) {
ret = PTR_ERR(rtc_dev);
goto err_rtc;
}
rtc->rtc->ops = &pl030_ops;
rtc->rtc->range_max = U32_MAX;
rtc_dev->ops = &pl030_ops;
rtc_dev->range_max = U32_MAX;
rtc->base = ioremap(dev->res.start, resource_size(&dev->res));
if (!rtc->base) {
ret = -ENOMEM;
@ -121,7 +121,7 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id)
if (ret)
goto err_irq;
ret = devm_rtc_register_device(rtc->rtc);
ret = devm_rtc_register_device(rtc_dev);
if (ret)
goto err_reg;
@ -148,7 +148,7 @@ static void pl030_remove(struct amba_device *dev)
amba_release_regions(dev);
}
static struct amba_id pl030_ids[] = {
static const struct amba_id pl030_ids[] = {
{
.id = 0x00041030,
.mask = 0x000fffff,

View File

@ -74,6 +74,8 @@
* @st_weekday: if this is an ST Microelectronics silicon version that need
* the weekday fix
* @irqflags: special IRQ flags per variant
* @range_min: minimum date/time supported by the RTC
* @range_max: maximum date/time supported by the RTC
*/
struct pl031_vendor_data {
struct rtc_class_ops ops;
@ -284,8 +286,6 @@ static void pl031_remove(struct amba_device *adev)
{
struct pl031_local *ldata = dev_get_drvdata(&adev->dev);
dev_pm_clear_wake_irq(&adev->dev);
device_init_wakeup(&adev->dev, false);
if (adev->irq[0])
free_irq(adev->irq[0], ldata);
amba_release_regions(adev);
@ -350,7 +350,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
}
}
device_init_wakeup(&adev->dev, true);
devm_device_init_wakeup(&adev->dev);
ldata->rtc = devm_rtc_allocate_device(&adev->dev);
if (IS_ERR(ldata->rtc)) {
ret = PTR_ERR(ldata->rtc);
@ -373,7 +373,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
vendor->irqflags, "rtc-pl031", ldata);
if (ret)
goto out;
dev_pm_set_wake_irq(&adev->dev, adev->irq[0]);
devm_pm_set_wake_irq(&adev->dev, adev->irq[0]);
}
return 0;

View File

@ -5,6 +5,7 @@
* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
* Copyright (c) 2023, Linaro Limited
*/
#include <linux/efi.h>
#include <linux/of.h>
#include <linux/module.h>
#include <linux/nvmem-consumer.h>
@ -16,9 +17,10 @@
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/unaligned.h>
#include <asm/byteorder.h>
/* RTC_CTRL register bit fields */
#define PM8xxx_RTC_ENABLE BIT(7)
#define PM8xxx_RTC_ALARM_CLEAR BIT(0)
@ -46,28 +48,125 @@ struct pm8xxx_rtc_regs {
unsigned int alarm_en;
};
struct qcom_uefi_rtc_info {
__le32 offset_gps;
u8 reserved[8];
} __packed;
/**
* struct pm8xxx_rtc - RTC driver internal structure
* @rtc: RTC device
* @regmap: regmap used to access registers
* @allow_set_time: whether the time can be set
* @use_uefi: use UEFI variable as fallback for offset
* @alarm_irq: alarm irq number
* @regs: register description
* @dev: device structure
* @rtc_info: qcom uefi rtc-info structure
* @nvmem_cell: nvmem cell for offset
* @offset: offset from epoch in seconds
* @offset_dirty: offset needs to be stored on shutdown
*/
struct pm8xxx_rtc {
struct rtc_device *rtc;
struct regmap *regmap;
bool allow_set_time;
bool use_uefi;
int alarm_irq;
const struct pm8xxx_rtc_regs *regs;
struct device *dev;
struct qcom_uefi_rtc_info rtc_info;
struct nvmem_cell *nvmem_cell;
u32 offset;
bool offset_dirty;
};
#ifdef CONFIG_EFI
MODULE_IMPORT_NS("EFIVAR");
#define QCOM_UEFI_NAME L"RTCInfo"
#define QCOM_UEFI_GUID EFI_GUID(0x882f8c2b, 0x9646, 0x435f, \
0x8d, 0xe5, 0xf2, 0x08, 0xff, 0x80, 0xc1, 0xbd)
#define QCOM_UEFI_ATTRS (EFI_VARIABLE_NON_VOLATILE | \
EFI_VARIABLE_BOOTSERVICE_ACCESS | \
EFI_VARIABLE_RUNTIME_ACCESS)
static int pm8xxx_rtc_read_uefi_offset(struct pm8xxx_rtc *rtc_dd)
{
struct qcom_uefi_rtc_info *rtc_info = &rtc_dd->rtc_info;
unsigned long size = sizeof(*rtc_info);
struct device *dev = rtc_dd->dev;
efi_status_t status;
u32 offset_gps;
int rc;
rc = efivar_lock();
if (rc)
return rc;
status = efivar_get_variable(QCOM_UEFI_NAME, &QCOM_UEFI_GUID, NULL,
&size, rtc_info);
efivar_unlock();
if (status != EFI_SUCCESS) {
dev_dbg(dev, "failed to read UEFI offset: %lu\n", status);
return efi_status_to_err(status);
}
if (size != sizeof(*rtc_info)) {
dev_dbg(dev, "unexpected UEFI structure size %lu\n", size);
return -EINVAL;
}
dev_dbg(dev, "uefi_rtc_info = %*ph\n", (int)size, rtc_info);
/* Convert from GPS to Unix time offset */
offset_gps = le32_to_cpu(rtc_info->offset_gps);
rtc_dd->offset = offset_gps + (u32)RTC_TIMESTAMP_EPOCH_GPS;
return 0;
}
static int pm8xxx_rtc_write_uefi_offset(struct pm8xxx_rtc *rtc_dd, u32 offset)
{
struct qcom_uefi_rtc_info *rtc_info = &rtc_dd->rtc_info;
unsigned long size = sizeof(*rtc_info);
struct device *dev = rtc_dd->dev;
efi_status_t status;
u32 offset_gps;
/* Convert from Unix to GPS time offset */
offset_gps = offset - (u32)RTC_TIMESTAMP_EPOCH_GPS;
rtc_info->offset_gps = cpu_to_le32(offset_gps);
dev_dbg(dev, "efi_rtc_info = %*ph\n", (int)size, rtc_info);
status = efivar_set_variable(QCOM_UEFI_NAME, &QCOM_UEFI_GUID,
QCOM_UEFI_ATTRS, size, rtc_info);
if (status != EFI_SUCCESS) {
dev_dbg(dev, "failed to write UEFI offset: %lx\n", status);
return efi_status_to_err(status);
}
return 0;
}
#else /* CONFIG_EFI */
static int pm8xxx_rtc_read_uefi_offset(struct pm8xxx_rtc *rtc_dd)
{
return -ENODEV;
}
static int pm8xxx_rtc_write_uefi_offset(struct pm8xxx_rtc *rtc_dd, u32 offset)
{
return -ENODEV;
}
#endif /* CONFIG_EFI */
static int pm8xxx_rtc_read_nvmem_offset(struct pm8xxx_rtc *rtc_dd)
{
size_t len;
@ -110,14 +209,6 @@ static int pm8xxx_rtc_write_nvmem_offset(struct pm8xxx_rtc *rtc_dd, u32 offset)
return 0;
}
static int pm8xxx_rtc_read_offset(struct pm8xxx_rtc *rtc_dd)
{
if (!rtc_dd->nvmem_cell)
return 0;
return pm8xxx_rtc_read_nvmem_offset(rtc_dd);
}
static int pm8xxx_rtc_read_raw(struct pm8xxx_rtc *rtc_dd, u32 *secs)
{
const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
@ -155,7 +246,7 @@ static int pm8xxx_rtc_update_offset(struct pm8xxx_rtc *rtc_dd, u32 secs)
u32 offset;
int rc;
if (!rtc_dd->nvmem_cell)
if (!rtc_dd->nvmem_cell && !rtc_dd->use_uefi)
return -ENODEV;
rc = pm8xxx_rtc_read_raw(rtc_dd, &raw_secs);
@ -167,10 +258,25 @@ static int pm8xxx_rtc_update_offset(struct pm8xxx_rtc *rtc_dd, u32 secs)
if (offset == rtc_dd->offset)
return 0;
rc = pm8xxx_rtc_write_nvmem_offset(rtc_dd, offset);
/*
* Reduce flash wear by deferring updates due to clock drift until
* shutdown.
*/
if (abs_diff(offset, rtc_dd->offset) < 30) {
rtc_dd->offset_dirty = true;
goto out;
}
if (rtc_dd->nvmem_cell)
rc = pm8xxx_rtc_write_nvmem_offset(rtc_dd, offset);
else
rc = pm8xxx_rtc_write_uefi_offset(rtc_dd, offset);
if (rc)
return rc;
rtc_dd->offset_dirty = false;
out:
rtc_dd->offset = offset;
return 0;
@ -455,6 +561,30 @@ static const struct of_device_id pm8xxx_id_table[] = {
};
MODULE_DEVICE_TABLE(of, pm8xxx_id_table);
static int pm8xxx_rtc_probe_offset(struct pm8xxx_rtc *rtc_dd)
{
int rc;
rtc_dd->nvmem_cell = devm_nvmem_cell_get(rtc_dd->dev, "offset");
if (IS_ERR(rtc_dd->nvmem_cell)) {
rc = PTR_ERR(rtc_dd->nvmem_cell);
if (rc != -ENOENT)
return rc;
rtc_dd->nvmem_cell = NULL;
} else {
return pm8xxx_rtc_read_nvmem_offset(rtc_dd);
}
/* Use UEFI storage as fallback if available */
if (efivar_is_available()) {
rc = pm8xxx_rtc_read_uefi_offset(rtc_dd);
if (rc == 0)
rtc_dd->use_uefi = true;
}
return 0;
}
static int pm8xxx_rtc_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
@ -469,30 +599,23 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev)
if (rtc_dd == NULL)
return -ENOMEM;
rtc_dd->regs = match->data;
rtc_dd->dev = &pdev->dev;
rtc_dd->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!rtc_dd->regmap)
return -ENXIO;
rtc_dd->alarm_irq = platform_get_irq(pdev, 0);
if (rtc_dd->alarm_irq < 0)
return -ENXIO;
if (!of_property_read_bool(pdev->dev.of_node, "qcom,no-alarm")) {
rtc_dd->alarm_irq = platform_get_irq(pdev, 0);
if (rtc_dd->alarm_irq < 0)
return -ENXIO;
}
rtc_dd->allow_set_time = of_property_read_bool(pdev->dev.of_node,
"allow-set-time");
rtc_dd->nvmem_cell = devm_nvmem_cell_get(&pdev->dev, "offset");
if (IS_ERR(rtc_dd->nvmem_cell)) {
rc = PTR_ERR(rtc_dd->nvmem_cell);
if (rc != -ENOENT)
return rc;
rtc_dd->nvmem_cell = NULL;
}
rtc_dd->regs = match->data;
rtc_dd->dev = &pdev->dev;
if (!rtc_dd->allow_set_time) {
rc = pm8xxx_rtc_read_offset(rtc_dd);
rc = pm8xxx_rtc_probe_offset(rtc_dd);
if (rc)
return rc;
}
@ -503,8 +626,6 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, rtc_dd);
device_init_wakeup(&pdev->dev, true);
rtc_dd->rtc = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc_dd->rtc))
return PTR_ERR(rtc_dd->rtc);
@ -512,32 +633,41 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev)
rtc_dd->rtc->ops = &pm8xxx_rtc_ops;
rtc_dd->rtc->range_max = U32_MAX;
rc = devm_request_any_context_irq(&pdev->dev, rtc_dd->alarm_irq,
pm8xxx_alarm_trigger,
IRQF_TRIGGER_RISING,
"pm8xxx_rtc_alarm", rtc_dd);
if (rc < 0)
return rc;
if (rtc_dd->alarm_irq) {
rc = devm_request_any_context_irq(&pdev->dev, rtc_dd->alarm_irq,
pm8xxx_alarm_trigger,
IRQF_TRIGGER_RISING,
"pm8xxx_rtc_alarm", rtc_dd);
if (rc < 0)
return rc;
rc = devm_rtc_register_device(rtc_dd->rtc);
if (rc)
return rc;
rc = devm_pm_set_wake_irq(&pdev->dev, rtc_dd->alarm_irq);
if (rc)
return rc;
rc = dev_pm_set_wake_irq(&pdev->dev, rtc_dd->alarm_irq);
if (rc)
return rc;
devm_device_init_wakeup(&pdev->dev);
} else {
clear_bit(RTC_FEATURE_ALARM, rtc_dd->rtc->features);
}
return 0;
return devm_rtc_register_device(rtc_dd->rtc);
}
static void pm8xxx_remove(struct platform_device *pdev)
static void pm8xxx_shutdown(struct platform_device *pdev)
{
dev_pm_clear_wake_irq(&pdev->dev);
struct pm8xxx_rtc *rtc_dd = platform_get_drvdata(pdev);
if (rtc_dd->offset_dirty) {
if (rtc_dd->nvmem_cell)
pm8xxx_rtc_write_nvmem_offset(rtc_dd, rtc_dd->offset);
else
pm8xxx_rtc_write_uefi_offset(rtc_dd, rtc_dd->offset);
}
}
static struct platform_driver pm8xxx_rtc_driver = {
.probe = pm8xxx_rtc_probe,
.remove = pm8xxx_remove,
.shutdown = pm8xxx_shutdown,
.driver = {
.name = "rtc-pm8xxx",
.of_match_table = pm8xxx_id_table,

View File

@ -586,17 +586,14 @@ static int rtca3_initial_setup(struct clk *clk, struct rtca3_priv *priv)
*/
usleep_range(sleep_us, sleep_us + 10);
/* Disable all interrupts. */
mask = RTCA3_RCR1_AIE | RTCA3_RCR1_CIE | RTCA3_RCR1_PIE;
ret = rtca3_alarm_irq_set_helper(priv, mask, 0);
if (ret)
return ret;
mask = RTCA3_RCR2_START | RTCA3_RCR2_HR24;
val = readb(priv->base + RTCA3_RCR2);
/* Nothing to do if already started in 24 hours and calendar count mode. */
if ((val & mask) == mask)
return 0;
/* Only disable the interrupts if already started in 24 hours and calendar count mode. */
if ((val & mask) == mask) {
/* Disable all interrupts. */
mask = RTCA3_RCR1_AIE | RTCA3_RCR1_CIE | RTCA3_RCR1_PIE;
return rtca3_alarm_irq_set_helper(priv, mask, 0);
}
/* Reconfigure the RTC in 24 hours and calendar count mode. */
mask = RTCA3_RCR2_START | RTCA3_RCR2_CNTMD;

View File

@ -69,8 +69,7 @@
#define RV3032_CLKOUT2_FD_MSK GENMASK(6, 5)
#define RV3032_CLKOUT2_OS BIT(7)
#define RV3032_CTRL1_EERD BIT(3)
#define RV3032_CTRL1_WADA BIT(5)
#define RV3032_CTRL1_EERD BIT(2)
#define RV3032_CTRL2_STOP BIT(0)
#define RV3032_CTRL2_EIE BIT(2)
@ -947,11 +946,6 @@ static int rv3032_probe(struct i2c_client *client)
if (!client->irq)
clear_bit(RTC_FEATURE_ALARM, rv3032->rtc->features);
ret = regmap_update_bits(rv3032->regmap, RV3032_CTRL1,
RV3032_CTRL1_WADA, RV3032_CTRL1_WADA);
if (ret)
return ret;
rv3032_trickle_charger_setup(&client->dev, rv3032);
set_bit(RTC_FEATURE_BACKUP_SWITCH_MODE, rv3032->rtc->features);

View File

@ -52,11 +52,6 @@
#define RX8571_USER_RAM 0x10
#define RX8571_NVRAM_SIZE 0x10
struct rx8581 {
struct regmap *regmap;
struct rtc_device *rtc;
};
struct rx85x1_config {
struct regmap_config regmap;
unsigned int num_nvram;
@ -72,14 +67,14 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm)
unsigned char date[7];
unsigned int data;
int err;
struct rx8581 *rx8581 = i2c_get_clientdata(client);
struct regmap *regmap = i2c_get_clientdata(client);
/* First we ensure that the "update flag" is not set, we read the
* time and date then re-read the "update flag". If the update flag
* has been set, we know that the time has changed during the read so
* we repeat the whole process again.
*/
err = regmap_read(rx8581->regmap, RX8581_REG_FLAG, &data);
err = regmap_read(regmap, RX8581_REG_FLAG, &data);
if (err < 0)
return err;
@ -92,20 +87,20 @@ static int rx8581_rtc_read_time(struct device *dev, struct rtc_time *tm)
do {
/* If update flag set, clear it */
if (data & RX8581_FLAG_UF) {
err = regmap_write(rx8581->regmap, RX8581_REG_FLAG,
data & ~RX8581_FLAG_UF);
err = regmap_write(regmap, RX8581_REG_FLAG,
data & ~RX8581_FLAG_UF);
if (err < 0)
return err;
}
/* Now read time and date */
err = regmap_bulk_read(rx8581->regmap, RX8581_REG_SC, date,
err = regmap_bulk_read(regmap, RX8581_REG_SC, date,
sizeof(date));
if (err < 0)
return err;
/* Check flag register */
err = regmap_read(rx8581->regmap, RX8581_REG_FLAG, &data);
err = regmap_read(regmap, RX8581_REG_FLAG, &data);
if (err < 0)
return err;
} while (data & RX8581_FLAG_UF);
@ -137,7 +132,7 @@ static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm)
struct i2c_client *client = to_i2c_client(dev);
int err;
unsigned char buf[7];
struct rx8581 *rx8581 = i2c_get_clientdata(client);
struct regmap *regmap = i2c_get_clientdata(client);
dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
@ -160,25 +155,23 @@ static int rx8581_rtc_set_time(struct device *dev, struct rtc_time *tm)
buf[RX8581_REG_DW] = (0x1 << tm->tm_wday);
/* Stop the clock */
err = regmap_update_bits(rx8581->regmap, RX8581_REG_CTRL,
err = regmap_update_bits(regmap, RX8581_REG_CTRL,
RX8581_CTRL_STOP, RX8581_CTRL_STOP);
if (err < 0)
return err;
/* write register's data */
err = regmap_bulk_write(rx8581->regmap, RX8581_REG_SC,
buf, sizeof(buf));
err = regmap_bulk_write(regmap, RX8581_REG_SC, buf, sizeof(buf));
if (err < 0)
return err;
/* get VLF and clear it */
err = regmap_update_bits(rx8581->regmap, RX8581_REG_FLAG,
RX8581_FLAG_VLF, 0);
err = regmap_update_bits(regmap, RX8581_REG_FLAG, RX8581_FLAG_VLF, 0);
if (err < 0)
return err;
/* Restart the clock */
return regmap_update_bits(rx8581->regmap, RX8581_REG_CTRL,
return regmap_update_bits(regmap, RX8581_REG_CTRL,
RX8581_CTRL_STOP, 0);
}
@ -190,29 +183,27 @@ static const struct rtc_class_ops rx8581_rtc_ops = {
static int rx8571_nvram_read(void *priv, unsigned int offset, void *val,
size_t bytes)
{
struct rx8581 *rx8581 = priv;
struct regmap *regmap = priv;
return regmap_bulk_read(rx8581->regmap, RX8571_USER_RAM + offset,
val, bytes);
return regmap_bulk_read(regmap, RX8571_USER_RAM + offset, val, bytes);
}
static int rx8571_nvram_write(void *priv, unsigned int offset, void *val,
size_t bytes)
{
struct rx8581 *rx8581 = priv;
struct regmap *regmap = priv;
return regmap_bulk_write(rx8581->regmap, RX8571_USER_RAM + offset,
val, bytes);
return regmap_bulk_write(regmap, RX8571_USER_RAM + offset, val, bytes);
}
static int rx85x1_nvram_read(void *priv, unsigned int offset, void *val,
size_t bytes)
{
struct rx8581 *rx8581 = priv;
struct regmap *regmap = priv;
unsigned int tmp_val;
int ret;
ret = regmap_read(rx8581->regmap, RX8581_REG_RAM, &tmp_val);
ret = regmap_read(regmap, RX8581_REG_RAM, &tmp_val);
(*(unsigned char *)val) = (unsigned char) tmp_val;
return ret;
@ -221,12 +212,11 @@ static int rx85x1_nvram_read(void *priv, unsigned int offset, void *val,
static int rx85x1_nvram_write(void *priv, unsigned int offset, void *val,
size_t bytes)
{
struct rx8581 *rx8581 = priv;
struct regmap *regmap = priv;
unsigned char tmp_val;
tmp_val = *((unsigned char *)val);
return regmap_write(rx8581->regmap, RX8581_REG_RAM,
(unsigned int)tmp_val);
return regmap_write(regmap, RX8581_REG_RAM, (unsigned int)tmp_val);
}
static const struct rx85x1_config rx8581_config = {
@ -249,9 +239,10 @@ static const struct rx85x1_config rx8571_config = {
static int rx8581_probe(struct i2c_client *client)
{
struct rx8581 *rx8581;
struct regmap *regmap;
const struct rx85x1_config *config = &rx8581_config;
const void *data = of_device_get_match_data(&client->dev);
struct rtc_device *rtc;
static struct nvmem_config nvmem_cfg[] = {
{
.name = "rx85x1-",
@ -276,31 +267,27 @@ static int rx8581_probe(struct i2c_client *client)
if (data)
config = data;
rx8581 = devm_kzalloc(&client->dev, sizeof(struct rx8581), GFP_KERNEL);
if (!rx8581)
return -ENOMEM;
regmap = devm_regmap_init_i2c(client, &config->regmap);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
i2c_set_clientdata(client, rx8581);
i2c_set_clientdata(client, regmap);
rx8581->regmap = devm_regmap_init_i2c(client, &config->regmap);
if (IS_ERR(rx8581->regmap))
return PTR_ERR(rx8581->regmap);
rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
rx8581->rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(rx8581->rtc))
return PTR_ERR(rx8581->rtc);
rtc->ops = &rx8581_rtc_ops;
rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rtc->range_max = RTC_TIMESTAMP_END_2099;
rtc->start_secs = 0;
rtc->set_start_time = true;
rx8581->rtc->ops = &rx8581_rtc_ops;
rx8581->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rx8581->rtc->range_max = RTC_TIMESTAMP_END_2099;
rx8581->rtc->start_secs = 0;
rx8581->rtc->set_start_time = true;
ret = devm_rtc_register_device(rx8581->rtc);
ret = devm_rtc_register_device(rtc);
for (i = 0; i < config->num_nvram; i++) {
nvmem_cfg[i].priv = rx8581;
devm_rtc_nvmem_register(rx8581->rtc, &nvmem_cfg[i]);
nvmem_cfg[i].priv = regmap;
devm_rtc_nvmem_register(rtc, &nvmem_cfg[i]);
}
return ret;

View File

@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/rtc.h>
#include <linux/spinlock.h>
#define RZN1_RTC_CTL0 0x00
#define RZN1_RTC_CTL0_SLSB_SUBU 0
@ -27,6 +28,7 @@
#define RZN1_RTC_CTL0_CE BIT(7)
#define RZN1_RTC_CTL1 0x04
#define RZN1_RTC_CTL1_1SE BIT(3)
#define RZN1_RTC_CTL1_ALME BIT(4)
#define RZN1_RTC_CTL2 0x08
@ -58,6 +60,13 @@
struct rzn1_rtc {
struct rtc_device *rtcdev;
void __iomem *base;
/*
* Protects access to RZN1_RTC_CTL1 reg. rtc_lock with threaded_irqs
* would introduce race conditions when switching interrupts because
* of potential sleeps
*/
spinlock_t ctl1_access_lock;
struct rtc_time tm_alarm;
};
static void rzn1_rtc_get_time_snapshot(struct rzn1_rtc *rtc, struct rtc_time *tm)
@ -135,8 +144,38 @@ static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm)
static irqreturn_t rzn1_rtc_alarm_irq(int irq, void *dev_id)
{
struct rzn1_rtc *rtc = dev_id;
u32 ctl1, set_irq_bits = 0;
rtc_update_irq(rtc->rtcdev, 1, RTC_AF | RTC_IRQF);
if (rtc->tm_alarm.tm_sec == 0)
rtc_update_irq(rtc->rtcdev, 1, RTC_AF | RTC_IRQF);
else
/* Switch to 1s interrupts */
set_irq_bits = RZN1_RTC_CTL1_1SE;
guard(spinlock)(&rtc->ctl1_access_lock);
ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
ctl1 &= ~RZN1_RTC_CTL1_ALME;
ctl1 |= set_irq_bits;
writel(ctl1, rtc->base + RZN1_RTC_CTL1);
return IRQ_HANDLED;
}
static irqreturn_t rzn1_rtc_1s_irq(int irq, void *dev_id)
{
struct rzn1_rtc *rtc = dev_id;
u32 ctl1;
if (readl(rtc->base + RZN1_RTC_SECC) == bin2bcd(rtc->tm_alarm.tm_sec)) {
guard(spinlock)(&rtc->ctl1_access_lock);
ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
ctl1 &= ~RZN1_RTC_CTL1_1SE;
writel(ctl1, rtc->base + RZN1_RTC_CTL1);
rtc_update_irq(rtc->rtcdev, 1, RTC_AF | RTC_IRQF);
}
return IRQ_HANDLED;
}
@ -144,14 +183,38 @@ static irqreturn_t rzn1_rtc_alarm_irq(int irq, void *dev_id)
static int rzn1_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
{
struct rzn1_rtc *rtc = dev_get_drvdata(dev);
u32 ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
struct rtc_time *tm = &rtc->tm_alarm, tm_now;
u32 ctl1;
int ret;
if (enable)
ctl1 |= RZN1_RTC_CTL1_ALME;
else
ctl1 &= ~RZN1_RTC_CTL1_ALME;
guard(spinlock_irqsave)(&rtc->ctl1_access_lock);
writel(ctl1, rtc->base + RZN1_RTC_CTL1);
ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
if (enable) {
/*
* Use alarm interrupt if alarm time is at least a minute away
* or less than a minute but in the next minute. Otherwise use
* 1 second interrupt to wait for the proper second
*/
do {
ctl1 &= ~(RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE);
ret = rzn1_rtc_read_time(dev, &tm_now);
if (ret)
return ret;
if (rtc_tm_sub(tm, &tm_now) > 59 || tm->tm_min != tm_now.tm_min)
ctl1 |= RZN1_RTC_CTL1_ALME;
else
ctl1 |= RZN1_RTC_CTL1_1SE;
writel(ctl1, rtc->base + RZN1_RTC_CTL1);
} while (readl(rtc->base + RZN1_RTC_SECC) != bin2bcd(tm_now.tm_sec));
} else {
ctl1 &= ~(RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE);
writel(ctl1, rtc->base + RZN1_RTC_CTL1);
}
return 0;
}
@ -185,7 +248,7 @@ static int rzn1_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
}
ctl1 = readl(rtc->base + RZN1_RTC_CTL1);
alrm->enabled = !!(ctl1 & RZN1_RTC_CTL1_ALME);
alrm->enabled = !!(ctl1 & (RZN1_RTC_CTL1_ALME | RZN1_RTC_CTL1_1SE));
return 0;
}
@ -216,6 +279,8 @@ static int rzn1_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
writel(bin2bcd(tm->tm_hour), rtc->base + RZN1_RTC_ALH);
writel(BIT(wday), rtc->base + RZN1_RTC_ALW);
rtc->tm_alarm = alrm->time;
rzn1_rtc_alarm_irq_enable(dev, alrm->enabled);
return 0;
@ -304,7 +369,7 @@ static const struct rtc_class_ops rzn1_rtc_ops = {
static int rzn1_rtc_probe(struct platform_device *pdev)
{
struct rzn1_rtc *rtc;
int alarm_irq;
int irq;
int ret;
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
@ -317,9 +382,9 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
if (IS_ERR(rtc->base))
return dev_err_probe(&pdev->dev, PTR_ERR(rtc->base), "Missing reg\n");
alarm_irq = platform_get_irq(pdev, 0);
if (alarm_irq < 0)
return alarm_irq;
irq = platform_get_irq_byname(pdev, "alarm");
if (irq < 0)
return irq;
rtc->rtcdev = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtc->rtcdev))
@ -329,8 +394,6 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
rtc->rtcdev->range_max = RTC_TIMESTAMP_END_2099;
rtc->rtcdev->alarm_offset_max = 7 * 86400;
rtc->rtcdev->ops = &rzn1_rtc_ops;
set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->rtcdev->features);
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtcdev->features);
ret = devm_pm_runtime_enable(&pdev->dev);
if (ret < 0)
@ -349,13 +412,24 @@ static int rzn1_rtc_probe(struct platform_device *pdev)
/* Disable all interrupts */
writel(0, rtc->base + RZN1_RTC_CTL1);
ret = devm_request_irq(&pdev->dev, alarm_irq, rzn1_rtc_alarm_irq, 0,
dev_name(&pdev->dev), rtc);
spin_lock_init(&rtc->ctl1_access_lock);
ret = devm_request_irq(&pdev->dev, irq, rzn1_rtc_alarm_irq, 0, "RZN1 RTC Alarm", rtc);
if (ret) {
dev_err(&pdev->dev, "RTC timer interrupt not available\n");
dev_err(&pdev->dev, "RTC alarm interrupt not available\n");
goto dis_runtime_pm;
}
irq = platform_get_irq_byname_optional(pdev, "pps");
if (irq >= 0)
ret = devm_request_irq(&pdev->dev, irq, rzn1_rtc_1s_irq, 0, "RZN1 RTC 1s", rtc);
if (irq < 0 || ret) {
set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->rtcdev->features);
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->rtcdev->features);
dev_warn(&pdev->dev, "RTC pps interrupt not available. Alarm has only minute accuracy\n");
}
ret = devm_rtc_register_device(rtc->rtcdev);
if (ret)
goto dis_runtime_pm;

View File

@ -63,7 +63,6 @@ MODULE_DEVICE_TABLE(of, s35390a_of_match);
struct s35390a {
struct i2c_client *client[8];
struct rtc_device *rtc;
int twentyfourhour;
};
@ -422,6 +421,7 @@ static int s35390a_probe(struct i2c_client *client)
int err, err_read;
unsigned int i;
struct s35390a *s35390a;
struct rtc_device *rtc;
char buf, status1;
struct device *dev = &client->dev;
@ -447,9 +447,9 @@ static int s35390a_probe(struct i2c_client *client)
}
}
s35390a->rtc = devm_rtc_allocate_device(dev);
if (IS_ERR(s35390a->rtc))
return PTR_ERR(s35390a->rtc);
rtc = devm_rtc_allocate_device(dev);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
err_read = s35390a_read_status(s35390a, &status1);
if (err_read < 0) {
@ -480,17 +480,17 @@ static int s35390a_probe(struct i2c_client *client)
device_set_wakeup_capable(dev, 1);
s35390a->rtc->ops = &s35390a_rtc_ops;
s35390a->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
s35390a->rtc->range_max = RTC_TIMESTAMP_END_2099;
rtc->ops = &s35390a_rtc_ops;
rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rtc->range_max = RTC_TIMESTAMP_END_2099;
set_bit(RTC_FEATURE_ALARM_RES_MINUTE, s35390a->rtc->features);
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, s35390a->rtc->features );
set_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features);
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features);
if (status1 & S35390A_FLAG_INT2)
rtc_update_irq(s35390a->rtc, 1, RTC_AF);
rtc_update_irq(rtc, 1, RTC_AF);
return devm_rtc_register_device(s35390a->rtc);
return devm_rtc_register_device(rtc);
}
static struct i2c_driver s35390a_driver = {

View File

@ -146,7 +146,6 @@ static const struct s5m_rtc_reg_config s2mps15_rtc_regs = {
struct s5m_rtc_info {
struct device *dev;
struct i2c_client *i2c;
struct sec_pmic_dev *s5m87xx;
struct regmap *regmap;
struct rtc_device *rtc_dev;
@ -627,11 +626,10 @@ static int s5m8767_rtc_init_reg(struct s5m_rtc_info *info)
}
info->rtc_24hr_mode = 1;
if (ret < 0) {
dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
__func__, ret);
return ret;
}
if (ret < 0)
return dev_err_probe(info->dev, ret,
"%s: fail to write controlm reg\n",
__func__);
return ret;
}
@ -640,6 +638,7 @@ static int s5m_rtc_probe(struct platform_device *pdev)
{
struct sec_pmic_dev *s5m87xx = dev_get_drvdata(pdev->dev.parent);
struct s5m_rtc_info *info;
struct i2c_client *i2c;
const struct regmap_config *regmap_cfg;
int ret, alarm_irq;
@ -669,26 +668,21 @@ static int s5m_rtc_probe(struct platform_device *pdev)
alarm_irq = S5M8767_IRQ_RTCA1;
break;
default:
dev_err(&pdev->dev,
"Device type %lu is not supported by RTC driver\n",
platform_get_device_id(pdev)->driver_data);
return -ENODEV;
return dev_err_probe(&pdev->dev, -ENODEV,
"Device type %lu is not supported by RTC driver\n",
platform_get_device_id(pdev)->driver_data);
}
info->i2c = devm_i2c_new_dummy_device(&pdev->dev, s5m87xx->i2c->adapter,
RTC_I2C_ADDR);
if (IS_ERR(info->i2c)) {
dev_err(&pdev->dev, "Failed to allocate I2C for RTC\n");
return PTR_ERR(info->i2c);
}
i2c = devm_i2c_new_dummy_device(&pdev->dev, s5m87xx->i2c->adapter,
RTC_I2C_ADDR);
if (IS_ERR(i2c))
return dev_err_probe(&pdev->dev, PTR_ERR(i2c),
"Failed to allocate I2C for RTC\n");
info->regmap = devm_regmap_init_i2c(info->i2c, regmap_cfg);
if (IS_ERR(info->regmap)) {
ret = PTR_ERR(info->regmap);
dev_err(&pdev->dev, "Failed to allocate RTC register map: %d\n",
ret);
return ret;
}
info->regmap = devm_regmap_init_i2c(i2c, regmap_cfg);
if (IS_ERR(info->regmap))
return dev_err_probe(&pdev->dev, PTR_ERR(info->regmap),
"Failed to allocate RTC register map\n");
info->dev = &pdev->dev;
info->s5m87xx = s5m87xx;
@ -696,11 +690,10 @@ static int s5m_rtc_probe(struct platform_device *pdev)
if (s5m87xx->irq_data) {
info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq);
if (info->irq <= 0) {
dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n",
alarm_irq);
return -EINVAL;
}
if (info->irq <= 0)
return dev_err_probe(&pdev->dev, -EINVAL,
"Failed to get virtual IRQ %d\n",
alarm_irq);
}
platform_set_drvdata(pdev, info);
@ -724,11 +717,10 @@ static int s5m_rtc_probe(struct platform_device *pdev)
ret = devm_request_threaded_irq(&pdev->dev, info->irq, NULL,
s5m_rtc_alarm_irq, 0, "rtc-alarm0",
info);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
info->irq, ret);
return ret;
}
if (ret < 0)
return dev_err_probe(&pdev->dev, ret,
"Failed to request alarm IRQ %d\n",
info->irq);
device_init_wakeup(&pdev->dev, true);
}

View File

@ -42,7 +42,6 @@
struct sd2405al {
struct device *dev;
struct rtc_device *rtc;
struct regmap *regmap;
};
@ -167,6 +166,7 @@ static const struct regmap_config sd2405al_regmap_conf = {
static int sd2405al_probe(struct i2c_client *client)
{
struct sd2405al *sd2405al;
struct rtc_device *rtc;
int ret;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
@ -182,17 +182,17 @@ static int sd2405al_probe(struct i2c_client *client)
if (IS_ERR(sd2405al->regmap))
return PTR_ERR(sd2405al->regmap);
sd2405al->rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(sd2405al->rtc))
return PTR_ERR(sd2405al->rtc);
rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
sd2405al->rtc->ops = &sd2405al_rtc_ops;
sd2405al->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
sd2405al->rtc->range_max = RTC_TIMESTAMP_END_2099;
rtc->ops = &sd2405al_rtc_ops;
rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rtc->range_max = RTC_TIMESTAMP_END_2099;
dev_set_drvdata(&client->dev, sd2405al);
ret = devm_rtc_register_device(sd2405al->rtc);
ret = devm_rtc_register_device(rtc);
if (ret < 0)
return ret;

View File

@ -36,11 +36,6 @@
*/
#define WRITE_PROTECT_EN 0
struct sd3078 {
struct rtc_device *rtc;
struct regmap *regmap;
};
/*
* In order to prevent arbitrary modification of the time register,
* when modification of the register,
@ -49,14 +44,11 @@ struct sd3078 {
* 2. set WRITE2 bit
* 3. set WRITE3 bit
*/
static void sd3078_enable_reg_write(struct sd3078 *sd3078)
static void sd3078_enable_reg_write(struct regmap *regmap)
{
regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL2,
KEY_WRITE1, KEY_WRITE1);
regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1,
KEY_WRITE2, KEY_WRITE2);
regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1,
KEY_WRITE3, KEY_WRITE3);
regmap_update_bits(regmap, SD3078_REG_CTRL2, KEY_WRITE1, KEY_WRITE1);
regmap_update_bits(regmap, SD3078_REG_CTRL1, KEY_WRITE2, KEY_WRITE2);
regmap_update_bits(regmap, SD3078_REG_CTRL1, KEY_WRITE3, KEY_WRITE3);
}
#if WRITE_PROTECT_EN
@ -69,14 +61,11 @@ static void sd3078_enable_reg_write(struct sd3078 *sd3078)
* 2. clear WRITE3 bit
* 3. clear WRITE1 bit
*/
static void sd3078_disable_reg_write(struct sd3078 *sd3078)
static void sd3078_disable_reg_write(struct regmap *regmap)
{
regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1,
KEY_WRITE2, 0);
regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL1,
KEY_WRITE3, 0);
regmap_update_bits(sd3078->regmap, SD3078_REG_CTRL2,
KEY_WRITE1, 0);
regmap_update_bits(regmap, SD3078_REG_CTRL1, KEY_WRITE2, 0);
regmap_update_bits(regmap, SD3078_REG_CTRL1, KEY_WRITE3, 0);
regmap_update_bits(regmap, SD3078_REG_CTRL2, KEY_WRITE1, 0);
}
#endif
@ -85,11 +74,10 @@ static int sd3078_rtc_read_time(struct device *dev, struct rtc_time *tm)
unsigned char hour;
unsigned char rtc_data[NUM_TIME_REGS] = {0};
struct i2c_client *client = to_i2c_client(dev);
struct sd3078 *sd3078 = i2c_get_clientdata(client);
struct regmap *regmap = i2c_get_clientdata(client);
int ret;
ret = regmap_bulk_read(sd3078->regmap, SD3078_REG_SC, rtc_data,
NUM_TIME_REGS);
ret = regmap_bulk_read(regmap, SD3078_REG_SC, rtc_data, NUM_TIME_REGS);
if (ret < 0) {
dev_err(dev, "reading from RTC failed with err:%d\n", ret);
return ret;
@ -123,7 +111,7 @@ static int sd3078_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
unsigned char rtc_data[NUM_TIME_REGS];
struct i2c_client *client = to_i2c_client(dev);
struct sd3078 *sd3078 = i2c_get_clientdata(client);
struct regmap *regmap = i2c_get_clientdata(client);
int ret;
rtc_data[SD3078_REG_SC] = bin2bcd(tm->tm_sec);
@ -135,10 +123,10 @@ static int sd3078_rtc_set_time(struct device *dev, struct rtc_time *tm)
rtc_data[SD3078_REG_YR] = bin2bcd(tm->tm_year - 100);
#if WRITE_PROTECT_EN
sd3078_enable_reg_write(sd3078);
sd3078_enable_reg_write(regmap);
#endif
ret = regmap_bulk_write(sd3078->regmap, SD3078_REG_SC, rtc_data,
ret = regmap_bulk_write(regmap, SD3078_REG_SC, rtc_data,
NUM_TIME_REGS);
if (ret < 0) {
dev_err(dev, "writing to RTC failed with err:%d\n", ret);
@ -146,7 +134,7 @@ static int sd3078_rtc_set_time(struct device *dev, struct rtc_time *tm)
}
#if WRITE_PROTECT_EN
sd3078_disable_reg_write(sd3078);
sd3078_disable_reg_write(regmap);
#endif
return 0;
@ -166,36 +154,33 @@ static const struct regmap_config regmap_config = {
static int sd3078_probe(struct i2c_client *client)
{
int ret;
struct sd3078 *sd3078;
struct regmap *regmap;
struct rtc_device *rtc;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
sd3078 = devm_kzalloc(&client->dev, sizeof(*sd3078), GFP_KERNEL);
if (!sd3078)
return -ENOMEM;
sd3078->regmap = devm_regmap_init_i2c(client, &regmap_config);
if (IS_ERR(sd3078->regmap)) {
regmap = devm_regmap_init_i2c(client, &regmap_config);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "regmap allocation failed\n");
return PTR_ERR(sd3078->regmap);
return PTR_ERR(regmap);
}
i2c_set_clientdata(client, sd3078);
i2c_set_clientdata(client, regmap);
sd3078->rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(sd3078->rtc))
return PTR_ERR(sd3078->rtc);
rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
sd3078->rtc->ops = &sd3078_rtc_ops;
sd3078->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
sd3078->rtc->range_max = RTC_TIMESTAMP_END_2099;
rtc->ops = &sd3078_rtc_ops;
rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rtc->range_max = RTC_TIMESTAMP_END_2099;
ret = devm_rtc_register_device(sd3078->rtc);
ret = devm_rtc_register_device(rtc);
if (ret)
return ret;
sd3078_enable_reg_write(sd3078);
sd3078_enable_reg_write(regmap);
return 0;
}

View File

@ -1143,11 +1143,11 @@ static int stm32_rtc_probe(struct platform_device *pdev)
goto err;
}
ret = device_init_wakeup(&pdev->dev, true);
ret = devm_device_init_wakeup(&pdev->dev);
if (ret)
goto err;
ret = dev_pm_set_wake_irq(&pdev->dev, rtc->irq_alarm);
ret = devm_pm_set_wake_irq(&pdev->dev, rtc->irq_alarm);
if (ret)
goto err;
@ -1208,9 +1208,6 @@ static int stm32_rtc_probe(struct platform_device *pdev)
if (rtc->data->need_dbp)
regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0);
dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
return ret;
}
@ -1237,9 +1234,6 @@ static void stm32_rtc_remove(struct platform_device *pdev)
/* Enable backup domain write protection if needed */
if (rtc->data->need_dbp)
regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0);
dev_pm_clear_wake_irq(&pdev->dev);
device_init_wakeup(&pdev->dev, false);
}
static int stm32_rtc_suspend(struct device *dev)

View File

@ -60,11 +60,6 @@
#define RTC_PDN2 0x002e
#define RTC_PDN2_PWRON_ALARM BIT(4)
#define RTC_MIN_YEAR 1968
#define RTC_BASE_YEAR 1900
#define RTC_NUM_YEARS 128
#define RTC_MIN_YEAR_OFFSET (RTC_MIN_YEAR - RTC_BASE_YEAR)
#define MTK_RTC_POLL_DELAY_US 10
#define MTK_RTC_POLL_TIMEOUT (jiffies_to_usecs(HZ))

View File

@ -170,6 +170,7 @@ struct rtc_device {
/* useful timestamps */
#define RTC_TIMESTAMP_BEGIN_0000 -62167219200ULL /* 0000-01-01 00:00:00 */
#define RTC_TIMESTAMP_BEGIN_1900 -2208988800LL /* 1900-01-01 00:00:00 */
#define RTC_TIMESTAMP_EPOCH_GPS 315964800LL /* 1980-01-06 00:00:00 */
#define RTC_TIMESTAMP_BEGIN_2000 946684800LL /* 2000-01-01 00:00:00 */
#define RTC_TIMESTAMP_END_2063 2966371199LL /* 2063-12-31 23:59:59 */
#define RTC_TIMESTAMP_END_2079 3471292799LL /* 2079-12-31 23:59:59 */

View File

@ -1,3 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
rtctest
setdate

View File

@ -4,8 +4,6 @@ LDLIBS += -lrt -lpthread -lm
TEST_GEN_PROGS = rtctest
TEST_GEN_PROGS_EXTENDED = setdate
TEST_FILES := settings
include ../lib.mk

View File

@ -29,6 +29,7 @@ enum rtc_alarm_state {
RTC_ALARM_UNKNOWN,
RTC_ALARM_ENABLED,
RTC_ALARM_DISABLED,
RTC_ALARM_RES_MINUTE,
};
FIXTURE(rtc) {
@ -88,7 +89,7 @@ static void nanosleep_with_retries(long ns)
}
}
static enum rtc_alarm_state get_rtc_alarm_state(int fd)
static enum rtc_alarm_state get_rtc_alarm_state(int fd, int need_seconds)
{
struct rtc_param param = { 0 };
int rc;
@ -103,6 +104,10 @@ static enum rtc_alarm_state get_rtc_alarm_state(int fd)
if ((param.uvalue & _BITUL(RTC_FEATURE_ALARM)) == 0)
return RTC_ALARM_DISABLED;
/* Check if alarm has desired granularity */
if (need_seconds && (param.uvalue & _BITUL(RTC_FEATURE_ALARM_RES_MINUTE)))
return RTC_ALARM_RES_MINUTE;
return RTC_ALARM_ENABLED;
}
@ -227,9 +232,11 @@ TEST_F(rtc, alarm_alm_set) {
SKIP(return, "Skipping test since %s does not exist", rtc_file);
ASSERT_NE(-1, self->fd);
alarm_state = get_rtc_alarm_state(self->fd);
alarm_state = get_rtc_alarm_state(self->fd, 1);
if (alarm_state == RTC_ALARM_DISABLED)
SKIP(return, "Skipping test since alarms are not supported.");
if (alarm_state == RTC_ALARM_RES_MINUTE)
SKIP(return, "Skipping test since alarms has only minute granularity.");
rc = ioctl(self->fd, RTC_RD_TIME, &tm);
ASSERT_NE(-1, rc);
@ -295,9 +302,11 @@ TEST_F(rtc, alarm_wkalm_set) {
SKIP(return, "Skipping test since %s does not exist", rtc_file);
ASSERT_NE(-1, self->fd);
alarm_state = get_rtc_alarm_state(self->fd);
alarm_state = get_rtc_alarm_state(self->fd, 1);
if (alarm_state == RTC_ALARM_DISABLED)
SKIP(return, "Skipping test since alarms are not supported.");
if (alarm_state == RTC_ALARM_RES_MINUTE)
SKIP(return, "Skipping test since alarms has only minute granularity.");
rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time);
ASSERT_NE(-1, rc);
@ -357,7 +366,7 @@ TEST_F_TIMEOUT(rtc, alarm_alm_set_minute, 65) {
SKIP(return, "Skipping test since %s does not exist", rtc_file);
ASSERT_NE(-1, self->fd);
alarm_state = get_rtc_alarm_state(self->fd);
alarm_state = get_rtc_alarm_state(self->fd, 0);
if (alarm_state == RTC_ALARM_DISABLED)
SKIP(return, "Skipping test since alarms are not supported.");
@ -425,7 +434,7 @@ TEST_F_TIMEOUT(rtc, alarm_wkalm_set_minute, 65) {
SKIP(return, "Skipping test since %s does not exist", rtc_file);
ASSERT_NE(-1, self->fd);
alarm_state = get_rtc_alarm_state(self->fd);
alarm_state = get_rtc_alarm_state(self->fd, 0);
if (alarm_state == RTC_ALARM_DISABLED)
SKIP(return, "Skipping test since alarms are not supported.");

View File

@ -1,77 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/* Real Time Clock Driver Test
* by: Benjamin Gaignard (benjamin.gaignard@linaro.org)
*
* To build
* gcc rtctest_setdate.c -o rtctest_setdate
*/
#include <stdio.h>
#include <linux/rtc.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
static const char default_time[] = "00:00:00";
int main(int argc, char **argv)
{
int fd, retval;
struct rtc_time new, current;
const char *rtc, *date;
const char *time = default_time;
switch (argc) {
case 4:
time = argv[3];
/* FALLTHROUGH */
case 3:
date = argv[2];
rtc = argv[1];
break;
default:
fprintf(stderr, "usage: rtctest_setdate <rtcdev> <DD-MM-YYYY> [HH:MM:SS]\n");
return 1;
}
fd = open(rtc, O_RDONLY);
if (fd == -1) {
perror(rtc);
exit(errno);
}
sscanf(date, "%d-%d-%d", &new.tm_mday, &new.tm_mon, &new.tm_year);
new.tm_mon -= 1;
new.tm_year -= 1900;
sscanf(time, "%d:%d:%d", &new.tm_hour, &new.tm_min, &new.tm_sec);
fprintf(stderr, "Test will set RTC date/time to %d-%d-%d, %02d:%02d:%02d.\n",
new.tm_mday, new.tm_mon + 1, new.tm_year + 1900,
new.tm_hour, new.tm_min, new.tm_sec);
/* Write the new date in RTC */
retval = ioctl(fd, RTC_SET_TIME, &new);
if (retval == -1) {
perror("RTC_SET_TIME ioctl");
close(fd);
exit(errno);
}
/* Read back */
retval = ioctl(fd, RTC_RD_TIME, &current);
if (retval == -1) {
perror("RTC_RD_TIME ioctl");
exit(errno);
}
fprintf(stderr, "\n\nCurrent RTC date/time is %d-%d-%d, %02d:%02d:%02d.\n",
current.tm_mday, current.tm_mon + 1, current.tm_year + 1900,
current.tm_hour, current.tm_min, current.tm_sec);
close(fd);
return 0;
}