RTC for 4.9
Subsystem: - delete owner assignment in multiple drivers - constify rtc_class_ops structures Drivers: - ac100: support clock-output-names - cmos: properly handle ACPI alarms and quirky BIOSes and other fixes - ds1307: fix century bit support while staying comaptible with previous behaviour by default - ds1347: switch to regmap - isl12057 is now handled by ds1307 - omap: support external wakeup - rv8803: allow to disable voltage drop detection -----BEGIN PGP SIGNATURE----- iQIcBAABCgAGBQJYASBeAAoJENiigzvaE+LCDO4QAJAi0TV2i0vYaJLDWyCGDx3P cts/Su2JdLgeLxilKvyYgwUpp8fsv681ZaZi+a6Jln/cn0MOcWwJoopiC30CSR8M 9UxmRsFR9Ev/Cm/NZChcsTQwyTHOumnzZzxtnYr0RWOw7s4K68gEQEpWWT7qHTp1 KVwfIvjAIPcozw25QWWGUWHu22PsI38NTH5Bg+rimMCToNbSDFAm+d62cdeIbkJF FoQIut0/Lh5UZ12+T8l0iBydY3bINeo1SZY5yAwQGRzJBecxRccbtKlnUjXnywke xAO5KQzegkLPTU4R6ssK/SQfVlDrfG3fkjWNvUEC/Vyw94v2SaFB1XjvlCXwL3mN XqzWXeestqFvKRjbYsM0NwsPX4+wxjDNq9YaAhpFYDAA9BL3vREB41qf/dCOFywG tqHBRpwN9g7u/72SLJ3icYdjmpaQIQbLF9wl8LJiPrWn4xwTNVIB2u3APcSuxE7/ q49jD72LyEVhOUyGs0Hev584s4PC2fMoveq52ng0gMVbOtX0A0FJQQMcR2/2DIOp GLzPVuupx/8Eck9RFdr06Iv74j/bD7tScfiifZt6LfY5c8K7HOYykoskaRz3XMV4 gx7Aajb8+jMVvI2TOthIa/WCXktQ8MBWTMZ6vbCxxpIRPBYuDqKmt1hXsYR5s6ql fMrn+tWltdRQKGIF2GrR =ZqqR -----END PGP SIGNATURE----- Merge tag 'rtc-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux Pull RTC updates from Alexandre Belloni: "RTC for 4.9 Subsystem: - delete owner assignment in multiple drivers - constify rtc_class_ops structures Drivers: - ac100: support clock-output-names - cmos: properly handle ACPI alarms and quirky BIOSes and other fixes - ds1307: fix century bit support while staying comaptible with previous behaviour by default - ds1347: switch to regmap - isl12057 is now handled by ds1307 - omap: support external wakeup - rv8803: allow to disable voltage drop detection" * tag 'rtc-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (25 commits) rtc: rv8803: set VDETOFF and SWOFF via device tree dt/bindings: Add bindings for Micro Crystal rv8803 devicetree: Add Micro Crystal AG vendor id rtc: cmos: avoid unused function warning rtc: ac100: Add NULL checking for devm_kzalloc call rtc: ds1347: changed raw spi calls to register map calls rtc: cmos: Restore alarm after resume rtc: cmos: Clear ACPI-driven alarms upon resume rtc: omap: Support ext_wakeup configuration rtc: cmos: Initialize hpet timer before irq is registered rtc: asm9260: rework locking rtc: asm9260: allow COMPILE_TEST rtc: constify rtc_class_ops structures rtc: ac100: support clock-output-names in device tree binding rtc: rx6110: remove owner assignment rtc: pic32: Delete owner assignment rtc: bq32k: Fix handling of oscillator failure flag rtc: bq32k: Use correct mask name for 'minutes' register. rtc: sysfs: fix a cast removing the const attribute Documentation: dt: Intersil isl12057 is not a trivial device ...
This commit is contained in:
commit
8b70f71617
|
@ -51,7 +51,6 @@ fsl,sgtl5000 SGTL5000: Ultra Low-Power Audio Codec
|
|||
gmt,g751 G751: Digital Temperature Sensor and Thermal Watchdog with Two-Wire Interface
|
||||
infineon,slb9635tt Infineon SLB9635 (Soft-) I2C TPM (old protocol, max 100khz)
|
||||
infineon,slb9645tt Infineon SLB9645 I2C TPM (new protocol, max 400khz)
|
||||
isil,isl12057 Intersil ISL12057 I2C RTC Chip
|
||||
isil,isl29028 Intersil ISL29028 Ambient Light and Proximity Sensor
|
||||
maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator
|
||||
maxim,max1237 Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs
|
||||
|
|
|
@ -11,7 +11,7 @@ Optional properties:
|
|||
- trickle-diode-disable : Do not use internal trickle charger diode
|
||||
Should be given if internal trickle charger diode should be disabled
|
||||
Example:
|
||||
ds1390: rtc@68 {
|
||||
ds1390: rtc@0 {
|
||||
compatible = "dallas,ds1390";
|
||||
trickle-resistor-ohms = <250>;
|
||||
reg = <0>;
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
Real Time Clock driver for:
|
||||
- Epson RX8900
|
||||
- Micro Crystal rv8803
|
||||
|
||||
Required properties:
|
||||
- compatible: should be: "microcrystal,rv8803" or "epson,rx8900"
|
||||
- reg : the I2C address of the device for I2C
|
||||
|
||||
Optional properties:
|
||||
- epson,vdet-disable : boolean, if present will disable voltage detector.
|
||||
Should be set if no backup battery is used.
|
||||
- trickle-diode-disable : boolean, if present will disable internal trickle
|
||||
charger diode
|
||||
|
||||
Example:
|
||||
|
||||
rtc: rtc@32 {
|
||||
compatible = "epson,rx8900"
|
||||
reg = <0x32>;
|
||||
epson,vdet-disable;
|
||||
trickle-diode-disable;
|
||||
};
|
|
@ -18,6 +18,18 @@ Optional properties:
|
|||
through pmic_power_en
|
||||
- clocks: Any internal or external clocks feeding in to rtc
|
||||
- clock-names: Corresponding names of the clocks
|
||||
- pinctrl-0: a phandle pointing to the pin settings for the device
|
||||
- pinctrl-names: should be "default"
|
||||
|
||||
Optional subnodes:
|
||||
- generic pinctrl node
|
||||
|
||||
Required pinctrl subnodes properties:
|
||||
- pins - Names of ext_wakeup pins to configure
|
||||
|
||||
Optional pinctrl subnodes properties:
|
||||
- input-enable - Enables ext_wakeup
|
||||
- ti,active-high - Set input active high (by default active low)
|
||||
|
||||
Example:
|
||||
|
||||
|
@ -30,4 +42,13 @@ rtc@1c23000 {
|
|||
system-power-controller;
|
||||
clocks = <&clk_32k_rtc>, <&clk_32768_ck>;
|
||||
clock-names = "ext-clk", "int-clk";
|
||||
|
||||
pinctrl-0 = <&ext_wakeup>;
|
||||
pinctrl-names = "default";
|
||||
|
||||
ext_wakeup: ext-wakeup {
|
||||
pins = "ext_wakeup0";
|
||||
input-enable;
|
||||
ti,active-high;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -166,6 +166,7 @@ melexis Melexis N.V.
|
|||
merrii Merrii Technology Co., Ltd.
|
||||
micrel Micrel Inc.
|
||||
microchip Microchip Technology Inc.
|
||||
microcrystal Micro Crystal AG
|
||||
micron Micron Technology Inc.
|
||||
minix MINIX Technology Ltd.
|
||||
mitsubishi Mitsubishi Electric Corporation
|
||||
|
|
|
@ -208,14 +208,14 @@ config RTC_DRV_AS3722
|
|||
will be called rtc-as3722.
|
||||
|
||||
config RTC_DRV_DS1307
|
||||
tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025"
|
||||
tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025, ISL12057"
|
||||
help
|
||||
If you say yes here you get support for various compatible RTC
|
||||
chips (often with battery backup) connected with I2C. This driver
|
||||
should handle DS1307, DS1337, DS1338, DS1339, DS1340, ST M41T00,
|
||||
EPSON RX-8025 and probably other chips. In some cases the RTC
|
||||
must already have been initialized (by manufacturing or a
|
||||
bootloader).
|
||||
EPSON RX-8025, Intersil ISL12057 and probably other chips. In some
|
||||
cases the RTC must already have been initialized (by manufacturing or
|
||||
a bootloader).
|
||||
|
||||
The first seven registers on these chips hold an RTC, and other
|
||||
registers may add features such as NVRAM, a trickle charger for
|
||||
|
@ -234,6 +234,20 @@ config RTC_DRV_DS1307_HWMON
|
|||
Say Y here if you want to expose temperature sensor data on
|
||||
rtc-ds1307 (only DS3231)
|
||||
|
||||
config RTC_DRV_DS1307_CENTURY
|
||||
bool "Century bit support for rtc-ds1307"
|
||||
depends on RTC_DRV_DS1307
|
||||
default n
|
||||
help
|
||||
The DS1307 driver suffered from a bug where it was enabling the
|
||||
century bit inconditionnally but never used it when reading the time.
|
||||
It made the driver unable to support dates beyond 2099.
|
||||
Setting this option will add proper support for the century bit but if
|
||||
the time was previously set using a kernel predating this option,
|
||||
reading the date will return a date in the next century.
|
||||
To solve that, you could boot a kernel without this option set, set
|
||||
the RTC date and then boot a kernel with this option set.
|
||||
|
||||
config RTC_DRV_DS1374
|
||||
tristate "Dallas/Maxim DS1374"
|
||||
help
|
||||
|
@ -374,16 +388,6 @@ config RTC_DRV_ISL12022
|
|||
This driver can also be built as a module. If so, the module
|
||||
will be called rtc-isl12022.
|
||||
|
||||
config RTC_DRV_ISL12057
|
||||
select REGMAP_I2C
|
||||
tristate "Intersil ISL12057"
|
||||
help
|
||||
If you say yes here you get support for the Intersil ISL12057
|
||||
I2C RTC chip.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called rtc-isl12057.
|
||||
|
||||
config RTC_DRV_X1205
|
||||
tristate "Xicor/Intersil X1205"
|
||||
help
|
||||
|
@ -661,6 +665,7 @@ config RTC_DRV_DS1343
|
|||
will be called rtc-ds1343.
|
||||
|
||||
config RTC_DRV_DS1347
|
||||
select REGMAP_SPI
|
||||
tristate "Dallas/Maxim DS1347"
|
||||
help
|
||||
If you say yes here you get support for the
|
||||
|
@ -1201,7 +1206,7 @@ comment "on-CPU RTC drivers"
|
|||
|
||||
config RTC_DRV_ASM9260
|
||||
tristate "Alphascale asm9260 RTC"
|
||||
depends on MACH_ASM9260
|
||||
depends on MACH_ASM9260 || COMPILE_TEST
|
||||
help
|
||||
If you say yes here you get support for the RTC on the
|
||||
Alphascale asm9260 SoC.
|
||||
|
@ -1241,6 +1246,9 @@ config RTC_DRV_IMXDI
|
|||
config RTC_DRV_OMAP
|
||||
tristate "TI OMAP Real Time Clock"
|
||||
depends on ARCH_OMAP || ARCH_DAVINCI || COMPILE_TEST
|
||||
depends on OF
|
||||
depends on PINCTRL
|
||||
select GENERIC_PINCONF
|
||||
help
|
||||
Say "yes" here to support the on chip real time clock
|
||||
present on TI OMAP1, AM33xx, DA8xx/OMAP-L13x, AM43xx and DRA7xx.
|
||||
|
|
|
@ -72,7 +72,6 @@ obj-$(CONFIG_RTC_DRV_HID_SENSOR_TIME) += rtc-hid-sensor-time.o
|
|||
obj-$(CONFIG_RTC_DRV_HYM8563) += rtc-hym8563.o
|
||||
obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o
|
||||
obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o
|
||||
obj-$(CONFIG_RTC_DRV_ISL12057) += rtc-isl12057.o
|
||||
obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
|
||||
obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o
|
||||
obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o
|
||||
|
|
|
@ -327,6 +327,8 @@ static int ac100_rtc_register_clks(struct ac100_rtc_dev *chip)
|
|||
.flags = 0,
|
||||
};
|
||||
|
||||
of_property_read_string_index(np, "clock-output-names",
|
||||
i, &init.name);
|
||||
clk->regmap = chip->regmap;
|
||||
clk->offset = AC100_CLKOUT_CTRL1 + i;
|
||||
clk->hw.init = &init;
|
||||
|
@ -552,6 +554,9 @@ static int ac100_rtc_probe(struct platform_device *pdev)
|
|||
int ret;
|
||||
|
||||
chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
|
||||
if (!chip)
|
||||
return -ENOMEM;
|
||||
|
||||
platform_set_drvdata(pdev, chip);
|
||||
chip->dev = &pdev->dev;
|
||||
chip->regmap = ac100->regmap;
|
||||
|
|
|
@ -112,8 +112,6 @@ struct asm9260_rtc_priv {
|
|||
void __iomem *iobase;
|
||||
struct rtc_device *rtc;
|
||||
struct clk *clk;
|
||||
/* io lock */
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
static irqreturn_t asm9260_rtc_irq(int irq, void *dev_id)
|
||||
|
@ -122,11 +120,15 @@ static irqreturn_t asm9260_rtc_irq(int irq, void *dev_id)
|
|||
u32 isr;
|
||||
unsigned long events = 0;
|
||||
|
||||
mutex_lock(&priv->rtc->ops_lock);
|
||||
isr = ioread32(priv->iobase + HW_CIIR);
|
||||
if (!isr)
|
||||
if (!isr) {
|
||||
mutex_unlock(&priv->rtc->ops_lock);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
iowrite32(0, priv->iobase + HW_CIIR);
|
||||
mutex_unlock(&priv->rtc->ops_lock);
|
||||
|
||||
events |= RTC_AF | RTC_IRQF;
|
||||
|
||||
|
@ -139,9 +141,7 @@ static int asm9260_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||
{
|
||||
struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
|
||||
u32 ctime0, ctime1, ctime2;
|
||||
unsigned long irq_flags;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, irq_flags);
|
||||
ctime0 = ioread32(priv->iobase + HW_CTIME0);
|
||||
ctime1 = ioread32(priv->iobase + HW_CTIME1);
|
||||
ctime2 = ioread32(priv->iobase + HW_CTIME2);
|
||||
|
@ -155,7 +155,6 @@ static int asm9260_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||
ctime1 = ioread32(priv->iobase + HW_CTIME1);
|
||||
ctime2 = ioread32(priv->iobase + HW_CTIME2);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->lock, irq_flags);
|
||||
|
||||
tm->tm_sec = (ctime0 >> BM_CTIME0_SEC_S) & BM_CTIME0_SEC_M;
|
||||
tm->tm_min = (ctime0 >> BM_CTIME0_MIN_S) & BM_CTIME0_MIN_M;
|
||||
|
@ -174,9 +173,7 @@ static int asm9260_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||
static int asm9260_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
|
||||
unsigned long irq_flags;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, irq_flags);
|
||||
/*
|
||||
* make sure SEC counter will not flip other counter on write time,
|
||||
* real value will be written at the enf of sequence.
|
||||
|
@ -191,7 +188,6 @@ static int asm9260_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
|||
iowrite32(tm->tm_hour, priv->iobase + HW_HOUR);
|
||||
iowrite32(tm->tm_min, priv->iobase + HW_MIN);
|
||||
iowrite32(tm->tm_sec, priv->iobase + HW_SEC);
|
||||
spin_unlock_irqrestore(&priv->lock, irq_flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -199,9 +195,7 @@ static int asm9260_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
|||
static int asm9260_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
{
|
||||
struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
|
||||
unsigned long irq_flags;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, irq_flags);
|
||||
alrm->time.tm_year = ioread32(priv->iobase + HW_ALYEAR);
|
||||
alrm->time.tm_mon = ioread32(priv->iobase + HW_ALMON);
|
||||
alrm->time.tm_mday = ioread32(priv->iobase + HW_ALDOM);
|
||||
|
@ -213,7 +207,6 @@ static int asm9260_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|||
|
||||
alrm->enabled = ioread32(priv->iobase + HW_AMR) ? 1 : 0;
|
||||
alrm->pending = ioread32(priv->iobase + HW_CIIR) ? 1 : 0;
|
||||
spin_unlock_irqrestore(&priv->lock, irq_flags);
|
||||
|
||||
return rtc_valid_tm(&alrm->time);
|
||||
}
|
||||
|
@ -221,9 +214,7 @@ static int asm9260_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|||
static int asm9260_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
||||
{
|
||||
struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
|
||||
unsigned long irq_flags;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, irq_flags);
|
||||
iowrite32(alrm->time.tm_year, priv->iobase + HW_ALYEAR);
|
||||
iowrite32(alrm->time.tm_mon, priv->iobase + HW_ALMON);
|
||||
iowrite32(alrm->time.tm_mday, priv->iobase + HW_ALDOM);
|
||||
|
@ -234,7 +225,6 @@ static int asm9260_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|||
iowrite32(alrm->time.tm_sec, priv->iobase + HW_ALSEC);
|
||||
|
||||
iowrite32(alrm->enabled ? 0 : BM_AMR_OFF, priv->iobase + HW_AMR);
|
||||
spin_unlock_irqrestore(&priv->lock, irq_flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -187,7 +187,7 @@ static irqreturn_t at32_rtc_interrupt(int irq, void *dev_id)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct rtc_class_ops at32_rtc_ops = {
|
||||
static const struct rtc_class_ops at32_rtc_ops = {
|
||||
.read_time = at32_rtc_readtime,
|
||||
.set_time = at32_rtc_settime,
|
||||
.read_alarm = at32_rtc_readalarm,
|
||||
|
|
|
@ -93,8 +93,15 @@ static int bq32k_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
|||
if (error)
|
||||
return error;
|
||||
|
||||
/*
|
||||
* In case of oscillator failure, the register contents should be
|
||||
* considered invalid. The flag is cleared the next time the RTC is set.
|
||||
*/
|
||||
if (regs.minutes & BQ32K_OF)
|
||||
return -EINVAL;
|
||||
|
||||
tm->tm_sec = bcd2bin(regs.seconds & BQ32K_SECONDS_MASK);
|
||||
tm->tm_min = bcd2bin(regs.minutes & BQ32K_SECONDS_MASK);
|
||||
tm->tm_min = bcd2bin(regs.minutes & BQ32K_MINUTES_MASK);
|
||||
tm->tm_hour = bcd2bin(regs.cent_hours & BQ32K_HOURS_MASK);
|
||||
tm->tm_mday = bcd2bin(regs.date);
|
||||
tm->tm_wday = bcd2bin(regs.day) - 1;
|
||||
|
@ -204,13 +211,10 @@ static int bq32k_probe(struct i2c_client *client,
|
|||
|
||||
/* Check Oscillator Failure flag */
|
||||
error = bq32k_read(dev, ®, BQ32K_MINUTES, 1);
|
||||
if (!error && (reg & BQ32K_OF)) {
|
||||
dev_warn(dev, "Oscillator Failure. Check RTC battery.\n");
|
||||
reg &= ~BQ32K_OF;
|
||||
error = bq32k_write(dev, ®, BQ32K_MINUTES, 1);
|
||||
}
|
||||
if (error)
|
||||
return error;
|
||||
if (reg & BQ32K_OF)
|
||||
dev_warn(dev, "Oscillator Failure. Check RTC battery.\n");
|
||||
|
||||
if (client->dev.of_node)
|
||||
trickle_charger_of_init(dev, client->dev.of_node);
|
||||
|
|
|
@ -62,6 +62,8 @@ struct cmos_rtc {
|
|||
u8 day_alrm;
|
||||
u8 mon_alrm;
|
||||
u8 century;
|
||||
|
||||
struct rtc_wkalrm saved_wkalrm;
|
||||
};
|
||||
|
||||
/* both platform and pnp busses use negative numbers for invalid irqs */
|
||||
|
@ -707,6 +709,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
|||
goto cleanup1;
|
||||
}
|
||||
|
||||
hpet_rtc_timer_init();
|
||||
|
||||
if (is_valid_irq(rtc_irq)) {
|
||||
irq_handler_t rtc_cmos_int_handler;
|
||||
|
||||
|
@ -714,6 +718,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
|||
rtc_cmos_int_handler = hpet_rtc_interrupt;
|
||||
retval = hpet_register_irq_handler(cmos_interrupt);
|
||||
if (retval) {
|
||||
hpet_mask_rtc_irq_bit(RTC_IRQMASK);
|
||||
dev_warn(dev, "hpet_register_irq_handler "
|
||||
" failed in rtc_init().");
|
||||
goto cleanup1;
|
||||
|
@ -729,7 +734,6 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
|
|||
goto cleanup1;
|
||||
}
|
||||
}
|
||||
hpet_rtc_timer_init();
|
||||
|
||||
/* export at least the first block of NVRAM */
|
||||
nvram.size = address_space - NVRAM_OFFSET;
|
||||
|
@ -844,8 +848,6 @@ static int cmos_aie_poweroff(struct device *dev)
|
|||
return retval;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int cmos_suspend(struct device *dev)
|
||||
{
|
||||
struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
||||
|
@ -877,6 +879,8 @@ static int cmos_suspend(struct device *dev)
|
|||
enable_irq_wake(cmos->irq);
|
||||
}
|
||||
|
||||
cmos_read_alarm(dev, &cmos->saved_wkalrm);
|
||||
|
||||
dev_dbg(dev, "suspend%s, ctrl %02x\n",
|
||||
(tmp & RTC_AIE) ? ", alarm may wake" : "",
|
||||
tmp);
|
||||
|
@ -892,12 +896,32 @@ static int cmos_suspend(struct device *dev)
|
|||
*/
|
||||
static inline int cmos_poweroff(struct device *dev)
|
||||
{
|
||||
if (!IS_ENABLED(CONFIG_PM))
|
||||
return -ENOSYS;
|
||||
|
||||
return cmos_suspend(dev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static void cmos_check_wkalrm(struct device *dev)
|
||||
{
|
||||
struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
||||
struct rtc_wkalrm current_alarm;
|
||||
time64_t t_current_expires;
|
||||
time64_t t_saved_expires;
|
||||
|
||||
static int cmos_resume(struct device *dev)
|
||||
cmos_read_alarm(dev, ¤t_alarm);
|
||||
t_current_expires = rtc_tm_to_time64(¤t_alarm.time);
|
||||
t_saved_expires = rtc_tm_to_time64(&cmos->saved_wkalrm.time);
|
||||
if (t_current_expires != t_saved_expires ||
|
||||
cmos->saved_wkalrm.enabled != current_alarm.enabled) {
|
||||
cmos_set_alarm(dev, &cmos->saved_wkalrm);
|
||||
}
|
||||
}
|
||||
|
||||
static void cmos_check_acpi_rtc_status(struct device *dev,
|
||||
unsigned char *rtc_control);
|
||||
|
||||
static int __maybe_unused cmos_resume(struct device *dev)
|
||||
{
|
||||
struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
||||
unsigned char tmp;
|
||||
|
@ -910,6 +934,9 @@ static int cmos_resume(struct device *dev)
|
|||
cmos->enabled_wake = 0;
|
||||
}
|
||||
|
||||
/* The BIOS might have changed the alarm, restore it */
|
||||
cmos_check_wkalrm(dev);
|
||||
|
||||
spin_lock_irq(&rtc_lock);
|
||||
tmp = cmos->suspend_ctrl;
|
||||
cmos->suspend_ctrl = 0;
|
||||
|
@ -936,6 +963,9 @@ static int cmos_resume(struct device *dev)
|
|||
tmp &= ~RTC_AIE;
|
||||
hpet_mask_rtc_irq_bit(RTC_AIE);
|
||||
} while (mask & RTC_AIE);
|
||||
|
||||
if (tmp & RTC_AIE)
|
||||
cmos_check_acpi_rtc_status(dev, &tmp);
|
||||
}
|
||||
spin_unlock_irq(&rtc_lock);
|
||||
|
||||
|
@ -944,16 +974,6 @@ static int cmos_resume(struct device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
#else
|
||||
|
||||
static inline int cmos_poweroff(struct device *dev)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(cmos_pm_ops, cmos_suspend, cmos_resume);
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
|
@ -973,6 +993,20 @@ static SIMPLE_DEV_PM_OPS(cmos_pm_ops, cmos_suspend, cmos_resume);
|
|||
static u32 rtc_handler(void *context)
|
||||
{
|
||||
struct device *dev = context;
|
||||
struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
||||
unsigned char rtc_control = 0;
|
||||
unsigned char rtc_intr;
|
||||
|
||||
spin_lock_irq(&rtc_lock);
|
||||
if (cmos_rtc.suspend_ctrl)
|
||||
rtc_control = CMOS_READ(RTC_CONTROL);
|
||||
if (rtc_control & RTC_AIE) {
|
||||
cmos_rtc.suspend_ctrl &= ~RTC_AIE;
|
||||
CMOS_WRITE(rtc_control, RTC_CONTROL);
|
||||
rtc_intr = CMOS_READ(RTC_INTR_FLAGS);
|
||||
rtc_update_irq(cmos->rtc, 1, rtc_intr);
|
||||
}
|
||||
spin_unlock_irq(&rtc_lock);
|
||||
|
||||
pm_wakeup_event(dev, 0);
|
||||
acpi_clear_event(ACPI_EVENT_RTC);
|
||||
|
@ -1039,12 +1073,39 @@ static void cmos_wake_setup(struct device *dev)
|
|||
device_init_wakeup(dev, 1);
|
||||
}
|
||||
|
||||
static void cmos_check_acpi_rtc_status(struct device *dev,
|
||||
unsigned char *rtc_control)
|
||||
{
|
||||
struct cmos_rtc *cmos = dev_get_drvdata(dev);
|
||||
acpi_event_status rtc_status;
|
||||
acpi_status status;
|
||||
|
||||
if (acpi_gbl_FADT.flags & ACPI_FADT_FIXED_RTC)
|
||||
return;
|
||||
|
||||
status = acpi_get_event_status(ACPI_EVENT_RTC, &rtc_status);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
dev_err(dev, "Could not get RTC status\n");
|
||||
} else if (rtc_status & ACPI_EVENT_FLAG_SET) {
|
||||
unsigned char mask;
|
||||
*rtc_control &= ~RTC_AIE;
|
||||
CMOS_WRITE(*rtc_control, RTC_CONTROL);
|
||||
mask = CMOS_READ(RTC_INTR_FLAGS);
|
||||
rtc_update_irq(cmos->rtc, 1, mask);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void cmos_wake_setup(struct device *dev)
|
||||
{
|
||||
}
|
||||
|
||||
static void cmos_check_acpi_rtc_status(struct device *dev,
|
||||
unsigned char *rtc_control)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PNP
|
||||
|
@ -1206,9 +1267,7 @@ static struct platform_driver cmos_platform_driver = {
|
|||
.shutdown = cmos_platform_shutdown,
|
||||
.driver = {
|
||||
.name = driver_name,
|
||||
#ifdef CONFIG_PM
|
||||
.pm = &cmos_pm_ops,
|
||||
#endif
|
||||
.of_match_table = of_match_ptr(of_cmos_match),
|
||||
}
|
||||
};
|
||||
|
|
|
@ -140,7 +140,7 @@ static int coh901331_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct rtc_class_ops coh901331_ops = {
|
||||
static const struct rtc_class_ops coh901331_ops = {
|
||||
.read_time = coh901331_read_time,
|
||||
.set_mmss = coh901331_set_mmss,
|
||||
.read_alarm = coh901331_read_alarm,
|
||||
|
|
|
@ -469,7 +469,7 @@ static int davinci_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct rtc_class_ops davinci_rtc_ops = {
|
||||
static const struct rtc_class_ops davinci_rtc_ops = {
|
||||
.ioctl = davinci_rtc_ioctl,
|
||||
.read_time = davinci_rtc_read_time,
|
||||
.set_time = davinci_rtc_set_time,
|
||||
|
|
|
@ -159,7 +159,7 @@ static int dc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct rtc_class_ops dc_rtc_ops = {
|
||||
static const struct rtc_class_ops dc_rtc_ops = {
|
||||
.read_time = dc_rtc_read_time,
|
||||
.set_mmss = dc_rtc_set_mmss,
|
||||
.read_alarm = dc_rtc_read_alarm,
|
||||
|
|
|
@ -102,7 +102,7 @@ static int ds1302_rtc_get_time(struct device *dev, struct rtc_time *time)
|
|||
return rtc_valid_tm(time);
|
||||
}
|
||||
|
||||
static struct rtc_class_ops ds1302_rtc_ops = {
|
||||
static const struct rtc_class_ops ds1302_rtc_ops = {
|
||||
.read_time = ds1302_rtc_get_time,
|
||||
.set_time = ds1302_rtc_set_time,
|
||||
};
|
||||
|
|
|
@ -186,6 +186,7 @@ static const struct i2c_device_id ds1307_id[] = {
|
|||
{ "mcp7941x", mcp794xx },
|
||||
{ "pt7c4338", ds_1307 },
|
||||
{ "rx8025", rx_8025 },
|
||||
{ "isl12057", ds_1337 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, ds1307_id);
|
||||
|
@ -382,10 +383,25 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
|
|||
t->tm_mday = bcd2bin(ds1307->regs[DS1307_REG_MDAY] & 0x3f);
|
||||
tmp = ds1307->regs[DS1307_REG_MONTH] & 0x1f;
|
||||
t->tm_mon = bcd2bin(tmp) - 1;
|
||||
|
||||
/* assume 20YY not 19YY, and ignore DS1337_BIT_CENTURY */
|
||||
t->tm_year = bcd2bin(ds1307->regs[DS1307_REG_YEAR]) + 100;
|
||||
|
||||
#ifdef CONFIG_RTC_DRV_DS1307_CENTURY
|
||||
switch (ds1307->type) {
|
||||
case ds_1337:
|
||||
case ds_1339:
|
||||
case ds_3231:
|
||||
if (ds1307->regs[DS1307_REG_MONTH] & DS1337_BIT_CENTURY)
|
||||
t->tm_year += 100;
|
||||
break;
|
||||
case ds_1340:
|
||||
if (ds1307->regs[DS1307_REG_HOUR] & DS1340_BIT_CENTURY)
|
||||
t->tm_year += 100;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
dev_dbg(dev, "%s secs=%d, mins=%d, "
|
||||
"hours=%d, mday=%d, mon=%d, year=%d, wday=%d\n",
|
||||
"read", t->tm_sec, t->tm_min,
|
||||
|
@ -409,6 +425,27 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
|
|||
t->tm_hour, t->tm_mday,
|
||||
t->tm_mon, t->tm_year, t->tm_wday);
|
||||
|
||||
#ifdef CONFIG_RTC_DRV_DS1307_CENTURY
|
||||
if (t->tm_year < 100)
|
||||
return -EINVAL;
|
||||
|
||||
switch (ds1307->type) {
|
||||
case ds_1337:
|
||||
case ds_1339:
|
||||
case ds_3231:
|
||||
case ds_1340:
|
||||
if (t->tm_year > 299)
|
||||
return -EINVAL;
|
||||
default:
|
||||
if (t->tm_year > 199)
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
if (t->tm_year < 100 || t->tm_year > 199)
|
||||
return -EINVAL;
|
||||
#endif
|
||||
|
||||
buf[DS1307_REG_SECS] = bin2bcd(t->tm_sec);
|
||||
buf[DS1307_REG_MIN] = bin2bcd(t->tm_min);
|
||||
buf[DS1307_REG_HOUR] = bin2bcd(t->tm_hour);
|
||||
|
@ -424,11 +461,13 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
|
|||
case ds_1337:
|
||||
case ds_1339:
|
||||
case ds_3231:
|
||||
buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY;
|
||||
if (t->tm_year > 199)
|
||||
buf[DS1307_REG_MONTH] |= DS1337_BIT_CENTURY;
|
||||
break;
|
||||
case ds_1340:
|
||||
buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN
|
||||
| DS1340_BIT_CENTURY;
|
||||
buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY_EN;
|
||||
if (t->tm_year > 199)
|
||||
buf[DS1307_REG_HOUR] |= DS1340_BIT_CENTURY;
|
||||
break;
|
||||
case mcp794xx:
|
||||
/*
|
||||
|
@ -1295,6 +1334,11 @@ static int ds1307_probe(struct i2c_client *client,
|
|||
if (of_property_read_bool(client->dev.of_node, "wakeup-source")) {
|
||||
ds1307_can_wakeup_device = true;
|
||||
}
|
||||
/* Intersil ISL12057 DT backward compatibility */
|
||||
if (of_property_read_bool(client->dev.of_node,
|
||||
"isil,irq2-can-wakeup-machine")) {
|
||||
ds1307_can_wakeup_device = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
switch (ds1307->type) {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/rtc.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
/* Registers in ds1347 rtc */
|
||||
|
||||
|
@ -32,37 +33,28 @@
|
|||
#define DS1347_STATUS_REG 0x17
|
||||
#define DS1347_CLOCK_BURST 0x3F
|
||||
|
||||
static int ds1347_read_reg(struct device *dev, unsigned char address,
|
||||
unsigned char *data)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
static const struct regmap_range ds1347_ranges[] = {
|
||||
{
|
||||
.range_min = DS1347_SECONDS_REG,
|
||||
.range_max = DS1347_STATUS_REG,
|
||||
},
|
||||
};
|
||||
|
||||
*data = address | 0x80;
|
||||
|
||||
return spi_write_then_read(spi, data, 1, data, 1);
|
||||
}
|
||||
|
||||
static int ds1347_write_reg(struct device *dev, unsigned char address,
|
||||
unsigned char data)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
unsigned char buf[2];
|
||||
|
||||
buf[0] = address & 0x7F;
|
||||
buf[1] = data;
|
||||
|
||||
return spi_write_then_read(spi, buf, 2, NULL, 0);
|
||||
}
|
||||
static const struct regmap_access_table ds1347_access_table = {
|
||||
.yes_ranges = ds1347_ranges,
|
||||
.n_yes_ranges = ARRAY_SIZE(ds1347_ranges),
|
||||
};
|
||||
|
||||
static int ds1347_read_time(struct device *dev, struct rtc_time *dt)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
struct regmap *map;
|
||||
int err;
|
||||
unsigned char buf[8];
|
||||
|
||||
buf[0] = DS1347_CLOCK_BURST | 0x80;
|
||||
map = spi_get_drvdata(spi);
|
||||
|
||||
err = spi_write_then_read(spi, buf, 1, buf, 8);
|
||||
err = regmap_bulk_read(map, DS1347_CLOCK_BURST, buf, 8);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
@ -80,25 +72,27 @@ static int ds1347_read_time(struct device *dev, struct rtc_time *dt)
|
|||
static int ds1347_set_time(struct device *dev, struct rtc_time *dt)
|
||||
{
|
||||
struct spi_device *spi = to_spi_device(dev);
|
||||
unsigned char buf[9];
|
||||
struct regmap *map;
|
||||
unsigned char buf[8];
|
||||
|
||||
buf[0] = DS1347_CLOCK_BURST & 0x7F;
|
||||
buf[1] = bin2bcd(dt->tm_sec);
|
||||
buf[2] = bin2bcd(dt->tm_min);
|
||||
buf[3] = (bin2bcd(dt->tm_hour) & 0x3F);
|
||||
buf[4] = bin2bcd(dt->tm_mday);
|
||||
buf[5] = bin2bcd(dt->tm_mon + 1);
|
||||
buf[6] = bin2bcd(dt->tm_wday + 1);
|
||||
map = spi_get_drvdata(spi);
|
||||
|
||||
buf[0] = bin2bcd(dt->tm_sec);
|
||||
buf[1] = bin2bcd(dt->tm_min);
|
||||
buf[2] = (bin2bcd(dt->tm_hour) & 0x3F);
|
||||
buf[3] = bin2bcd(dt->tm_mday);
|
||||
buf[4] = bin2bcd(dt->tm_mon + 1);
|
||||
buf[5] = bin2bcd(dt->tm_wday + 1);
|
||||
|
||||
/* year in linux is from 1900 i.e in range of 100
|
||||
in rtc it is from 00 to 99 */
|
||||
dt->tm_year = dt->tm_year % 100;
|
||||
|
||||
buf[7] = bin2bcd(dt->tm_year);
|
||||
buf[8] = bin2bcd(0x00);
|
||||
buf[6] = bin2bcd(dt->tm_year);
|
||||
buf[7] = bin2bcd(0x00);
|
||||
|
||||
/* write the rtc settings */
|
||||
return spi_write_then_read(spi, buf, 9, NULL, 0);
|
||||
return regmap_bulk_write(map, DS1347_CLOCK_BURST, buf, 8);
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops ds1347_rtc_ops = {
|
||||
|
@ -109,35 +103,53 @@ static const struct rtc_class_ops ds1347_rtc_ops = {
|
|||
static int ds1347_probe(struct spi_device *spi)
|
||||
{
|
||||
struct rtc_device *rtc;
|
||||
unsigned char data;
|
||||
struct regmap_config config;
|
||||
struct regmap *map;
|
||||
unsigned int data;
|
||||
int res;
|
||||
|
||||
memset(&config, 0, sizeof(config));
|
||||
config.reg_bits = 8;
|
||||
config.val_bits = 8;
|
||||
config.read_flag_mask = 0x80;
|
||||
config.max_register = 0x3F;
|
||||
config.wr_table = &ds1347_access_table;
|
||||
|
||||
/* spi setup with ds1347 in mode 3 and bits per word as 8 */
|
||||
spi->mode = SPI_MODE_3;
|
||||
spi->bits_per_word = 8;
|
||||
spi_setup(spi);
|
||||
|
||||
map = devm_regmap_init_spi(spi, &config);
|
||||
|
||||
if (IS_ERR(map)) {
|
||||
dev_err(&spi->dev, "ds1347 regmap init spi failed\n");
|
||||
return PTR_ERR(map);
|
||||
}
|
||||
|
||||
spi_set_drvdata(spi, map);
|
||||
|
||||
/* RTC Settings */
|
||||
res = ds1347_read_reg(&spi->dev, DS1347_SECONDS_REG, &data);
|
||||
res = regmap_read(map, DS1347_SECONDS_REG, &data);
|
||||
if (res)
|
||||
return res;
|
||||
|
||||
/* Disable the write protect of rtc */
|
||||
ds1347_read_reg(&spi->dev, DS1347_CONTROL_REG, &data);
|
||||
regmap_read(map, DS1347_CONTROL_REG, &data);
|
||||
data = data & ~(1<<7);
|
||||
ds1347_write_reg(&spi->dev, DS1347_CONTROL_REG, data);
|
||||
regmap_write(map, DS1347_CONTROL_REG, data);
|
||||
|
||||
/* Enable the oscillator , disable the oscillator stop flag,
|
||||
and glitch filter to reduce current consumption */
|
||||
ds1347_read_reg(&spi->dev, DS1347_STATUS_REG, &data);
|
||||
regmap_read(map, DS1347_STATUS_REG, &data);
|
||||
data = data & 0x1B;
|
||||
ds1347_write_reg(&spi->dev, DS1347_STATUS_REG, data);
|
||||
regmap_write(map, DS1347_STATUS_REG, data);
|
||||
|
||||
/* display the settings */
|
||||
ds1347_read_reg(&spi->dev, DS1347_CONTROL_REG, &data);
|
||||
regmap_read(map, DS1347_CONTROL_REG, &data);
|
||||
dev_info(&spi->dev, "DS1347 RTC CTRL Reg = 0x%02x\n", data);
|
||||
|
||||
ds1347_read_reg(&spi->dev, DS1347_STATUS_REG, &data);
|
||||
regmap_read(map, DS1347_STATUS_REG, &data);
|
||||
dev_info(&spi->dev, "DS1347 RTC Status Reg = 0x%02x\n", data);
|
||||
|
||||
rtc = devm_rtc_device_register(&spi->dev, "ds1347",
|
||||
|
@ -146,8 +158,6 @@ static int ds1347_probe(struct spi_device *spi)
|
|||
if (IS_ERR(rtc))
|
||||
return PTR_ERR(rtc);
|
||||
|
||||
spi_set_drvdata(spi, rtc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ static int gemini_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct rtc_class_ops gemini_rtc_ops = {
|
||||
static const struct rtc_class_ops gemini_rtc_ops = {
|
||||
.read_time = gemini_rtc_read_time,
|
||||
.set_time = gemini_rtc_set_time,
|
||||
};
|
||||
|
|
|
@ -1,643 +0,0 @@
|
|||
/*
|
||||
* rtc-isl12057 - Driver for Intersil ISL12057 I2C Real Time Clock
|
||||
*
|
||||
* Copyright (C) 2013, Arnaud EBALARD <arno@natisbad.org>
|
||||
*
|
||||
* This work is largely based on Intersil ISL1208 driver developed by
|
||||
* Hebert Valerio Riedel <hvr@gnu.org>.
|
||||
*
|
||||
* Detailed datasheet on which this development is based is available here:
|
||||
*
|
||||
* http://natisbad.org/NAS2/refs/ISL12057.pdf
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#define DRV_NAME "rtc-isl12057"
|
||||
|
||||
/* RTC section */
|
||||
#define ISL12057_REG_RTC_SC 0x00 /* Seconds */
|
||||
#define ISL12057_REG_RTC_MN 0x01 /* Minutes */
|
||||
#define ISL12057_REG_RTC_HR 0x02 /* Hours */
|
||||
#define ISL12057_REG_RTC_HR_PM BIT(5) /* AM/PM bit in 12h format */
|
||||
#define ISL12057_REG_RTC_HR_MIL BIT(6) /* 24h/12h format */
|
||||
#define ISL12057_REG_RTC_DW 0x03 /* Day of the Week */
|
||||
#define ISL12057_REG_RTC_DT 0x04 /* Date */
|
||||
#define ISL12057_REG_RTC_MO 0x05 /* Month */
|
||||
#define ISL12057_REG_RTC_MO_CEN BIT(7) /* Century bit */
|
||||
#define ISL12057_REG_RTC_YR 0x06 /* Year */
|
||||
#define ISL12057_RTC_SEC_LEN 7
|
||||
|
||||
/* Alarm 1 section */
|
||||
#define ISL12057_REG_A1_SC 0x07 /* Alarm 1 Seconds */
|
||||
#define ISL12057_REG_A1_MN 0x08 /* Alarm 1 Minutes */
|
||||
#define ISL12057_REG_A1_HR 0x09 /* Alarm 1 Hours */
|
||||
#define ISL12057_REG_A1_HR_PM BIT(5) /* AM/PM bit in 12h format */
|
||||
#define ISL12057_REG_A1_HR_MIL BIT(6) /* 24h/12h format */
|
||||
#define ISL12057_REG_A1_DWDT 0x0A /* Alarm 1 Date / Day of the week */
|
||||
#define ISL12057_REG_A1_DWDT_B BIT(6) /* DW / DT selection bit */
|
||||
#define ISL12057_A1_SEC_LEN 4
|
||||
|
||||
/* Alarm 2 section */
|
||||
#define ISL12057_REG_A2_MN 0x0B /* Alarm 2 Minutes */
|
||||
#define ISL12057_REG_A2_HR 0x0C /* Alarm 2 Hours */
|
||||
#define ISL12057_REG_A2_DWDT 0x0D /* Alarm 2 Date / Day of the week */
|
||||
#define ISL12057_A2_SEC_LEN 3
|
||||
|
||||
/* Control/Status registers */
|
||||
#define ISL12057_REG_INT 0x0E
|
||||
#define ISL12057_REG_INT_A1IE BIT(0) /* Alarm 1 interrupt enable bit */
|
||||
#define ISL12057_REG_INT_A2IE BIT(1) /* Alarm 2 interrupt enable bit */
|
||||
#define ISL12057_REG_INT_INTCN BIT(2) /* Interrupt control enable bit */
|
||||
#define ISL12057_REG_INT_RS1 BIT(3) /* Freq out control bit 1 */
|
||||
#define ISL12057_REG_INT_RS2 BIT(4) /* Freq out control bit 2 */
|
||||
#define ISL12057_REG_INT_EOSC BIT(7) /* Oscillator enable bit */
|
||||
|
||||
#define ISL12057_REG_SR 0x0F
|
||||
#define ISL12057_REG_SR_A1F BIT(0) /* Alarm 1 interrupt bit */
|
||||
#define ISL12057_REG_SR_A2F BIT(1) /* Alarm 2 interrupt bit */
|
||||
#define ISL12057_REG_SR_OSF BIT(7) /* Oscillator failure bit */
|
||||
|
||||
/* Register memory map length */
|
||||
#define ISL12057_MEM_MAP_LEN 0x10
|
||||
|
||||
struct isl12057_rtc_data {
|
||||
struct rtc_device *rtc;
|
||||
struct regmap *regmap;
|
||||
struct mutex lock;
|
||||
int irq;
|
||||
};
|
||||
|
||||
static void isl12057_rtc_regs_to_tm(struct rtc_time *tm, u8 *regs)
|
||||
{
|
||||
tm->tm_sec = bcd2bin(regs[ISL12057_REG_RTC_SC]);
|
||||
tm->tm_min = bcd2bin(regs[ISL12057_REG_RTC_MN]);
|
||||
|
||||
if (regs[ISL12057_REG_RTC_HR] & ISL12057_REG_RTC_HR_MIL) { /* AM/PM */
|
||||
tm->tm_hour = bcd2bin(regs[ISL12057_REG_RTC_HR] & 0x1f);
|
||||
if (regs[ISL12057_REG_RTC_HR] & ISL12057_REG_RTC_HR_PM)
|
||||
tm->tm_hour += 12;
|
||||
} else { /* 24 hour mode */
|
||||
tm->tm_hour = bcd2bin(regs[ISL12057_REG_RTC_HR] & 0x3f);
|
||||
}
|
||||
|
||||
tm->tm_mday = bcd2bin(regs[ISL12057_REG_RTC_DT]);
|
||||
tm->tm_wday = bcd2bin(regs[ISL12057_REG_RTC_DW]) - 1; /* starts at 1 */
|
||||
tm->tm_mon = bcd2bin(regs[ISL12057_REG_RTC_MO] & 0x1f) - 1; /* ditto */
|
||||
tm->tm_year = bcd2bin(regs[ISL12057_REG_RTC_YR]) + 100;
|
||||
|
||||
/* Check if years register has overflown from 99 to 00 */
|
||||
if (regs[ISL12057_REG_RTC_MO] & ISL12057_REG_RTC_MO_CEN)
|
||||
tm->tm_year += 100;
|
||||
}
|
||||
|
||||
static int isl12057_rtc_tm_to_regs(u8 *regs, struct rtc_time *tm)
|
||||
{
|
||||
u8 century_bit;
|
||||
|
||||
/*
|
||||
* The clock has an 8 bit wide bcd-coded register for the year.
|
||||
* It also has a century bit encoded in MO flag which provides
|
||||
* information about overflow of year register from 99 to 00.
|
||||
* tm_year is an offset from 1900 and we are interested in the
|
||||
* 2000-2199 range, so any value less than 100 or larger than
|
||||
* 299 is invalid.
|
||||
*/
|
||||
if (tm->tm_year < 100 || tm->tm_year > 299)
|
||||
return -EINVAL;
|
||||
|
||||
century_bit = (tm->tm_year > 199) ? ISL12057_REG_RTC_MO_CEN : 0;
|
||||
|
||||
regs[ISL12057_REG_RTC_SC] = bin2bcd(tm->tm_sec);
|
||||
regs[ISL12057_REG_RTC_MN] = bin2bcd(tm->tm_min);
|
||||
regs[ISL12057_REG_RTC_HR] = bin2bcd(tm->tm_hour); /* 24-hour format */
|
||||
regs[ISL12057_REG_RTC_DT] = bin2bcd(tm->tm_mday);
|
||||
regs[ISL12057_REG_RTC_MO] = bin2bcd(tm->tm_mon + 1) | century_bit;
|
||||
regs[ISL12057_REG_RTC_YR] = bin2bcd(tm->tm_year % 100);
|
||||
regs[ISL12057_REG_RTC_DW] = bin2bcd(tm->tm_wday + 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try and match register bits w/ fixed null values to see whether we
|
||||
* are dealing with an ISL12057. Note: this function is called early
|
||||
* during init and hence does need mutex protection.
|
||||
*/
|
||||
static int isl12057_i2c_validate_chip(struct regmap *regmap)
|
||||
{
|
||||
u8 regs[ISL12057_MEM_MAP_LEN];
|
||||
static const u8 mask[ISL12057_MEM_MAP_LEN] = { 0x80, 0x80, 0x80, 0xf8,
|
||||
0xc0, 0x60, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x60, 0x7c };
|
||||
int ret, i;
|
||||
|
||||
ret = regmap_bulk_read(regmap, 0, regs, ISL12057_MEM_MAP_LEN);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < ISL12057_MEM_MAP_LEN; ++i) {
|
||||
if (regs[i] & mask[i]) /* check if bits are cleared */
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _isl12057_rtc_clear_alarm(struct device *dev)
|
||||
{
|
||||
struct isl12057_rtc_data *data = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(data->regmap, ISL12057_REG_SR,
|
||||
ISL12057_REG_SR_A1F, 0);
|
||||
if (ret)
|
||||
dev_err(dev, "%s: clearing alarm failed (%d)\n", __func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _isl12057_rtc_update_alarm(struct device *dev, int enable)
|
||||
{
|
||||
struct isl12057_rtc_data *data = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = regmap_update_bits(data->regmap, ISL12057_REG_INT,
|
||||
ISL12057_REG_INT_A1IE,
|
||||
enable ? ISL12057_REG_INT_A1IE : 0);
|
||||
if (ret)
|
||||
dev_err(dev, "%s: changing alarm interrupt flag failed (%d)\n",
|
||||
__func__, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: as we only read from device and do not perform any update, there is
|
||||
* no need for an equivalent function which would try and get driver's main
|
||||
* lock. Here, it is safe for everyone if we just use regmap internal lock
|
||||
* on the device when reading.
|
||||
*/
|
||||
static int _isl12057_rtc_read_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct isl12057_rtc_data *data = dev_get_drvdata(dev);
|
||||
u8 regs[ISL12057_RTC_SEC_LEN];
|
||||
unsigned int sr;
|
||||
int ret;
|
||||
|
||||
ret = regmap_read(data->regmap, ISL12057_REG_SR, &sr);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: unable to read oscillator status flag (%d)\n",
|
||||
__func__, ret);
|
||||
goto out;
|
||||
} else {
|
||||
if (sr & ISL12057_REG_SR_OSF) {
|
||||
ret = -ENODATA;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = regmap_bulk_read(data->regmap, ISL12057_REG_RTC_SC, regs,
|
||||
ISL12057_RTC_SEC_LEN);
|
||||
if (ret)
|
||||
dev_err(dev, "%s: unable to read RTC time section (%d)\n",
|
||||
__func__, ret);
|
||||
|
||||
out:
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
isl12057_rtc_regs_to_tm(tm, regs);
|
||||
|
||||
return rtc_valid_tm(tm);
|
||||
}
|
||||
|
||||
static int isl12057_rtc_update_alarm(struct device *dev, int enable)
|
||||
{
|
||||
struct isl12057_rtc_data *data = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
ret = _isl12057_rtc_update_alarm(dev, enable);
|
||||
mutex_unlock(&data->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int isl12057_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
|
||||
{
|
||||
struct isl12057_rtc_data *data = dev_get_drvdata(dev);
|
||||
struct rtc_time *alarm_tm = &alarm->time;
|
||||
u8 regs[ISL12057_A1_SEC_LEN];
|
||||
unsigned int ir;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
ret = regmap_bulk_read(data->regmap, ISL12057_REG_A1_SC, regs,
|
||||
ISL12057_A1_SEC_LEN);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: reading alarm section failed (%d)\n",
|
||||
__func__, ret);
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
alarm_tm->tm_sec = bcd2bin(regs[0] & 0x7f);
|
||||
alarm_tm->tm_min = bcd2bin(regs[1] & 0x7f);
|
||||
alarm_tm->tm_hour = bcd2bin(regs[2] & 0x3f);
|
||||
alarm_tm->tm_mday = bcd2bin(regs[3] & 0x3f);
|
||||
|
||||
ret = regmap_read(data->regmap, ISL12057_REG_INT, &ir);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: reading alarm interrupt flag failed (%d)\n",
|
||||
__func__, ret);
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
alarm->enabled = !!(ir & ISL12057_REG_INT_A1IE);
|
||||
|
||||
err_unlock:
|
||||
mutex_unlock(&data->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int isl12057_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
|
||||
{
|
||||
struct isl12057_rtc_data *data = dev_get_drvdata(dev);
|
||||
struct rtc_time *alarm_tm = &alarm->time;
|
||||
unsigned long rtc_secs, alarm_secs;
|
||||
u8 regs[ISL12057_A1_SEC_LEN];
|
||||
struct rtc_time rtc_tm;
|
||||
int ret, enable = 1;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
ret = _isl12057_rtc_read_time(dev, &rtc_tm);
|
||||
if (ret)
|
||||
goto err_unlock;
|
||||
|
||||
ret = rtc_tm_to_time(&rtc_tm, &rtc_secs);
|
||||
if (ret)
|
||||
goto err_unlock;
|
||||
|
||||
ret = rtc_tm_to_time(alarm_tm, &alarm_secs);
|
||||
if (ret)
|
||||
goto err_unlock;
|
||||
|
||||
/* If alarm time is before current time, disable the alarm */
|
||||
if (!alarm->enabled || alarm_secs <= rtc_secs) {
|
||||
enable = 0;
|
||||
} else {
|
||||
/*
|
||||
* Chip only support alarms up to one month in the future. Let's
|
||||
* return an error if we get something after that limit.
|
||||
* Comparison is done by incrementing rtc_tm month field by one
|
||||
* and checking alarm value is still below.
|
||||
*/
|
||||
if (rtc_tm.tm_mon == 11) { /* handle year wrapping */
|
||||
rtc_tm.tm_mon = 0;
|
||||
rtc_tm.tm_year += 1;
|
||||
} else {
|
||||
rtc_tm.tm_mon += 1;
|
||||
}
|
||||
|
||||
ret = rtc_tm_to_time(&rtc_tm, &rtc_secs);
|
||||
if (ret)
|
||||
goto err_unlock;
|
||||
|
||||
if (alarm_secs > rtc_secs) {
|
||||
dev_err(dev, "%s: max for alarm is one month (%d)\n",
|
||||
__func__, ret);
|
||||
ret = -EINVAL;
|
||||
goto err_unlock;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the alarm before modifying it */
|
||||
ret = _isl12057_rtc_update_alarm(dev, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: unable to disable the alarm (%d)\n",
|
||||
__func__, ret);
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
/* Program alarm registers */
|
||||
regs[0] = bin2bcd(alarm_tm->tm_sec) & 0x7f;
|
||||
regs[1] = bin2bcd(alarm_tm->tm_min) & 0x7f;
|
||||
regs[2] = bin2bcd(alarm_tm->tm_hour) & 0x3f;
|
||||
regs[3] = bin2bcd(alarm_tm->tm_mday) & 0x3f;
|
||||
|
||||
ret = regmap_bulk_write(data->regmap, ISL12057_REG_A1_SC, regs,
|
||||
ISL12057_A1_SEC_LEN);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: writing alarm section failed (%d)\n",
|
||||
__func__, ret);
|
||||
goto err_unlock;
|
||||
}
|
||||
|
||||
/* Enable or disable alarm */
|
||||
ret = _isl12057_rtc_update_alarm(dev, enable);
|
||||
|
||||
err_unlock:
|
||||
mutex_unlock(&data->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int isl12057_rtc_set_time(struct device *dev, struct rtc_time *tm)
|
||||
{
|
||||
struct isl12057_rtc_data *data = dev_get_drvdata(dev);
|
||||
u8 regs[ISL12057_RTC_SEC_LEN];
|
||||
int ret;
|
||||
|
||||
ret = isl12057_rtc_tm_to_regs(regs, tm);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mutex_lock(&data->lock);
|
||||
ret = regmap_bulk_write(data->regmap, ISL12057_REG_RTC_SC, regs,
|
||||
ISL12057_RTC_SEC_LEN);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: unable to write RTC time section (%d)\n",
|
||||
__func__, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that RTC time has been updated, let's clear oscillator
|
||||
* failure flag, if needed.
|
||||
*/
|
||||
ret = regmap_update_bits(data->regmap, ISL12057_REG_SR,
|
||||
ISL12057_REG_SR_OSF, 0);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "%s: unable to clear osc. failure bit (%d)\n",
|
||||
__func__, ret);
|
||||
|
||||
out:
|
||||
mutex_unlock(&data->lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check current RTC status and enable/disable what needs to be. Return 0 if
|
||||
* everything went ok and a negative value upon error. Note: this function
|
||||
* is called early during init and hence does need mutex protection.
|
||||
*/
|
||||
static int isl12057_check_rtc_status(struct device *dev, struct regmap *regmap)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Enable oscillator if not already running */
|
||||
ret = regmap_update_bits(regmap, ISL12057_REG_INT,
|
||||
ISL12057_REG_INT_EOSC, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: unable to enable oscillator (%d)\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Clear alarm bit if needed */
|
||||
ret = regmap_update_bits(regmap, ISL12057_REG_SR,
|
||||
ISL12057_REG_SR_A1F, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: unable to clear alarm bit (%d)\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
/*
|
||||
* One would expect the device to be marked as a wakeup source only
|
||||
* when an IRQ pin of the RTC is routed to an interrupt line of the
|
||||
* CPU. In practice, such an IRQ pin can be connected to a PMIC and
|
||||
* this allows the device to be powered up when RTC alarm rings. This
|
||||
* is for instance the case on ReadyNAS 102, 104 and 2120. On those
|
||||
* devices with no IRQ driectly connected to the SoC, the RTC chip
|
||||
* can be forced as a wakeup source by stating that explicitly in
|
||||
* the device's .dts file using the "wakeup-source" boolean property.
|
||||
* This will guarantee 'wakealarm' sysfs entry is available on the device.
|
||||
*
|
||||
* The function below returns 1, i.e. the capability of the chip to
|
||||
* wakeup the device, based on IRQ availability or if the boolean
|
||||
* property has been set in the .dts file. Otherwise, it returns 0.
|
||||
*/
|
||||
|
||||
static bool isl12057_can_wakeup_machine(struct device *dev)
|
||||
{
|
||||
struct isl12057_rtc_data *data = dev_get_drvdata(dev);
|
||||
|
||||
return data->irq || of_property_read_bool(dev->of_node, "wakeup-source")
|
||||
|| of_property_read_bool(dev->of_node, /* legacy */
|
||||
"isil,irq2-can-wakeup-machine");
|
||||
}
|
||||
#else
|
||||
static bool isl12057_can_wakeup_machine(struct device *dev)
|
||||
{
|
||||
struct isl12057_rtc_data *data = dev_get_drvdata(dev);
|
||||
|
||||
return !!data->irq;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int isl12057_rtc_alarm_irq_enable(struct device *dev,
|
||||
unsigned int enable)
|
||||
{
|
||||
struct isl12057_rtc_data *rtc_data = dev_get_drvdata(dev);
|
||||
int ret = -ENOTTY;
|
||||
|
||||
if (rtc_data->irq)
|
||||
ret = isl12057_rtc_update_alarm(dev, enable);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t isl12057_rtc_interrupt(int irq, void *data)
|
||||
{
|
||||
struct i2c_client *client = data;
|
||||
struct isl12057_rtc_data *rtc_data = dev_get_drvdata(&client->dev);
|
||||
struct rtc_device *rtc = rtc_data->rtc;
|
||||
int ret, handled = IRQ_NONE;
|
||||
unsigned int sr;
|
||||
|
||||
ret = regmap_read(rtc_data->regmap, ISL12057_REG_SR, &sr);
|
||||
if (!ret && (sr & ISL12057_REG_SR_A1F)) {
|
||||
dev_dbg(&client->dev, "RTC alarm!\n");
|
||||
|
||||
rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF);
|
||||
|
||||
/* Acknowledge and disable the alarm */
|
||||
_isl12057_rtc_clear_alarm(&client->dev);
|
||||
_isl12057_rtc_update_alarm(&client->dev, 0);
|
||||
|
||||
handled = IRQ_HANDLED;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
static const struct rtc_class_ops rtc_ops = {
|
||||
.read_time = _isl12057_rtc_read_time,
|
||||
.set_time = isl12057_rtc_set_time,
|
||||
.read_alarm = isl12057_rtc_read_alarm,
|
||||
.set_alarm = isl12057_rtc_set_alarm,
|
||||
.alarm_irq_enable = isl12057_rtc_alarm_irq_enable,
|
||||
};
|
||||
|
||||
static const struct regmap_config isl12057_rtc_regmap_config = {
|
||||
.reg_bits = 8,
|
||||
.val_bits = 8,
|
||||
};
|
||||
|
||||
static int isl12057_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct isl12057_rtc_data *data;
|
||||
struct regmap *regmap;
|
||||
int ret;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_I2C_BLOCK))
|
||||
return -ENODEV;
|
||||
|
||||
regmap = devm_regmap_init_i2c(client, &isl12057_rtc_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
ret = PTR_ERR(regmap);
|
||||
dev_err(dev, "%s: regmap allocation failed (%d)\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = isl12057_i2c_validate_chip(regmap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = isl12057_check_rtc_status(dev, regmap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_init(&data->lock);
|
||||
data->regmap = regmap;
|
||||
dev_set_drvdata(dev, data);
|
||||
|
||||
if (client->irq > 0) {
|
||||
ret = devm_request_threaded_irq(dev, client->irq, NULL,
|
||||
isl12057_rtc_interrupt,
|
||||
IRQF_SHARED|IRQF_ONESHOT,
|
||||
DRV_NAME, client);
|
||||
if (!ret)
|
||||
data->irq = client->irq;
|
||||
else
|
||||
dev_err(dev, "%s: irq %d unavailable (%d)\n", __func__,
|
||||
client->irq, ret);
|
||||
}
|
||||
|
||||
if (isl12057_can_wakeup_machine(dev))
|
||||
device_init_wakeup(dev, true);
|
||||
|
||||
data->rtc = devm_rtc_device_register(dev, DRV_NAME, &rtc_ops,
|
||||
THIS_MODULE);
|
||||
ret = PTR_ERR_OR_ZERO(data->rtc);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s: unable to register RTC device (%d)\n",
|
||||
__func__, ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* We cannot support UIE mode if we do not have an IRQ line */
|
||||
if (!data->irq)
|
||||
data->rtc->uie_unsupported = 1;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int isl12057_remove(struct i2c_client *client)
|
||||
{
|
||||
if (isl12057_can_wakeup_machine(&client->dev))
|
||||
device_init_wakeup(&client->dev, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int isl12057_rtc_suspend(struct device *dev)
|
||||
{
|
||||
struct isl12057_rtc_data *rtc_data = dev_get_drvdata(dev);
|
||||
|
||||
if (rtc_data->irq && device_may_wakeup(dev))
|
||||
return enable_irq_wake(rtc_data->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int isl12057_rtc_resume(struct device *dev)
|
||||
{
|
||||
struct isl12057_rtc_data *rtc_data = dev_get_drvdata(dev);
|
||||
|
||||
if (rtc_data->irq && device_may_wakeup(dev))
|
||||
return disable_irq_wake(rtc_data->irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(isl12057_rtc_pm_ops, isl12057_rtc_suspend,
|
||||
isl12057_rtc_resume);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id isl12057_dt_match[] = {
|
||||
{ .compatible = "isl,isl12057" }, /* for backward compat., don't use */
|
||||
{ .compatible = "isil,isl12057" },
|
||||
{ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, isl12057_dt_match);
|
||||
#endif
|
||||
|
||||
static const struct i2c_device_id isl12057_id[] = {
|
||||
{ "isl12057", 0 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, isl12057_id);
|
||||
|
||||
static struct i2c_driver isl12057_driver = {
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.pm = &isl12057_rtc_pm_ops,
|
||||
.of_match_table = of_match_ptr(isl12057_dt_match),
|
||||
},
|
||||
.probe = isl12057_probe,
|
||||
.remove = isl12057_remove,
|
||||
.id_table = isl12057_id,
|
||||
};
|
||||
module_i2c_driver(isl12057_driver);
|
||||
|
||||
MODULE_AUTHOR("Arnaud EBALARD <arno@natisbad.org>");
|
||||
MODULE_DESCRIPTION("Intersil ISL12057 RTC driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -174,7 +174,7 @@ static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
|
|||
return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_AF_IRQ, enable);
|
||||
}
|
||||
|
||||
static struct rtc_class_ops jz4740_rtc_ops = {
|
||||
static const struct rtc_class_ops jz4740_rtc_ops = {
|
||||
.read_time = jz4740_rtc_read_time,
|
||||
.set_mmss = jz4740_rtc_set_mmss,
|
||||
.read_alarm = jz4740_rtc_read_alarm,
|
||||
|
|
|
@ -151,7 +151,7 @@ static int mcp795_read_time(struct device *dev, struct rtc_time *tim)
|
|||
return rtc_valid_tm(tim);
|
||||
}
|
||||
|
||||
static struct rtc_class_ops mcp795_rtc_ops = {
|
||||
static const struct rtc_class_ops mcp795_rtc_ops = {
|
||||
.read_time = mcp795_read_time,
|
||||
.set_time = mcp795_set_time
|
||||
};
|
||||
|
|
|
@ -301,7 +301,7 @@ exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct rtc_class_ops mtk_rtc_ops = {
|
||||
static const struct rtc_class_ops mtk_rtc_ops = {
|
||||
.read_time = mtk_rtc_read_time,
|
||||
.set_time = mtk_rtc_set_time,
|
||||
.read_alarm = mtk_rtc_read_alarm,
|
||||
|
|
|
@ -214,7 +214,7 @@ static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct rtc_class_ops nuc900_rtc_ops = {
|
||||
static const struct rtc_class_ops nuc900_rtc_ops = {
|
||||
.read_time = nuc900_rtc_read_time,
|
||||
.set_time = nuc900_rtc_set_time,
|
||||
.read_alarm = nuc900_rtc_read_alarm,
|
||||
|
|
|
@ -13,19 +13,23 @@
|
|||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
#include <linux/bcd.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinconf.h>
|
||||
#include <linux/pinctrl/pinconf-generic.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/rtc.h>
|
||||
|
||||
/*
|
||||
* The OMAP RTC is a year/month/day/hours/minutes/seconds BCD clock
|
||||
|
@ -115,6 +119,8 @@
|
|||
|
||||
/* OMAP_RTC_PMIC bit fields: */
|
||||
#define OMAP_RTC_PMIC_POWER_EN_EN BIT(16)
|
||||
#define OMAP_RTC_PMIC_EXT_WKUP_EN(x) BIT(x)
|
||||
#define OMAP_RTC_PMIC_EXT_WKUP_POL(x) BIT(4 + x)
|
||||
|
||||
/* OMAP_RTC_KICKER values */
|
||||
#define KICK0_VALUE 0x83e70b13
|
||||
|
@ -141,6 +147,7 @@ struct omap_rtc {
|
|||
bool is_pmic_controller;
|
||||
bool has_ext_clk;
|
||||
const struct omap_rtc_device_type *type;
|
||||
struct pinctrl_dev *pctldev;
|
||||
};
|
||||
|
||||
static inline u8 rtc_read(struct omap_rtc *rtc, unsigned int reg)
|
||||
|
@ -469,7 +476,7 @@ static void omap_rtc_power_off(void)
|
|||
mdelay(2500);
|
||||
}
|
||||
|
||||
static struct rtc_class_ops omap_rtc_ops = {
|
||||
static const struct rtc_class_ops omap_rtc_ops = {
|
||||
.read_time = omap_rtc_read_time,
|
||||
.set_time = omap_rtc_set_time,
|
||||
.read_alarm = omap_rtc_read_alarm,
|
||||
|
@ -525,6 +532,139 @@ static const struct of_device_id omap_rtc_of_match[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
|
||||
|
||||
static const struct pinctrl_pin_desc rtc_pins_desc[] = {
|
||||
PINCTRL_PIN(0, "ext_wakeup0"),
|
||||
PINCTRL_PIN(1, "ext_wakeup1"),
|
||||
PINCTRL_PIN(2, "ext_wakeup2"),
|
||||
PINCTRL_PIN(3, "ext_wakeup3"),
|
||||
};
|
||||
|
||||
static int rtc_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *rtc_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
|
||||
unsigned int group)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops rtc_pinctrl_ops = {
|
||||
.get_groups_count = rtc_pinctrl_get_groups_count,
|
||||
.get_group_name = rtc_pinctrl_get_group_name,
|
||||
.dt_node_to_map = pinconf_generic_dt_node_to_map_pin,
|
||||
.dt_free_map = pinconf_generic_dt_free_map,
|
||||
};
|
||||
|
||||
enum rtc_pin_config_param {
|
||||
PIN_CONFIG_ACTIVE_HIGH = PIN_CONFIG_END + 1,
|
||||
};
|
||||
|
||||
static const struct pinconf_generic_params rtc_params[] = {
|
||||
{"ti,active-high", PIN_CONFIG_ACTIVE_HIGH, 0},
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static const struct pin_config_item rtc_conf_items[ARRAY_SIZE(rtc_params)] = {
|
||||
PCONFDUMP(PIN_CONFIG_ACTIVE_HIGH, "input active high", NULL, false),
|
||||
};
|
||||
#endif
|
||||
|
||||
static int rtc_pinconf_get(struct pinctrl_dev *pctldev,
|
||||
unsigned int pin, unsigned long *config)
|
||||
{
|
||||
struct omap_rtc *rtc = pinctrl_dev_get_drvdata(pctldev);
|
||||
unsigned int param = pinconf_to_config_param(*config);
|
||||
u32 val;
|
||||
u16 arg = 0;
|
||||
|
||||
rtc->type->unlock(rtc);
|
||||
val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
|
||||
rtc->type->lock(rtc);
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
if (!(val & OMAP_RTC_PMIC_EXT_WKUP_EN(pin)))
|
||||
return -EINVAL;
|
||||
break;
|
||||
case PIN_CONFIG_ACTIVE_HIGH:
|
||||
if (val & OMAP_RTC_PMIC_EXT_WKUP_POL(pin))
|
||||
return -EINVAL;
|
||||
break;
|
||||
default:
|
||||
return -ENOTSUPP;
|
||||
};
|
||||
|
||||
*config = pinconf_to_config_packed(param, arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rtc_pinconf_set(struct pinctrl_dev *pctldev,
|
||||
unsigned int pin, unsigned long *configs,
|
||||
unsigned int num_configs)
|
||||
{
|
||||
struct omap_rtc *rtc = pinctrl_dev_get_drvdata(pctldev);
|
||||
u32 val;
|
||||
unsigned int param;
|
||||
u16 param_val;
|
||||
int i;
|
||||
|
||||
rtc->type->unlock(rtc);
|
||||
val = rtc_readl(rtc, OMAP_RTC_PMIC_REG);
|
||||
rtc->type->lock(rtc);
|
||||
|
||||
/* active low by default */
|
||||
val |= OMAP_RTC_PMIC_EXT_WKUP_POL(pin);
|
||||
|
||||
for (i = 0; i < num_configs; i++) {
|
||||
param = pinconf_to_config_param(configs[i]);
|
||||
param_val = pinconf_to_config_argument(configs[i]);
|
||||
|
||||
switch (param) {
|
||||
case PIN_CONFIG_INPUT_ENABLE:
|
||||
if (param_val)
|
||||
val |= OMAP_RTC_PMIC_EXT_WKUP_EN(pin);
|
||||
else
|
||||
val &= ~OMAP_RTC_PMIC_EXT_WKUP_EN(pin);
|
||||
break;
|
||||
case PIN_CONFIG_ACTIVE_HIGH:
|
||||
val &= ~OMAP_RTC_PMIC_EXT_WKUP_POL(pin);
|
||||
break;
|
||||
default:
|
||||
dev_err(&rtc->rtc->dev, "Property %u not supported\n",
|
||||
param);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
}
|
||||
|
||||
rtc->type->unlock(rtc);
|
||||
rtc_writel(rtc, OMAP_RTC_PMIC_REG, val);
|
||||
rtc->type->lock(rtc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pinconf_ops rtc_pinconf_ops = {
|
||||
.is_generic = true,
|
||||
.pin_config_get = rtc_pinconf_get,
|
||||
.pin_config_set = rtc_pinconf_set,
|
||||
};
|
||||
|
||||
static struct pinctrl_desc rtc_pinctrl_desc = {
|
||||
.pins = rtc_pins_desc,
|
||||
.npins = ARRAY_SIZE(rtc_pins_desc),
|
||||
.pctlops = &rtc_pinctrl_ops,
|
||||
.confops = &rtc_pinconf_ops,
|
||||
.custom_params = rtc_params,
|
||||
.num_custom_params = ARRAY_SIZE(rtc_params),
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
.custom_conf_items = rtc_conf_items,
|
||||
#endif
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int omap_rtc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_rtc *rtc;
|
||||
|
@ -681,6 +821,15 @@ static int omap_rtc_probe(struct platform_device *pdev)
|
|||
}
|
||||
}
|
||||
|
||||
/* Support ext_wakeup pinconf */
|
||||
rtc_pinctrl_desc.name = dev_name(&pdev->dev);
|
||||
|
||||
rtc->pctldev = pinctrl_register(&rtc_pinctrl_desc, &pdev->dev, rtc);
|
||||
if (IS_ERR(rtc->pctldev)) {
|
||||
dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
|
||||
return PTR_ERR(rtc->pctldev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
|
@ -724,6 +873,9 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
|
|||
pm_runtime_put_sync(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
/* Remove ext_wakeup pinconf */
|
||||
pinctrl_unregister(rtc->pctldev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -225,7 +225,7 @@ static irqreturn_t palmas_rtc_interrupt(int irq, void *context)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct rtc_class_ops palmas_rtc_ops = {
|
||||
static const struct rtc_class_ops palmas_rtc_ops = {
|
||||
.read_time = palmas_rtc_read_time,
|
||||
.set_time = palmas_rtc_set_time,
|
||||
.read_alarm = palmas_rtc_read_alarm,
|
||||
|
|
|
@ -182,7 +182,8 @@ static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr,
|
|||
}
|
||||
|
||||
static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buffer, size_t count) {
|
||||
const char *buffer, size_t count)
|
||||
{
|
||||
struct pcf2123_sysfs_reg *r;
|
||||
unsigned long reg;
|
||||
unsigned long val;
|
||||
|
@ -199,7 +200,7 @@ static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
pcf2123_write_reg(dev, reg, val);
|
||||
ret = pcf2123_write_reg(dev, reg, val);
|
||||
if (ret < 0)
|
||||
return -EIO;
|
||||
return count;
|
||||
|
|
|
@ -232,7 +232,7 @@ static int pcf50633_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct rtc_class_ops pcf50633_rtc_ops = {
|
||||
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,
|
||||
|
|
|
@ -400,7 +400,6 @@ static struct platform_driver pic32_rtc_driver = {
|
|||
.remove = pic32_rtc_remove,
|
||||
.driver = {
|
||||
.name = "pic32-rtc",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(pic32_rtc_dt_ids),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -52,11 +52,21 @@
|
|||
#define RV8803_CTRL_TIE BIT(4)
|
||||
#define RV8803_CTRL_UIE BIT(5)
|
||||
|
||||
#define RX8900_BACKUP_CTRL 0x18
|
||||
#define RX8900_FLAG_SWOFF BIT(2)
|
||||
#define RX8900_FLAG_VDETOFF BIT(3)
|
||||
|
||||
enum rv8803_type {
|
||||
rv_8803,
|
||||
rx_8900
|
||||
};
|
||||
|
||||
struct rv8803_data {
|
||||
struct i2c_client *client;
|
||||
struct rtc_device *rtc;
|
||||
struct mutex flags_lock;
|
||||
u8 ctrl;
|
||||
enum rv8803_type type;
|
||||
};
|
||||
|
||||
static int rv8803_read_reg(const struct i2c_client *client, u8 reg)
|
||||
|
@ -497,6 +507,35 @@ static struct rtc_class_ops rv8803_rtc_ops = {
|
|||
.ioctl = rv8803_ioctl,
|
||||
};
|
||||
|
||||
static int rx8900_trickle_charger_init(struct rv8803_data *rv8803)
|
||||
{
|
||||
struct i2c_client *client = rv8803->client;
|
||||
struct device_node *node = client->dev.of_node;
|
||||
int err;
|
||||
u8 flags;
|
||||
|
||||
if (!node)
|
||||
return 0;
|
||||
|
||||
if (rv8803->type != rx_8900)
|
||||
return 0;
|
||||
|
||||
err = i2c_smbus_read_byte_data(rv8803->client, RX8900_BACKUP_CTRL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
flags = ~(RX8900_FLAG_VDETOFF | RX8900_FLAG_SWOFF) & (u8)err;
|
||||
|
||||
if (of_property_read_bool(node, "epson,vdet-disable"))
|
||||
flags |= RX8900_FLAG_VDETOFF;
|
||||
|
||||
if (of_property_read_bool(node, "trickle-diode-disable"))
|
||||
flags |= RX8900_FLAG_SWOFF;
|
||||
|
||||
return i2c_smbus_write_byte_data(rv8803->client, RX8900_BACKUP_CTRL,
|
||||
flags);
|
||||
}
|
||||
|
||||
static int rv8803_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
@ -517,6 +556,7 @@ static int rv8803_probe(struct i2c_client *client,
|
|||
|
||||
mutex_init(&rv8803->flags_lock);
|
||||
rv8803->client = client;
|
||||
rv8803->type = id->driver_data;
|
||||
i2c_set_clientdata(client, rv8803);
|
||||
|
||||
flags = rv8803_read_reg(client, RV8803_FLAG);
|
||||
|
@ -558,6 +598,12 @@ static int rv8803_probe(struct i2c_client *client,
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
err = rx8900_trickle_charger_init(rv8803);
|
||||
if (err) {
|
||||
dev_err(&client->dev, "failed to init charger\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = device_create_bin_file(&client->dev, &rv8803_nvram_attr);
|
||||
if (err)
|
||||
return err;
|
||||
|
@ -575,8 +621,8 @@ static int rv8803_remove(struct i2c_client *client)
|
|||
}
|
||||
|
||||
static const struct i2c_device_id rv8803_id[] = {
|
||||
{ "rv8803", 0 },
|
||||
{ "rx8900", 0 },
|
||||
{ "rv8803", rv_8803 },
|
||||
{ "rx8900", rx_8900 },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, rv8803_id);
|
||||
|
|
|
@ -317,7 +317,7 @@ static int rx6110_init(struct rx6110_data *rx6110)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct rtc_class_ops rx6110_rtc_ops = {
|
||||
static const struct rtc_class_ops rx6110_rtc_ops = {
|
||||
.read_time = rx6110_get_time,
|
||||
.set_time = rx6110_set_time,
|
||||
};
|
||||
|
@ -388,7 +388,6 @@ MODULE_DEVICE_TABLE(spi, rx6110_id);
|
|||
static struct spi_driver rx6110_driver = {
|
||||
.driver = {
|
||||
.name = RX6110_DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = rx6110_probe,
|
||||
.remove = rx6110_remove,
|
||||
|
|
|
@ -403,7 +403,7 @@ static int rx8025_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct rtc_class_ops rx8025_rtc_ops = {
|
||||
static const struct rtc_class_ops rx8025_rtc_ops = {
|
||||
.read_time = rx8025_get_time,
|
||||
.set_time = rx8025_set_time,
|
||||
.read_alarm = rx8025_read_alarm,
|
||||
|
|
|
@ -343,7 +343,7 @@ static int spear_alarm_irq_enable(struct device *dev, unsigned int enabled)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct rtc_class_ops spear_rtc_ops = {
|
||||
static const struct rtc_class_ops spear_rtc_ops = {
|
||||
.read_time = spear_rtc_read_time,
|
||||
.set_time = spear_rtc_set_time,
|
||||
.read_alarm = spear_rtc_read_alarm,
|
||||
|
|
|
@ -231,7 +231,7 @@ static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct rtc_class_ops stmp3xxx_rtc_ops = {
|
||||
static const struct rtc_class_ops stmp3xxx_rtc_ops = {
|
||||
.alarm_irq_enable =
|
||||
stmp3xxx_alarm_irq_enable,
|
||||
.read_time = stmp3xxx_rtc_gettime,
|
||||
|
|
|
@ -160,7 +160,7 @@ wakealarm_store(struct device *dev, struct device_attribute *attr,
|
|||
unsigned long push = 0;
|
||||
struct rtc_wkalrm alm;
|
||||
struct rtc_device *rtc = to_rtc_device(dev);
|
||||
char *buf_ptr;
|
||||
const char *buf_ptr;
|
||||
int adjust = 0;
|
||||
|
||||
/* Only request alarms that trigger in the future. Disable them
|
||||
|
@ -171,7 +171,7 @@ wakealarm_store(struct device *dev, struct device_attribute *attr,
|
|||
return retval;
|
||||
rtc_tm_to_time(&alm.time, &now);
|
||||
|
||||
buf_ptr = (char *)buf;
|
||||
buf_ptr = buf;
|
||||
if (*buf_ptr == '+') {
|
||||
buf_ptr++;
|
||||
if (*buf_ptr == '=') {
|
||||
|
|
|
@ -291,7 +291,7 @@ static irqreturn_t tegra_rtc_irq_handler(int irq, void *data)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct rtc_class_ops tegra_rtc_ops = {
|
||||
static const struct rtc_class_ops tegra_rtc_ops = {
|
||||
.read_time = tegra_rtc_read_time,
|
||||
.set_time = tegra_rtc_set_time,
|
||||
.read_alarm = tegra_rtc_read_alarm,
|
||||
|
|
|
@ -462,7 +462,7 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct rtc_class_ops twl_rtc_ops = {
|
||||
static const struct rtc_class_ops twl_rtc_ops = {
|
||||
.read_time = twl_rtc_read_time,
|
||||
.set_time = twl_rtc_set_time,
|
||||
.read_alarm = twl_rtc_read_alarm,
|
||||
|
|
Loading…
Reference in New Issue