Commit b7769c45 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull RTC updates from Alexandre Belloni:
 "A new driver this cycle is making the bulk of the changes and the
  rx8010 driver has been rework to use the modern APIs.

  Summary:

  Subsystem:
   - new generic DT properties: aux-voltage-chargeable,
     trickle-voltage-millivolt

  New driver:
   - Microcrystal RV-3032

  Drivers:
   - ds1307: use aux-voltage-chargeable
   - r9701, rx8010: modernization of the driver
   - rv3028: fix clock output, trickle resistor values, RAM
     configuration registers"

* tag 'rtc-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (50 commits)
  rtc: r9701: set range
  rtc: r9701: convert to devm_rtc_allocate_device
  rtc: r9701: stop setting RWKCNT
  rtc: r9701: remove useless memset
  rtc: r9701: stop setting a default time
  rtc: r9701: remove leftover comment
  rtc: rv3032: Add a driver for Microcrystal RV-3032
  dt-bindings: rtc: rv3032: add RV-3032 bindings
  dt-bindings: rtc: add trickle-voltage-millivolt
  rtc: rv3028: ensure ram configuration registers are saved
  rtc: rv3028: factorize EERD bit handling
  rtc: rv3028: fix trickle resistor values
  rtc: rv3028: fix clock output support
  rtc: mt6397: Remove unused member dev
  rtc: rv8803: simplify the return expression of rv8803_nvram_write
  rtc: meson: simplify the return expression of meson_vrtc_probe
  rtc: rx8010: rename rx8010_init_client() to rx8010_init()
  rtc: ds1307: enable rx8130's backup battery, make it chargeable optionally
  rtc: ds1307: consider aux-voltage-chargeable
  rtc: ds1307: store previous charge default per chip
  ...
parents 68a36336 35331b50
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/microcrystal,rv3032.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Microchip RV-3032 RTC Device Tree Bindings
allOf:
- $ref: "rtc.yaml#"
maintainers:
- Alexandre Belloni <alexandre.belloni@bootlin.com>
properties:
compatible:
const: microcrystal,rv3032
reg:
maxItems: 1
interrupts:
maxItems: 1
start-year: true
trickle-resistor-ohms:
enum:
- 1000
- 2000
- 7000
- 11000
trickle-voltage-millivolt:
enum:
- 1750
- 3000
- 4400
required:
- compatible
- reg
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
rtc@51 {
compatible = "microcrystal,rv3032";
reg = <0x51>;
status = "okay";
pinctrl-0 = <&rtc_nint_pins>;
interrupts-extended = <&gpio1 16 IRQ_TYPE_LEVEL_HIGH>;
trickle-resistor-ohms = <7000>;
trickle-voltage-millivolt = <1750>;
};
};
...
...@@ -31,9 +31,16 @@ Optional properties: ...@@ -31,9 +31,16 @@ Optional properties:
Selected resistor for trickle charger Selected resistor for trickle charger
Possible values are 250, 2000, 4000 Possible values are 250, 2000, 4000
Should be given if trickle charger should be enabled Should be given if trickle charger should be enabled
- trickle-diode-disable : ds1339, ds1340 and ds 1388 only - aux-voltage-chargeable: ds1339, ds1340, ds1388 and rx8130 only
Tells whether the battery/supercap of the RTC (if any) is
chargeable or not.
Possible values are 0 (not chargeable), 1 (chargeable)
Deprecated properties:
- trickle-diode-disable : ds1339, ds1340 and ds1388 only
Do not use internal trickle charger diode Do not use internal trickle charger diode
Should be given if internal trickle charger diode should be disabled Should be given if internal trickle charger diode should be disabled
(superseded by aux-voltage-chargeable)
Example: Example:
ds1339: rtc@68 { ds1339: rtc@68 {
......
...@@ -17,6 +17,15 @@ properties: ...@@ -17,6 +17,15 @@ properties:
$nodename: $nodename:
pattern: "^rtc(@.*|-[0-9a-f])*$" pattern: "^rtc(@.*|-[0-9a-f])*$"
aux-voltage-chargeable:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1]
description: |
Tells whether the battery/supercap of the RTC (if any) is
chargeable or not:
0: not chargeable
1: chargeable
quartz-load-femtofarads: quartz-load-femtofarads:
$ref: /schemas/types.yaml#/definitions/uint32 $ref: /schemas/types.yaml#/definitions/uint32
description: description:
...@@ -35,6 +44,7 @@ properties: ...@@ -35,6 +44,7 @@ properties:
description: description:
Do not use internal trickle charger diode. Should be given if Do not use internal trickle charger diode. Should be given if
internal trickle charger diode should be disabled. internal trickle charger diode should be disabled.
deprecated: true
trickle-resistor-ohms: trickle-resistor-ohms:
$ref: /schemas/types.yaml#/definitions/uint32 $ref: /schemas/types.yaml#/definitions/uint32
...@@ -42,6 +52,12 @@ properties: ...@@ -42,6 +52,12 @@ properties:
Selected resistor for trickle charger. Should be given Selected resistor for trickle charger. Should be given
if trickle charger should be enabled. if trickle charger should be enabled.
trickle-voltage-millivolt:
description:
Selected voltage for trickle charger. Should be given
if trickle charger should be enabled and the trickle voltage is different
from the RTC main power supply.
wakeup-source: wakeup-source:
$ref: /schemas/types.yaml#/definitions/flag $ref: /schemas/types.yaml#/definitions/flag
description: description:
......
...@@ -669,6 +669,16 @@ config RTC_DRV_RV3028 ...@@ -669,6 +669,16 @@ config RTC_DRV_RV3028
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-rv3028. will be called rtc-rv3028.
config RTC_DRV_RV3032
tristate "Micro Crystal RV3032"
select REGMAP_I2C
help
If you say yes here you get support for the Micro Crystal
RV3032.
This driver can also be built as a module. If so, the module
will be called rtc-rv3032.
config RTC_DRV_RV8803 config RTC_DRV_RV8803
tristate "Micro Crystal RV8803, Epson RX8900" tristate "Micro Crystal RV8803, Epson RX8900"
help help
......
...@@ -141,6 +141,7 @@ obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o ...@@ -141,6 +141,7 @@ obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
obj-$(CONFIG_RTC_DRV_RTD119X) += rtc-rtd119x.o obj-$(CONFIG_RTC_DRV_RTD119X) += rtc-rtd119x.o
obj-$(CONFIG_RTC_DRV_RV3028) += rtc-rv3028.o obj-$(CONFIG_RTC_DRV_RV3028) += rtc-rv3028.o
obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o
obj-$(CONFIG_RTC_DRV_RV3032) += rtc-rv3032.o
obj-$(CONFIG_RTC_DRV_RV8803) += rtc-rv8803.o obj-$(CONFIG_RTC_DRV_RV8803) += rtc-rv8803.o
obj-$(CONFIG_RTC_DRV_RX4581) += rtc-rx4581.o obj-$(CONFIG_RTC_DRV_RX4581) += rtc-rx4581.o
obj-$(CONFIG_RTC_DRV_RX6110) += rtc-rx6110.o obj-$(CONFIG_RTC_DRV_RX6110) += rtc-rx6110.o
......
...@@ -1006,6 +1006,7 @@ static int cmos_suspend(struct device *dev) ...@@ -1006,6 +1006,7 @@ static int cmos_suspend(struct device *dev)
enable_irq_wake(cmos->irq); enable_irq_wake(cmos->irq);
} }
memset(&cmos->saved_wkalrm, 0, sizeof(struct rtc_wkalrm));
cmos_read_alarm(dev, &cmos->saved_wkalrm); cmos_read_alarm(dev, &cmos->saved_wkalrm);
dev_dbg(dev, "suspend%s, ctrl %02x\n", dev_dbg(dev, "suspend%s, ctrl %02x\n",
...@@ -1054,6 +1055,7 @@ static void cmos_check_wkalrm(struct device *dev) ...@@ -1054,6 +1055,7 @@ static void cmos_check_wkalrm(struct device *dev)
return; return;
} }
memset(&current_alarm, 0, sizeof(struct rtc_wkalrm));
cmos_read_alarm(dev, &current_alarm); cmos_read_alarm(dev, &current_alarm);
t_current_expires = rtc_tm_to_time64(&current_alarm.time); t_current_expires = rtc_tm_to_time64(&current_alarm.time);
t_saved_expires = rtc_tm_to_time64(&cmos->saved_wkalrm.time); t_saved_expires = rtc_tm_to_time64(&cmos->saved_wkalrm.time);
......
...@@ -122,6 +122,9 @@ enum ds_type { ...@@ -122,6 +122,9 @@ enum ds_type {
#define RX8130_REG_FLAG_AF BIT(3) #define RX8130_REG_FLAG_AF BIT(3)
#define RX8130_REG_CONTROL0 0x1e #define RX8130_REG_CONTROL0 0x1e
#define RX8130_REG_CONTROL0_AIE BIT(3) #define RX8130_REG_CONTROL0_AIE BIT(3)
#define RX8130_REG_CONTROL1 0x1f
#define RX8130_REG_CONTROL1_INIEN BIT(4)
#define RX8130_REG_CONTROL1_CHGEN BIT(5)
#define MCP794XX_REG_CONTROL 0x07 #define MCP794XX_REG_CONTROL 0x07
# define MCP794XX_BIT_ALM0_EN 0x10 # define MCP794XX_BIT_ALM0_EN 0x10
...@@ -153,6 +156,7 @@ enum ds_type { ...@@ -153,6 +156,7 @@ enum ds_type {
#define DS1388_REG_CONTROL 0x0c #define DS1388_REG_CONTROL 0x0c
# define DS1388_BIT_RST BIT(0) # define DS1388_BIT_RST BIT(0)
# define DS1388_BIT_WDE BIT(1) # define DS1388_BIT_WDE BIT(1)
# define DS1388_BIT_nEOSC BIT(7)
/* negative offset step is -2.034ppm */ /* negative offset step is -2.034ppm */
#define M41TXX_NEG_OFFSET_STEP_PPB 2034 #define M41TXX_NEG_OFFSET_STEP_PPB 2034
...@@ -190,6 +194,15 @@ struct chip_desc { ...@@ -190,6 +194,15 @@ struct chip_desc {
u16 trickle_charger_reg; u16 trickle_charger_reg;
u8 (*do_trickle_setup)(struct ds1307 *, u32, u8 (*do_trickle_setup)(struct ds1307 *, u32,
bool); bool);
/* Does the RTC require trickle-resistor-ohms to select the value of
* the resistor between Vcc and Vbackup?
*/
bool requires_trickle_resistor;
/* Some RTC's batteries and supercaps were charged by default, others
* allow charging but were not configured previously to do so.
* Remember this behavior to stay backwards compatible.
*/
bool charge_default;
}; };
static const struct chip_desc chips[last_ds_type]; static const struct chip_desc chips[last_ds_type];
...@@ -352,6 +365,10 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) ...@@ -352,6 +365,10 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t)
regmap_update_bits(ds1307->regmap, DS1340_REG_FLAG, regmap_update_bits(ds1307->regmap, DS1340_REG_FLAG,
DS1340_BIT_OSF, 0); DS1340_BIT_OSF, 0);
break; break;
case ds_1388:
regmap_update_bits(ds1307->regmap, DS1388_REG_FLAG,
DS1388_BIT_OSF, 0);
break;
case mcp794xx: case mcp794xx:
/* /*
* these bits were cleared when preparing the date/time * these bits were cleared when preparing the date/time
...@@ -507,6 +524,8 @@ static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode) ...@@ -507,6 +524,8 @@ static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode)
u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE : u8 setup = (diode) ? DS1307_TRICKLE_CHARGER_DIODE :
DS1307_TRICKLE_CHARGER_NO_DIODE; DS1307_TRICKLE_CHARGER_NO_DIODE;
setup |= DS13XX_TRICKLE_CHARGER_MAGIC;
switch (ohms) { switch (ohms) {
case 250: case 250:
setup |= DS1307_TRICKLE_CHARGER_250_OHM; setup |= DS1307_TRICKLE_CHARGER_250_OHM;
...@@ -525,6 +544,16 @@ static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode) ...@@ -525,6 +544,16 @@ static u8 do_trickle_setup_ds1339(struct ds1307 *ds1307, u32 ohms, bool diode)
return setup; return setup;
} }
static u8 do_trickle_setup_rx8130(struct ds1307 *ds1307, u32 ohms, bool diode)
{
/* make sure that the backup battery is enabled */
u8 setup = RX8130_REG_CONTROL1_INIEN;
if (diode)
setup |= RX8130_REG_CONTROL1_CHGEN;
return setup;
}
static irqreturn_t rx8130_irq(int irq, void *dev_id) static irqreturn_t rx8130_irq(int irq, void *dev_id)
{ {
struct ds1307 *ds1307 = dev_id; struct ds1307 *ds1307 = dev_id;
...@@ -979,6 +1008,8 @@ static const struct chip_desc chips[last_ds_type] = { ...@@ -979,6 +1008,8 @@ static const struct chip_desc chips[last_ds_type] = {
.bbsqi_bit = DS1339_BIT_BBSQI, .bbsqi_bit = DS1339_BIT_BBSQI,
.trickle_charger_reg = 0x10, .trickle_charger_reg = 0x10,
.do_trickle_setup = &do_trickle_setup_ds1339, .do_trickle_setup = &do_trickle_setup_ds1339,
.requires_trickle_resistor = true,
.charge_default = true,
}, },
[ds_1340] = { [ds_1340] = {
.century_reg = DS1307_REG_HOUR, .century_reg = DS1307_REG_HOUR,
...@@ -986,6 +1017,8 @@ static const struct chip_desc chips[last_ds_type] = { ...@@ -986,6 +1017,8 @@ static const struct chip_desc chips[last_ds_type] = {
.century_bit = DS1340_BIT_CENTURY, .century_bit = DS1340_BIT_CENTURY,
.do_trickle_setup = &do_trickle_setup_ds1339, .do_trickle_setup = &do_trickle_setup_ds1339,
.trickle_charger_reg = 0x08, .trickle_charger_reg = 0x08,
.requires_trickle_resistor = true,
.charge_default = true,
}, },
[ds_1341] = { [ds_1341] = {
.century_reg = DS1307_REG_MONTH, .century_reg = DS1307_REG_MONTH,
...@@ -1009,6 +1042,8 @@ static const struct chip_desc chips[last_ds_type] = { ...@@ -1009,6 +1042,8 @@ static const struct chip_desc chips[last_ds_type] = {
.offset = 0x10, .offset = 0x10,
.irq_handler = rx8130_irq, .irq_handler = rx8130_irq,
.rtc_ops = &rx8130_rtc_ops, .rtc_ops = &rx8130_rtc_ops,
.trickle_charger_reg = RX8130_REG_CONTROL1,
.do_trickle_setup = &do_trickle_setup_rx8130,
}, },
[m41t0] = { [m41t0] = {
.rtc_ops = &m41txx_rtc_ops, .rtc_ops = &m41txx_rtc_ops,
...@@ -1293,18 +1328,37 @@ static int ds1307_nvram_write(void *priv, unsigned int offset, void *val, ...@@ -1293,18 +1328,37 @@ static int ds1307_nvram_write(void *priv, unsigned int offset, void *val,
static u8 ds1307_trickle_init(struct ds1307 *ds1307, static u8 ds1307_trickle_init(struct ds1307 *ds1307,
const struct chip_desc *chip) const struct chip_desc *chip)
{ {
u32 ohms; u32 ohms, chargeable;
bool diode = true; bool diode = chip->charge_default;
if (!chip->do_trickle_setup) if (!chip->do_trickle_setup)
return 0; return 0;
if (device_property_read_u32(ds1307->dev, "trickle-resistor-ohms", if (device_property_read_u32(ds1307->dev, "trickle-resistor-ohms",
&ohms)) &ohms) && chip->requires_trickle_resistor)
return 0; return 0;
if (device_property_read_bool(ds1307->dev, "trickle-diode-disable")) /* aux-voltage-chargeable takes precedence over the deprecated
* trickle-diode-disable
*/
if (!device_property_read_u32(ds1307->dev, "aux-voltage-chargeable",
&chargeable)) {
switch (chargeable) {
case 0:
diode = false;
break;
case 1:
diode = true;
break;
default:
dev_warn(ds1307->dev,
"unsupported aux-voltage-chargeable value\n");
break;
}
} else if (device_property_read_bool(ds1307->dev,
"trickle-diode-disable")) {
diode = false; diode = false;
}
return chip->do_trickle_setup(ds1307, ohms, diode); return chip->do_trickle_setup(ds1307, ohms, diode);
} }
...@@ -1758,7 +1812,6 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -1758,7 +1812,6 @@ static int ds1307_probe(struct i2c_client *client,
trickle_charger_setup = pdata->trickle_charger_setup; trickle_charger_setup = pdata->trickle_charger_setup;
if (trickle_charger_setup && chip->trickle_charger_reg) { if (trickle_charger_setup && chip->trickle_charger_reg) {
trickle_charger_setup |= DS13XX_TRICKLE_CHARGER_MAGIC;
dev_dbg(ds1307->dev, dev_dbg(ds1307->dev,
"writing trickle charger info 0x%x to 0x%x\n", "writing trickle charger info 0x%x to 0x%x\n",
trickle_charger_setup, chip->trickle_charger_reg); trickle_charger_setup, chip->trickle_charger_reg);
...@@ -1881,6 +1934,19 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -1881,6 +1934,19 @@ static int ds1307_probe(struct i2c_client *client,
DS1307_REG_HOUR << 4 | 0x08, hour); DS1307_REG_HOUR << 4 | 0x08, hour);
} }
break; break;
case ds_1388:
err = regmap_read(ds1307->regmap, DS1388_REG_CONTROL, &tmp);
if (err) {
dev_dbg(ds1307->dev, "read error %d\n", err);
goto exit;
}
/* oscillator off? turn it on, so clock can tick. */
if (tmp & DS1388_BIT_nEOSC) {
tmp &= ~DS1388_BIT_nEOSC;
regmap_write(ds1307->regmap, DS1388_REG_CONTROL, tmp);
}
break;
default: default:
break; break;
} }
......
...@@ -193,12 +193,12 @@ ds1685_rtc_begin_data_access(struct ds1685_priv *rtc) ...@@ -193,12 +193,12 @@ ds1685_rtc_begin_data_access(struct ds1685_priv *rtc)
rtc->write(rtc, RTC_CTRL_B, rtc->write(rtc, RTC_CTRL_B,
(rtc->read(rtc, RTC_CTRL_B) | RTC_CTRL_B_SET)); (rtc->read(rtc, RTC_CTRL_B) | RTC_CTRL_B_SET));
/* Switch to Bank 1 */
ds1685_rtc_switch_to_bank1(rtc);
/* Read Ext Ctrl 4A and check the INCR bit to avoid a lockout. */ /* Read Ext Ctrl 4A and check the INCR bit to avoid a lockout. */
while (rtc->read(rtc, RTC_EXT_CTRL_4A) & RTC_CTRL_4A_INCR) while (rtc->read(rtc, RTC_EXT_CTRL_4A) & RTC_CTRL_4A_INCR)
cpu_relax(); cpu_relax();
/* Switch to Bank 1 */
ds1685_rtc_switch_to_bank1(rtc);
} }
/** /**
...@@ -213,7 +213,7 @@ static inline void ...@@ -213,7 +213,7 @@ static inline void
ds1685_rtc_end_data_access(struct ds1685_priv *rtc) ds1685_rtc_end_data_access(struct ds1685_priv *rtc)
{ {
/* Switch back to Bank 0 */ /* Switch back to Bank 0 */
ds1685_rtc_switch_to_bank1(rtc); ds1685_rtc_switch_to_bank0(rtc);
/* Clear the SET bit in Ctrl B */ /* Clear the SET bit in Ctrl B */
rtc->write(rtc, RTC_CTRL_B, rtc->write(rtc, RTC_CTRL_B,
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* Freescale FlexTimer Module (FTM) alarm device driver. * Freescale FlexTimer Module (FTM) alarm device driver.
* *
* Copyright 2014 Freescale Semiconductor, Inc. * Copyright 2014 Freescale Semiconductor, Inc.
* Copyright 2019 NXP * Copyright 2019-2020 NXP
* *
*/ */
...@@ -312,7 +312,7 @@ static const struct of_device_id ftm_rtc_match[] = { ...@@ -312,7 +312,7 @@ static const struct of_device_id ftm_rtc_match[] = {
}; };
static const struct acpi_device_id ftm_imx_acpi_ids[] = { static const struct acpi_device_id ftm_imx_acpi_ids[] = {
{"NXP0011",}, {"NXP0014",},
{ } { }
}; };
MODULE_DEVICE_TABLE(acpi, ftm_imx_acpi_ids); MODULE_DEVICE_TABLE(acpi, ftm_imx_acpi_ids);
......
...@@ -65,7 +65,6 @@ static const struct rtc_class_ops meson_vrtc_ops = { ...@@ -65,7 +65,6 @@ static const struct rtc_class_ops meson_vrtc_ops = {
static int meson_vrtc_probe(struct platform_device *pdev) static int meson_vrtc_probe(struct platform_device *pdev)
{ {
struct meson_vrtc_data *vrtc; struct meson_vrtc_data *vrtc;
int ret;
vrtc = devm_kzalloc(&pdev->dev, sizeof(*vrtc), GFP_KERNEL); vrtc = devm_kzalloc(&pdev->dev, sizeof(*vrtc), GFP_KERNEL);
if (!vrtc) if (!vrtc)
...@@ -84,11 +83,7 @@ static int meson_vrtc_probe(struct platform_device *pdev) ...@@ -84,11 +83,7 @@ static int meson_vrtc_probe(struct platform_device *pdev)
return PTR_ERR(vrtc->rtc); return PTR_ERR(vrtc->rtc);
vrtc->rtc->ops = &meson_vrtc_ops; vrtc->rtc->ops = &meson_vrtc_ops;
ret = rtc_register_device(vrtc->rtc); return rtc_register_device(vrtc->rtc);
if (ret)
return ret;
return 0;
} }
static int __maybe_unused meson_vrtc_suspend(struct device *dev) static int __maybe_unused meson_vrtc_suspend(struct device *dev)
......
...@@ -31,7 +31,8 @@ static int mtk_rtc_write_trigger(struct mt6397_rtc *rtc) ...@@ -31,7 +31,8 @@ static int mtk_rtc_write_trigger(struct mt6397_rtc *rtc)
MTK_RTC_POLL_DELAY_US, MTK_RTC_POLL_DELAY_US,
MTK_RTC_POLL_TIMEOUT); MTK_RTC_POLL_TIMEOUT);
if (ret < 0) if (ret < 0)
dev_err(rtc->dev, "failed to write WRTGE: %d\n", ret); dev_err(rtc->rtc_dev->dev.parent,
"failed to write WRTGR: %d\n", ret);
return ret; return ret;
} }
......
...@@ -559,7 +559,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, ...@@ -559,7 +559,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
pcf2127->rtc->set_start_time = true; /* Sets actual start to 1970 */ pcf2127->rtc->set_start_time = true; /* Sets actual start to 1970 */
pcf2127->rtc->uie_unsupported = 1; pcf2127->rtc->uie_unsupported = 1;
if (alarm_irq >= 0) { if (alarm_irq > 0) {
ret = devm_request_threaded_irq(dev, alarm_irq, NULL, ret = devm_request_threaded_irq(dev, alarm_irq, NULL,
pcf2127_rtc_irq, pcf2127_rtc_irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
...@@ -570,7 +570,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, ...@@ -570,7 +570,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap,
} }
} }
if (alarm_irq >= 0 || device_property_read_bool(dev, "wakeup-source")) { if (alarm_irq > 0 || device_property_read_bool(dev, "wakeup-source")) {
device_init_wakeup(dev, true); device_init_wakeup(dev, true);
pcf2127->rtc->ops = &pcf2127_rtc_alrm_ops; pcf2127->rtc->ops = &pcf2127_rtc_alrm_ops;
} }
......
...@@ -75,8 +75,6 @@ static int r9701_get_datetime(struct device *dev, struct rtc_time *dt) ...@@ -75,8 +75,6 @@ static int r9701_get_datetime(struct device *dev, struct rtc_time *dt)
if (ret) if (ret)
return ret; return ret;
memset(dt, 0, sizeof(*dt));
dt->tm_sec = bcd2bin(buf[0]); /* RSECCNT */ dt->tm_sec = bcd2bin(buf[0]); /* RSECCNT */
dt->tm_min = bcd2bin(buf[1]); /* RMINCNT */ dt->tm_min = bcd2bin(buf[1]); /* RMINCNT */
dt->tm_hour = bcd2bin(buf[2]); /* RHRCNT */ dt->tm_hour = bcd2bin(buf[2]); /* RHRCNT */
...@@ -85,20 +83,12 @@ static int r9701_get_datetime(struct device *dev, struct rtc_time *dt) ...@@ -85,20 +83,12 @@ static int r9701_get_datetime(struct device *dev, struct rtc_time *dt)
dt->tm_mon = bcd2bin(buf[4]) - 1; /* RMONCNT */ dt->tm_mon = bcd2bin(buf[4]) - 1; /* RMONCNT */
dt->tm_year = bcd2bin(buf[5]) + 100; /* RYRCNT */ dt->tm_year = bcd2bin(buf[5]) + 100; /* RYRCNT */
/* the rtc device may contain illegal values on power up
* according to the data sheet. make sure they are valid.
*/
return 0; return 0;
} }
static int r9701_set_datetime(struct device *dev, struct rtc_time *dt) static int r9701_set_datetime(struct device *dev, struct rtc_time *dt)
{ {
int ret, year; int ret;
year = dt->tm_year + 1900;
if (year >= 2100 || year < 2000)
return -EINVAL;
ret = write_reg(dev, RHRCNT, bin2bcd(dt->tm_hour)); ret = write_reg(dev, RHRCNT, bin2bcd(dt->tm_hour));
ret = ret ? ret : write_reg(dev, RMINCNT, bin2bcd(dt->tm_min)); ret = ret ? ret : write_reg(dev, RMINCNT, bin2bcd(dt->tm_min));
...@@ -106,7 +96,6 @@ static int r9701_set_datetime(struct device *dev, struct rtc_time *dt) ...@@ -106,7 +96,6 @@ static int r9701_set_datetime(struct device *dev, struct rtc_time *dt)
ret = ret ? ret : write_reg(dev, RDAYCNT, bin2bcd(dt->tm_mday)); ret = ret ? ret : write_reg(dev, RDAYCNT, bin2bcd(dt->tm_mday));
ret = ret ? ret : write_reg(dev, RMONCNT, bin2bcd(dt->tm_mon + 1)); ret = ret ? ret : write_reg(dev, RMONCNT, bin2bcd(dt->tm_mon + 1));
ret = ret ? ret : write_reg(dev, RYRCNT, bin2bcd(dt->tm_year - 100)); ret = ret ? ret : write_reg(dev, RYRCNT, bin2bcd(dt->tm_year - 100));
ret = ret ? ret : write_reg(dev, RWKCNT, 1 << dt->tm_wday);
return ret; return ret;
} }
...@@ -119,7 +108,6 @@ static const struct rtc_class_ops r9701_rtc_ops = { ...@@ -119,7 +108,6 @@ static const struct rtc_class_ops r9701_rtc_ops = {
static int r9701_probe(struct spi_device *spi) static int r9701_probe(struct spi_device *spi)
{ {
struct rtc_device *rtc; struct rtc_device *rtc;
struct rtc_time dt;
unsigned char tmp; unsigned char tmp;
int res; int res;
...@@ -130,35 +118,16 @@ static int r9701_probe(struct spi_device *spi) ...@@ -130,35 +118,16 @@ static int r9701_probe(struct spi_device *spi)
return -ENODEV; return -ENODEV;
} }
/* rtc = devm_rtc_allocate_device(&spi->dev);
* The device seems to be present. Now check if the registers
* contain invalid values. If so, try to write a default date:
* 2000/1/1 00:00:00
*/
if (r9701_get_datetime(&spi->dev, &dt)) {
dev_info(&spi->dev, "trying to repair invalid date/time\n");
dt.tm_sec = 0;
dt.tm_min = 0;
dt.tm_hour = 0;
dt.tm_mday = 1;
dt.tm_mon = 0;
dt.tm_year = 100;
if (r9701_set_datetime(&spi->dev, &dt) ||
r9701_get_datetime(&spi->dev, &dt)) {
dev_err(&spi->dev, "cannot repair RTC register\n");
return -ENODEV;
}
}
rtc = devm_rtc_device_register(&spi->dev, "r9701",
&r9701_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc)) if (IS_ERR(rtc))
return PTR_ERR(rtc); return PTR_ERR(rtc);
spi_set_drvdata(spi, rtc); spi_set_drvdata(spi, rtc);
rtc->ops = &r9701_rtc_ops;
rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rtc->range_max = RTC_TIMESTAMP_END_2099;
return 0; return rtc_register_device(rtc);
} }
static struct spi_driver r9701_driver = { static struct spi_driver r9701_driver = {
......
...@@ -366,15 +366,15 @@ static const struct rtc_class_ops rs5c313_rtc_ops = { ...@@ -366,15 +366,15 @@ static const struct rtc_class_ops rs5c313_rtc_ops = {
static int rs5c313_rtc_probe(struct platform_device *pdev) static int rs5c313_rtc_probe(struct platform_device *pdev)
{ {
struct rtc_device *rtc = devm_rtc_device_register(&pdev->dev, "rs5c313", struct rtc_device *rtc;
&rs5c313_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc)) rs5c313_init_port();
return PTR_ERR(rtc); rs5c313_check_xstp_bit();
platform_set_drvdata(pdev, rtc); rtc = devm_rtc_device_register(&pdev->dev, "rs5c313", &rs5c313_rtc_ops,
THIS_MODULE);
return 0; return PTR_ERR_OR_ZERO(rtc);
} }
static struct platform_driver rs5c313_rtc_platform_driver = { static struct platform_driver rs5c313_rtc_platform_driver = {
...@@ -384,27 +384,7 @@ static struct platform_driver rs5c313_rtc_platform_driver = { ...@@ -384,27 +384,7 @@ static struct platform_driver rs5c313_rtc_platform_driver = {
.probe = rs5c313_rtc_probe, .probe = rs5c313_rtc_probe,
}; };
static int __init rs5c313_rtc_init(void) module_platform_driver(rs5c313_rtc_platform_driver);
{
int err;
err = platform_driver_register(&rs5c313_rtc_platform_driver);
if (err)
return err;
rs5c313_init_port();
rs5c313_check_xstp_bit();
return 0;
}
static void __exit rs5c313_rtc_exit(void)
{
platform_driver_unregister(&rs5c313_rtc_platform_driver);
}
module_init(rs5c313_rtc_init);
module_exit(rs5c313_rtc_exit);
MODULE_AUTHOR("kogiidena , Nobuhiro Iwamatsu <iwamatsu@nigauri.org>"); MODULE_AUTHOR("kogiidena , Nobuhiro Iwamatsu <iwamatsu@nigauri.org>");
MODULE_DESCRIPTION("Ricoh RS5C313 RTC device driver"); MODULE_DESCRIPTION("Ricoh RS5C313 RTC device driver");
......
...@@ -71,6 +71,7 @@ ...@@ -71,6 +71,7 @@
#define RV3028_EVT_CTRL_TSR BIT(2) #define RV3028_EVT_CTRL_TSR BIT(2)
#define RV3028_EEPROM_CMD_UPDATE 0x11
#define RV3028_EEPROM_CMD_WRITE 0x21 #define RV3028_EEPROM_CMD_WRITE 0x21
#define RV3028_EEPROM_CMD_READ 0x22 #define RV3028_EEPROM_CMD_READ 0x22
...@@ -95,7 +96,7 @@ struct rv3028_data { ...@@ -95,7 +96,7 @@ struct rv3028_data {
#endif #endif
}; };
static u16 rv3028_trickle_resistors[] = {1000, 3000, 6000, 11000}; static u16 rv3028_trickle_resistors[] = {3000, 5000, 9000, 15000};
static ssize_t timestamp0_store(struct device *dev, static ssize_t timestamp0_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
...@@ -171,6 +172,88 @@ static const struct attribute_group rv3028_attr_group = { ...@@ -171,6 +172,88 @@ static const struct attribute_group rv3028_attr_group = {
.attrs = rv3028_attrs, .attrs = rv3028_attrs,
}; };
static int rv3028_exit_eerd(struct rv3028_data *rv3028, u32 eerd)
{
if (eerd)
return 0;
return regmap_update_bits(rv3028->regmap, RV3028_CTRL1, RV3028_CTRL1_EERD, 0);
}
static int rv3028_enter_eerd(struct rv3028_data *rv3028, u32 *eerd)
{
u32 ctrl1, status;
int ret;
ret = regmap_read(rv3028->regmap, RV3028_CTRL1, &ctrl1);
if (ret)
return ret;
*eerd = ctrl1 & RV3028_CTRL1_EERD;
if (*eerd)
return 0;
ret = regmap_update_bits(rv3028->regmap, RV3028_CTRL1,
RV3028_CTRL1_EERD, RV3028_CTRL1_EERD);
if (ret)
return ret;
ret = regmap_read_poll_timeout(rv3028->regmap, RV3028_STATUS, status,
!(status & RV3028_STATUS_EEBUSY),
RV3028_EEBUSY_POLL, RV3028_EEBUSY_TIMEOUT);
if (ret) {
rv3028_exit_eerd(rv3028, *eerd);
return ret;
}
return 0;
}
static int rv3028_update_eeprom(struct rv3028_data *rv3028, u32 eerd)
{
u32 status;
int ret;
ret = regmap_write(rv3028->regmap, RV3028_EEPROM_CMD, 0x0);
if (ret)
goto exit_eerd;
ret = regmap_write(rv3028->regmap, RV3028_EEPROM_CMD, RV3028_EEPROM_CMD_UPDATE);
if (ret)
goto exit_eerd;
usleep_range(63000, RV3028_EEBUSY_TIMEOUT);
ret = regmap_read_poll_timeout(rv3028->regmap, RV3028_STATUS, status,
!(status & RV3028_STATUS_EEBUSY),
RV3028_EEBUSY_POLL, RV3028_EEBUSY_TIMEOUT);
exit_eerd:
rv3028_exit_eerd(rv3028, eerd);
return ret;
}
static int rv3028_update_cfg(struct rv3028_data *rv3028, unsigned int reg,
unsigned int mask, unsigned int val)
{
u32 eerd;
int ret;
ret = rv3028_enter_eerd(rv3028, &eerd);
if (ret)
return ret;
ret = regmap_update_bits(rv3028->regmap, reg, mask, val);
if (ret) {
rv3028_exit_eerd(rv3028, eerd);
return ret;
}
return rv3028_update_eeprom(rv3028, eerd);
}
static irqreturn_t rv3028_handle_irq(int irq, void *dev_id) static irqreturn_t rv3028_handle_irq(int irq, void *dev_id)
{ {
struct rv3028_data *rv3028 = dev_id; struct rv3028_data *rv3028 = dev_id;
...@@ -404,17 +487,32 @@ static int rv3028_read_offset(struct device *dev, long *offset) ...@@ -404,17 +487,32 @@ static int rv3028_read_offset(struct device *dev, long *offset)
static int rv3028_set_offset(struct device *dev, long offset) static int rv3028_set_offset(struct device *dev, long offset)
{ {
struct rv3028_data *rv3028 = dev_get_drvdata(dev); struct rv3028_data *rv3028 = dev_get_drvdata(dev);
u32 eerd;
int ret; int ret;
offset = clamp(offset, -244141L, 243187L) * 1000; offset = clamp(offset, -244141L, 243187L) * 1000;
offset = DIV_ROUND_CLOSEST(offset, OFFSET_STEP_PPT); offset = DIV_ROUND_CLOSEST(offset, OFFSET_STEP_PPT);
ret = rv3028_enter_eerd(rv3028, &eerd);
if (ret)
return ret;
ret = regmap_write(rv3028->regmap, RV3028_OFFSET, offset >> 1); ret = regmap_write(rv3028->regmap, RV3028_OFFSET, offset >> 1);
if (ret < 0) if (ret < 0)
return ret; goto exit_eerd;
return regmap_update_bits(rv3028->regmap, RV3028_BACKUP, BIT(7), ret = regmap_update_bits(rv3028->regmap, RV3028_BACKUP, BIT(7),
offset << 7); offset << 7);
if (ret < 0)
goto exit_eerd;
return rv3028_update_eeprom(rv3028, eerd);
exit_eerd:
rv3028_exit_eerd(rv3028, eerd);
return ret;
} }
static int rv3028_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) static int rv3028_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
...@@ -451,49 +549,36 @@ static int rv3028_nvram_read(void *priv, unsigned int offset, void *val, ...@@ -451,49 +549,36 @@ static int rv3028_nvram_read(void *priv, unsigned int offset, void *val,
static int rv3028_eeprom_write(void *priv, unsigned int offset, void *val, static int rv3028_eeprom_write(void *priv, unsigned int offset, void *val,
size_t bytes) size_t bytes)
{ {
u32 status, ctrl1; struct rv3028_data *rv3028 = priv;
int i, ret, err; u32 status, eerd;
int i, ret;
u8 *buf = val; u8 *buf = val;
ret = regmap_read(priv, RV3028_CTRL1, &ctrl1); ret = rv3028_enter_eerd(rv3028, &eerd);
if (ret)
return ret;
if (!(ctrl1 & RV3028_CTRL1_EERD)) {
ret = regmap_update_bits(priv, RV3028_CTRL1,
RV3028_CTRL1_EERD, RV3028_CTRL1_EERD);
if (ret) if (ret)
return ret; return ret;
ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
!(status & RV3028_STATUS_EEBUSY),
RV3028_EEBUSY_POLL,
RV3028_EEBUSY_TIMEOUT);
if (ret)
goto restore_eerd;
}
for (i = 0; i < bytes; i++) { for (i = 0; i < bytes; i++) {
ret = regmap_write(priv, RV3028_EEPROM_ADDR, offset + i); ret = regmap_write(rv3028->regmap, RV3028_EEPROM_ADDR, offset + i);
if (ret) if (ret)
goto restore_eerd; goto restore_eerd;
ret = regmap_write(priv, RV3028_EEPROM_DATA, buf[i]); ret = regmap_write(rv3028->regmap, RV3028_EEPROM_DATA, buf[i]);
if (ret) if (ret)
goto restore_eerd; goto restore_eerd;
ret = regmap_write(priv, RV3028_EEPROM_CMD, 0x0); ret = regmap_write(rv3028->regmap, RV3028_EEPROM_CMD, 0x0);
if (ret) if (ret)
goto restore_eerd; goto restore_eerd;
ret = regmap_write(priv, RV3028_EEPROM_CMD, ret = regmap_write(rv3028->regmap, RV3028_EEPROM_CMD,
RV3028_EEPROM_CMD_WRITE); RV3028_EEPROM_CMD_WRITE);
if (ret) if (ret)
goto restore_eerd; goto restore_eerd;
usleep_range(RV3028_EEBUSY_POLL, RV3028_EEBUSY_TIMEOUT); usleep_range(RV3028_EEBUSY_POLL, RV3028_EEBUSY_TIMEOUT);
ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status, ret = regmap_read_poll_timeout(rv3028->regmap, RV3028_STATUS, status,
!(status & RV3028_STATUS_EEBUSY), !(status & RV3028_STATUS_EEBUSY),
RV3028_EEBUSY_POLL, RV3028_EEBUSY_POLL,
RV3028_EEBUSY_TIMEOUT); RV3028_EEBUSY_TIMEOUT);
...@@ -502,13 +587,7 @@ static int rv3028_eeprom_write(void *priv, unsigned int offset, void *val, ...@@ -502,13 +587,7 @@ static int rv3028_eeprom_write(void *priv, unsigned int offset, void *val,
} }
restore_eerd: restore_eerd:
if (!(ctrl1 & RV3028_CTRL1_EERD)) rv3028_exit_eerd(rv3028, eerd);
{
err = regmap_update_bits(priv, RV3028_CTRL1, RV3028_CTRL1_EERD,
0);
if (err && !ret)
ret = err;
}
return ret; return ret;
} }
...@@ -516,63 +595,44 @@ static int rv3028_eeprom_write(void *priv, unsigned int offset, void *val, ...@@ -516,63 +595,44 @@ static int rv3028_eeprom_write(void *priv, unsigned int offset, void *val,
static int rv3028_eeprom_read(void *priv, unsigned int offset, void *val, static int rv3028_eeprom_read(void *priv, unsigned int offset, void *val,
size_t bytes) size_t bytes)
{ {
u32 status, ctrl1, data; struct rv3028_data *rv3028 = priv;
int i, ret, err; u32 status, eerd, data;
int i, ret;
u8 *buf = val; u8 *buf = val;
ret = regmap_read(priv, RV3028_CTRL1, &ctrl1); ret = rv3028_enter_eerd(rv3028, &eerd);
if (ret)
return ret;
if (!(ctrl1 & RV3028_CTRL1_EERD)) {
ret = regmap_update_bits(priv, RV3028_CTRL1,
RV3028_CTRL1_EERD, RV3028_CTRL1_EERD);
if (ret) if (ret)
return ret; return ret;
ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status,
!(status & RV3028_STATUS_EEBUSY),
RV3028_EEBUSY_POLL,
RV3028_EEBUSY_TIMEOUT);
if (ret)
goto restore_eerd;
}
for (i = 0; i < bytes; i++) { for (i = 0; i < bytes; i++) {
ret = regmap_write(priv, RV3028_EEPROM_ADDR, offset + i); ret = regmap_write(rv3028->regmap, RV3028_EEPROM_ADDR, offset + i);
if (ret) if (ret)
goto restore_eerd; goto restore_eerd;
ret = regmap_write(priv, RV3028_EEPROM_CMD, 0x0); ret = regmap_write(rv3028->regmap, RV3028_EEPROM_CMD, 0x0);
if (ret) if (ret)
goto restore_eerd; goto restore_eerd;
ret = regmap_write(priv, RV3028_EEPROM_CMD, ret = regmap_write(rv3028->regmap, RV3028_EEPROM_CMD,
RV3028_EEPROM_CMD_READ); RV3028_EEPROM_CMD_READ);
if (ret) if (ret)
goto restore_eerd; goto restore_eerd;
ret = regmap_read_poll_timeout(priv, RV3028_STATUS, status, ret = regmap_read_poll_timeout(rv3028->regmap, RV3028_STATUS, status,
!(status & RV3028_STATUS_EEBUSY), !(status & RV3028_STATUS_EEBUSY),
RV3028_EEBUSY_POLL, RV3028_EEBUSY_POLL,
RV3028_EEBUSY_TIMEOUT); RV3028_EEBUSY_TIMEOUT);
if (ret) if (ret)
goto restore_eerd; goto restore_eerd;
ret = regmap_read(priv, RV3028_EEPROM_DATA, &data); ret = regmap_read(rv3028->regmap, RV3028_EEPROM_DATA, &data);
if (ret) if (ret)
goto restore_eerd; goto restore_eerd;
buf[i] = data; buf[i] = data;
} }
restore_eerd: restore_eerd:
if (!(ctrl1 & RV3028_CTRL1_EERD)) rv3028_exit_eerd(rv3028, eerd);
{
err = regmap_update_bits(priv, RV3028_CTRL1, RV3028_CTRL1_EERD,
0);
if (err && !ret)
ret = err;
}
return ret; return ret;
} }
...@@ -619,24 +679,23 @@ static int rv3028_clkout_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -619,24 +679,23 @@ static int rv3028_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate) unsigned long parent_rate)
{ {
int i, ret; int i, ret;
u32 enabled;
struct rv3028_data *rv3028 = clkout_hw_to_rv3028(hw); struct rv3028_data *rv3028 = clkout_hw_to_rv3028(hw);
ret = regmap_write(rv3028->regmap, RV3028_CLKOUT, 0x0); ret = regmap_read(rv3028->regmap, RV3028_CLKOUT, &enabled);
if (ret < 0) if (ret < 0)
return ret; return ret;
for (i = 0; i < ARRAY_SIZE(clkout_rates); i++) { ret = regmap_write(rv3028->regmap, RV3028_CLKOUT, 0x0);
if (clkout_rates[i] == rate) {
ret = regmap_update_bits(rv3028->regmap,
RV3028_CLKOUT,
RV3028_CLKOUT_FD_MASK, i);
if (ret < 0) if (ret < 0)
return ret; return ret;
return regmap_write(rv3028->regmap, RV3028_CLKOUT, enabled &= RV3028_CLKOUT_CLKOE;
RV3028_CLKOUT_CLKSY | RV3028_CLKOUT_CLKOE);
} for (i = 0; i < ARRAY_SIZE(clkout_rates); i++)
} if (clkout_rates[i] == rate)
return rv3028_update_cfg(rv3028, RV3028_CLKOUT, 0xff,
RV3028_CLKOUT_CLKSY | enabled | i);
return -EINVAL; return -EINVAL;
} }
...@@ -811,10 +870,8 @@ static int rv3028_probe(struct i2c_client *client) ...@@ -811,10 +870,8 @@ static int rv3028_probe(struct i2c_client *client)
break; break;
if (i < ARRAY_SIZE(rv3028_trickle_resistors)) { if (i < ARRAY_SIZE(rv3028_trickle_resistors)) {
ret = regmap_update_bits(rv3028->regmap, RV3028_BACKUP, ret = rv3028_update_cfg(rv3028, RV3028_BACKUP, RV3028_BACKUP_TCE |
RV3028_BACKUP_TCE | RV3028_BACKUP_TCR_MASK, RV3028_BACKUP_TCE | i);
RV3028_BACKUP_TCR_MASK,
RV3028_BACKUP_TCE | i);
if (ret) if (ret)
return ret; return ret;
} else { } else {
...@@ -835,7 +892,7 @@ static int rv3028_probe(struct i2c_client *client) ...@@ -835,7 +892,7 @@ static int rv3028_probe(struct i2c_client *client)
nvmem_cfg.priv = rv3028->regmap; nvmem_cfg.priv = rv3028->regmap;
rtc_nvmem_register(rv3028->rtc, &nvmem_cfg); rtc_nvmem_register(rv3028->rtc, &nvmem_cfg);
eeprom_cfg.priv = rv3028->regmap; eeprom_cfg.priv = rv3028;
rtc_nvmem_register(rv3028->rtc, &eeprom_cfg); rtc_nvmem_register(rv3028->rtc, &eeprom_cfg);
rv3028->rtc->max_user_freq = 1; rv3028->rtc->max_user_freq = 1;
......
// SPDX-License-Identifier: GPL-2.0
/*
* RTC driver for the Micro Crystal RV3032
*
* Copyright (C) 2020 Micro Crystal SA
*
* Alexandre Belloni <alexandre.belloni@bootlin.com>
*
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/bcd.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/hwmon.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/log2.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/regmap.h>
#include <linux/rtc.h>
#define RV3032_SEC 0x01
#define RV3032_MIN 0x02
#define RV3032_HOUR 0x03
#define RV3032_WDAY 0x04
#define RV3032_DAY 0x05
#define RV3032_MONTH 0x06
#define RV3032_YEAR 0x07
#define RV3032_ALARM_MIN 0x08
#define RV3032_ALARM_HOUR 0x09
#define RV3032_ALARM_DAY 0x0A
#define RV3032_STATUS 0x0D
#define RV3032_TLSB 0x0E
#define RV3032_TMSB 0x0F
#define RV3032_CTRL1 0x10
#define RV3032_CTRL2 0x11
#define RV3032_CTRL3 0x12
#define RV3032_TS_CTRL 0x13
#define RV3032_CLK_IRQ 0x14
#define RV3032_EEPROM_ADDR 0x3D
#define RV3032_EEPROM_DATA 0x3E
#define RV3032_EEPROM_CMD 0x3F
#define RV3032_RAM1 0x40
#define RV3032_PMU 0xC0
#define RV3032_OFFSET 0xC1
#define RV3032_CLKOUT1 0xC2
#define RV3032_CLKOUT2 0xC3
#define RV3032_TREF0 0xC4
#define RV3032_TREF1 0xC5
#define RV3032_STATUS_VLF BIT(0)
#define RV3032_STATUS_PORF BIT(1)
#define RV3032_STATUS_EVF BIT(2)
#define RV3032_STATUS_AF BIT(3)
#define RV3032_STATUS_TF BIT(4)
#define RV3032_STATUS_UF BIT(5)
#define RV3032_STATUS_TLF BIT(6)
#define RV3032_STATUS_THF BIT(7)
#define RV3032_TLSB_CLKF BIT(1)
#define RV3032_TLSB_EEBUSY BIT(2)
#define RV3032_TLSB_TEMP GENMASK(7, 4)
#define RV3032_CLKOUT2_HFD_MSK GENMASK(4, 0)
#define RV3032_CLKOUT2_FD_MSK GENMASK(6, 5)
#define RV3032_CLKOUT2_OS BIT(7)
#define RV3032_CTRL1_EERD BIT(3)
#define RV3032_CTRL1_WADA BIT(5)
#define RV3032_CTRL2_STOP BIT(0)
#define RV3032_CTRL2_EIE BIT(2)
#define RV3032_CTRL2_AIE BIT(3)
#define RV3032_CTRL2_TIE BIT(4)
#define RV3032_CTRL2_UIE BIT(5)
#define RV3032_CTRL2_CLKIE BIT(6)
#define RV3032_CTRL2_TSE BIT(7)
#define RV3032_PMU_TCM GENMASK(1, 0)
#define RV3032_PMU_TCR GENMASK(3, 2)
#define RV3032_PMU_BSM GENMASK(5, 4)
#define RV3032_PMU_NCLKE BIT(6)
#define RV3032_PMU_BSM_DSM 1
#define RV3032_PMU_BSM_LSM 2
#define RV3032_OFFSET_MSK GENMASK(5, 0)
#define RV3032_EVT_CTRL_TSR BIT(2)
#define RV3032_EEPROM_CMD_UPDATE 0x11
#define RV3032_EEPROM_CMD_WRITE 0x21
#define RV3032_EEPROM_CMD_READ 0x22
#define RV3032_EEPROM_USER 0xCB
#define RV3032_EEBUSY_POLL 10000
#define RV3032_EEBUSY_TIMEOUT 100000
#define OFFSET_STEP_PPT 238419
struct rv3032_data {
struct regmap *regmap;
struct rtc_device *rtc;
#ifdef CONFIG_COMMON_CLK
struct clk_hw clkout_hw;
#endif
};
static u16 rv3032_trickle_resistors[] = {1000, 2000, 7000, 11000};
static u16 rv3032_trickle_voltages[] = {0, 1750, 3000, 4400};
static int rv3032_exit_eerd(struct rv3032_data *rv3032, u32 eerd)
{
if (eerd)
return 0;
return regmap_update_bits(rv3032->regmap, RV3032_CTRL1, RV3032_CTRL1_EERD, 0);
}
static int rv3032_enter_eerd(struct rv3032_data *rv3032, u32 *eerd)
{
u32 ctrl1, status;
int ret;
ret = regmap_read(rv3032->regmap, RV3032_CTRL1, &ctrl1);
if (ret)
return ret;
*eerd = ctrl1 & RV3032_CTRL1_EERD;
if (*eerd)
return 0;
ret = regmap_update_bits(rv3032->regmap, RV3032_CTRL1,
RV3032_CTRL1_EERD, RV3032_CTRL1_EERD);
if (ret)
return ret;
ret = regmap_read_poll_timeout(rv3032->regmap, RV3032_TLSB, status,
!(status & RV3032_TLSB_EEBUSY),
RV3032_EEBUSY_POLL, RV3032_EEBUSY_TIMEOUT);
if (ret) {
rv3032_exit_eerd(rv3032, *eerd);
return ret;
}
return 0;
}
static int rv3032_update_cfg(struct rv3032_data *rv3032, unsigned int reg,
unsigned int mask, unsigned int val)
{
u32 status, eerd;
int ret;
ret = rv3032_enter_eerd(rv3032, &eerd);
if (ret)
return ret;
ret = regmap_update_bits(rv3032->regmap, reg, mask, val);
if (ret)
goto exit_eerd;
ret = regmap_write(rv3032->regmap, RV3032_EEPROM_CMD, RV3032_EEPROM_CMD_UPDATE);
if (ret)
goto exit_eerd;
usleep_range(46000, RV3032_EEBUSY_TIMEOUT);
ret = regmap_read_poll_timeout(rv3032->regmap, RV3032_TLSB, status,
!(status & RV3032_TLSB_EEBUSY),
RV3032_EEBUSY_POLL, RV3032_EEBUSY_TIMEOUT);
exit_eerd:
rv3032_exit_eerd(rv3032, eerd);
return ret;
}
static irqreturn_t rv3032_handle_irq(int irq, void *dev_id)
{
struct rv3032_data *rv3032 = dev_id;
unsigned long events = 0;
u32 status = 0, ctrl = 0;
if (regmap_read(rv3032->regmap, RV3032_STATUS, &status) < 0 ||
status == 0) {
return IRQ_NONE;
}
if (status & RV3032_STATUS_TF) {
status |= RV3032_STATUS_TF;
ctrl |= RV3032_CTRL2_TIE;
events |= RTC_PF;
}
if (status & RV3032_STATUS_AF) {
status |= RV3032_STATUS_AF;
ctrl |= RV3032_CTRL2_AIE;
events |= RTC_AF;
}
if (status & RV3032_STATUS_UF) {
status |= RV3032_STATUS_UF;
ctrl |= RV3032_CTRL2_UIE;
events |= RTC_UF;
}
if (events) {
rtc_update_irq(rv3032->rtc, 1, events);
regmap_update_bits(rv3032->regmap, RV3032_STATUS, status, 0);
regmap_update_bits(rv3032->regmap, RV3032_CTRL2, ctrl, 0);
}
return IRQ_HANDLED;
}
static int rv3032_get_time(struct device *dev, struct rtc_time *tm)
{
struct rv3032_data *rv3032 = dev_get_drvdata(dev);
u8 date[7];
int ret, status;
ret = regmap_read(rv3032->regmap, RV3032_STATUS, &status);
if (ret < 0)
return ret;
if (status & (RV3032_STATUS_PORF | RV3032_STATUS_VLF))
return -EINVAL;
ret = regmap_bulk_read(rv3032->regmap, RV3032_SEC, date, sizeof(date));
if (ret)
return ret;
tm->tm_sec = bcd2bin(date[0] & 0x7f);
tm->tm_min = bcd2bin(date[1] & 0x7f);
tm->tm_hour = bcd2bin(date[2] & 0x3f);
tm->tm_wday = date[3] & 0x7;
tm->tm_mday = bcd2bin(date[4] & 0x3f);
tm->tm_mon = bcd2bin(date[5] & 0x1f) - 1;
tm->tm_year = bcd2bin(date[6]) + 100;
return 0;
}
static int rv3032_set_time(struct device *dev, struct rtc_time *tm)
{
struct rv3032_data *rv3032 = dev_get_drvdata(dev);
u8 date[7];
int ret;
date[0] = bin2bcd(tm->tm_sec);
date[1] = bin2bcd(tm->tm_min);
date[2] = bin2bcd(tm->tm_hour);
date[3] = tm->tm_wday;
date[4] = bin2bcd(tm->tm_mday);
date[5] = bin2bcd(tm->tm_mon + 1);
date[6] = bin2bcd(tm->tm_year - 100);
ret = regmap_bulk_write(rv3032->regmap, RV3032_SEC, date,
sizeof(date));
if (ret)
return ret;
ret = regmap_update_bits(rv3032->regmap, RV3032_STATUS,
RV3032_STATUS_PORF | RV3032_STATUS_VLF, 0);
return ret;
}
static int rv3032_get_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct rv3032_data *rv3032 = dev_get_drvdata(dev);
u8 alarmvals[3];
int status, ctrl, ret;
ret = regmap_bulk_read(rv3032->regmap, RV3032_ALARM_MIN, alarmvals,
sizeof(alarmvals));
if (ret)
return ret;
ret = regmap_read(rv3032->regmap, RV3032_STATUS, &status);
if (ret < 0)
return ret;
ret = regmap_read(rv3032->regmap, RV3032_CTRL2, &ctrl);
if (ret < 0)
return ret;
alrm->time.tm_sec = 0;
alrm->time.tm_min = bcd2bin(alarmvals[0] & 0x7f);
alrm->time.tm_hour = bcd2bin(alarmvals[1] & 0x3f);
alrm->time.tm_mday = bcd2bin(alarmvals[2] & 0x3f);
alrm->enabled = !!(ctrl & RV3032_CTRL2_AIE);
alrm->pending = (status & RV3032_STATUS_AF) && alrm->enabled;
return 0;
}
static int rv3032_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct rv3032_data *rv3032 = dev_get_drvdata(dev);
u8 alarmvals[3];
u8 ctrl = 0;
int ret;
/* The alarm has no seconds, round up to nearest minute */
if (alrm->time.tm_sec) {
time64_t alarm_time = rtc_tm_to_time64(&alrm->time);
alarm_time += 60 - alrm->time.tm_sec;
rtc_time64_to_tm(alarm_time, &alrm->time);
}
ret = regmap_update_bits(rv3032->regmap, RV3032_CTRL2,
RV3032_CTRL2_AIE | RV3032_CTRL2_UIE, 0);
if (ret)
return ret;
alarmvals[0] = bin2bcd(alrm->time.tm_min);
alarmvals[1] = bin2bcd(alrm->time.tm_hour);
alarmvals[2] = bin2bcd(alrm->time.tm_mday);
ret = regmap_update_bits(rv3032->regmap, RV3032_STATUS,
RV3032_STATUS_AF, 0);
if (ret)
return ret;
ret = regmap_bulk_write(rv3032->regmap, RV3032_ALARM_MIN, alarmvals,
sizeof(alarmvals));
if (ret)
return ret;
if (alrm->enabled) {
if (rv3032->rtc->uie_rtctimer.enabled)
ctrl |= RV3032_CTRL2_UIE;
if (rv3032->rtc->aie_timer.enabled)
ctrl |= RV3032_CTRL2_AIE;
}
ret = regmap_update_bits(rv3032->regmap, RV3032_CTRL2,
RV3032_CTRL2_UIE | RV3032_CTRL2_AIE, ctrl);
return ret;
}
static int rv3032_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
struct rv3032_data *rv3032 = dev_get_drvdata(dev);
int ctrl = 0, ret;
if (enabled) {
if (rv3032->rtc->uie_rtctimer.enabled)
ctrl |= RV3032_CTRL2_UIE;
if (rv3032->rtc->aie_timer.enabled)
ctrl |= RV3032_CTRL2_AIE;
}
ret = regmap_update_bits(rv3032->regmap, RV3032_STATUS,
RV3032_STATUS_AF | RV3032_STATUS_UF, 0);
if (ret)
return ret;
ret = regmap_update_bits(rv3032->regmap, RV3032_CTRL2,
RV3032_CTRL2_UIE | RV3032_CTRL2_AIE, ctrl);
if (ret)
return ret;
return 0;
}
static int rv3032_read_offset(struct device *dev, long *offset)
{
struct rv3032_data *rv3032 = dev_get_drvdata(dev);
int ret, value, steps;
ret = regmap_read(rv3032->regmap, RV3032_OFFSET, &value);
if (ret < 0)
return ret;
steps = sign_extend32(FIELD_GET(RV3032_OFFSET_MSK, value), 5);
*offset = DIV_ROUND_CLOSEST(steps * OFFSET_STEP_PPT, 1000);
return 0;
}
static int rv3032_set_offset(struct device *dev, long offset)
{
struct rv3032_data *rv3032 = dev_get_drvdata(dev);
offset = clamp(offset, -7629L, 7391L) * 1000;
offset = DIV_ROUND_CLOSEST(offset, OFFSET_STEP_PPT);
return rv3032_update_cfg(rv3032, RV3032_OFFSET, RV3032_OFFSET_MSK,
FIELD_PREP(RV3032_OFFSET_MSK, offset));
}
static int rv3032_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
struct rv3032_data *rv3032 = dev_get_drvdata(dev);
int status, val = 0, ret = 0;
switch (cmd) {
case RTC_VL_READ:
ret = regmap_read(rv3032->regmap, RV3032_STATUS, &status);
if (ret < 0)
return ret;
if (status & (RV3032_STATUS_PORF | RV3032_STATUS_VLF))
val = RTC_VL_DATA_INVALID;
return put_user(val, (unsigned int __user *)arg);
default:
return -ENOIOCTLCMD;
}
}
static int rv3032_nvram_write(void *priv, unsigned int offset, void *val, size_t bytes)
{
return regmap_bulk_write(priv, RV3032_RAM1 + offset, val, bytes);
}
static int rv3032_nvram_read(void *priv, unsigned int offset, void *val, size_t bytes)
{
return regmap_bulk_read(priv, RV3032_RAM1 + offset, val, bytes);
}
static int rv3032_eeprom_write(void *priv, unsigned int offset, void *val, size_t bytes)
{
struct rv3032_data *rv3032 = priv;
u32 status, eerd;
int i, ret;
u8 *buf = val;
ret = rv3032_enter_eerd(rv3032, &eerd);
if (ret)
return ret;
for (i = 0; i < bytes; i++) {
ret = regmap_write(rv3032->regmap, RV3032_EEPROM_ADDR,
RV3032_EEPROM_USER + offset + i);
if (ret)
goto exit_eerd;
ret = regmap_write(rv3032->regmap, RV3032_EEPROM_DATA, buf[i]);
if (ret)
goto exit_eerd;
ret = regmap_write(rv3032->regmap, RV3032_EEPROM_CMD,
RV3032_EEPROM_CMD_WRITE);
if (ret)
goto exit_eerd;
usleep_range(RV3032_EEBUSY_POLL, RV3032_EEBUSY_TIMEOUT);
ret = regmap_read_poll_timeout(rv3032->regmap, RV3032_TLSB, status,
!(status & RV3032_TLSB_EEBUSY),
RV3032_EEBUSY_POLL, RV3032_EEBUSY_TIMEOUT);
if (ret)
goto exit_eerd;
}
exit_eerd:
rv3032_exit_eerd(rv3032, eerd);
return ret;
}
static int rv3032_eeprom_read(void *priv, unsigned int offset, void *val, size_t bytes)
{
struct rv3032_data *rv3032 = priv;
u32 status, eerd, data;
int i, ret;
u8 *buf = val;
ret = rv3032_enter_eerd(rv3032, &eerd);
if (ret)
return ret;
for (i = 0; i < bytes; i++) {
ret = regmap_write(rv3032->regmap, RV3032_EEPROM_ADDR,
RV3032_EEPROM_USER + offset + i);
if (ret)
goto exit_eerd;
ret = regmap_write(rv3032->regmap, RV3032_EEPROM_CMD,
RV3032_EEPROM_CMD_READ);
if (ret)
goto exit_eerd;
ret = regmap_read_poll_timeout(rv3032->regmap, RV3032_TLSB, status,
!(status & RV3032_TLSB_EEBUSY),
RV3032_EEBUSY_POLL, RV3032_EEBUSY_TIMEOUT);
if (ret)
goto exit_eerd;
ret = regmap_read(rv3032->regmap, RV3032_EEPROM_DATA, &data);
if (ret)
goto exit_eerd;
buf[i] = data;
}
exit_eerd:
rv3032_exit_eerd(rv3032, eerd);
return ret;
}
static int rv3032_trickle_charger_setup(struct device *dev, struct rv3032_data *rv3032)
{
u32 val, ohms, voltage;
int i;
val = FIELD_PREP(RV3032_PMU_TCM, 1) | FIELD_PREP(RV3032_PMU_BSM, RV3032_PMU_BSM_DSM);
if (!device_property_read_u32(dev, "trickle-voltage-millivolt", &voltage)) {
for (i = 0; i < ARRAY_SIZE(rv3032_trickle_voltages); i++)
if (voltage == rv3032_trickle_voltages[i])
break;
if (i < ARRAY_SIZE(rv3032_trickle_voltages))
val = FIELD_PREP(RV3032_PMU_TCM, i) |
FIELD_PREP(RV3032_PMU_BSM, RV3032_PMU_BSM_LSM);
}
if (device_property_read_u32(dev, "trickle-resistor-ohms", &ohms))
return 0;
for (i = 0; i < ARRAY_SIZE(rv3032_trickle_resistors); i++)
if (ohms == rv3032_trickle_resistors[i])
break;
if (i >= ARRAY_SIZE(rv3032_trickle_resistors)) {
dev_warn(dev, "invalid trickle resistor value\n");
return 0;
}
return rv3032_update_cfg(rv3032, RV3032_PMU,
RV3032_PMU_TCR | RV3032_PMU_TCM | RV3032_PMU_BSM,
val | FIELD_PREP(RV3032_PMU_TCR, i));
}
#ifdef CONFIG_COMMON_CLK
#define clkout_hw_to_rv3032(hw) container_of(hw, struct rv3032_data, clkout_hw)
static int clkout_xtal_rates[] = {
32768,
1024,
64,
1,
};
#define RV3032_HFD_STEP 8192
static unsigned long rv3032_clkout_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
int clkout, ret;
struct rv3032_data *rv3032 = clkout_hw_to_rv3032(hw);
ret = regmap_read(rv3032->regmap, RV3032_CLKOUT2, &clkout);
if (ret < 0)
return 0;
if (clkout & RV3032_CLKOUT2_OS) {
unsigned long rate = FIELD_GET(RV3032_CLKOUT2_HFD_MSK, clkout) << 8;
ret = regmap_read(rv3032->regmap, RV3032_CLKOUT1, &clkout);
if (ret < 0)
return 0;
rate += clkout + 1;
return rate * RV3032_HFD_STEP;
}
return clkout_xtal_rates[FIELD_GET(RV3032_CLKOUT2_FD_MSK, clkout)];
}
static long rv3032_clkout_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
int i, hfd;
if (rate < RV3032_HFD_STEP)
for (i = 0; i < ARRAY_SIZE(clkout_xtal_rates); i++)
if (clkout_xtal_rates[i] <= rate)
return clkout_xtal_rates[i];
hfd = DIV_ROUND_CLOSEST(rate, RV3032_HFD_STEP);
return RV3032_HFD_STEP * clamp(hfd, 0, 8192);
}
static int rv3032_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct rv3032_data *rv3032 = clkout_hw_to_rv3032(hw);
u32 status, eerd;
int i, hfd, ret;
for (i = 0; i < ARRAY_SIZE(clkout_xtal_rates); i++) {
if (clkout_xtal_rates[i] == rate) {
return rv3032_update_cfg(rv3032, RV3032_CLKOUT2, 0xff,
FIELD_PREP(RV3032_CLKOUT2_FD_MSK, i));
}
}
hfd = DIV_ROUND_CLOSEST(rate, RV3032_HFD_STEP);
hfd = clamp(hfd, 1, 8192) - 1;
ret = rv3032_enter_eerd(rv3032, &eerd);
if (ret)
goto exit_eerd;
ret = regmap_write(rv3032->regmap, RV3032_CLKOUT1, hfd & 0xff);
if (ret)
return ret;
ret = regmap_write(rv3032->regmap, RV3032_CLKOUT2, RV3032_CLKOUT2_OS |
FIELD_PREP(RV3032_CLKOUT2_HFD_MSK, hfd >> 8));
if (ret)
goto exit_eerd;
ret = regmap_write(rv3032->regmap, RV3032_EEPROM_CMD, RV3032_EEPROM_CMD_UPDATE);
if (ret)
goto exit_eerd;
usleep_range(46000, RV3032_EEBUSY_TIMEOUT);
ret = regmap_read_poll_timeout(rv3032->regmap, RV3032_TLSB, status,
!(status & RV3032_TLSB_EEBUSY),
RV3032_EEBUSY_POLL, RV3032_EEBUSY_TIMEOUT);
exit_eerd:
rv3032_exit_eerd(rv3032, eerd);
return ret;
}
static int rv3032_clkout_prepare(struct clk_hw *hw)
{
struct rv3032_data *rv3032 = clkout_hw_to_rv3032(hw);
return rv3032_update_cfg(rv3032, RV3032_PMU, RV3032_PMU_NCLKE, 0);
}
static void rv3032_clkout_unprepare(struct clk_hw *hw)
{
struct rv3032_data *rv3032 = clkout_hw_to_rv3032(hw);
rv3032_update_cfg(rv3032, RV3032_PMU, RV3032_PMU_NCLKE, RV3032_PMU_NCLKE);
}
static int rv3032_clkout_is_prepared(struct clk_hw *hw)
{
int val, ret;
struct rv3032_data *rv3032 = clkout_hw_to_rv3032(hw);
ret = regmap_read(rv3032->regmap, RV3032_PMU, &val);
if (ret < 0)
return ret;
return !(val & RV3032_PMU_NCLKE);
}
static const struct clk_ops rv3032_clkout_ops = {
.prepare = rv3032_clkout_prepare,
.unprepare = rv3032_clkout_unprepare,
.is_prepared = rv3032_clkout_is_prepared,
.recalc_rate = rv3032_clkout_recalc_rate,
.round_rate = rv3032_clkout_round_rate,
.set_rate = rv3032_clkout_set_rate,
};
static int rv3032_clkout_register_clk(struct rv3032_data *rv3032,
struct i2c_client *client)
{
int ret;
struct clk *clk;
struct clk_init_data init;
struct device_node *node = client->dev.of_node;
ret = regmap_update_bits(rv3032->regmap, RV3032_TLSB, RV3032_TLSB_CLKF, 0);
if (ret < 0)
return ret;
ret = regmap_update_bits(rv3032->regmap, RV3032_CTRL2, RV3032_CTRL2_CLKIE, 0);
if (ret < 0)
return ret;
ret = regmap_write(rv3032->regmap, RV3032_CLK_IRQ, 0);
if (ret < 0)
return ret;
init.name = "rv3032-clkout";
init.ops = &rv3032_clkout_ops;
init.flags = 0;
init.parent_names = NULL;
init.num_parents = 0;
rv3032->clkout_hw.init = &init;
of_property_read_string(node, "clock-output-names", &init.name);
clk = devm_clk_register(&client->dev, &rv3032->clkout_hw);
if (!IS_ERR(clk))
of_clk_add_provider(node, of_clk_src_simple_get, clk);
return 0;
}
#endif
static int rv3032_hwmon_read_temp(struct device *dev, long *mC)
{
struct rv3032_data *rv3032 = dev_get_drvdata(dev);
u8 buf[2];
int temp, prev = 0;
int ret;
ret = regmap_bulk_read(rv3032->regmap, RV3032_TLSB, buf, sizeof(buf));
if (ret)
return ret;
temp = sign_extend32(buf[1], 7) << 4;
temp |= FIELD_GET(RV3032_TLSB_TEMP, buf[0]);
/* No blocking or shadowing on RV3032_TLSB and RV3032_TMSB */
do {
prev = temp;
ret = regmap_bulk_read(rv3032->regmap, RV3032_TLSB, buf, sizeof(buf));
if (ret)
return ret;
temp = sign_extend32(buf[1], 7) << 4;
temp |= FIELD_GET(RV3032_TLSB_TEMP, buf[0]);
} while (temp != prev);
*mC = (temp * 1000) / 16;
return 0;
}
static umode_t rv3032_hwmon_is_visible(const void *data, enum hwmon_sensor_types type,
u32 attr, int channel)
{
if (type != hwmon_temp)
return 0;
switch (attr) {
case hwmon_temp_input:
return 0444;
default:
return 0;
}
}
static int rv3032_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *temp)
{
int err;
switch (attr) {
case hwmon_temp_input:
err = rv3032_hwmon_read_temp(dev, temp);
break;
default:
err = -EOPNOTSUPP;
break;
}
return err;
}
static const struct hwmon_channel_info *rv3032_hwmon_info[] = {
HWMON_CHANNEL_INFO(chip, HWMON_C_REGISTER_TZ),
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MAX_HYST),
NULL
};
static const struct hwmon_ops rv3032_hwmon_hwmon_ops = {
.is_visible = rv3032_hwmon_is_visible,
.read = rv3032_hwmon_read,
};
static const struct hwmon_chip_info rv3032_hwmon_chip_info = {
.ops = &rv3032_hwmon_hwmon_ops,
.info = rv3032_hwmon_info,
};
static void rv3032_hwmon_register(struct device *dev)
{
struct rv3032_data *rv3032 = dev_get_drvdata(dev);
if (!IS_REACHABLE(CONFIG_HWMON))
return;
devm_hwmon_device_register_with_info(dev, "rv3032", rv3032, &rv3032_hwmon_chip_info, NULL);
}
static struct rtc_class_ops rv3032_rtc_ops = {
.read_time = rv3032_get_time,
.set_time = rv3032_set_time,
.read_offset = rv3032_read_offset,
.set_offset = rv3032_set_offset,
.ioctl = rv3032_ioctl,
};
static const struct regmap_config regmap_config = {
.reg_bits = 8,
.val_bits = 8,
.max_register = 0xCA,
};
static int rv3032_probe(struct i2c_client *client)
{
struct rv3032_data *rv3032;
int ret, status;
struct nvmem_config nvmem_cfg = {
.name = "rv3032_nvram",
.word_size = 1,
.stride = 1,
.size = 16,
.type = NVMEM_TYPE_BATTERY_BACKED,
.reg_read = rv3032_nvram_read,
.reg_write = rv3032_nvram_write,
};
struct nvmem_config eeprom_cfg = {
.name = "rv3032_eeprom",
.word_size = 1,
.stride = 1,
.size = 32,
.type = NVMEM_TYPE_EEPROM,
.reg_read = rv3032_eeprom_read,
.reg_write = rv3032_eeprom_write,
};
rv3032 = devm_kzalloc(&client->dev, sizeof(struct rv3032_data),
GFP_KERNEL);
if (!rv3032)
return -ENOMEM;
rv3032->regmap = devm_regmap_init_i2c(client, &regmap_config);
if (IS_ERR(rv3032->regmap))
return PTR_ERR(rv3032->regmap);
i2c_set_clientdata(client, rv3032);
ret = regmap_read(rv3032->regmap, RV3032_STATUS, &status);
if (ret < 0)
return ret;
rv3032->rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(rv3032->rtc))
return PTR_ERR(rv3032->rtc);
if (client->irq > 0) {
ret = devm_request_threaded_irq(&client->dev, client->irq,
NULL, rv3032_handle_irq,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"rv3032", rv3032);
if (ret) {
dev_warn(&client->dev, "unable to request IRQ, alarms disabled\n");
client->irq = 0;
} else {
rv3032_rtc_ops.read_alarm = rv3032_get_alarm;
rv3032_rtc_ops.set_alarm = rv3032_set_alarm;
rv3032_rtc_ops.alarm_irq_enable = rv3032_alarm_irq_enable;
}
}
ret = regmap_update_bits(rv3032->regmap, RV3032_CTRL1,
RV3032_CTRL1_WADA, RV3032_CTRL1_WADA);
if (ret)
return ret;
rv3032_trickle_charger_setup(&client->dev, rv3032);
rv3032->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rv3032->rtc->range_max = RTC_TIMESTAMP_END_2099;
rv3032->rtc->ops = &rv3032_rtc_ops;
ret = rtc_register_device(rv3032->rtc);
if (ret)
return ret;
nvmem_cfg.priv = rv3032;
rtc_nvmem_register(rv3032->rtc, &nvmem_cfg);
eeprom_cfg.priv = rv3032;
rtc_nvmem_register(rv3032->rtc, &eeprom_cfg);
rv3032->rtc->max_user_freq = 1;
#ifdef CONFIG_COMMON_CLK
rv3032_clkout_register_clk(rv3032, client);
#endif
rv3032_hwmon_register(&client->dev);
return 0;
}
static const struct of_device_id rv3032_of_match[] = {
{ .compatible = "microcrystal,rv3032", },
{ }
};
MODULE_DEVICE_TABLE(of, rv3032_of_match);
static struct i2c_driver rv3032_driver = {
.driver = {
.name = "rtc-rv3032",
.of_match_table = of_match_ptr(rv3032_of_match),
},
.probe_new = rv3032_probe,
};
module_i2c_driver(rv3032_driver);
MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>");
MODULE_DESCRIPTION("Micro Crystal RV3032 RTC driver");
MODULE_LICENSE("GPL v2");
...@@ -454,13 +454,7 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) ...@@ -454,13 +454,7 @@ static int rv8803_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
static int rv8803_nvram_write(void *priv, unsigned int offset, void *val, static int rv8803_nvram_write(void *priv, unsigned int offset, void *val,
size_t bytes) size_t bytes)
{ {
int ret; return rv8803_write_reg(priv, RV8803_RAM, *(u8 *)val);
ret = rv8803_write_reg(priv, RV8803_RAM, *(u8 *)val);
if (ret)
return ret;
return 0;
} }
static int rv8803_nvram_read(void *priv, unsigned int offset, static int rv8803_nvram_read(void *priv, unsigned int offset,
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/regmap.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#define RX8010_SEC 0x10 #define RX8010_SEC 0x10
...@@ -61,7 +62,7 @@ static const struct of_device_id rx8010_of_match[] = { ...@@ -61,7 +62,7 @@ static const struct of_device_id rx8010_of_match[] = {
MODULE_DEVICE_TABLE(of, rx8010_of_match); MODULE_DEVICE_TABLE(of, rx8010_of_match);
struct rx8010_data { struct rx8010_data {
struct i2c_client *client; struct regmap *regs;
struct rtc_device *rtc; struct rtc_device *rtc;
u8 ctrlreg; u8 ctrlreg;
}; };
...@@ -70,13 +71,12 @@ static irqreturn_t rx8010_irq_1_handler(int irq, void *dev_id) ...@@ -70,13 +71,12 @@ static irqreturn_t rx8010_irq_1_handler(int irq, void *dev_id)
{ {
struct i2c_client *client = dev_id; struct i2c_client *client = dev_id;
struct rx8010_data *rx8010 = i2c_get_clientdata(client); struct rx8010_data *rx8010 = i2c_get_clientdata(client);
int flagreg; int flagreg, err;
mutex_lock(&rx8010->rtc->ops_lock); mutex_lock(&rx8010->rtc->ops_lock);
flagreg = i2c_smbus_read_byte_data(client, RX8010_FLAG); err = regmap_read(rx8010->regs, RX8010_FLAG, &flagreg);
if (err) {
if (flagreg <= 0) {
mutex_unlock(&rx8010->rtc->ops_lock); mutex_unlock(&rx8010->rtc->ops_lock);
return IRQ_NONE; return IRQ_NONE;
} }
...@@ -99,32 +99,29 @@ static irqreturn_t rx8010_irq_1_handler(int irq, void *dev_id) ...@@ -99,32 +99,29 @@ static irqreturn_t rx8010_irq_1_handler(int irq, void *dev_id)
rtc_update_irq(rx8010->rtc, 1, RTC_UF | RTC_IRQF); rtc_update_irq(rx8010->rtc, 1, RTC_UF | RTC_IRQF);
} }
i2c_smbus_write_byte_data(client, RX8010_FLAG, flagreg); err = regmap_write(rx8010->regs, RX8010_FLAG, flagreg);
mutex_unlock(&rx8010->rtc->ops_lock); mutex_unlock(&rx8010->rtc->ops_lock);
return IRQ_HANDLED; return err ? IRQ_NONE : IRQ_HANDLED;
} }
static int rx8010_get_time(struct device *dev, struct rtc_time *dt) static int rx8010_get_time(struct device *dev, struct rtc_time *dt)
{ {
struct rx8010_data *rx8010 = dev_get_drvdata(dev); struct rx8010_data *rx8010 = dev_get_drvdata(dev);
u8 date[7]; u8 date[RX8010_YEAR - RX8010_SEC + 1];
int flagreg; int flagreg, err;
int err;
flagreg = i2c_smbus_read_byte_data(rx8010->client, RX8010_FLAG); err = regmap_read(rx8010->regs, RX8010_FLAG, &flagreg);
if (flagreg < 0) if (err)
return flagreg; return err;
if (flagreg & RX8010_FLAG_VLF) { if (flagreg & RX8010_FLAG_VLF) {
dev_warn(dev, "Frequency stop detected\n"); dev_warn(dev, "Frequency stop detected\n");
return -EINVAL; return -EINVAL;
} }
err = i2c_smbus_read_i2c_block_data(rx8010->client, RX8010_SEC, err = regmap_bulk_read(rx8010->regs, RX8010_SEC, date, sizeof(date));
7, date); if (err)
if (err != 7) return err;
return err < 0 ? err : -EIO;
dt->tm_sec = bcd2bin(date[RX8010_SEC - RX8010_SEC] & 0x7f); dt->tm_sec = bcd2bin(date[RX8010_SEC - RX8010_SEC] & 0x7f);
dt->tm_min = bcd2bin(date[RX8010_MIN - RX8010_SEC] & 0x7f); dt->tm_min = bcd2bin(date[RX8010_MIN - RX8010_SEC] & 0x7f);
...@@ -140,22 +137,13 @@ static int rx8010_get_time(struct device *dev, struct rtc_time *dt) ...@@ -140,22 +137,13 @@ static int rx8010_get_time(struct device *dev, struct rtc_time *dt)
static int rx8010_set_time(struct device *dev, struct rtc_time *dt) static int rx8010_set_time(struct device *dev, struct rtc_time *dt)
{ {
struct rx8010_data *rx8010 = dev_get_drvdata(dev); struct rx8010_data *rx8010 = dev_get_drvdata(dev);
u8 date[7]; u8 date[RX8010_YEAR - RX8010_SEC + 1];
int ctrl, flagreg; int err;
int ret;
if ((dt->tm_year < 100) || (dt->tm_year > 199))
return -EINVAL;
/* set STOP bit before changing clock/calendar */ /* set STOP bit before changing clock/calendar */
ctrl = i2c_smbus_read_byte_data(rx8010->client, RX8010_CTRL); err = regmap_set_bits(rx8010->regs, RX8010_CTRL, RX8010_CTRL_STOP);
if (ctrl < 0) if (err)
return ctrl; return err;
rx8010->ctrlreg = ctrl | RX8010_CTRL_STOP;
ret = i2c_smbus_write_byte_data(rx8010->client, RX8010_CTRL,
rx8010->ctrlreg);
if (ret < 0)
return ret;
date[RX8010_SEC - RX8010_SEC] = bin2bcd(dt->tm_sec); date[RX8010_SEC - RX8010_SEC] = bin2bcd(dt->tm_sec);
date[RX8010_MIN - RX8010_SEC] = bin2bcd(dt->tm_min); date[RX8010_MIN - RX8010_SEC] = bin2bcd(dt->tm_min);
...@@ -165,66 +153,54 @@ static int rx8010_set_time(struct device *dev, struct rtc_time *dt) ...@@ -165,66 +153,54 @@ static int rx8010_set_time(struct device *dev, struct rtc_time *dt)
date[RX8010_YEAR - RX8010_SEC] = bin2bcd(dt->tm_year - 100); date[RX8010_YEAR - RX8010_SEC] = bin2bcd(dt->tm_year - 100);
date[RX8010_WDAY - RX8010_SEC] = bin2bcd(1 << dt->tm_wday); date[RX8010_WDAY - RX8010_SEC] = bin2bcd(1 << dt->tm_wday);
ret = i2c_smbus_write_i2c_block_data(rx8010->client, err = regmap_bulk_write(rx8010->regs, RX8010_SEC, date, sizeof(date));
RX8010_SEC, 7, date); if (err)
if (ret < 0) return err;
return ret;
/* clear STOP bit after changing clock/calendar */ /* clear STOP bit after changing clock/calendar */
ctrl = i2c_smbus_read_byte_data(rx8010->client, RX8010_CTRL); err = regmap_clear_bits(rx8010->regs, RX8010_CTRL, RX8010_CTRL_STOP);
if (ctrl < 0) if (err)
return ctrl; return err;
rx8010->ctrlreg = ctrl & ~RX8010_CTRL_STOP;
ret = i2c_smbus_write_byte_data(rx8010->client, RX8010_CTRL,
rx8010->ctrlreg);
if (ret < 0)
return ret;
flagreg = i2c_smbus_read_byte_data(rx8010->client, RX8010_FLAG);
if (flagreg < 0) {
return flagreg;
}
if (flagreg & RX8010_FLAG_VLF) err = regmap_clear_bits(rx8010->regs, RX8010_FLAG, RX8010_FLAG_VLF);
ret = i2c_smbus_write_byte_data(rx8010->client, RX8010_FLAG, if (err)
flagreg & ~RX8010_FLAG_VLF); return err;
return 0; return 0;
} }
static int rx8010_init_client(struct i2c_client *client) static int rx8010_init(struct device *dev)
{ {
struct rx8010_data *rx8010 = i2c_get_clientdata(client); struct rx8010_data *rx8010 = dev_get_drvdata(dev);
u8 ctrl[2]; u8 ctrl[2];
int need_clear = 0, err = 0; int need_clear = 0, err;
/* Initialize reserved registers as specified in datasheet */ /* Initialize reserved registers as specified in datasheet */
err = i2c_smbus_write_byte_data(client, RX8010_RESV17, 0xD8); err = regmap_write(rx8010->regs, RX8010_RESV17, 0xD8);
if (err < 0) if (err)
return err; return err;
err = i2c_smbus_write_byte_data(client, RX8010_RESV30, 0x00); err = regmap_write(rx8010->regs, RX8010_RESV30, 0x00);
if (err < 0) if (err)
return err; return err;
err = i2c_smbus_write_byte_data(client, RX8010_RESV31, 0x08); err = regmap_write(rx8010->regs, RX8010_RESV31, 0x08);
if (err < 0) if (err)
return err; return err;
err = i2c_smbus_write_byte_data(client, RX8010_IRQ, 0x00); err = regmap_write(rx8010->regs, RX8010_IRQ, 0x00);
if (err < 0) if (err)
return err; return err;
err = i2c_smbus_read_i2c_block_data(rx8010->client, RX8010_FLAG, err = regmap_bulk_read(rx8010->regs, RX8010_FLAG, ctrl, 2);
2, ctrl); if (err)
if (err != 2) return err;
return err < 0 ? err : -EIO;
if (ctrl[0] & RX8010_FLAG_VLF) if (ctrl[0] & RX8010_FLAG_VLF)
dev_warn(&client->dev, "Frequency stop was detected\n"); dev_warn(dev, "Frequency stop was detected\n");
if (ctrl[0] & RX8010_FLAG_AF) { if (ctrl[0] & RX8010_FLAG_AF) {
dev_warn(&client->dev, "Alarm was detected\n"); dev_warn(dev, "Alarm was detected\n");
need_clear = 1; need_clear = 1;
} }
...@@ -236,8 +212,8 @@ static int rx8010_init_client(struct i2c_client *client) ...@@ -236,8 +212,8 @@ static int rx8010_init_client(struct i2c_client *client)
if (need_clear) { if (need_clear) {
ctrl[0] &= ~(RX8010_FLAG_AF | RX8010_FLAG_TF | RX8010_FLAG_UF); ctrl[0] &= ~(RX8010_FLAG_AF | RX8010_FLAG_TF | RX8010_FLAG_UF);
err = i2c_smbus_write_byte_data(client, RX8010_FLAG, ctrl[0]); err = regmap_write(rx8010->regs, RX8010_FLAG, ctrl[0]);
if (err < 0) if (err)
return err; return err;
} }
...@@ -249,18 +225,16 @@ static int rx8010_init_client(struct i2c_client *client) ...@@ -249,18 +225,16 @@ static int rx8010_init_client(struct i2c_client *client)
static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t) static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t)
{ {
struct rx8010_data *rx8010 = dev_get_drvdata(dev); struct rx8010_data *rx8010 = dev_get_drvdata(dev);
struct i2c_client *client = rx8010->client;
u8 alarmvals[3]; u8 alarmvals[3];
int flagreg; int flagreg, err;
int err;
err = i2c_smbus_read_i2c_block_data(client, RX8010_ALMIN, 3, alarmvals); err = regmap_bulk_read(rx8010->regs, RX8010_ALMIN, alarmvals, 3);
if (err != 3) if (err)
return err < 0 ? err : -EIO; return err;
flagreg = i2c_smbus_read_byte_data(client, RX8010_FLAG); err = regmap_read(rx8010->regs, RX8010_FLAG, &flagreg);
if (flagreg < 0) if (err)
return flagreg; return err;
t->time.tm_sec = 0; t->time.tm_sec = 0;
t->time.tm_min = bcd2bin(alarmvals[0] & 0x7f); t->time.tm_min = bcd2bin(alarmvals[0] & 0x7f);
...@@ -277,55 +251,38 @@ static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t) ...@@ -277,55 +251,38 @@ static int rx8010_read_alarm(struct device *dev, struct rtc_wkalrm *t)
static int rx8010_set_alarm(struct device *dev, struct rtc_wkalrm *t) static int rx8010_set_alarm(struct device *dev, struct rtc_wkalrm *t)
{ {
struct i2c_client *client = to_i2c_client(dev);
struct rx8010_data *rx8010 = dev_get_drvdata(dev); struct rx8010_data *rx8010 = dev_get_drvdata(dev);
u8 alarmvals[3]; u8 alarmvals[3];
int extreg, flagreg;
int err; int err;
flagreg = i2c_smbus_read_byte_data(client, RX8010_FLAG);
if (flagreg < 0) {
return flagreg;
}
if (rx8010->ctrlreg & (RX8010_CTRL_AIE | RX8010_CTRL_UIE)) { if (rx8010->ctrlreg & (RX8010_CTRL_AIE | RX8010_CTRL_UIE)) {
rx8010->ctrlreg &= ~(RX8010_CTRL_AIE | RX8010_CTRL_UIE); rx8010->ctrlreg &= ~(RX8010_CTRL_AIE | RX8010_CTRL_UIE);
err = i2c_smbus_write_byte_data(rx8010->client, RX8010_CTRL, err = regmap_write(rx8010->regs, RX8010_CTRL, rx8010->ctrlreg);
rx8010->ctrlreg); if (err)
if (err < 0) {
return err; return err;
} }
}
flagreg &= ~RX8010_FLAG_AF; err = regmap_clear_bits(rx8010->regs, RX8010_FLAG, RX8010_FLAG_AF);
err = i2c_smbus_write_byte_data(rx8010->client, RX8010_FLAG, flagreg); if (err)
if (err < 0)
return err; return err;
alarmvals[0] = bin2bcd(t->time.tm_min); alarmvals[0] = bin2bcd(t->time.tm_min);
alarmvals[1] = bin2bcd(t->time.tm_hour); alarmvals[1] = bin2bcd(t->time.tm_hour);
alarmvals[2] = bin2bcd(t->time.tm_mday); alarmvals[2] = bin2bcd(t->time.tm_mday);
err = i2c_smbus_write_i2c_block_data(rx8010->client, RX8010_ALMIN, err = regmap_bulk_write(rx8010->regs, RX8010_ALMIN, alarmvals, 2);
2, alarmvals); if (err)
if (err < 0)
return err; return err;
extreg = i2c_smbus_read_byte_data(client, RX8010_EXT); err = regmap_clear_bits(rx8010->regs, RX8010_EXT, RX8010_EXT_WADA);
if (extreg < 0) if (err)
return extreg;
extreg |= RX8010_EXT_WADA;
err = i2c_smbus_write_byte_data(rx8010->client, RX8010_EXT, extreg);
if (err < 0)
return err; return err;
if (alarmvals[2] == 0) if (alarmvals[2] == 0)
alarmvals[2] |= RX8010_ALARM_AE; alarmvals[2] |= RX8010_ALARM_AE;
err = i2c_smbus_write_byte_data(rx8010->client, RX8010_ALWDAY, err = regmap_write(rx8010->regs, RX8010_ALWDAY, alarmvals[2]);
alarmvals[2]); if (err)
if (err < 0)
return err; return err;
if (t->enabled) { if (t->enabled) {
...@@ -335,9 +292,8 @@ static int rx8010_set_alarm(struct device *dev, struct rtc_wkalrm *t) ...@@ -335,9 +292,8 @@ static int rx8010_set_alarm(struct device *dev, struct rtc_wkalrm *t)
rx8010->ctrlreg |= rx8010->ctrlreg |=
(RX8010_CTRL_AIE | RX8010_CTRL_UIE); (RX8010_CTRL_AIE | RX8010_CTRL_UIE);
err = i2c_smbus_write_byte_data(rx8010->client, RX8010_CTRL, err = regmap_write(rx8010->regs, RX8010_CTRL, rx8010->ctrlreg);
rx8010->ctrlreg); if (err)
if (err < 0)
return err; return err;
} }
...@@ -347,11 +303,9 @@ static int rx8010_set_alarm(struct device *dev, struct rtc_wkalrm *t) ...@@ -347,11 +303,9 @@ static int rx8010_set_alarm(struct device *dev, struct rtc_wkalrm *t)
static int rx8010_alarm_irq_enable(struct device *dev, static int rx8010_alarm_irq_enable(struct device *dev,
unsigned int enabled) unsigned int enabled)
{ {
struct i2c_client *client = to_i2c_client(dev);
struct rx8010_data *rx8010 = dev_get_drvdata(dev); struct rx8010_data *rx8010 = dev_get_drvdata(dev);
int flagreg;
u8 ctrl;
int err; int err;
u8 ctrl;
ctrl = rx8010->ctrlreg; ctrl = rx8010->ctrlreg;
...@@ -367,20 +321,14 @@ static int rx8010_alarm_irq_enable(struct device *dev, ...@@ -367,20 +321,14 @@ static int rx8010_alarm_irq_enable(struct device *dev,
ctrl &= ~RX8010_CTRL_AIE; ctrl &= ~RX8010_CTRL_AIE;
} }
flagreg = i2c_smbus_read_byte_data(client, RX8010_FLAG); err = regmap_clear_bits(rx8010->regs, RX8010_FLAG, RX8010_FLAG_AF);
if (flagreg < 0) if (err)
return flagreg;
flagreg &= ~RX8010_FLAG_AF;
err = i2c_smbus_write_byte_data(rx8010->client, RX8010_FLAG, flagreg);
if (err < 0)
return err; return err;
if (ctrl != rx8010->ctrlreg) { if (ctrl != rx8010->ctrlreg) {
rx8010->ctrlreg = ctrl; rx8010->ctrlreg = ctrl;
err = i2c_smbus_write_byte_data(rx8010->client, RX8010_CTRL, err = regmap_write(rx8010->regs, RX8010_CTRL, rx8010->ctrlreg);
rx8010->ctrlreg); if (err)
if (err < 0)
return err; return err;
} }
...@@ -390,14 +338,13 @@ static int rx8010_alarm_irq_enable(struct device *dev, ...@@ -390,14 +338,13 @@ static int rx8010_alarm_irq_enable(struct device *dev,
static int rx8010_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) static int rx8010_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{ {
struct rx8010_data *rx8010 = dev_get_drvdata(dev); struct rx8010_data *rx8010 = dev_get_drvdata(dev);
int tmp; int tmp, flagreg, err;
int flagreg;
switch (cmd) { switch (cmd) {
case RTC_VL_READ: case RTC_VL_READ:
flagreg = i2c_smbus_read_byte_data(rx8010->client, RX8010_FLAG); err = regmap_read(rx8010->regs, RX8010_FLAG, &flagreg);
if (flagreg < 0) if (err)
return flagreg; return err;
tmp = flagreg & RX8010_FLAG_VLF ? RTC_VL_DATA_INVALID : 0; tmp = flagreg & RX8010_FLAG_VLF ? RTC_VL_DATA_INVALID : 0;
return put_user(tmp, (unsigned int __user *)arg); return put_user(tmp, (unsigned int __user *)arg);
...@@ -407,65 +354,72 @@ static int rx8010_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) ...@@ -407,65 +354,72 @@ static int rx8010_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
} }
} }
static struct rtc_class_ops rx8010_rtc_ops = { static const struct rtc_class_ops rx8010_rtc_ops_default = {
.read_time = rx8010_get_time, .read_time = rx8010_get_time,
.set_time = rx8010_set_time, .set_time = rx8010_set_time,
.ioctl = rx8010_ioctl, .ioctl = rx8010_ioctl,
}; };
static int rx8010_probe(struct i2c_client *client, static const struct rtc_class_ops rx8010_rtc_ops_alarm = {
const struct i2c_device_id *id) .read_time = rx8010_get_time,
.set_time = rx8010_set_time,
.ioctl = rx8010_ioctl,
.read_alarm = rx8010_read_alarm,
.set_alarm = rx8010_set_alarm,
.alarm_irq_enable = rx8010_alarm_irq_enable,
};
static const struct regmap_config rx8010_regmap_config = {
.name = "rx8010-rtc",
.reg_bits = 8,
.val_bits = 8,
};
static int rx8010_probe(struct i2c_client *client)
{ {
struct i2c_adapter *adapter = client->adapter; struct device *dev = &client->dev;
struct rx8010_data *rx8010; struct rx8010_data *rx8010;
int err = 0; int err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA rx8010 = devm_kzalloc(dev, sizeof(*rx8010), GFP_KERNEL);
| I2C_FUNC_SMBUS_I2C_BLOCK)) {
dev_err(&adapter->dev, "doesn't support required functionality\n");
return -EIO;
}
rx8010 = devm_kzalloc(&client->dev, sizeof(struct rx8010_data),
GFP_KERNEL);
if (!rx8010) if (!rx8010)
return -ENOMEM; return -ENOMEM;
rx8010->client = client;
i2c_set_clientdata(client, rx8010); i2c_set_clientdata(client, rx8010);
err = rx8010_init_client(client); rx8010->regs = devm_regmap_init_i2c(client, &rx8010_regmap_config);
if (IS_ERR(rx8010->regs))
return PTR_ERR(rx8010->regs);
err = rx8010_init(dev);
if (err) if (err)
return err; return err;
rx8010->rtc = devm_rtc_allocate_device(dev);
if (IS_ERR(rx8010->rtc))
return PTR_ERR(rx8010->rtc);
if (client->irq > 0) { if (client->irq > 0) {
dev_info(&client->dev, "IRQ %d supplied\n", client->irq); dev_info(dev, "IRQ %d supplied\n", client->irq);
err = devm_request_threaded_irq(&client->dev, client->irq, NULL, err = devm_request_threaded_irq(dev, client->irq, NULL,
rx8010_irq_1_handler, rx8010_irq_1_handler,
IRQF_TRIGGER_LOW | IRQF_ONESHOT, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"rx8010", client); "rx8010", client);
if (err) { if (err) {
dev_err(&client->dev, "unable to request IRQ\n"); dev_err(dev, "unable to request IRQ\n");
client->irq = 0; return err;
} else {
rx8010_rtc_ops.read_alarm = rx8010_read_alarm;
rx8010_rtc_ops.set_alarm = rx8010_set_alarm;
rx8010_rtc_ops.alarm_irq_enable = rx8010_alarm_irq_enable;
}
} }
rx8010->rtc = devm_rtc_device_register(&client->dev, client->name, rx8010->rtc->ops = &rx8010_rtc_ops_alarm;
&rx8010_rtc_ops, THIS_MODULE); } else {
rx8010->rtc->ops = &rx8010_rtc_ops_default;
if (IS_ERR(rx8010->rtc)) {
dev_err(&client->dev, "unable to register the class device\n");
return PTR_ERR(rx8010->rtc);
} }
rx8010->rtc->max_user_freq = 1; rx8010->rtc->max_user_freq = 1;
rx8010->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rx8010->rtc->range_max = RTC_TIMESTAMP_END_2099;
return 0; return rtc_register_device(rx8010->rtc);
} }
static struct i2c_driver rx8010_driver = { static struct i2c_driver rx8010_driver = {
...@@ -473,7 +427,7 @@ static struct i2c_driver rx8010_driver = { ...@@ -473,7 +427,7 @@ static struct i2c_driver rx8010_driver = {
.name = "rtc-rx8010", .name = "rtc-rx8010",
.of_match_table = of_match_ptr(rx8010_of_match), .of_match_table = of_match_ptr(rx8010_of_match),
}, },
.probe = rx8010_probe, .probe_new = rx8010_probe,
.id_table = rx8010_id, .id_table = rx8010_id,
}; };
......
...@@ -494,13 +494,8 @@ static int s3c_rtc_probe(struct platform_device *pdev) ...@@ -494,13 +494,8 @@ static int s3c_rtc_probe(struct platform_device *pdev)
if (info->data->needs_src_clk) { if (info->data->needs_src_clk) {
info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src"); info->rtc_src_clk = devm_clk_get(&pdev->dev, "rtc_src");
if (IS_ERR(info->rtc_src_clk)) { if (IS_ERR(info->rtc_src_clk)) {
ret = PTR_ERR(info->rtc_src_clk); ret = dev_err_probe(&pdev->dev, PTR_ERR(info->rtc_src_clk),
if (ret != -EPROBE_DEFER)
dev_err(&pdev->dev,
"failed to find rtc source clock\n"); "failed to find rtc source clock\n");
else
dev_dbg(&pdev->dev,
"probe deferred due to missing rtc src clk\n");
goto err_src_clk; goto err_src_clk;
} }
ret = clk_prepare_enable(info->rtc_src_clk); ret = clk_prepare_enable(info->rtc_src_clk);
......
...@@ -173,7 +173,7 @@ static int st_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t) ...@@ -173,7 +173,7 @@ static int st_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t)
return 0; return 0;
} }
static struct rtc_class_ops st_rtc_ops = { static const struct rtc_class_ops st_rtc_ops = {
.read_time = st_rtc_read_time, .read_time = st_rtc_read_time,
.set_time = st_rtc_set_time, .set_time = st_rtc_set_time,
.read_alarm = st_rtc_read_alarm, .read_alarm = st_rtc_read_alarm,
......
...@@ -72,7 +72,6 @@ struct mtk_rtc_data { ...@@ -72,7 +72,6 @@ struct mtk_rtc_data {
}; };
struct mt6397_rtc { struct mt6397_rtc {
struct device *dev;
struct rtc_device *rtc_dev; struct rtc_device *rtc_dev;
/* Protect register access from multiple tasks */ /* Protect register access from multiple tasks */
......
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