Commit 1b8c5cd8 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull RTC updates from Alexandre Belloni:
 "There is nothing scary this cycle, mostly driver fixes and updates.

  The core fix has been in for a while and has been tested on multiple
  kernel revisions by multiple teams.

  Core:
   - Fix setting the alarm to the next expiring timer

  New drivers:
   - Mediatek MT7622 RTC
   - NXP PCF85363
   - Spreadtrum SC27xx PMIC RTC

  Drivers updates:
   - Use generic nvmem to expose the Non volatile ram for ds1305,
     ds1511, m48t86 and omap
   - abx80x: solve possible race condition at probe
   - armada38x: support trimming the RTC oscillator
   - at91rm9200: fix reading the alarm value at boot
   - ds1511: allow waking platform
   - m41t80: rework square wave output
   - pcf8523: support trimming the RTC oscillator
   - pcf8563: fix clock output rate
   - pl031: make interrupt optional
   - xgene: fix suspend/resume"

* tag 'rtc-4.15' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (50 commits)
  dt-bindings: rtc: imxdi: Improve the bindings text
  rtc: sc27xx: Add Spreadtrum SC27xx PMIC RTC driver
  dt-bindings: rtc: Add Spreadtrum SC27xx RTC documentation
  rtc: at91rm9200: fix reading alarm value
  rtc: at91rm9200: stop calculating yday in at91_rtc_readalarm
  rtc: sysfs: Use time64_t variables to set time/alarm
  rtc: xgene: mark PM functions as __maybe_unused
  rtc: xgene: Fix suspend/resume
  rtc: pcf8563: don't alway enable the alarm
  rtc: pcf8563: fix output clock rate
  rtc: rx8010: Fix for incorrect return value
  rtc: rx8010: Specify correct address for RX8010_RESV31
  rtc: rx8010: Remove duplicate define
  rtc: m41t80: remove unneeded checks from m41t80_sqw_set_rate
  rtc: m41t80: avoid i2c read in m41t80_sqw_is_prepared
  rtc: m41t80: avoid i2c read in m41t80_sqw_recalc_rate
  rtc: m41t80: fix m41t80_sqw_round_rate return value
  rtc: m41t80: m41t80_sqw_set_rate should return 0 on success
  rtc: add support for NXP PCF85363 real-time clock
  rtc: omap: Support scratch registers
  ...
parents 14b661eb 87c9fd81
* i.MX25 Real Time Clock controller * i.MX25 Real Time Clock controller
This binding supports the following chips: i.MX25, i.MX53
Required properties: Required properties:
- compatible: should be: "fsl,imx25-rtc" - compatible: should be: "fsl,imx25-rtc"
- reg: physical base address of the controller and length of memory mapped - reg: physical base address of the controller and length of memory mapped
region. region.
- clocks: should contain the phandle for the rtc clock
- interrupts: rtc alarm interrupt - interrupts: rtc alarm interrupt
Optional properties: Optional properties:
- interrupts: dryice security violation interrupt - interrupts: dryice security violation interrupt (second entry)
Example: Example:
rtc@80056000 { rtc@53ffc000 {
compatible = "fsl,imx53-rtc", "fsl,imx25-rtc"; compatible = "fsl,imx25-rtc";
reg = <0x80056000 2000>; reg = <0x53ffc000 0x4000>;
interrupts = <29 56>; clocks = <&clks 81>;
interrupts = <25 56>;
}; };
NXP PCF85363 Real Time Clock
============================
Required properties:
- compatible: Should contain "nxp,pcf85363".
- reg: I2C address for chip.
Optional properties:
- interrupts: IRQ line for the RTC (not implemented).
Example:
pcf85363: pcf85363@51 {
compatible = "nxp,pcf85363";
reg = <0x51>;
};
Device-Tree bindings for MediaTek SoC based RTC
Required properties:
- compatible : Should be
"mediatek,mt7622-rtc", "mediatek,soc-rtc" : for MT7622 SoC
- reg : Specifies base physical address and size of the registers;
- interrupts : Should contain the interrupt for RTC alarm;
- clocks : Specifies list of clock specifiers, corresponding to
entries in clock-names property;
- clock-names : Should contain "rtc" entries
Example:
rtc: rtc@10212800 {
compatible = "mediatek,mt7622-rtc",
"mediatek,soc-rtc";
reg = <0 0x10212800 0 0x200>;
interrupts = <GIC_SPI 129 IRQ_TYPE_LEVEL_LOW>;
clocks = <&topckgen CLK_TOP_RTC>;
clock-names = "rtc";
};
Spreadtrum SC27xx Real Time Clock
Required properties:
- compatible: should be "sprd,sc2731-rtc".
- reg: address offset of rtc register.
- interrupt-parent: phandle for the interrupt controller.
- interrupts: rtc alarm interrupt.
Example:
sc2731_pmic: pmic@0 {
compatible = "sprd,sc2731";
reg = <0>;
spi-max-frequency = <26000000>;
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <2>;
#address-cells = <1>;
#size-cells = <0>;
rtc@280 {
compatible = "sprd,sc2731-rtc";
reg = <0x280>;
interrupt-parent = <&sc2731_pmic>;
interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
};
};
...@@ -72,7 +72,6 @@ maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator ...@@ -72,7 +72,6 @@ maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator
maxim,max1237 Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs maxim,max1237 Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs
maxim,max6621 PECI-to-I2C translator for PECI-to-SMBus/I2C protocol conversion maxim,max6621 PECI-to-I2C translator for PECI-to-SMBus/I2C protocol conversion
maxim,max6625 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface maxim,max6625 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface
mc,rv3029c2 Real Time Clock Module with I2C-Bus
mcube,mc3230 mCube 3-axis 8-bit digital accelerometer mcube,mc3230 mCube 3-axis 8-bit digital accelerometer
memsic,mxc6225 MEMSIC 2-axis 8-bit digital accelerometer memsic,mxc6225 MEMSIC 2-axis 8-bit digital accelerometer
microchip,mcp4531-502 Microchip 7-bit Single I2C Digital Potentiometer (5k) microchip,mcp4531-502 Microchip 7-bit Single I2C Digital Potentiometer (5k)
...@@ -141,6 +140,7 @@ microchip,mcp4662-503 Microchip 8-bit Dual I2C Digital Potentiometer with NV Mem ...@@ -141,6 +140,7 @@ microchip,mcp4662-503 Microchip 8-bit Dual I2C Digital Potentiometer with NV Mem
microchip,mcp4662-104 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (100k) microchip,mcp4662-104 Microchip 8-bit Dual I2C Digital Potentiometer with NV Memory (100k)
microchip,tc654 PWM Fan Speed Controller With Fan Fault Detection microchip,tc654 PWM Fan Speed Controller With Fan Fault Detection
microchip,tc655 PWM Fan Speed Controller With Fan Fault Detection microchip,tc655 PWM Fan Speed Controller With Fan Fault Detection
microcrystal,rv3029 Real Time Clock Module with I2C-Bus
miramems,da226 MiraMEMS DA226 2-axis 14-bit digital accelerometer miramems,da226 MiraMEMS DA226 2-axis 14-bit digital accelerometer
miramems,da280 MiraMEMS DA280 3-axis 14-bit digital accelerometer miramems,da280 MiraMEMS DA280 3-axis 14-bit digital accelerometer
miramems,da311 MiraMEMS DA311 3-axis 12-bit digital accelerometer miramems,da311 MiraMEMS DA311 3-axis 12-bit digital accelerometer
......
...@@ -1590,10 +1590,13 @@ F: drivers/rtc/rtc-armada38x.c ...@@ -1590,10 +1590,13 @@ F: drivers/rtc/rtc-armada38x.c
ARM/Mediatek RTC DRIVER ARM/Mediatek RTC DRIVER
M: Eddie Huang <eddie.huang@mediatek.com> M: Eddie Huang <eddie.huang@mediatek.com>
M: Sean Wang <sean.wang@mediatek.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers) L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained S: Maintained
F: Documentation/devicetree/bindings/rtc/rtc-mt7622.txt
F: drivers/rtc/rtc-mt6397.c F: drivers/rtc/rtc-mt6397.c
F: drivers/rtc/rtc-mt7622.c
ARM/Mediatek SoC support ARM/Mediatek SoC support
M: Matthias Brugger <matthias.bgg@gmail.com> M: Matthias Brugger <matthias.bgg@gmail.com>
......
...@@ -433,6 +433,19 @@ config RTC_DRV_PCF85063 ...@@ -433,6 +433,19 @@ config RTC_DRV_PCF85063
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-pcf85063. will be called rtc-pcf85063.
config RTC_DRV_PCF85363
tristate "NXP PCF85363"
depends on I2C
select REGMAP_I2C
help
If you say yes here you get support for the PCF85363 RTC chip.
This driver can also be built as a module. If so, the module
will be called rtc-pcf85363.
The nvmem interface will be named pcf85363-#, where # is the
zero-based instance number.
config RTC_DRV_PCF8563 config RTC_DRV_PCF8563
tristate "Philips PCF8563/Epson RTC8564" tristate "Philips PCF8563/Epson RTC8564"
help help
...@@ -1174,6 +1187,17 @@ config RTC_DRV_WM8350 ...@@ -1174,6 +1187,17 @@ config RTC_DRV_WM8350
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called "rtc-wm8350". will be called "rtc-wm8350".
config RTC_DRV_SC27XX
tristate "Spreadtrum SC27xx RTC"
depends on MFD_SC27XX_PMIC || COMPILE_TEST
help
If you say Y here you will get support for the RTC subsystem
of the Spreadtrum SC27xx series PMICs. The SC27xx series PMICs
includes the SC2720, SC2721, SC2723, SC2730 and SC2731 chips.
This driver can also be built as a module. If so, the module
will be called rtc-sc27xx.
config RTC_DRV_SPEAR config RTC_DRV_SPEAR
tristate "SPEAR ST RTC" tristate "SPEAR ST RTC"
depends on PLAT_SPEAR || COMPILE_TEST depends on PLAT_SPEAR || COMPILE_TEST
...@@ -1706,14 +1730,24 @@ config RTC_DRV_MOXART ...@@ -1706,14 +1730,24 @@ config RTC_DRV_MOXART
will be called rtc-moxart will be called rtc-moxart
config RTC_DRV_MT6397 config RTC_DRV_MT6397
tristate "Mediatek Real Time Clock driver" tristate "MediaTek PMIC based RTC"
depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN) depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN)
help help
This selects the Mediatek(R) RTC driver. RTC is part of Mediatek This selects the MediaTek(R) RTC driver. RTC is part of MediaTek
MT6397 PMIC. You should enable MT6397 PMIC MFD before select MT6397 PMIC. You should enable MT6397 PMIC MFD before select
Mediatek(R) RTC driver. MediaTek(R) RTC driver.
If you want to use MediaTek(R) RTC interface, select Y or M here.
If you want to use Mediatek(R) RTC interface, select Y or M here. config RTC_DRV_MT7622
tristate "MediaTek SoC based RTC"
depends on ARCH_MEDIATEK || COMPILE_TEST
help
This enables support for the real time clock built in the MediaTek
SoCs.
This drive can also be built as a module. If so, the module
will be called rtc-mt7622.
config RTC_DRV_XGENE config RTC_DRV_XGENE
tristate "APM X-Gene RTC" tristate "APM X-Gene RTC"
......
...@@ -103,6 +103,7 @@ obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o ...@@ -103,6 +103,7 @@ obj-$(CONFIG_RTC_DRV_MPC5121) += rtc-mpc5121.o
obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o
obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o obj-$(CONFIG_RTC_DRV_MSM6242) += rtc-msm6242.o
obj-$(CONFIG_RTC_DRV_MT6397) += rtc-mt6397.o obj-$(CONFIG_RTC_DRV_MT6397) += rtc-mt6397.o
obj-$(CONFIG_RTC_DRV_MT7622) += rtc-mt7622.o
obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o
obj-$(CONFIG_RTC_DRV_MXC) += rtc-mxc.o obj-$(CONFIG_RTC_DRV_MXC) += rtc-mxc.o
obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o
...@@ -114,6 +115,7 @@ obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o ...@@ -114,6 +115,7 @@ obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o
obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o obj-$(CONFIG_RTC_DRV_PCF2127) += rtc-pcf2127.o
obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o
obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o
obj-$(CONFIG_RTC_DRV_PCF85363) += rtc-pcf85363.o
obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o
obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o
...@@ -144,6 +146,7 @@ obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o ...@@ -144,6 +146,7 @@ obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o
obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
obj-$(CONFIG_RTC_DRV_S5M) += rtc-s5m.o obj-$(CONFIG_RTC_DRV_S5M) += rtc-s5m.o
obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
obj-$(CONFIG_RTC_DRV_SC27XX) += rtc-sc27xx.o
obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o
obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o
obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o
......
...@@ -779,7 +779,7 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer) ...@@ -779,7 +779,7 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)
} }
timerqueue_add(&rtc->timerqueue, &timer->node); timerqueue_add(&rtc->timerqueue, &timer->node);
if (!next) { if (!next || ktime_before(timer->node.expires, next->expires)) {
struct rtc_wkalrm alarm; struct rtc_wkalrm alarm;
int err; int err;
alarm.time = rtc_ktime_to_tm(timer->node.expires); alarm.time = rtc_ktime_to_tm(timer->node.expires);
...@@ -1004,6 +1004,10 @@ int rtc_read_offset(struct rtc_device *rtc, long *offset) ...@@ -1004,6 +1004,10 @@ int rtc_read_offset(struct rtc_device *rtc, long *offset)
* to compensate for differences in the actual clock rate due to temperature, * to compensate for differences in the actual clock rate due to temperature,
* the crystal, capacitor, etc. * the crystal, capacitor, etc.
* *
* The adjustment applied is as follows:
* t = t0 * (1 + offset * 1e-9)
* where t0 is the measured length of 1 RTC second with offset = 0
*
* Kernel interface to adjust an rtc clock offset. * Kernel interface to adjust an rtc clock offset.
* Return 0 on success, or a negative number on error. * Return 0 on success, or a negative number on error.
* If the rtc offset is not setable (or not implemented), return -EINVAL * If the rtc offset is not setable (or not implemented), return -EINVAL
......
...@@ -614,12 +614,12 @@ static int abx80x_probe(struct i2c_client *client, ...@@ -614,12 +614,12 @@ static int abx80x_probe(struct i2c_client *client,
if (err) if (err)
return err; return err;
rtc = devm_rtc_device_register(&client->dev, "abx8xx", rtc = devm_rtc_allocate_device(&client->dev);
&abx80x_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc)) if (IS_ERR(rtc))
return PTR_ERR(rtc); return PTR_ERR(rtc);
rtc->ops = &abx80x_rtc_ops;
i2c_set_clientdata(client, rtc); i2c_set_clientdata(client, rtc);
if (client->irq > 0) { if (client->irq > 0) {
...@@ -646,10 +646,14 @@ static int abx80x_probe(struct i2c_client *client, ...@@ -646,10 +646,14 @@ static int abx80x_probe(struct i2c_client *client,
err = devm_add_action_or_reset(&client->dev, err = devm_add_action_or_reset(&client->dev,
rtc_calib_remove_sysfs_group, rtc_calib_remove_sysfs_group,
&client->dev); &client->dev);
if (err) if (err) {
dev_err(&client->dev, dev_err(&client->dev,
"Failed to add sysfs cleanup action: %d\n", "Failed to add sysfs cleanup action: %d\n",
err); err);
return err;
}
err = rtc_register_device(rtc);
return err; return err;
} }
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#define RTC_IRQ_AL_EN BIT(0) #define RTC_IRQ_AL_EN BIT(0)
#define RTC_IRQ_FREQ_EN BIT(1) #define RTC_IRQ_FREQ_EN BIT(1)
#define RTC_IRQ_FREQ_1HZ BIT(2) #define RTC_IRQ_FREQ_1HZ BIT(2)
#define RTC_CCR 0x18
#define RTC_CCR_MODE BIT(15)
#define RTC_TIME 0xC #define RTC_TIME 0xC
#define RTC_ALARM1 0x10 #define RTC_ALARM1 0x10
...@@ -343,18 +345,117 @@ static irqreturn_t armada38x_rtc_alarm_irq(int irq, void *data) ...@@ -343,18 +345,117 @@ static irqreturn_t armada38x_rtc_alarm_irq(int irq, void *data)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
/*
* The information given in the Armada 388 functional spec is complex.
* They give two different formulas for calculating the offset value,
* but when considering "Offset" as an 8-bit signed integer, they both
* reduce down to (we shall rename "Offset" as "val" here):
*
* val = (f_ideal / f_measured - 1) / resolution where f_ideal = 32768
*
* Converting to time, f = 1/t:
* val = (t_measured / t_ideal - 1) / resolution where t_ideal = 1/32768
*
* => t_measured / t_ideal = val * resolution + 1
*
* "offset" in the RTC interface is defined as:
* t = t0 * (1 + offset * 1e-9)
* where t is the desired period, t0 is the measured period with a zero
* offset, which is t_measured above. With t0 = t_measured and t = t_ideal,
* offset = (t_ideal / t_measured - 1) / 1e-9
*
* => t_ideal / t_measured = offset * 1e-9 + 1
*
* so:
*
* offset * 1e-9 + 1 = 1 / (val * resolution + 1)
*
* We want "resolution" to be an integer, so resolution = R * 1e-9, giving
* offset = 1e18 / (val * R + 1e9) - 1e9
* val = (1e18 / (offset + 1e9) - 1e9) / R
* with a common transformation:
* f(x) = 1e18 / (x + 1e9) - 1e9
* offset = f(val * R)
* val = f(offset) / R
*
* Armada 38x supports two modes, fine mode (954ppb) and coarse mode (3815ppb).
*/
static long armada38x_ppb_convert(long ppb)
{
long div = ppb + 1000000000L;
return div_s64(1000000000000000000LL + div / 2, div) - 1000000000L;
}
static int armada38x_rtc_read_offset(struct device *dev, long *offset)
{
struct armada38x_rtc *rtc = dev_get_drvdata(dev);
unsigned long ccr, flags;
long ppb_cor;
spin_lock_irqsave(&rtc->lock, flags);
ccr = rtc->data->read_rtc_reg(rtc, RTC_CCR);
spin_unlock_irqrestore(&rtc->lock, flags);
ppb_cor = (ccr & RTC_CCR_MODE ? 3815 : 954) * (s8)ccr;
/* ppb_cor + 1000000000L can never be zero */
*offset = armada38x_ppb_convert(ppb_cor);
return 0;
}
static int armada38x_rtc_set_offset(struct device *dev, long offset)
{
struct armada38x_rtc *rtc = dev_get_drvdata(dev);
unsigned long ccr = 0;
long ppb_cor, off;
/*
* The maximum ppb_cor is -128 * 3815 .. 127 * 3815, but we
* need to clamp the input. This equates to -484270 .. 488558.
* Not only is this to stop out of range "off" but also to
* avoid the division by zero in armada38x_ppb_convert().
*/
offset = clamp(offset, -484270L, 488558L);
ppb_cor = armada38x_ppb_convert(offset);
/*
* Use low update mode where possible, which gives a better
* resolution of correction.
*/
off = DIV_ROUND_CLOSEST(ppb_cor, 954);
if (off > 127 || off < -128) {
ccr = RTC_CCR_MODE;
off = DIV_ROUND_CLOSEST(ppb_cor, 3815);
}
/*
* Armada 388 requires a bit pattern in bits 14..8 depending on
* the sign bit: { 0, ~S, S, S, S, S, S }
*/
ccr |= (off & 0x3fff) ^ 0x2000;
rtc_delayed_write(ccr, rtc, RTC_CCR);
return 0;
}
static const struct rtc_class_ops armada38x_rtc_ops = { static const struct rtc_class_ops armada38x_rtc_ops = {
.read_time = armada38x_rtc_read_time, .read_time = armada38x_rtc_read_time,
.set_time = armada38x_rtc_set_time, .set_time = armada38x_rtc_set_time,
.read_alarm = armada38x_rtc_read_alarm, .read_alarm = armada38x_rtc_read_alarm,
.set_alarm = armada38x_rtc_set_alarm, .set_alarm = armada38x_rtc_set_alarm,
.alarm_irq_enable = armada38x_rtc_alarm_irq_enable, .alarm_irq_enable = armada38x_rtc_alarm_irq_enable,
.read_offset = armada38x_rtc_read_offset,
.set_offset = armada38x_rtc_set_offset,
}; };
static const struct rtc_class_ops armada38x_rtc_ops_noirq = { static const struct rtc_class_ops armada38x_rtc_ops_noirq = {
.read_time = armada38x_rtc_read_time, .read_time = armada38x_rtc_read_time,
.set_time = armada38x_rtc_set_time, .set_time = armada38x_rtc_set_time,
.read_alarm = armada38x_rtc_read_alarm, .read_alarm = armada38x_rtc_read_alarm,
.read_offset = armada38x_rtc_read_offset,
.set_offset = armada38x_rtc_set_offset,
}; };
static const struct armada38x_rtc_data armada38x_data = { static const struct armada38x_rtc_data armada38x_data = {
......
...@@ -42,8 +42,6 @@ ...@@ -42,8 +42,6 @@
#define at91_rtc_write(field, val) \ #define at91_rtc_write(field, val) \
writel_relaxed((val), at91_rtc_regs + field) writel_relaxed((val), at91_rtc_regs + field)
#define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */
struct at91_rtc_config { struct at91_rtc_config {
bool use_shadow_imr; bool use_shadow_imr;
}; };
...@@ -51,7 +49,6 @@ struct at91_rtc_config { ...@@ -51,7 +49,6 @@ struct at91_rtc_config {
static const struct at91_rtc_config *at91_rtc_config; static const struct at91_rtc_config *at91_rtc_config;
static DECLARE_COMPLETION(at91_rtc_updated); static DECLARE_COMPLETION(at91_rtc_updated);
static DECLARE_COMPLETION(at91_rtc_upd_rdy); static DECLARE_COMPLETION(at91_rtc_upd_rdy);
static unsigned int at91_alarm_year = AT91_RTC_EPOCH;
static void __iomem *at91_rtc_regs; static void __iomem *at91_rtc_regs;
static int irq; static int irq;
static DEFINE_SPINLOCK(at91_rtc_lock); static DEFINE_SPINLOCK(at91_rtc_lock);
...@@ -131,8 +128,7 @@ static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg, ...@@ -131,8 +128,7 @@ static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg,
/* /*
* The Calendar Alarm register does not have a field for * The Calendar Alarm register does not have a field for
* the year - so these will return an invalid value. When an * the year - so these will return an invalid value.
* alarm is set, at91_alarm_year will store the current year.
*/ */
tm->tm_year = bcd2bin(date & AT91_RTC_CENT) * 100; /* century */ tm->tm_year = bcd2bin(date & AT91_RTC_CENT) * 100; /* century */
tm->tm_year += bcd2bin((date & AT91_RTC_YEAR) >> 8); /* year */ tm->tm_year += bcd2bin((date & AT91_RTC_YEAR) >> 8); /* year */
...@@ -208,15 +204,14 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -208,15 +204,14 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
struct rtc_time *tm = &alrm->time; struct rtc_time *tm = &alrm->time;
at91_rtc_decodetime(AT91_RTC_TIMALR, AT91_RTC_CALALR, tm); at91_rtc_decodetime(AT91_RTC_TIMALR, AT91_RTC_CALALR, tm);
tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); tm->tm_year = -1;
tm->tm_year = at91_alarm_year - 1900;
alrm->enabled = (at91_rtc_read_imr() & AT91_RTC_ALARM) alrm->enabled = (at91_rtc_read_imr() & AT91_RTC_ALARM)
? 1 : 0; ? 1 : 0;
dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, dev_dbg(dev, "%s(): %02d-%02d %02d:%02d:%02d %sabled\n", __func__,
1900 + tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec,
tm->tm_hour, tm->tm_min, tm->tm_sec); alrm->enabled ? "en" : "dis");
return 0; return 0;
} }
...@@ -230,8 +225,6 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -230,8 +225,6 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, &tm); at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, &tm);
at91_alarm_year = tm.tm_year;
tm.tm_mon = alrm->time.tm_mon; tm.tm_mon = alrm->time.tm_mon;
tm.tm_mday = alrm->time.tm_mday; tm.tm_mday = alrm->time.tm_mday;
tm.tm_hour = alrm->time.tm_hour; tm.tm_hour = alrm->time.tm_hour;
...@@ -255,7 +248,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) ...@@ -255,7 +248,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
} }
dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__,
at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
tm.tm_min, tm.tm_sec); tm.tm_min, tm.tm_sec);
return 0; return 0;
......
...@@ -514,56 +514,43 @@ static void msg_init(struct spi_message *m, struct spi_transfer *x, ...@@ -514,56 +514,43 @@ static void msg_init(struct spi_message *m, struct spi_transfer *x,
spi_message_add_tail(x, m); spi_message_add_tail(x, m);
} }
static ssize_t static int ds1305_nvram_read(void *priv, unsigned int off, void *buf,
ds1305_nvram_read(struct file *filp, struct kobject *kobj, size_t count)
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{ {
struct spi_device *spi; struct ds1305 *ds1305 = priv;
struct spi_device *spi = ds1305->spi;
u8 addr; u8 addr;
struct spi_message m; struct spi_message m;
struct spi_transfer x[2]; struct spi_transfer x[2];
int status;
spi = to_spi_device(kobj_to_dev(kobj));
addr = DS1305_NVRAM + off; addr = DS1305_NVRAM + off;
msg_init(&m, x, &addr, count, NULL, buf); msg_init(&m, x, &addr, count, NULL, buf);
status = spi_sync(spi, &m); return spi_sync(spi, &m);
if (status < 0)
dev_err(&spi->dev, "nvram %s error %d\n", "read", status);
return (status < 0) ? status : count;
} }
static ssize_t static int ds1305_nvram_write(void *priv, unsigned int off, void *buf,
ds1305_nvram_write(struct file *filp, struct kobject *kobj, size_t count)
struct bin_attribute *attr,
char *buf, loff_t off, size_t count)
{ {
struct spi_device *spi; struct ds1305 *ds1305 = priv;
struct spi_device *spi = ds1305->spi;
u8 addr; u8 addr;
struct spi_message m; struct spi_message m;
struct spi_transfer x[2]; struct spi_transfer x[2];
int status;
spi = to_spi_device(kobj_to_dev(kobj));
addr = (DS1305_WRITE | DS1305_NVRAM) + off; addr = (DS1305_WRITE | DS1305_NVRAM) + off;
msg_init(&m, x, &addr, count, buf, NULL); msg_init(&m, x, &addr, count, buf, NULL);
status = spi_sync(spi, &m); return spi_sync(spi, &m);
if (status < 0)
dev_err(&spi->dev, "nvram %s error %d\n", "write", status);
return (status < 0) ? status : count;
} }
static struct bin_attribute nvram = { static struct nvmem_config ds1305_nvmem_cfg = {
.attr.name = "nvram", .name = "ds1305_nvram",
.attr.mode = S_IRUGO | S_IWUSR, .word_size = 1,
.read = ds1305_nvram_read, .stride = 1,
.write = ds1305_nvram_write, .size = DS1305_NVRAM_LEN,
.size = DS1305_NVRAM_LEN, .reg_read = ds1305_nvram_read,
.reg_write = ds1305_nvram_write,
}; };
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
...@@ -708,10 +695,19 @@ static int ds1305_probe(struct spi_device *spi) ...@@ -708,10 +695,19 @@ static int ds1305_probe(struct spi_device *spi)
dev_dbg(&spi->dev, "AM/PM\n"); dev_dbg(&spi->dev, "AM/PM\n");
/* register RTC ... from here on, ds1305->ctrl needs locking */ /* register RTC ... from here on, ds1305->ctrl needs locking */
ds1305->rtc = devm_rtc_device_register(&spi->dev, "ds1305", ds1305->rtc = devm_rtc_allocate_device(&spi->dev);
&ds1305_ops, THIS_MODULE);
if (IS_ERR(ds1305->rtc)) { if (IS_ERR(ds1305->rtc)) {
status = PTR_ERR(ds1305->rtc); return PTR_ERR(ds1305->rtc);
}
ds1305->rtc->ops = &ds1305_ops;
ds1305_nvmem_cfg.priv = ds1305;
ds1305->rtc->nvmem_config = &ds1305_nvmem_cfg;
ds1305->rtc->nvram_old_abi = true;
status = rtc_register_device(ds1305->rtc);
if (status) {
dev_dbg(&spi->dev, "register rtc --> %d\n", status); dev_dbg(&spi->dev, "register rtc --> %d\n", status);
return status; return status;
} }
...@@ -734,12 +730,6 @@ static int ds1305_probe(struct spi_device *spi) ...@@ -734,12 +730,6 @@ static int ds1305_probe(struct spi_device *spi)
} }
} }
/* export NVRAM */
status = sysfs_create_bin_file(&spi->dev.kobj, &nvram);
if (status < 0) {
dev_err(&spi->dev, "register nvram --> %d\n", status);
}
return 0; return 0;
} }
...@@ -747,8 +737,6 @@ static int ds1305_remove(struct spi_device *spi) ...@@ -747,8 +737,6 @@ static int ds1305_remove(struct spi_device *spi)
{ {
struct ds1305 *ds1305 = spi_get_drvdata(spi); struct ds1305 *ds1305 = spi_get_drvdata(spi);
sysfs_remove_bin_file(&spi->dev.kobj, &nvram);
/* carefully shut down irq and workqueue, if present */ /* carefully shut down irq and workqueue, if present */
if (spi->irq) { if (spi->irq) {
set_bit(FLAG_EXITING, &ds1305->flags); set_bit(FLAG_EXITING, &ds1305->flags);
......
...@@ -325,6 +325,10 @@ static const struct of_device_id ds1307_of_match[] = { ...@@ -325,6 +325,10 @@ static const struct of_device_id ds1307_of_match[] = {
.compatible = "isil,isl12057", .compatible = "isil,isl12057",
.data = (void *)ds_1337 .data = (void *)ds_1337
}, },
{
.compatible = "epson,rx8130",
.data = (void *)rx_8130
},
{ } { }
}; };
MODULE_DEVICE_TABLE(of, ds1307_of_match); MODULE_DEVICE_TABLE(of, ds1307_of_match);
...@@ -348,6 +352,7 @@ static const struct acpi_device_id ds1307_acpi_ids[] = { ...@@ -348,6 +352,7 @@ static const struct acpi_device_id ds1307_acpi_ids[] = {
{ .id = "PT7C4338", .driver_data = ds_1307 }, { .id = "PT7C4338", .driver_data = ds_1307 },
{ .id = "RX8025", .driver_data = rx_8025 }, { .id = "RX8025", .driver_data = rx_8025 },
{ .id = "ISL12057", .driver_data = ds_1337 }, { .id = "ISL12057", .driver_data = ds_1337 },
{ .id = "RX8130", .driver_data = rx_8130 },
{ } { }
}; };
MODULE_DEVICE_TABLE(acpi, ds1307_acpi_ids); MODULE_DEVICE_TABLE(acpi, ds1307_acpi_ids);
...@@ -787,8 +792,6 @@ static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled) ...@@ -787,8 +792,6 @@ static int rx8130_alarm_irq_enable(struct device *dev, unsigned int enabled)
* Alarm support for mcp794xx devices. * Alarm support for mcp794xx devices.
*/ */
#define MCP794XX_REG_WEEKDAY 0x3
#define MCP794XX_REG_WEEKDAY_WDAY_MASK 0x7
#define MCP794XX_REG_CONTROL 0x07 #define MCP794XX_REG_CONTROL 0x07
# define MCP794XX_BIT_ALM0_EN 0x10 # define MCP794XX_BIT_ALM0_EN 0x10
# define MCP794XX_BIT_ALM1_EN 0x20 # define MCP794XX_BIT_ALM1_EN 0x20
...@@ -877,15 +880,38 @@ static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t) ...@@ -877,15 +880,38 @@ static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t)
return 0; return 0;
} }
/*
* We may have a random RTC weekday, therefore calculate alarm weekday based
* on current weekday we read from the RTC timekeeping regs
*/
static int mcp794xx_alm_weekday(struct device *dev, struct rtc_time *tm_alarm)
{
struct rtc_time tm_now;
int days_now, days_alarm, ret;
ret = ds1307_get_time(dev, &tm_now);
if (ret)
return ret;
days_now = div_s64(rtc_tm_to_time64(&tm_now), 24 * 60 * 60);
days_alarm = div_s64(rtc_tm_to_time64(tm_alarm), 24 * 60 * 60);
return (tm_now.tm_wday + days_alarm - days_now) % 7 + 1;
}
static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t) static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t)
{ {
struct ds1307 *ds1307 = dev_get_drvdata(dev); struct ds1307 *ds1307 = dev_get_drvdata(dev);
unsigned char regs[10]; unsigned char regs[10];
int ret; int wday, ret;
if (!test_bit(HAS_ALARM, &ds1307->flags)) if (!test_bit(HAS_ALARM, &ds1307->flags))
return -EINVAL; return -EINVAL;
wday = mcp794xx_alm_weekday(dev, &t->time);
if (wday < 0)
return wday;
dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d " dev_dbg(dev, "%s, sec=%d min=%d hour=%d wday=%d mday=%d mon=%d "
"enabled=%d pending=%d\n", __func__, "enabled=%d pending=%d\n", __func__,
t->time.tm_sec, t->time.tm_min, t->time.tm_hour, t->time.tm_sec, t->time.tm_min, t->time.tm_hour,
...@@ -902,7 +928,7 @@ static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t) ...@@ -902,7 +928,7 @@ static int mcp794xx_set_alarm(struct device *dev, struct rtc_wkalrm *t)
regs[3] = bin2bcd(t->time.tm_sec); regs[3] = bin2bcd(t->time.tm_sec);
regs[4] = bin2bcd(t->time.tm_min); regs[4] = bin2bcd(t->time.tm_min);
regs[5] = bin2bcd(t->time.tm_hour); regs[5] = bin2bcd(t->time.tm_hour);
regs[6] = bin2bcd(t->time.tm_wday + 1); regs[6] = wday;
regs[7] = bin2bcd(t->time.tm_mday); regs[7] = bin2bcd(t->time.tm_mday);
regs[8] = bin2bcd(t->time.tm_mon + 1); regs[8] = bin2bcd(t->time.tm_mon + 1);
...@@ -1354,14 +1380,12 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -1354,14 +1380,12 @@ static int ds1307_probe(struct i2c_client *client,
{ {
struct ds1307 *ds1307; struct ds1307 *ds1307;
int err = -ENODEV; int err = -ENODEV;
int tmp, wday; int tmp;
const struct chip_desc *chip; const struct chip_desc *chip;
bool want_irq; bool want_irq;
bool ds1307_can_wakeup_device = false; bool ds1307_can_wakeup_device = false;
unsigned char regs[8]; unsigned char regs[8];
struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev); struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
struct rtc_time tm;
unsigned long timestamp;
u8 trickle_charger_setup = 0; u8 trickle_charger_setup = 0;
ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL); ds1307 = devm_kzalloc(&client->dev, sizeof(struct ds1307), GFP_KERNEL);
...@@ -1641,25 +1665,6 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -1641,25 +1665,6 @@ static int ds1307_probe(struct i2c_client *client,
bin2bcd(tmp)); bin2bcd(tmp));
} }
/*
* Some IPs have weekday reset value = 0x1 which might not correct
* hence compute the wday using the current date/month/year values
*/
ds1307_get_time(ds1307->dev, &tm);
wday = tm.tm_wday;
timestamp = rtc_tm_to_time64(&tm);
rtc_time64_to_tm(timestamp, &tm);
/*
* Check if reset wday is different from the computed wday
* If different then set the wday which we computed using
* timestamp
*/
if (wday != tm.tm_wday)
regmap_update_bits(ds1307->regmap, MCP794XX_REG_WEEKDAY,
MCP794XX_REG_WEEKDAY_WDAY_MASK,
tm.tm_wday + 1);
if (want_irq || ds1307_can_wakeup_device) { if (want_irq || ds1307_can_wakeup_device) {
device_set_wakeup_capable(ds1307->dev, true); device_set_wakeup_capable(ds1307->dev, true);
set_bit(HAS_ALARM, &ds1307->flags); set_bit(HAS_ALARM, &ds1307->flags);
......
...@@ -216,9 +216,16 @@ static int ds1390_probe(struct spi_device *spi) ...@@ -216,9 +216,16 @@ static int ds1390_probe(struct spi_device *spi)
return res; return res;
} }
static const struct of_device_id ds1390_of_match[] = {
{ .compatible = "dallas,ds1390" },
{}
};
MODULE_DEVICE_TABLE(of, ds1390_of_match);
static struct spi_driver ds1390_driver = { static struct spi_driver ds1390_driver = {
.driver = { .driver = {
.name = "rtc-ds1390", .name = "rtc-ds1390",
.of_match_table = of_match_ptr(ds1390_of_match),
}, },
.probe = ds1390_probe, .probe = ds1390_probe,
}; };
......
...@@ -398,42 +398,37 @@ static const struct rtc_class_ops ds1511_rtc_ops = { ...@@ -398,42 +398,37 @@ static const struct rtc_class_ops ds1511_rtc_ops = {
.alarm_irq_enable = ds1511_rtc_alarm_irq_enable, .alarm_irq_enable = ds1511_rtc_alarm_irq_enable,
}; };
static ssize_t static int ds1511_nvram_read(void *priv, unsigned int pos, void *buf,
ds1511_nvram_read(struct file *filp, struct kobject *kobj, size_t size)
struct bin_attribute *ba,
char *buf, loff_t pos, size_t size)
{ {
ssize_t count; int i;
rtc_write(pos, DS1511_RAMADDR_LSB); rtc_write(pos, DS1511_RAMADDR_LSB);
for (count = 0; count < size; count++) for (i = 0; i < size; i++)
*buf++ = rtc_read(DS1511_RAMDATA); *(char *)buf++ = rtc_read(DS1511_RAMDATA);
return count; return 0;
} }
static ssize_t static int ds1511_nvram_write(void *priv, unsigned int pos, void *buf,
ds1511_nvram_write(struct file *filp, struct kobject *kobj, size_t size)
struct bin_attribute *bin_attr,
char *buf, loff_t pos, size_t size)
{ {
ssize_t count; int i;
rtc_write(pos, DS1511_RAMADDR_LSB); rtc_write(pos, DS1511_RAMADDR_LSB);
for (count = 0; count < size; count++) for (i = 0; i < size; i++)
rtc_write(*buf++, DS1511_RAMDATA); rtc_write(*(char *)buf++, DS1511_RAMDATA);
return count; return 0;
} }
static struct bin_attribute ds1511_nvram_attr = { static struct nvmem_config ds1511_nvmem_cfg = {
.attr = { .name = "ds1511_nvram",
.name = "nvram", .word_size = 1,
.mode = S_IRUGO | S_IWUSR, .stride = 1,
},
.size = DS1511_RAM_MAX, .size = DS1511_RAM_MAX,
.read = ds1511_nvram_read, .reg_read = ds1511_nvram_read,
.write = ds1511_nvram_write, .reg_write = ds1511_nvram_write,
}; };
static int ds1511_rtc_probe(struct platform_device *pdev) static int ds1511_rtc_probe(struct platform_device *pdev)
...@@ -477,11 +472,20 @@ static int ds1511_rtc_probe(struct platform_device *pdev) ...@@ -477,11 +472,20 @@ static int ds1511_rtc_probe(struct platform_device *pdev)
spin_lock_init(&pdata->lock); spin_lock_init(&pdata->lock);
platform_set_drvdata(pdev, pdata); platform_set_drvdata(pdev, pdata);
pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, pdata->rtc = devm_rtc_allocate_device(&pdev->dev);
&ds1511_rtc_ops, THIS_MODULE);
if (IS_ERR(pdata->rtc)) if (IS_ERR(pdata->rtc))
return PTR_ERR(pdata->rtc); return PTR_ERR(pdata->rtc);
pdata->rtc->ops = &ds1511_rtc_ops;
ds1511_nvmem_cfg.priv = &pdev->dev;
pdata->rtc->nvmem_config = &ds1511_nvmem_cfg;
pdata->rtc->nvram_old_abi = true;
ret = rtc_register_device(pdata->rtc);
if (ret)
return ret;
/* /*
* if the platform has an interrupt in mind for this device, * if the platform has an interrupt in mind for this device,
* then by all means, set it * then by all means, set it
...@@ -496,26 +500,6 @@ static int ds1511_rtc_probe(struct platform_device *pdev) ...@@ -496,26 +500,6 @@ static int ds1511_rtc_probe(struct platform_device *pdev)
} }
} }
ret = sysfs_create_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr);
if (ret)
dev_err(&pdev->dev, "Unable to create sysfs entry: %s\n",
ds1511_nvram_attr.attr.name);
return 0;
}
static int ds1511_rtc_remove(struct platform_device *pdev)
{
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
sysfs_remove_bin_file(&pdev->dev.kobj, &ds1511_nvram_attr);
if (pdata->irq > 0) {
/*
* disable the alarm interrupt
*/
rtc_write(rtc_read(RTC_CMD) & ~RTC_TIE, RTC_CMD);
rtc_read(RTC_CMD1);
}
return 0; return 0;
} }
...@@ -524,7 +508,6 @@ MODULE_ALIAS("platform:ds1511"); ...@@ -524,7 +508,6 @@ MODULE_ALIAS("platform:ds1511");
static struct platform_driver ds1511_rtc_driver = { static struct platform_driver ds1511_rtc_driver = {
.probe = ds1511_rtc_probe, .probe = ds1511_rtc_probe,
.remove = ds1511_rtc_remove,
.driver = { .driver = {
.name = "ds1511", .name = "ds1511",
}, },
......
...@@ -82,7 +82,7 @@ static inline uint32_t jz4740_rtc_reg_read(struct jz4740_rtc *rtc, size_t reg) ...@@ -82,7 +82,7 @@ static inline uint32_t jz4740_rtc_reg_read(struct jz4740_rtc *rtc, size_t reg)
static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc) static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc)
{ {
uint32_t ctrl; uint32_t ctrl;
int timeout = 1000; int timeout = 10000;
do { do {
ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL); ctrl = jz4740_rtc_reg_read(rtc, JZ_REG_RTC_CTRL);
...@@ -94,7 +94,7 @@ static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc) ...@@ -94,7 +94,7 @@ static int jz4740_rtc_wait_write_ready(struct jz4740_rtc *rtc)
static inline int jz4780_rtc_enable_write(struct jz4740_rtc *rtc) static inline int jz4780_rtc_enable_write(struct jz4740_rtc *rtc)
{ {
uint32_t ctrl; uint32_t ctrl;
int ret, timeout = 1000; int ret, timeout = 10000;
ret = jz4740_rtc_wait_write_ready(rtc); ret = jz4740_rtc_wait_write_ready(rtc);
if (ret != 0) if (ret != 0)
...@@ -368,7 +368,7 @@ static int jz4740_rtc_probe(struct platform_device *pdev) ...@@ -368,7 +368,7 @@ static int jz4740_rtc_probe(struct platform_device *pdev)
ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678); ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SCRATCHPAD, 0x12345678);
ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0); ret = jz4740_rtc_reg_write(rtc, JZ_REG_RTC_SEC, 0);
if (ret) { if (ret) {
dev_err(&pdev->dev, "Could not write write to RTC registers\n"); dev_err(&pdev->dev, "Could not write to RTC registers\n");
return ret; return ret;
} }
} }
......
...@@ -154,6 +154,8 @@ struct m41t80_data { ...@@ -154,6 +154,8 @@ struct m41t80_data {
struct rtc_device *rtc; struct rtc_device *rtc;
#ifdef CONFIG_COMMON_CLK #ifdef CONFIG_COMMON_CLK
struct clk_hw sqw; struct clk_hw sqw;
unsigned long freq;
unsigned int sqwe;
#endif #endif
}; };
...@@ -443,43 +445,40 @@ static SIMPLE_DEV_PM_OPS(m41t80_pm, m41t80_suspend, m41t80_resume); ...@@ -443,43 +445,40 @@ static SIMPLE_DEV_PM_OPS(m41t80_pm, m41t80_suspend, m41t80_resume);
#ifdef CONFIG_COMMON_CLK #ifdef CONFIG_COMMON_CLK
#define sqw_to_m41t80_data(_hw) container_of(_hw, struct m41t80_data, sqw) #define sqw_to_m41t80_data(_hw) container_of(_hw, struct m41t80_data, sqw)
static unsigned long m41t80_sqw_recalc_rate(struct clk_hw *hw, static unsigned long m41t80_decode_freq(int setting)
unsigned long parent_rate) {
return (setting == 0) ? 0 : (setting == 1) ? M41T80_SQW_MAX_FREQ :
M41T80_SQW_MAX_FREQ >> setting;
}
static unsigned long m41t80_get_freq(struct m41t80_data *m41t80)
{ {
struct m41t80_data *m41t80 = sqw_to_m41t80_data(hw);
struct i2c_client *client = m41t80->client; struct i2c_client *client = m41t80->client;
int reg_sqw = (m41t80->features & M41T80_FEATURE_SQ_ALT) ? int reg_sqw = (m41t80->features & M41T80_FEATURE_SQ_ALT) ?
M41T80_REG_WDAY : M41T80_REG_SQW; M41T80_REG_WDAY : M41T80_REG_SQW;
int ret = i2c_smbus_read_byte_data(client, reg_sqw); int ret = i2c_smbus_read_byte_data(client, reg_sqw);
unsigned long val = M41T80_SQW_MAX_FREQ;
if (ret < 0) if (ret < 0)
return 0; return 0;
return m41t80_decode_freq(ret >> 4);
}
ret >>= 4; static unsigned long m41t80_sqw_recalc_rate(struct clk_hw *hw,
if (ret == 0) unsigned long parent_rate)
val = 0; {
else if (ret > 1) return sqw_to_m41t80_data(hw)->freq;
val = val / (1 << ret);
return val;
} }
static long m41t80_sqw_round_rate(struct clk_hw *hw, unsigned long rate, static long m41t80_sqw_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate) unsigned long *prate)
{ {
int i, freq = M41T80_SQW_MAX_FREQ; if (rate >= M41T80_SQW_MAX_FREQ)
return M41T80_SQW_MAX_FREQ;
if (freq <= rate) if (rate >= M41T80_SQW_MAX_FREQ / 4)
return freq; return M41T80_SQW_MAX_FREQ / 4;
if (!rate)
for (i = 2; i <= ilog2(M41T80_SQW_MAX_FREQ); i++) { return 0;
freq /= 1 << i; return 1 << ilog2(rate);
if (freq <= rate)
return freq;
}
return 0;
} }
static int m41t80_sqw_set_rate(struct clk_hw *hw, unsigned long rate, static int m41t80_sqw_set_rate(struct clk_hw *hw, unsigned long rate,
...@@ -491,17 +490,12 @@ static int m41t80_sqw_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -491,17 +490,12 @@ static int m41t80_sqw_set_rate(struct clk_hw *hw, unsigned long rate,
M41T80_REG_WDAY : M41T80_REG_SQW; M41T80_REG_WDAY : M41T80_REG_SQW;
int reg, ret, val = 0; int reg, ret, val = 0;
if (rate) { if (rate >= M41T80_SQW_MAX_FREQ)
if (!is_power_of_2(rate)) val = 1;
return -EINVAL; else if (rate >= M41T80_SQW_MAX_FREQ / 4)
val = ilog2(rate); val = 2;
if (val == ilog2(M41T80_SQW_MAX_FREQ)) else if (rate)
val = 1; val = 15 - ilog2(rate);
else if (val < (ilog2(M41T80_SQW_MAX_FREQ) - 1))
val = ilog2(M41T80_SQW_MAX_FREQ) - val;
else
return -EINVAL;
}
reg = i2c_smbus_read_byte_data(client, reg_sqw); reg = i2c_smbus_read_byte_data(client, reg_sqw);
if (reg < 0) if (reg < 0)
...@@ -510,10 +504,9 @@ static int m41t80_sqw_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -510,10 +504,9 @@ static int m41t80_sqw_set_rate(struct clk_hw *hw, unsigned long rate,
reg = (reg & 0x0f) | (val << 4); reg = (reg & 0x0f) | (val << 4);
ret = i2c_smbus_write_byte_data(client, reg_sqw, reg); ret = i2c_smbus_write_byte_data(client, reg_sqw, reg);
if (ret < 0) if (!ret)
return ret; m41t80->freq = m41t80_decode_freq(val);
return ret;
return -EINVAL;
} }
static int m41t80_sqw_control(struct clk_hw *hw, bool enable) static int m41t80_sqw_control(struct clk_hw *hw, bool enable)
...@@ -530,7 +523,10 @@ static int m41t80_sqw_control(struct clk_hw *hw, bool enable) ...@@ -530,7 +523,10 @@ static int m41t80_sqw_control(struct clk_hw *hw, bool enable)
else else
ret &= ~M41T80_ALMON_SQWE; ret &= ~M41T80_ALMON_SQWE;
return i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, ret); ret = i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, ret);
if (!ret)
m41t80->sqwe = enable;
return ret;
} }
static int m41t80_sqw_prepare(struct clk_hw *hw) static int m41t80_sqw_prepare(struct clk_hw *hw)
...@@ -545,14 +541,7 @@ static void m41t80_sqw_unprepare(struct clk_hw *hw) ...@@ -545,14 +541,7 @@ static void m41t80_sqw_unprepare(struct clk_hw *hw)
static int m41t80_sqw_is_prepared(struct clk_hw *hw) static int m41t80_sqw_is_prepared(struct clk_hw *hw)
{ {
struct m41t80_data *m41t80 = sqw_to_m41t80_data(hw); return sqw_to_m41t80_data(hw)->sqwe;
struct i2c_client *client = m41t80->client;
int ret = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON);
if (ret < 0)
return ret;
return !!(ret & M41T80_ALMON_SQWE);
} }
static const struct clk_ops m41t80_sqw_ops = { static const struct clk_ops m41t80_sqw_ops = {
...@@ -587,6 +576,7 @@ static struct clk *m41t80_sqw_register_clk(struct m41t80_data *m41t80) ...@@ -587,6 +576,7 @@ static struct clk *m41t80_sqw_register_clk(struct m41t80_data *m41t80)
init.parent_names = NULL; init.parent_names = NULL;
init.num_parents = 0; init.num_parents = 0;
m41t80->sqw.init = &init; m41t80->sqw.init = &init;
m41t80->freq = m41t80_get_freq(m41t80);
/* optional override of the clockname */ /* optional override of the clockname */
of_property_read_string(node, "clock-output-names", &init.name); of_property_read_string(node, "clock-output-names", &init.name);
......
...@@ -163,35 +163,30 @@ static const struct rtc_class_ops m48t86_rtc_ops = { ...@@ -163,35 +163,30 @@ static const struct rtc_class_ops m48t86_rtc_ops = {
.proc = m48t86_rtc_proc, .proc = m48t86_rtc_proc,
}; };
static ssize_t m48t86_nvram_read(struct file *filp, struct kobject *kobj, static int m48t86_nvram_read(void *priv, unsigned int off, void *buf,
struct bin_attribute *attr, size_t count)
char *buf, loff_t off, size_t count)
{ {
struct device *dev = kobj_to_dev(kobj); struct device *dev = priv;
unsigned int i; unsigned int i;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
buf[i] = m48t86_readb(dev, M48T86_NVRAM(off + i)); ((u8 *)buf)[i] = m48t86_readb(dev, M48T86_NVRAM(off + i));
return count; return 0;
} }
static ssize_t m48t86_nvram_write(struct file *filp, struct kobject *kobj, static int m48t86_nvram_write(void *priv, unsigned int off, void *buf,
struct bin_attribute *attr, size_t count)
char *buf, loff_t off, size_t count)
{ {
struct device *dev = kobj_to_dev(kobj); struct device *dev = priv;
unsigned int i; unsigned int i;
for (i = 0; i < count; i++) for (i = 0; i < count; i++)
m48t86_writeb(dev, buf[i], M48T86_NVRAM(off + i)); m48t86_writeb(dev, ((u8 *)buf)[i], M48T86_NVRAM(off + i));
return count; return 0;
} }
static BIN_ATTR(nvram, 0644, m48t86_nvram_read, m48t86_nvram_write,
M48T86_NVRAM_LEN);
/* /*
* The RTC is an optional feature at purchase time on some Technologic Systems * The RTC is an optional feature at purchase time on some Technologic Systems
* boards. Verify that it actually exists by checking if the last two bytes * boards. Verify that it actually exists by checking if the last two bytes
...@@ -223,11 +218,21 @@ static bool m48t86_verify_chip(struct platform_device *pdev) ...@@ -223,11 +218,21 @@ static bool m48t86_verify_chip(struct platform_device *pdev)
return false; return false;
} }
static struct nvmem_config m48t86_nvmem_cfg = {
.name = "m48t86_nvram",
.word_size = 1,
.stride = 1,
.size = M48T86_NVRAM_LEN,
.reg_read = m48t86_nvram_read,
.reg_write = m48t86_nvram_write,
};
static int m48t86_rtc_probe(struct platform_device *pdev) static int m48t86_rtc_probe(struct platform_device *pdev)
{ {
struct m48t86_rtc_info *info; struct m48t86_rtc_info *info;
struct resource *res; struct resource *res;
unsigned char reg; unsigned char reg;
int err;
info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
if (!info) if (!info)
...@@ -254,25 +259,25 @@ static int m48t86_rtc_probe(struct platform_device *pdev) ...@@ -254,25 +259,25 @@ static int m48t86_rtc_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
} }
info->rtc = devm_rtc_device_register(&pdev->dev, "m48t86", info->rtc = devm_rtc_allocate_device(&pdev->dev);
&m48t86_rtc_ops, THIS_MODULE);
if (IS_ERR(info->rtc)) if (IS_ERR(info->rtc))
return PTR_ERR(info->rtc); return PTR_ERR(info->rtc);
info->rtc->ops = &m48t86_rtc_ops;
m48t86_nvmem_cfg.priv = &pdev->dev;
info->rtc->nvmem_config = &m48t86_nvmem_cfg;
info->rtc->nvram_old_abi = true;
err = rtc_register_device(info->rtc);
if (err)
return err;
/* read battery status */ /* read battery status */
reg = m48t86_readb(&pdev->dev, M48T86_D); reg = m48t86_readb(&pdev->dev, M48T86_D);
dev_info(&pdev->dev, "battery %s\n", dev_info(&pdev->dev, "battery %s\n",
(reg & M48T86_D_VRT) ? "ok" : "exhausted"); (reg & M48T86_D_VRT) ? "ok" : "exhausted");
if (device_create_bin_file(&pdev->dev, &bin_attr_nvram))
dev_err(&pdev->dev, "failed to create nvram sysfs entry\n");
return 0;
}
static int m48t86_rtc_remove(struct platform_device *pdev)
{
device_remove_bin_file(&pdev->dev, &bin_attr_nvram);
return 0; return 0;
} }
...@@ -281,7 +286,6 @@ static struct platform_driver m48t86_rtc_platform_driver = { ...@@ -281,7 +286,6 @@ static struct platform_driver m48t86_rtc_platform_driver = {
.name = "rtc-m48t86", .name = "rtc-m48t86",
}, },
.probe = m48t86_rtc_probe, .probe = m48t86_rtc_probe,
.remove = m48t86_rtc_remove,
}; };
module_platform_driver(m48t86_rtc_platform_driver); module_platform_driver(m48t86_rtc_platform_driver);
......
This diff is collapsed.
...@@ -70,6 +70,10 @@ ...@@ -70,6 +70,10 @@
#define OMAP_RTC_COMP_MSB_REG 0x50 #define OMAP_RTC_COMP_MSB_REG 0x50
#define OMAP_RTC_OSC_REG 0x54 #define OMAP_RTC_OSC_REG 0x54
#define OMAP_RTC_SCRATCH0_REG 0x60
#define OMAP_RTC_SCRATCH1_REG 0x64
#define OMAP_RTC_SCRATCH2_REG 0x68
#define OMAP_RTC_KICK0_REG 0x6c #define OMAP_RTC_KICK0_REG 0x6c
#define OMAP_RTC_KICK1_REG 0x70 #define OMAP_RTC_KICK1_REG 0x70
...@@ -667,6 +671,45 @@ static struct pinctrl_desc rtc_pinctrl_desc = { ...@@ -667,6 +671,45 @@ static struct pinctrl_desc rtc_pinctrl_desc = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
static int omap_rtc_scratch_read(void *priv, unsigned int offset, void *_val,
size_t bytes)
{
struct omap_rtc *rtc = priv;
u32 *val = _val;
int i;
for (i = 0; i < bytes / 4; i++)
val[i] = rtc_readl(rtc,
OMAP_RTC_SCRATCH0_REG + offset + (i * 4));
return 0;
}
static int omap_rtc_scratch_write(void *priv, unsigned int offset, void *_val,
size_t bytes)
{
struct omap_rtc *rtc = priv;
u32 *val = _val;
int i;
rtc->type->unlock(rtc);
for (i = 0; i < bytes / 4; i++)
rtc_writel(rtc,
OMAP_RTC_SCRATCH0_REG + offset + (i * 4), val[i]);
rtc->type->lock(rtc);
return 0;
}
static struct nvmem_config omap_rtc_nvmem_config = {
.name = "omap_rtc_scratch",
.word_size = 4,
.stride = 4,
.size = OMAP_RTC_KICK0_REG - OMAP_RTC_SCRATCH0_REG,
.reg_read = omap_rtc_scratch_read,
.reg_write = omap_rtc_scratch_write,
};
static int omap_rtc_probe(struct platform_device *pdev) static int omap_rtc_probe(struct platform_device *pdev)
{ {
struct omap_rtc *rtc; struct omap_rtc *rtc;
...@@ -797,13 +840,16 @@ static int omap_rtc_probe(struct platform_device *pdev) ...@@ -797,13 +840,16 @@ static int omap_rtc_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, true); device_init_wakeup(&pdev->dev, true);
rtc->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, rtc->rtc = devm_rtc_allocate_device(&pdev->dev);
&omap_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc)) { if (IS_ERR(rtc->rtc)) {
ret = PTR_ERR(rtc->rtc); ret = PTR_ERR(rtc->rtc);
goto err; goto err;
} }
rtc->rtc->ops = &omap_rtc_ops;
omap_rtc_nvmem_config.priv = rtc;
rtc->rtc->nvmem_config = &omap_rtc_nvmem_config;
/* handle periodic and alarm irqs */ /* handle periodic and alarm irqs */
ret = devm_request_irq(&pdev->dev, rtc->irq_timer, rtc_irq, 0, ret = devm_request_irq(&pdev->dev, rtc->irq_timer, rtc_irq, 0,
dev_name(&rtc->rtc->dev), rtc); dev_name(&rtc->rtc->dev), rtc);
...@@ -830,9 +876,14 @@ static int omap_rtc_probe(struct platform_device *pdev) ...@@ -830,9 +876,14 @@ static int omap_rtc_probe(struct platform_device *pdev)
rtc->pctldev = pinctrl_register(&rtc_pinctrl_desc, &pdev->dev, rtc); rtc->pctldev = pinctrl_register(&rtc_pinctrl_desc, &pdev->dev, rtc);
if (IS_ERR(rtc->pctldev)) { if (IS_ERR(rtc->pctldev)) {
dev_err(&pdev->dev, "Couldn't register pinctrl driver\n"); dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
return PTR_ERR(rtc->pctldev); ret = PTR_ERR(rtc->pctldev);
goto err;
} }
ret = rtc_register_device(rtc->rtc);
if (ret)
goto err;
return 0; return 0;
err: err:
......
...@@ -35,6 +35,9 @@ ...@@ -35,6 +35,9 @@
#define REG_MONTHS 0x08 #define REG_MONTHS 0x08
#define REG_YEARS 0x09 #define REG_YEARS 0x09
#define REG_OFFSET 0x0e
#define REG_OFFSET_MODE BIT(7)
struct pcf8523 { struct pcf8523 {
struct rtc_device *rtc; struct rtc_device *rtc;
}; };
...@@ -272,10 +275,47 @@ static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd, ...@@ -272,10 +275,47 @@ static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd,
#define pcf8523_rtc_ioctl NULL #define pcf8523_rtc_ioctl NULL
#endif #endif
static int pcf8523_rtc_read_offset(struct device *dev, long *offset)
{
struct i2c_client *client = to_i2c_client(dev);
int err;
u8 value;
s8 val;
err = pcf8523_read(client, REG_OFFSET, &value);
if (err < 0)
return err;
/* sign extend the 7-bit offset value */
val = value << 1;
*offset = (value & REG_OFFSET_MODE ? 4069 : 4340) * (val >> 1);
return 0;
}
static int pcf8523_rtc_set_offset(struct device *dev, long offset)
{
struct i2c_client *client = to_i2c_client(dev);
long reg_m0, reg_m1;
u8 value;
reg_m0 = clamp(DIV_ROUND_CLOSEST(offset, 4340), -64L, 63L);
reg_m1 = clamp(DIV_ROUND_CLOSEST(offset, 4069), -64L, 63L);
if (abs(reg_m0 * 4340 - offset) < abs(reg_m1 * 4069 - offset))
value = reg_m0 & 0x7f;
else
value = (reg_m1 & 0x7f) | REG_OFFSET_MODE;
return pcf8523_write(client, REG_OFFSET, value);
}
static const struct rtc_class_ops pcf8523_rtc_ops = { static const struct rtc_class_ops pcf8523_rtc_ops = {
.read_time = pcf8523_rtc_read_time, .read_time = pcf8523_rtc_read_time,
.set_time = pcf8523_rtc_set_time, .set_time = pcf8523_rtc_set_time,
.ioctl = pcf8523_rtc_ioctl, .ioctl = pcf8523_rtc_ioctl,
.read_offset = pcf8523_rtc_read_offset,
.set_offset = pcf8523_rtc_set_offset,
}; };
static int pcf8523_probe(struct i2c_client *client, static int pcf8523_probe(struct i2c_client *client,
......
/*
* drivers/rtc/rtc-pcf85363.c
*
* Driver for NXP PCF85363 real-time clock.
*
* Copyright (C) 2017 Eric Nelson
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Based loosely on rtc-8583 by Russell King, Wolfram Sang and Juergen Beisert
*/
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/rtc.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/bcd.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
/*
* Date/Time registers
*/
#define DT_100THS 0x00
#define DT_SECS 0x01
#define DT_MINUTES 0x02
#define DT_HOURS 0x03
#define DT_DAYS 0x04
#define DT_WEEKDAYS 0x05
#define DT_MONTHS 0x06
#define DT_YEARS 0x07
/*
* Alarm registers
*/
#define DT_SECOND_ALM1 0x08
#define DT_MINUTE_ALM1 0x09
#define DT_HOUR_ALM1 0x0a
#define DT_DAY_ALM1 0x0b
#define DT_MONTH_ALM1 0x0c
#define DT_MINUTE_ALM2 0x0d
#define DT_HOUR_ALM2 0x0e
#define DT_WEEKDAY_ALM2 0x0f
#define DT_ALARM_EN 0x10
/*
* Time stamp registers
*/
#define DT_TIMESTAMP1 0x11
#define DT_TIMESTAMP2 0x17
#define DT_TIMESTAMP3 0x1d
#define DT_TS_MODE 0x23
/*
* control registers
*/
#define CTRL_OFFSET 0x24
#define CTRL_OSCILLATOR 0x25
#define CTRL_BATTERY 0x26
#define CTRL_PIN_IO 0x27
#define CTRL_FUNCTION 0x28
#define CTRL_INTA_EN 0x29
#define CTRL_INTB_EN 0x2a
#define CTRL_FLAGS 0x2b
#define CTRL_RAMBYTE 0x2c
#define CTRL_WDOG 0x2d
#define CTRL_STOP_EN 0x2e
#define CTRL_RESETS 0x2f
#define CTRL_RAM 0x40
#define NVRAM_SIZE 0x40
static struct i2c_driver pcf85363_driver;
struct pcf85363 {
struct device *dev;
struct rtc_device *rtc;
struct nvmem_config nvmem_cfg;
struct regmap *regmap;
};
static int pcf85363_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct pcf85363 *pcf85363 = dev_get_drvdata(dev);
unsigned char buf[DT_YEARS + 1];
int ret, len = sizeof(buf);
/* read the RTC date and time registers all at once */
ret = regmap_bulk_read(pcf85363->regmap, DT_100THS, buf, len);
if (ret) {
dev_err(dev, "%s: error %d\n", __func__, ret);
return ret;
}
tm->tm_year = bcd2bin(buf[DT_YEARS]);
/* adjust for 1900 base of rtc_time */
tm->tm_year += 100;
tm->tm_wday = buf[DT_WEEKDAYS] & 7;
buf[DT_SECS] &= 0x7F;
tm->tm_sec = bcd2bin(buf[DT_SECS]);
buf[DT_MINUTES] &= 0x7F;
tm->tm_min = bcd2bin(buf[DT_MINUTES]);
tm->tm_hour = bcd2bin(buf[DT_HOURS]);
tm->tm_mday = bcd2bin(buf[DT_DAYS]);
tm->tm_mon = bcd2bin(buf[DT_MONTHS]) - 1;
return 0;
}
static int pcf85363_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct pcf85363 *pcf85363 = dev_get_drvdata(dev);
unsigned char buf[DT_YEARS + 1];
int len = sizeof(buf);
buf[DT_100THS] = 0;
buf[DT_SECS] = bin2bcd(tm->tm_sec);
buf[DT_MINUTES] = bin2bcd(tm->tm_min);
buf[DT_HOURS] = bin2bcd(tm->tm_hour);
buf[DT_DAYS] = bin2bcd(tm->tm_mday);
buf[DT_WEEKDAYS] = tm->tm_wday;
buf[DT_MONTHS] = bin2bcd(tm->tm_mon + 1);
buf[DT_YEARS] = bin2bcd(tm->tm_year % 100);
return regmap_bulk_write(pcf85363->regmap, DT_100THS,
buf, len);
}
static const struct rtc_class_ops rtc_ops = {
.read_time = pcf85363_rtc_read_time,
.set_time = pcf85363_rtc_set_time,
};
static int pcf85363_nvram_read(void *priv, unsigned int offset, void *val,
size_t bytes)
{
struct pcf85363 *pcf85363 = priv;
return regmap_bulk_read(pcf85363->regmap, CTRL_RAM + offset,
val, bytes);
}
static int pcf85363_nvram_write(void *priv, unsigned int offset, void *val,
size_t bytes)
{
struct pcf85363 *pcf85363 = priv;
return regmap_bulk_write(pcf85363->regmap, CTRL_RAM + offset,
val, bytes);
}
static const struct regmap_config regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static int pcf85363_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pcf85363 *pcf85363;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
pcf85363 = devm_kzalloc(&client->dev, sizeof(struct pcf85363),
GFP_KERNEL);
if (!pcf85363)
return -ENOMEM;
pcf85363->regmap = devm_regmap_init_i2c(client, &regmap_config);
if (IS_ERR(pcf85363->regmap)) {
dev_err(&client->dev, "regmap allocation failed\n");
return PTR_ERR(pcf85363->regmap);
}
pcf85363->dev = &client->dev;
i2c_set_clientdata(client, pcf85363);
pcf85363->rtc = devm_rtc_allocate_device(pcf85363->dev);
if (IS_ERR(pcf85363->rtc))
return PTR_ERR(pcf85363->rtc);
pcf85363->nvmem_cfg.name = "pcf85363-";
pcf85363->nvmem_cfg.word_size = 1;
pcf85363->nvmem_cfg.stride = 1;
pcf85363->nvmem_cfg.size = NVRAM_SIZE;
pcf85363->nvmem_cfg.reg_read = pcf85363_nvram_read;
pcf85363->nvmem_cfg.reg_write = pcf85363_nvram_write;
pcf85363->nvmem_cfg.priv = pcf85363;
pcf85363->rtc->nvmem_config = &pcf85363->nvmem_cfg;
pcf85363->rtc->ops = &rtc_ops;
return rtc_register_device(pcf85363->rtc);
}
static const struct of_device_id dev_ids[] = {
{ .compatible = "nxp,pcf85363" },
{}
};
MODULE_DEVICE_TABLE(of, dev_ids);
static struct i2c_driver pcf85363_driver = {
.driver = {
.name = "pcf85363",
.of_match_table = of_match_ptr(dev_ids),
},
.probe = pcf85363_probe,
};
module_i2c_driver(pcf85363_driver);
MODULE_AUTHOR("Eric Nelson");
MODULE_DESCRIPTION("pcf85363 I2C RTC driver");
MODULE_LICENSE("GPL");
...@@ -387,7 +387,7 @@ static int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm) ...@@ -387,7 +387,7 @@ static int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
if (err) if (err)
return err; return err;
return pcf8563_set_alarm_mode(client, 1); return pcf8563_set_alarm_mode(client, !!tm->enabled);
} }
static int pcf8563_irq_enable(struct device *dev, unsigned int enabled) static int pcf8563_irq_enable(struct device *dev, unsigned int enabled)
...@@ -422,7 +422,7 @@ static unsigned long pcf8563_clkout_recalc_rate(struct clk_hw *hw, ...@@ -422,7 +422,7 @@ static unsigned long pcf8563_clkout_recalc_rate(struct clk_hw *hw,
return 0; return 0;
buf &= PCF8563_REG_CLKO_F_MASK; buf &= PCF8563_REG_CLKO_F_MASK;
return clkout_rates[ret]; return clkout_rates[buf];
} }
static long pcf8563_clkout_round_rate(struct clk_hw *hw, unsigned long rate, static long pcf8563_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
......
...@@ -308,10 +308,9 @@ static int pl031_remove(struct amba_device *adev) ...@@ -308,10 +308,9 @@ static int pl031_remove(struct amba_device *adev)
dev_pm_clear_wake_irq(&adev->dev); dev_pm_clear_wake_irq(&adev->dev);
device_init_wakeup(&adev->dev, false); device_init_wakeup(&adev->dev, false);
free_irq(adev->irq[0], ldata); if (adev->irq[0])
free_irq(adev->irq[0], ldata);
rtc_device_unregister(ldata->rtc); rtc_device_unregister(ldata->rtc);
iounmap(ldata->base);
kfree(ldata);
amba_release_regions(adev); amba_release_regions(adev);
return 0; return 0;
...@@ -322,25 +321,28 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -322,25 +321,28 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
int ret; int ret;
struct pl031_local *ldata; struct pl031_local *ldata;
struct pl031_vendor_data *vendor = id->data; struct pl031_vendor_data *vendor = id->data;
struct rtc_class_ops *ops = &vendor->ops; struct rtc_class_ops *ops;
unsigned long time, data; unsigned long time, data;
ret = amba_request_regions(adev, NULL); ret = amba_request_regions(adev, NULL);
if (ret) if (ret)
goto err_req; goto err_req;
ldata = kzalloc(sizeof(struct pl031_local), GFP_KERNEL); ldata = devm_kzalloc(&adev->dev, sizeof(struct pl031_local),
if (!ldata) { GFP_KERNEL);
ops = devm_kmemdup(&adev->dev, &vendor->ops, sizeof(vendor->ops),
GFP_KERNEL);
if (!ldata || !ops) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
ldata->vendor = vendor;
ldata->base = ioremap(adev->res.start, resource_size(&adev->res));
ldata->vendor = vendor;
ldata->base = devm_ioremap(&adev->dev, adev->res.start,
resource_size(&adev->res));
if (!ldata->base) { if (!ldata->base) {
ret = -ENOMEM; ret = -ENOMEM;
goto out_no_remap; goto out;
} }
amba_set_drvdata(adev, ldata); amba_set_drvdata(adev, ldata);
...@@ -373,28 +375,32 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) ...@@ -373,28 +375,32 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
} }
} }
if (!adev->irq[0]) {
/* When there's no interrupt, no point in exposing the alarm */
ops->read_alarm = NULL;
ops->set_alarm = NULL;
ops->alarm_irq_enable = NULL;
}
device_init_wakeup(&adev->dev, true); device_init_wakeup(&adev->dev, true);
ldata->rtc = rtc_device_register("pl031", &adev->dev, ops, ldata->rtc = rtc_device_register("pl031", &adev->dev, ops,
THIS_MODULE); THIS_MODULE);
if (IS_ERR(ldata->rtc)) { if (IS_ERR(ldata->rtc)) {
ret = PTR_ERR(ldata->rtc); ret = PTR_ERR(ldata->rtc);
goto out_no_rtc; goto out;
} }
if (request_irq(adev->irq[0], pl031_interrupt, if (adev->irq[0]) {
vendor->irqflags, "rtc-pl031", ldata)) { ret = request_irq(adev->irq[0], pl031_interrupt,
ret = -EIO; vendor->irqflags, "rtc-pl031", ldata);
goto out_no_irq; if (ret)
goto out_no_irq;
dev_pm_set_wake_irq(&adev->dev, adev->irq[0]);
} }
dev_pm_set_wake_irq(&adev->dev, adev->irq[0]);
return 0; return 0;
out_no_irq: out_no_irq:
rtc_device_unregister(ldata->rtc); rtc_device_unregister(ldata->rtc);
out_no_rtc:
iounmap(ldata->base);
out_no_remap:
kfree(ldata);
out: out:
amba_release_regions(adev); amba_release_regions(adev);
err_req: err_req:
...@@ -446,7 +452,7 @@ static struct pl031_vendor_data stv2_pl031 = { ...@@ -446,7 +452,7 @@ static struct pl031_vendor_data stv2_pl031 = {
.irqflags = IRQF_SHARED | IRQF_COND_SUSPEND, .irqflags = IRQF_SHARED | IRQF_COND_SUSPEND,
}; };
static struct amba_id pl031_ids[] = { static const struct amba_id pl031_ids[] = {
{ {
.id = 0x00041031, .id = 0x00041031,
.mask = 0x000fffff, .mask = 0x000fffff,
......
...@@ -282,13 +282,13 @@ static int rv3029_eeprom_read(struct device *dev, u8 reg, ...@@ -282,13 +282,13 @@ static int rv3029_eeprom_read(struct device *dev, u8 reg,
static int rv3029_eeprom_write(struct device *dev, u8 reg, static int rv3029_eeprom_write(struct device *dev, u8 reg,
u8 const buf[], size_t len) u8 const buf[], size_t len)
{ {
int ret, err; int ret;
size_t i; size_t i;
u8 tmp; u8 tmp;
err = rv3029_eeprom_enter(dev); ret = rv3029_eeprom_enter(dev);
if (err < 0) if (ret < 0)
return err; return ret;
for (i = 0; i < len; i++, reg++) { for (i = 0; i < len; i++, reg++) {
ret = rv3029_read_regs(dev, reg, &tmp, 1); ret = rv3029_read_regs(dev, reg, &tmp, 1);
...@@ -304,11 +304,11 @@ static int rv3029_eeprom_write(struct device *dev, u8 reg, ...@@ -304,11 +304,11 @@ static int rv3029_eeprom_write(struct device *dev, u8 reg,
break; break;
} }
err = rv3029_eeprom_exit(dev); ret = rv3029_eeprom_exit(dev);
if (err < 0) if (ret < 0)
return err; return ret;
return ret; return 0;
} }
static int rv3029_eeprom_update_bits(struct device *dev, static int rv3029_eeprom_update_bits(struct device *dev,
...@@ -876,6 +876,8 @@ static const struct i2c_device_id rv3029_id[] = { ...@@ -876,6 +876,8 @@ static const struct i2c_device_id rv3029_id[] = {
MODULE_DEVICE_TABLE(i2c, rv3029_id); MODULE_DEVICE_TABLE(i2c, rv3029_id);
static const struct of_device_id rv3029_of_match[] = { static const struct of_device_id rv3029_of_match[] = {
{ .compatible = "microcrystal,rv3029" },
/* Backward compatibility only, do not use compatibles below: */
{ .compatible = "rv3029" }, { .compatible = "rv3029" },
{ .compatible = "rv3029c2" }, { .compatible = "rv3029c2" },
{ .compatible = "mc,rv3029c2" }, { .compatible = "mc,rv3029c2" },
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#define RX8010_MDAY 0x14 #define RX8010_MDAY 0x14
#define RX8010_MONTH 0x15 #define RX8010_MONTH 0x15
#define RX8010_YEAR 0x16 #define RX8010_YEAR 0x16
#define RX8010_YEAR 0x16
#define RX8010_RESV17 0x17 #define RX8010_RESV17 0x17
#define RX8010_ALMIN 0x18 #define RX8010_ALMIN 0x18
#define RX8010_ALHOUR 0x19 #define RX8010_ALHOUR 0x19
...@@ -36,7 +35,7 @@ ...@@ -36,7 +35,7 @@
#define RX8010_CTRL 0x1F #define RX8010_CTRL 0x1F
/* 0x20 to 0x2F are user registers */ /* 0x20 to 0x2F are user registers */
#define RX8010_RESV30 0x30 #define RX8010_RESV30 0x30
#define RX8010_RESV31 0x32 #define RX8010_RESV31 0x31
#define RX8010_IRQ 0x32 #define RX8010_IRQ 0x32
#define RX8010_EXT_WADA BIT(3) #define RX8010_EXT_WADA BIT(3)
...@@ -248,7 +247,7 @@ static int rx8010_init_client(struct i2c_client *client) ...@@ -248,7 +247,7 @@ static int rx8010_init_client(struct i2c_client *client)
rx8010->ctrlreg = (ctrl[1] & ~RX8010_CTRL_TEST); rx8010->ctrlreg = (ctrl[1] & ~RX8010_CTRL_TEST);
return err; return 0;
} }
static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t) static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t)
...@@ -277,7 +276,7 @@ static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t) ...@@ -277,7 +276,7 @@ static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t)
t->enabled = !!(rx8010->ctrlreg & RX8010_CTRL_AIE); t->enabled = !!(rx8010->ctrlreg & RX8010_CTRL_AIE);
t->pending = (flagreg & RX8010_FLAG_AF) && t->enabled; t->pending = (flagreg & RX8010_FLAG_AF) && t->enabled;
return err; return 0;
} }
static int rx8010_set_alarm(struct device *dev, struct rtc_wkalrm *t) static int rx8010_set_alarm(struct device *dev, struct rtc_wkalrm *t)
......
This diff is collapsed.
...@@ -72,9 +72,10 @@ since_epoch_show(struct device *dev, struct device_attribute *attr, char *buf) ...@@ -72,9 +72,10 @@ since_epoch_show(struct device *dev, struct device_attribute *attr, char *buf)
retval = rtc_read_time(to_rtc_device(dev), &tm); retval = rtc_read_time(to_rtc_device(dev), &tm);
if (retval == 0) { if (retval == 0) {
unsigned long time; time64_t time;
rtc_tm_to_time(&tm, &time);
retval = sprintf(buf, "%lu\n", time); time = rtc_tm_to_time64(&tm);
retval = sprintf(buf, "%lld\n", time);
} }
return retval; return retval;
...@@ -132,7 +133,7 @@ static ssize_t ...@@ -132,7 +133,7 @@ static ssize_t
wakealarm_show(struct device *dev, struct device_attribute *attr, char *buf) wakealarm_show(struct device *dev, struct device_attribute *attr, char *buf)
{ {
ssize_t retval; ssize_t retval;
unsigned long alarm; time64_t alarm;
struct rtc_wkalrm alm; struct rtc_wkalrm alm;
/* Don't show disabled alarms. For uniformity, RTC alarms are /* Don't show disabled alarms. For uniformity, RTC alarms are
...@@ -145,8 +146,8 @@ wakealarm_show(struct device *dev, struct device_attribute *attr, char *buf) ...@@ -145,8 +146,8 @@ wakealarm_show(struct device *dev, struct device_attribute *attr, char *buf)
*/ */
retval = rtc_read_alarm(to_rtc_device(dev), &alm); retval = rtc_read_alarm(to_rtc_device(dev), &alm);
if (retval == 0 && alm.enabled) { if (retval == 0 && alm.enabled) {
rtc_tm_to_time(&alm.time, &alarm); alarm = rtc_tm_to_time64(&alm.time);
retval = sprintf(buf, "%lu\n", alarm); retval = sprintf(buf, "%lld\n", alarm);
} }
return retval; return retval;
...@@ -157,8 +158,8 @@ wakealarm_store(struct device *dev, struct device_attribute *attr, ...@@ -157,8 +158,8 @@ wakealarm_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t n) const char *buf, size_t n)
{ {
ssize_t retval; ssize_t retval;
unsigned long now, alarm; time64_t now, alarm;
unsigned long push = 0; time64_t push = 0;
struct rtc_wkalrm alm; struct rtc_wkalrm alm;
struct rtc_device *rtc = to_rtc_device(dev); struct rtc_device *rtc = to_rtc_device(dev);
const char *buf_ptr; const char *buf_ptr;
...@@ -170,7 +171,7 @@ wakealarm_store(struct device *dev, struct device_attribute *attr, ...@@ -170,7 +171,7 @@ wakealarm_store(struct device *dev, struct device_attribute *attr,
retval = rtc_read_time(rtc, &alm.time); retval = rtc_read_time(rtc, &alm.time);
if (retval < 0) if (retval < 0)
return retval; return retval;
rtc_tm_to_time(&alm.time, &now); now = rtc_tm_to_time64(&alm.time);
buf_ptr = buf; buf_ptr = buf;
if (*buf_ptr == '+') { if (*buf_ptr == '+') {
...@@ -181,7 +182,7 @@ wakealarm_store(struct device *dev, struct device_attribute *attr, ...@@ -181,7 +182,7 @@ wakealarm_store(struct device *dev, struct device_attribute *attr,
} else } else
adjust = 1; adjust = 1;
} }
retval = kstrtoul(buf_ptr, 0, &alarm); retval = kstrtos64(buf_ptr, 0, &alarm);
if (retval) if (retval)
return retval; return retval;
if (adjust) { if (adjust) {
...@@ -197,7 +198,7 @@ wakealarm_store(struct device *dev, struct device_attribute *attr, ...@@ -197,7 +198,7 @@ wakealarm_store(struct device *dev, struct device_attribute *attr,
return retval; return retval;
if (alm.enabled) { if (alm.enabled) {
if (push) { if (push) {
rtc_tm_to_time(&alm.time, &push); push = rtc_tm_to_time64(&alm.time);
alarm += push; alarm += push;
} else } else
return -EBUSY; return -EBUSY;
...@@ -212,7 +213,7 @@ wakealarm_store(struct device *dev, struct device_attribute *attr, ...@@ -212,7 +213,7 @@ wakealarm_store(struct device *dev, struct device_attribute *attr,
*/ */
alarm = now + 300; alarm = now + 300;
} }
rtc_time_to_tm(alarm, &alm.time); rtc_time64_to_tm(alarm, &alm.time);
retval = rtc_set_alarm(rtc, &alm); retval = rtc_set_alarm(rtc, &alm);
return (retval < 0) ? retval : n; return (retval < 0) ? retval : n;
......
...@@ -52,6 +52,7 @@ struct xgene_rtc_dev { ...@@ -52,6 +52,7 @@ struct xgene_rtc_dev {
void __iomem *csr_base; void __iomem *csr_base;
struct clk *clk; struct clk *clk;
unsigned int irq_wake; unsigned int irq_wake;
unsigned int irq_enabled;
}; };
static int xgene_rtc_read_time(struct device *dev, struct rtc_time *tm) static int xgene_rtc_read_time(struct device *dev, struct rtc_time *tm)
...@@ -104,15 +105,19 @@ static int xgene_rtc_alarm_irq_enable(struct device *dev, u32 enabled) ...@@ -104,15 +105,19 @@ static int xgene_rtc_alarm_irq_enable(struct device *dev, u32 enabled)
return 0; return 0;
} }
static int xgene_rtc_alarm_irq_enabled(struct device *dev)
{
struct xgene_rtc_dev *pdata = dev_get_drvdata(dev);
return readl(pdata->csr_base + RTC_CCR) & RTC_CCR_IE ? 1 : 0;
}
static int xgene_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) static int xgene_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{ {
struct xgene_rtc_dev *pdata = dev_get_drvdata(dev); struct xgene_rtc_dev *pdata = dev_get_drvdata(dev);
unsigned long rtc_time;
unsigned long alarm_time; unsigned long alarm_time;
rtc_time = readl(pdata->csr_base + RTC_CCVR);
rtc_tm_to_time(&alrm->time, &alarm_time); rtc_tm_to_time(&alrm->time, &alarm_time);
pdata->alarm_time = alarm_time; pdata->alarm_time = alarm_time;
writel((u32) pdata->alarm_time, pdata->csr_base + RTC_CMR); writel((u32) pdata->alarm_time, pdata->csr_base + RTC_CMR);
...@@ -180,12 +185,18 @@ static int xgene_rtc_probe(struct platform_device *pdev) ...@@ -180,12 +185,18 @@ static int xgene_rtc_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "Couldn't get the clock for RTC\n"); dev_err(&pdev->dev, "Couldn't get the clock for RTC\n");
return -ENODEV; return -ENODEV;
} }
clk_prepare_enable(pdata->clk); ret = clk_prepare_enable(pdata->clk);
if (ret)
return ret;
/* Turn on the clock and the crystal */ /* Turn on the clock and the crystal */
writel(RTC_CCR_EN, pdata->csr_base + RTC_CCR); writel(RTC_CCR_EN, pdata->csr_base + RTC_CCR);
device_init_wakeup(&pdev->dev, 1); ret = device_init_wakeup(&pdev->dev, 1);
if (ret) {
clk_disable_unprepare(pdata->clk);
return ret;
}
pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, pdata->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&xgene_rtc_ops, THIS_MODULE); &xgene_rtc_ops, THIS_MODULE);
...@@ -210,45 +221,55 @@ static int xgene_rtc_remove(struct platform_device *pdev) ...@@ -210,45 +221,55 @@ static int xgene_rtc_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM_SLEEP static int __maybe_unused xgene_rtc_suspend(struct device *dev)
static int xgene_rtc_suspend(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev); struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev);
int irq; int irq;
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
/*
* If this RTC alarm will be used for waking the system up,
* don't disable it of course. Else we just disable the alarm
* and await suspension.
*/
if (device_may_wakeup(&pdev->dev)) { if (device_may_wakeup(&pdev->dev)) {
if (!enable_irq_wake(irq)) if (!enable_irq_wake(irq))
pdata->irq_wake = 1; pdata->irq_wake = 1;
} else { } else {
pdata->irq_enabled = xgene_rtc_alarm_irq_enabled(dev);
xgene_rtc_alarm_irq_enable(dev, 0); xgene_rtc_alarm_irq_enable(dev, 0);
clk_disable(pdata->clk); clk_disable_unprepare(pdata->clk);
} }
return 0; return 0;
} }
static int xgene_rtc_resume(struct device *dev) static int __maybe_unused xgene_rtc_resume(struct device *dev)
{ {
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev); struct xgene_rtc_dev *pdata = platform_get_drvdata(pdev);
int irq; int irq;
int rc;
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (device_may_wakeup(&pdev->dev)) { if (device_may_wakeup(&pdev->dev)) {
if (pdata->irq_wake) { if (pdata->irq_wake) {
disable_irq_wake(irq); disable_irq_wake(irq);
pdata->irq_wake = 0; pdata->irq_wake = 0;
} }
} else { } else {
clk_enable(pdata->clk); rc = clk_prepare_enable(pdata->clk);
xgene_rtc_alarm_irq_enable(dev, 1); if (rc) {
dev_err(dev, "Unable to enable clock error %d\n", rc);
return rc;
}
xgene_rtc_alarm_irq_enable(dev, pdata->irq_enabled);
} }
return 0; return 0;
} }
#endif
static SIMPLE_DEV_PM_OPS(xgene_rtc_pm_ops, xgene_rtc_suspend, xgene_rtc_resume); static SIMPLE_DEV_PM_OPS(xgene_rtc_pm_ops, xgene_rtc_suspend, xgene_rtc_resume);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment