RTC for 6.5

Subsystem:
  - Switch i2c drivers back to use .probe()
  - Constify pointers to hwmon_channel_info
 
 New driver:
  - Loongson on chip RTC, replacing the Loongson 1 only driver
 
 Drivers:
  - isl1208: cleanup and support for RAA215300
  - st-lpc: cleanups
  - stm32: fix wakeup
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEBqsFVZXh8s/0O5JiY6TcMGxwOjIFAmSh9hIACgkQY6TcMGxw
 OjL53Q//SgdS6dFJwaWrol+MihLa092PkrVHLnBiPfA77huVSFPkPb1hD+1/PWGe
 ThTwXypQwiFk1hrLQUHLM8NiUo5DmmRrDlphSLrmCOloB0d0fNpfhH6FU5yOP9V4
 XoYaQlY3FX8RXqHYjn5Vc5Fp1pSyNGo4MAzYbMb8j/hrTJmRFocbdygQiHjrKgIp
 mOegYrffrMZz24vCAIs3mvT2mgBmDxe7QwuI2Wmbm0ZLfEigv1ETIHGUyBfjTMJH
 ZAd0MA9dg1+hLJw4BkJFo6PpvKEY6wjquP+1nKQpfSB3kfOyEeXtf9Y9M3cXEj36
 u8EDSfz0xrHpd4W0XzakeD90tovsCRWeA5sNooefwz5BJQ3aJjGfDZTXCEaWGV4S
 fQ7TS2pz2+ZzW3nBUFxtVD0SmctovixO8KOwhmMhCJXz3XprVdmulD6PTheRNZ/Z
 edJdty0XTYMYpvIQuaxO/bA4Df4PB4FSBHtKPg2w+KMxDivr+fS/klxSo3OcLJIU
 7EZMcJ7Ygvdw4a7/QZZbWEaJrnZ7XerFOFRdXggdTdhy1ozSObtXpJTdXL5/6hR5
 6if0fbGYVSjUkooj+oEaCihpc+8tmbdKk+iC55Gkay9M2lCbbeXSy9VFLKP/UnnU
 q7NUYRTDWgAjJAleHG9TSO02iS+nKZ6dv+IRVL01mVSVxglSQpg=
 =+0zF
 -----END PGP SIGNATURE-----

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

Pull RTC updates from Alexandre Belloni:
 "The isl1208 dirver was reworked tobe able to work as part of an MFD.

  All the Loongson chips are now supported through a new driver, the old
  one is removed.

  Summary:

  Subsystem:
   - Switch i2c drivers back to use .probe()
   - Constify pointers to hwmon_channel_info

  New driver:
   - Loongson on chip RTC, replacing the Loongson 1 only driver

  Drivers:
   - isl1208: cleanup and support for RAA215300
   - st-lpc: cleanups
   - stm32: fix wakeup"

* tag 'rtc-6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (21 commits)
  rtc: Add rtc driver for the Loongson family chips
  rtc: Remove the Loongson-1 RTC driver
  dt-bindings: rtc: Split loongson,ls2x-rtc into SoC-based compatibles
  rtc: rv3028: make rv3028 probeable from userspace
  rtc: isl1208: Add support for the built-in RTC on the PMIC RAA215300
  rtc: isl1208: Add isl1208_set_xtoscb()
  rtc: isl1208: Drop enum isl1208_id and split isl1208_configs[]
  rtc: isl1208: Make similar I2C and DT-based matching table
  rtc: isl1208: Drop name variable
  dt-bindings: rtc: isil,isl1208: Document clock and clock-names properties
  dt-bindings: rtc: isl1208: Convert to json-schema
  rtc: st-lpc: Simplify clk handling in st_rtc_probe()
  rtc: st-lpc: Release some resources in st_rtc_probe() in case of error
  rtc: stm32: remove dedicated wakeup management
  dt-bindings: rtc: restrict node name suffixes
  rtc: add HAS_IOPORT dependencies
  rtc: Switch i2c drivers back to use .probe()
  rtc: rv3032: constify pointers to hwmon_channel_info
  rtc: isl12022: constify pointers to hwmon_channel_info
  rtc: ds3232: constify pointers to hwmon_channel_info
  ...
This commit is contained in:
Linus Torvalds 2023-07-03 10:43:10 -07:00
commit b349de4c91
46 changed files with 726 additions and 350 deletions

View File

@ -1,38 +0,0 @@
Intersil ISL1209/19 I2C RTC/Alarm chip with event in
ISL12X9 have additional pins EVIN and #EVDET for tamper detection, while the
ISL1208 and ISL1218 do not. They are all use the same driver with the bindings
described here, with chip specific properties as noted.
Required properties supported by the device:
- "compatible": Should be one of the following:
- "isil,isl1208"
- "isil,isl1209"
- "isil,isl1218"
- "isil,isl1219"
- "reg": I2C bus address of the device
Optional properties:
- "interrupt-names": list which may contains "irq" and "evdet"
evdet applies to isl1209 and isl1219 only
- "interrupts": list of interrupts for "irq" and "evdet"
evdet applies to isl1209 and isl1219 only
- "isil,ev-evienb": Enable or disable internal pull on EVIN pin
Applies to isl1209 and isl1219 only
Possible values are 0 and 1
Value 0 enables internal pull-up on evin pin, 1 disables it.
Default will leave the non-volatile configuration of the pullup
as is.
Example isl1219 node with #IRQ pin connected to SoC gpio1 pin12 and #EVDET pin
connected to SoC gpio2 pin 24 and internal pull-up enabled in EVIN pin.
isl1219: rtc@68 {
compatible = "isil,isl1219";
reg = <0x68>;
interrupt-names = "irq", "evdet";
interrupts-extended = <&gpio1 12 IRQ_TYPE_EDGE_FALLING>,
<&gpio2 24 IRQ_TYPE_EDGE_FALLING>;
isil,ev-evienb = <1>;
};

View File

@ -0,0 +1,100 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/isil,isl1208.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intersil ISL1209/19 I2C RTC/Alarm chip with event in
maintainers:
- Biju Das <biju.das.jz@bp.renesas.com>
- Trent Piepho <tpiepho@gmail.com>
description:
ISL12X9 have additional pins EVIN and EVDET for tamper detection, while the
ISL1208 and ISL1218 do not.
properties:
compatible:
enum:
- isil,isl1208
- isil,isl1209
- isil,isl1218
- isil,isl1219
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
description: |
Use xin, if connected to an external crystal.
Use clkin, if connected to an external clock signal.
enum:
- xin
- clkin
interrupts:
minItems: 1
maxItems: 2
interrupt-names:
minItems: 1
items:
- const: irq
- const: evdet
isil,ev-evienb:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [ 0, 1 ]
description: |
Enable or disable internal pull on EVIN pin
Default will leave the non-volatile configuration of the pullup
as is.
<0> : Enables internal pull-up on evin pin
<1> : Disables internal pull-up on evin pin
required:
- compatible
- reg
allOf:
- $ref: rtc.yaml#
- if:
properties:
compatible:
contains:
enum:
- isil,isl1209
- isil,isl1219
then:
properties:
interrupts:
maxItems: 2
interrupt-names:
items:
- const: irq
- const: evdet
else:
properties:
interrupts:
maxItems: 1
interrupt-names:
items:
- const: irq
unevaluatedProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
rtc_twi: rtc@6f {
compatible = "isil,isl1208";
reg = <0x6f>;
};
};

View File

@ -0,0 +1,57 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/rtc/loongson,rtc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Loongson Real-Time Clock
description:
The Loongson family chips use an on-chip counter 0 (Time Of Year
counter) as the RTC.
maintainers:
- Binbin Zhou <zhoubinbin@loongson.cn>
allOf:
- $ref: rtc.yaml#
properties:
compatible:
oneOf:
- enum:
- loongson,ls1b-rtc
- loongson,ls1c-rtc
- loongson,ls7a-rtc
- loongson,ls2k1000-rtc
- items:
- enum:
- loongson,ls2k2000-rtc
- loongson,ls2k0500-rtc
- const: loongson,ls7a-rtc
reg:
maxItems: 1
interrupts:
maxItems: 1
required:
- compatible
- reg
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
rtc@1fe27800 {
compatible = "loongson,ls2k1000-rtc";
reg = <0x1fe27800 0x100>;
interrupt-parent = <&liointc1>;
interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
};
...

View File

@ -15,7 +15,7 @@ description: |
properties:
$nodename:
pattern: "^rtc(@.*|-[0-9a-f])*$"
pattern: "^rtc(@.*|-([0-9]|[1-9][0-9]+))?$"
aux-voltage-chargeable:
$ref: /schemas/types.yaml#/definitions/uint32

View File

@ -47,8 +47,6 @@ properties:
- isil,isl1218
# Intersil ISL12022 Real-time Clock
- isil,isl12022
# Loongson-2K Socs/LS7A bridge Real-time Clock
- loongson,ls2x-rtc
# Real Time Clock Module with I2C-Bus
- microcrystal,rv3029
# Real Time Clock

View File

@ -956,6 +956,7 @@ comment "Platform RTC drivers"
config RTC_DRV_CMOS
tristate "PC-style 'CMOS'"
depends on X86 || ARM || PPC || MIPS || SPARC64
depends on HAS_IOPORT || MACH_DECSTATION
default y if X86
select RTC_MC146818_LIB
help
@ -976,6 +977,7 @@ config RTC_DRV_CMOS
config RTC_DRV_ALPHA
bool "Alpha PC-style CMOS"
depends on ALPHA
depends on HAS_IOPORT
select RTC_MC146818_LIB
default y
help
@ -1193,7 +1195,7 @@ config RTC_DRV_MSM6242
config RTC_DRV_BQ4802
tristate "TI BQ4802"
depends on HAS_IOMEM
depends on HAS_IOMEM && HAS_IOPORT
help
If you say Y here you will get support for the TI
BQ4802 RTC chip.
@ -1685,6 +1687,19 @@ config RTC_DRV_JZ4740
This driver can also be built as a module. If so, the module
will be called rtc-jz4740.
config RTC_DRV_LOONGSON
tristate "Loongson On-chip RTC"
depends on MACH_LOONGSON32 || MACH_LOONGSON64 || COMPILE_TEST
select REGMAP_MMIO
help
This is a driver for the Loongson on-chip Counter0 (Time-Of-Year
counter) to be used as a RTC.
It can be found on Loongson-1 series cpu, Loongson-2K series cpu
and Loongson LS7A bridge chips.
This driver can also be built as a module. If so, the module
will be called rtc-loongson.
config RTC_DRV_LPC24XX
tristate "NXP RTC for LPC178x/18xx/408x/43xx"
depends on ARCH_LPC18XX || COMPILE_TEST
@ -1726,16 +1741,6 @@ config RTC_DRV_TEGRA
This drive can also be built as a module. If so, the module
will be called rtc-tegra.
config RTC_DRV_LOONGSON1
tristate "loongson1 RTC support"
depends on MACH_LOONGSON32
help
This is a driver for the loongson1 on-chip Counter0 (Time-Of-Year
counter) to be used as a RTC.
This driver can also be built as a module. If so, the module
will be called rtc-ls1x.
config RTC_DRV_MXC
tristate "Freescale MXC Real Time Clock"
depends on ARCH_MXC || COMPILE_TEST

View File

@ -78,7 +78,7 @@ obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o
obj-$(CONFIG_RTC_DRV_ISL12026) += rtc-isl12026.o
obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o
obj-$(CONFIG_RTC_DRV_LOONGSON1) += rtc-ls1x.o
obj-$(CONFIG_RTC_DRV_LOONGSON) += rtc-loongson.o
obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o
obj-$(CONFIG_RTC_DRV_LPC24XX) += rtc-lpc24xx.o
obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o

View File

@ -944,7 +944,7 @@ static struct i2c_driver abb5zes3_driver = {
.pm = &abb5zes3_rtc_pm_ops,
.of_match_table = of_match_ptr(abb5zes3_dt_match),
},
.probe_new = abb5zes3_probe,
.probe = abb5zes3_probe,
.id_table = abb5zes3_id,
};
module_i2c_driver(abb5zes3_driver);

View File

@ -455,7 +455,7 @@ static const struct hwmon_channel_info abeoz9_temp = {
.config = abeoz9_temp_config,
};
static const struct hwmon_channel_info *abeoz9_info[] = {
static const struct hwmon_channel_info * const abeoz9_info[] = {
&abeoz9_chip,
&abeoz9_temp,
NULL
@ -584,7 +584,7 @@ static struct i2c_driver abeoz9_driver = {
.name = "rtc-ab-eoz9",
.of_match_table = of_match_ptr(abeoz9_dt_match),
},
.probe_new = abeoz9_probe,
.probe = abeoz9_probe,
.id_table = abeoz9_id,
};

View File

@ -992,7 +992,7 @@ static struct i2c_driver abx80x_driver = {
.name = "rtc-abx80x",
.of_match_table = of_match_ptr(abx80x_of_match),
},
.probe_new = abx80x_probe,
.probe = abx80x_probe,
.id_table = abx80x_id,
};

View File

@ -320,7 +320,7 @@ static struct i2c_driver bq32k_driver = {
.name = "bq32k",
.of_match_table = of_match_ptr(bq32k_of_match),
},
.probe_new = bq32k_probe,
.probe = bq32k_probe,
.remove = bq32k_remove,
.id_table = bq32k_id,
};

View File

@ -2011,7 +2011,7 @@ static struct i2c_driver ds1307_driver = {
.name = "rtc-ds1307",
.of_match_table = ds1307_of_match,
},
.probe_new = ds1307_probe,
.probe = ds1307_probe,
.id_table = ds1307_id,
};

View File

@ -572,7 +572,7 @@ static struct i2c_driver ds1374_driver = {
.of_match_table = of_match_ptr(ds1374_of_match),
.pm = &ds1374_pm,
},
.probe_new = ds1374_probe,
.probe = ds1374_probe,
.remove = ds1374_remove,
.id_table = ds1374_id,
};

View File

@ -149,7 +149,7 @@ static struct i2c_driver ds1672_driver = {
.name = "rtc-ds1672",
.of_match_table = of_match_ptr(ds1672_of_match),
},
.probe_new = ds1672_probe,
.probe = ds1672_probe,
.id_table = ds1672_id,
};

View File

@ -359,7 +359,7 @@ static const struct hwmon_channel_info ds3232_hwmon_temp = {
.config = ds3232_hwmon_temp_config,
};
static const struct hwmon_channel_info *ds3232_hwmon_info[] = {
static const struct hwmon_channel_info * const ds3232_hwmon_info[] = {
&ds3232_hwmon_chip,
&ds3232_hwmon_temp,
NULL
@ -603,7 +603,7 @@ static struct i2c_driver ds3232_driver = {
.of_match_table = of_match_ptr(ds3232_of_match),
.pm = &ds3232_pm_ops,
},
.probe_new = ds3232_i2c_probe,
.probe = ds3232_i2c_probe,
.id_table = ds3232_id,
};

View File

@ -147,7 +147,7 @@ static struct i2c_driver em3027_driver = {
.name = "rtc-em3027",
.of_match_table = of_match_ptr(em3027_of_match),
},
.probe_new = em3027_probe,
.probe = em3027_probe,
.id_table = em3027_id,
};

View File

@ -517,7 +517,7 @@ static struct i2c_driver fm3130_driver = {
.driver = {
.name = "rtc-fm3130",
},
.probe_new = fm3130_probe,
.probe = fm3130_probe,
.id_table = fm3130_id,
};

View File

@ -576,7 +576,7 @@ static struct i2c_driver hym8563_driver = {
.pm = &hym8563_pm_ops,
.of_match_table = hym8563_dt_idtable,
},
.probe_new = hym8563_probe,
.probe = hym8563_probe,
.id_table = hym8563_id,
};

View File

@ -89,7 +89,7 @@ static int isl12022_hwmon_read(struct device *dev,
return -EOPNOTSUPP;
}
static const struct hwmon_channel_info *isl12022_hwmon_info[] = {
static const struct hwmon_channel_info * const isl12022_hwmon_info[] = {
HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
NULL
};
@ -262,7 +262,7 @@ static struct i2c_driver isl12022_driver = {
.name = "rtc-isl12022",
.of_match_table = isl12022_dt_match,
},
.probe_new = isl12022_probe,
.probe = isl12022_probe,
.id_table = isl12022_id,
};

View File

@ -490,7 +490,7 @@ static struct i2c_driver isl12026_driver = {
.name = "rtc-isl12026",
.of_match_table = isl12026_dt_match,
},
.probe_new = isl12026_probe_new,
.probe = isl12026_probe_new,
.remove = isl12026_remove,
};

View File

@ -6,6 +6,7 @@
*/
#include <linux/bcd.h>
#include <linux/clk.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of_device.h>
@ -68,42 +69,60 @@
static struct i2c_driver isl1208_driver;
/* ISL1208 various variants */
enum isl1208_id {
TYPE_ISL1208 = 0,
TYPE_ISL1209,
TYPE_ISL1218,
TYPE_ISL1219,
ISL_LAST_ID
};
/* Chip capabilities table */
static const struct isl1208_config {
const char name[8];
struct isl1208_config {
unsigned int nvmem_length;
unsigned has_tamper:1;
unsigned has_timestamp:1;
} isl1208_configs[] = {
[TYPE_ISL1208] = { "isl1208", 2, false, false },
[TYPE_ISL1209] = { "isl1209", 2, true, false },
[TYPE_ISL1218] = { "isl1218", 8, false, false },
[TYPE_ISL1219] = { "isl1219", 2, true, true },
unsigned has_inverted_osc_bit:1;
};
static const struct isl1208_config config_isl1208 = {
.nvmem_length = 2,
.has_tamper = false,
.has_timestamp = false
};
static const struct isl1208_config config_isl1209 = {
.nvmem_length = 2,
.has_tamper = true,
.has_timestamp = false
};
static const struct isl1208_config config_isl1218 = {
.nvmem_length = 8,
.has_tamper = false,
.has_timestamp = false
};
static const struct isl1208_config config_isl1219 = {
.nvmem_length = 2,
.has_tamper = true,
.has_timestamp = true
};
static const struct isl1208_config config_raa215300_a0 = {
.nvmem_length = 2,
.has_tamper = false,
.has_timestamp = false,
.has_inverted_osc_bit = true
};
static const struct i2c_device_id isl1208_id[] = {
{ "isl1208", TYPE_ISL1208 },
{ "isl1209", TYPE_ISL1209 },
{ "isl1218", TYPE_ISL1218 },
{ "isl1219", TYPE_ISL1219 },
{ "isl1208", .driver_data = (kernel_ulong_t)&config_isl1208 },
{ "isl1209", .driver_data = (kernel_ulong_t)&config_isl1209 },
{ "isl1218", .driver_data = (kernel_ulong_t)&config_isl1218 },
{ "isl1219", .driver_data = (kernel_ulong_t)&config_isl1219 },
{ "raa215300_a0", .driver_data = (kernel_ulong_t)&config_raa215300_a0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, isl1208_id);
static const __maybe_unused struct of_device_id isl1208_of_match[] = {
{ .compatible = "isil,isl1208", .data = &isl1208_configs[TYPE_ISL1208] },
{ .compatible = "isil,isl1209", .data = &isl1208_configs[TYPE_ISL1209] },
{ .compatible = "isil,isl1218", .data = &isl1208_configs[TYPE_ISL1218] },
{ .compatible = "isil,isl1219", .data = &isl1208_configs[TYPE_ISL1219] },
{ .compatible = "isil,isl1208", .data = &config_isl1208 },
{ .compatible = "isil,isl1209", .data = &config_isl1209 },
{ .compatible = "isil,isl1218", .data = &config_isl1218 },
{ .compatible = "isil,isl1219", .data = &config_isl1219 },
{ }
};
MODULE_DEVICE_TABLE(of, isl1208_of_match);
@ -166,6 +185,20 @@ isl1208_i2c_validate_client(struct i2c_client *client)
return 0;
}
static int isl1208_set_xtoscb(struct i2c_client *client, int sr, int xtosb_val)
{
/* Do nothing if bit is already set to desired value */
if ((sr & ISL1208_REG_SR_XTOSCB) == xtosb_val)
return 0;
if (xtosb_val)
sr |= ISL1208_REG_SR_XTOSCB;
else
sr &= ~ISL1208_REG_SR_XTOSCB;
return i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr);
}
static int
isl1208_i2c_get_sr(struct i2c_client *client)
{
@ -502,7 +535,6 @@ isl1208_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm)
return 0;
}
static int
isl1208_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
@ -796,12 +828,26 @@ static int isl1208_setup_irq(struct i2c_client *client, int irq)
return rc;
}
static int
isl1208_clk_present(struct i2c_client *client, const char *name)
{
struct clk *clk;
clk = devm_clk_get_optional(&client->dev, name);
if (IS_ERR(clk))
return PTR_ERR(clk);
return !!clk;
}
static int
isl1208_probe(struct i2c_client *client)
{
int rc = 0;
struct isl1208_state *isl1208;
int evdet_irq = -1;
int xtosb_val = 0;
int rc = 0;
int sr;
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
@ -823,9 +869,22 @@ isl1208_probe(struct i2c_client *client)
} else {
const struct i2c_device_id *id = i2c_match_id(isl1208_id, client);
if (id->driver_data >= ISL_LAST_ID)
if (!id)
return -ENODEV;
isl1208->config = &isl1208_configs[id->driver_data];
isl1208->config = (struct isl1208_config *)id->driver_data;
}
rc = isl1208_clk_present(client, "xin");
if (rc < 0)
return rc;
if (!rc) {
rc = isl1208_clk_present(client, "clkin");
if (rc < 0)
return rc;
if (rc)
xtosb_val = 1;
}
isl1208->rtc = devm_rtc_allocate_device(&client->dev);
@ -839,13 +898,20 @@ isl1208_probe(struct i2c_client *client)
isl1208->nvmem_config.size = isl1208->config->nvmem_length;
isl1208->nvmem_config.priv = isl1208;
rc = isl1208_i2c_get_sr(client);
if (rc < 0) {
sr = isl1208_i2c_get_sr(client);
if (sr < 0) {
dev_err(&client->dev, "reading status failed\n");
return rc;
return sr;
}
if (rc & ISL1208_REG_SR_RTCF)
if (isl1208->config->has_inverted_osc_bit)
xtosb_val = !xtosb_val;
rc = isl1208_set_xtoscb(client, sr, xtosb_val);
if (rc)
return rc;
if (sr & ISL1208_REG_SR_RTCF)
dev_warn(&client->dev, "rtc power failure detected, "
"please set clock.\n");
@ -908,7 +974,7 @@ static struct i2c_driver isl1208_driver = {
.name = "rtc-isl1208",
.of_match_table = of_match_ptr(isl1208_of_match),
},
.probe_new = isl1208_probe,
.probe = isl1208_probe,
.id_table = isl1208_id,
};

397
drivers/rtc/rtc-loongson.c Normal file
View File

@ -0,0 +1,397 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Loongson RTC driver
*
* Maintained out-of-tree by Huacai Chen <chenhuacai@kernel.org>.
* Rewritten for mainline by WANG Xuerui <git@xen0n.name>.
* Binbin Zhou <zhoubinbin@loongson.cn>
*/
#include <linux/bitfield.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/rtc.h>
#include <linux/acpi.h>
/* Time Of Year(TOY) counters registers */
#define TOY_TRIM_REG 0x20 /* Must be initialized to 0 */
#define TOY_WRITE0_REG 0x24 /* TOY low 32-bits value (write-only) */
#define TOY_WRITE1_REG 0x28 /* TOY high 32-bits value (write-only) */
#define TOY_READ0_REG 0x2c /* TOY low 32-bits value (read-only) */
#define TOY_READ1_REG 0x30 /* TOY high 32-bits value (read-only) */
#define TOY_MATCH0_REG 0x34 /* TOY timing interrupt 0 */
#define TOY_MATCH1_REG 0x38 /* TOY timing interrupt 1 */
#define TOY_MATCH2_REG 0x3c /* TOY timing interrupt 2 */
/* RTC counters registers */
#define RTC_CTRL_REG 0x40 /* TOY and RTC control register */
#define RTC_TRIM_REG 0x60 /* Must be initialized to 0 */
#define RTC_WRITE0_REG 0x64 /* RTC counters value (write-only) */
#define RTC_READ0_REG 0x68 /* RTC counters value (read-only) */
#define RTC_MATCH0_REG 0x6c /* RTC timing interrupt 0 */
#define RTC_MATCH1_REG 0x70 /* RTC timing interrupt 1 */
#define RTC_MATCH2_REG 0x74 /* RTC timing interrupt 2 */
/* bitmask of TOY_WRITE0_REG */
#define TOY_MON GENMASK(31, 26)
#define TOY_DAY GENMASK(25, 21)
#define TOY_HOUR GENMASK(20, 16)
#define TOY_MIN GENMASK(15, 10)
#define TOY_SEC GENMASK(9, 4)
#define TOY_MSEC GENMASK(3, 0)
/* bitmask of TOY_MATCH0/1/2_REG */
#define TOY_MATCH_YEAR GENMASK(31, 26)
#define TOY_MATCH_MON GENMASK(25, 22)
#define TOY_MATCH_DAY GENMASK(21, 17)
#define TOY_MATCH_HOUR GENMASK(16, 12)
#define TOY_MATCH_MIN GENMASK(11, 6)
#define TOY_MATCH_SEC GENMASK(5, 0)
/* bitmask of RTC_CTRL_REG */
#define RTC_ENABLE BIT(13) /* 1: RTC counters enable */
#define TOY_ENABLE BIT(11) /* 1: TOY counters enable */
#define OSC_ENABLE BIT(8) /* 1: 32.768k crystal enable */
#define TOY_ENABLE_MASK (TOY_ENABLE | OSC_ENABLE)
/* PM domain registers */
#define PM1_STS_REG 0x0c /* Power management 1 status register */
#define RTC_STS BIT(10) /* RTC status */
#define PM1_EN_REG 0x10 /* Power management 1 enable register */
#define RTC_EN BIT(10) /* RTC event enable */
/*
* According to the LS1C manual, RTC_CTRL and alarm-related registers are not defined.
* Accessing the relevant registers will cause the system to hang.
*/
#define LS1C_RTC_CTRL_WORKAROUND BIT(0)
struct loongson_rtc_config {
u32 pm_offset; /* Offset of PM domain, for RTC alarm wakeup */
u32 flags; /* Workaround bits */
};
struct loongson_rtc_priv {
spinlock_t lock; /* protects PM registers access */
u32 fix_year; /* RTC alarm year compensation value */
struct rtc_device *rtcdev;
struct regmap *regmap;
void __iomem *pm_base; /* PM domain base, for RTC alarm wakeup */
const struct loongson_rtc_config *config;
};
static const struct loongson_rtc_config ls1b_rtc_config = {
.pm_offset = 0,
.flags = 0,
};
static const struct loongson_rtc_config ls1c_rtc_config = {
.pm_offset = 0,
.flags = LS1C_RTC_CTRL_WORKAROUND,
};
static const struct loongson_rtc_config generic_rtc_config = {
.pm_offset = 0x100,
.flags = 0,
};
static const struct loongson_rtc_config ls2k1000_rtc_config = {
.pm_offset = 0x800,
.flags = 0,
};
static const struct regmap_config loongson_rtc_regmap_config = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
};
/* RTC alarm irq handler */
static irqreturn_t loongson_rtc_isr(int irq, void *id)
{
struct loongson_rtc_priv *priv = (struct loongson_rtc_priv *)id;
rtc_update_irq(priv->rtcdev, 1, RTC_AF | RTC_IRQF);
return IRQ_HANDLED;
}
/* For ACPI fixed event handler */
static u32 loongson_rtc_handler(void *id)
{
struct loongson_rtc_priv *priv = (struct loongson_rtc_priv *)id;
spin_lock(&priv->lock);
/* Disable RTC alarm wakeup and interrupt */
writel(readl(priv->pm_base + PM1_EN_REG) & ~RTC_EN,
priv->pm_base + PM1_EN_REG);
/* Clear RTC interrupt status */
writel(RTC_STS, priv->pm_base + PM1_STS_REG);
spin_unlock(&priv->lock);
/*
* The TOY_MATCH0_REG should be cleared 0 here,
* otherwise the interrupt cannot be cleared.
*/
return regmap_write(priv->regmap, TOY_MATCH0_REG, 0);
}
static int loongson_rtc_set_enabled(struct device *dev)
{
struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
if (priv->config->flags & LS1C_RTC_CTRL_WORKAROUND)
return 0;
/* Enable RTC TOY counters and crystal */
return regmap_update_bits(priv->regmap, RTC_CTRL_REG, TOY_ENABLE_MASK,
TOY_ENABLE_MASK);
}
static bool loongson_rtc_get_enabled(struct device *dev)
{
int ret;
u32 ctrl_data;
struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
if (priv->config->flags & LS1C_RTC_CTRL_WORKAROUND)
return true;
ret = regmap_read(priv->regmap, RTC_CTRL_REG, &ctrl_data);
if (ret < 0)
return false;
return ctrl_data & TOY_ENABLE_MASK;
}
static int loongson_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
int ret;
u32 rtc_data[2];
struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
if (!loongson_rtc_get_enabled(dev))
return -EINVAL;
ret = regmap_bulk_read(priv->regmap, TOY_READ0_REG, rtc_data,
ARRAY_SIZE(rtc_data));
if (ret < 0)
return ret;
tm->tm_sec = FIELD_GET(TOY_SEC, rtc_data[0]);
tm->tm_min = FIELD_GET(TOY_MIN, rtc_data[0]);
tm->tm_hour = FIELD_GET(TOY_HOUR, rtc_data[0]);
tm->tm_mday = FIELD_GET(TOY_DAY, rtc_data[0]);
tm->tm_mon = FIELD_GET(TOY_MON, rtc_data[0]) - 1;
tm->tm_year = rtc_data[1];
/* Prepare for RTC alarm year compensation value. */
priv->fix_year = tm->tm_year / 64 * 64;
return 0;
}
static int loongson_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
int ret;
u32 rtc_data[2];
struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
rtc_data[0] = FIELD_PREP(TOY_SEC, tm->tm_sec)
| FIELD_PREP(TOY_MIN, tm->tm_min)
| FIELD_PREP(TOY_HOUR, tm->tm_hour)
| FIELD_PREP(TOY_DAY, tm->tm_mday)
| FIELD_PREP(TOY_MON, tm->tm_mon + 1);
rtc_data[1] = tm->tm_year;
ret = regmap_bulk_write(priv->regmap, TOY_WRITE0_REG, rtc_data,
ARRAY_SIZE(rtc_data));
if (ret < 0)
return ret;
return loongson_rtc_set_enabled(dev);
}
static int loongson_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
int ret;
u32 alarm_data;
struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
ret = regmap_read(priv->regmap, TOY_MATCH0_REG, &alarm_data);
if (ret < 0)
return ret;
alrm->time.tm_sec = FIELD_GET(TOY_MATCH_SEC, alarm_data);
alrm->time.tm_min = FIELD_GET(TOY_MATCH_MIN, alarm_data);
alrm->time.tm_hour = FIELD_GET(TOY_MATCH_HOUR, alarm_data);
alrm->time.tm_mday = FIELD_GET(TOY_MATCH_DAY, alarm_data);
alrm->time.tm_mon = FIELD_GET(TOY_MATCH_MON, alarm_data) - 1;
/*
* This is a hardware bug: the year field of SYS_TOYMATCH is only 6 bits,
* making it impossible to save year values larger than 64.
*
* SYS_TOYMATCH is used to match the alarm time value and determine if
* an alarm is triggered, so we must keep the lower 6 bits of the year
* value constant during the value conversion.
*
* In summary, we need to manually add 64(or a multiple of 64) to the
* year value to avoid the invalid alarm prompt at startup.
*/
alrm->time.tm_year = FIELD_GET(TOY_MATCH_YEAR, alarm_data) + priv->fix_year;
alrm->enabled = !!(readl(priv->pm_base + PM1_EN_REG) & RTC_EN);
return 0;
}
static int loongson_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
u32 val;
struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
spin_lock(&priv->lock);
val = readl(priv->pm_base + PM1_EN_REG);
/* Enable RTC alarm wakeup */
writel(enabled ? val | RTC_EN : val & ~RTC_EN,
priv->pm_base + PM1_EN_REG);
spin_unlock(&priv->lock);
return 0;
}
static int loongson_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
int ret;
u32 alarm_data;
struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
alarm_data = FIELD_PREP(TOY_MATCH_SEC, alrm->time.tm_sec)
| FIELD_PREP(TOY_MATCH_MIN, alrm->time.tm_min)
| FIELD_PREP(TOY_MATCH_HOUR, alrm->time.tm_hour)
| FIELD_PREP(TOY_MATCH_DAY, alrm->time.tm_mday)
| FIELD_PREP(TOY_MATCH_MON, alrm->time.tm_mon + 1)
| FIELD_PREP(TOY_MATCH_YEAR, alrm->time.tm_year - priv->fix_year);
ret = regmap_write(priv->regmap, TOY_MATCH0_REG, alarm_data);
if (ret < 0)
return ret;
return loongson_rtc_alarm_irq_enable(dev, alrm->enabled);
}
static const struct rtc_class_ops loongson_rtc_ops = {
.read_time = loongson_rtc_read_time,
.set_time = loongson_rtc_set_time,
.read_alarm = loongson_rtc_read_alarm,
.set_alarm = loongson_rtc_set_alarm,
.alarm_irq_enable = loongson_rtc_alarm_irq_enable,
};
static int loongson_rtc_probe(struct platform_device *pdev)
{
int ret, alarm_irq;
void __iomem *regs;
struct loongson_rtc_priv *priv;
struct device *dev = &pdev->dev;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs))
return dev_err_probe(dev, PTR_ERR(regs),
"devm_platform_ioremap_resource failed\n");
priv->regmap = devm_regmap_init_mmio(dev, regs,
&loongson_rtc_regmap_config);
if (IS_ERR(priv->regmap))
return dev_err_probe(dev, PTR_ERR(priv->regmap),
"devm_regmap_init_mmio failed\n");
priv->config = device_get_match_data(dev);
spin_lock_init(&priv->lock);
platform_set_drvdata(pdev, priv);
priv->rtcdev = devm_rtc_allocate_device(dev);
if (IS_ERR(priv->rtcdev))
return dev_err_probe(dev, PTR_ERR(priv->rtcdev),
"devm_rtc_allocate_device failed\n");
/* Get RTC alarm irq */
alarm_irq = platform_get_irq(pdev, 0);
if (alarm_irq > 0) {
ret = devm_request_irq(dev, alarm_irq, loongson_rtc_isr,
0, "loongson-alarm", priv);
if (ret < 0)
return dev_err_probe(dev, ret, "Unable to request irq %d\n",
alarm_irq);
priv->pm_base = regs - priv->config->pm_offset;
device_init_wakeup(dev, 1);
if (has_acpi_companion(dev))
acpi_install_fixed_event_handler(ACPI_EVENT_RTC,
loongson_rtc_handler, priv);
} else {
/* Loongson-1C RTC does not support alarm */
clear_bit(RTC_FEATURE_ALARM, priv->rtcdev->features);
}
/* Loongson RTC does not support UIE */
clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, priv->rtcdev->features);
priv->rtcdev->ops = &loongson_rtc_ops;
priv->rtcdev->range_min = RTC_TIMESTAMP_BEGIN_2000;
priv->rtcdev->range_max = RTC_TIMESTAMP_END_2099;
return devm_rtc_register_device(priv->rtcdev);
}
static void loongson_rtc_remove(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct loongson_rtc_priv *priv = dev_get_drvdata(dev);
if (!test_bit(RTC_FEATURE_ALARM, priv->rtcdev->features))
return;
if (has_acpi_companion(dev))
acpi_remove_fixed_event_handler(ACPI_EVENT_RTC,
loongson_rtc_handler);
device_init_wakeup(dev, 0);
loongson_rtc_alarm_irq_enable(dev, 0);
}
static const struct of_device_id loongson_rtc_of_match[] = {
{ .compatible = "loongson,ls1b-rtc", .data = &ls1b_rtc_config },
{ .compatible = "loongson,ls1c-rtc", .data = &ls1c_rtc_config },
{ .compatible = "loongson,ls7a-rtc", .data = &generic_rtc_config },
{ .compatible = "loongson,ls2k1000-rtc", .data = &ls2k1000_rtc_config },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, loongson_rtc_of_match);
static const struct acpi_device_id loongson_rtc_acpi_match[] = {
{ "LOON0001", .driver_data = (kernel_ulong_t)&generic_rtc_config },
{ }
};
MODULE_DEVICE_TABLE(acpi, loongson_rtc_acpi_match);
static struct platform_driver loongson_rtc_driver = {
.probe = loongson_rtc_probe,
.remove_new = loongson_rtc_remove,
.driver = {
.name = "loongson-rtc",
.of_match_table = loongson_rtc_of_match,
.acpi_match_table = loongson_rtc_acpi_match,
},
};
module_platform_driver(loongson_rtc_driver);
MODULE_DESCRIPTION("Loongson RTC driver");
MODULE_AUTHOR("Binbin Zhou <zhoubinbin@loongson.cn>");
MODULE_AUTHOR("WANG Xuerui <git@xen0n.name>");
MODULE_AUTHOR("Huacai Chen <chenhuacai@kernel.org>");
MODULE_LICENSE("GPL");

View File

@ -1,192 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2011 Zhao Zhang <zhzhl555@gmail.com>
*
* Derived from driver/rtc/rtc-au1xxx.c
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/rtc.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/types.h>
#include <linux/io.h>
#include <loongson1.h>
#define LS1X_RTC_REG_OFFSET (LS1X_RTC_BASE + 0x20)
#define LS1X_RTC_REGS(x) \
((void __iomem *)KSEG1ADDR(LS1X_RTC_REG_OFFSET + (x)))
/*RTC programmable counters 0 and 1*/
#define SYS_COUNTER_CNTRL (LS1X_RTC_REGS(0x20))
#define SYS_CNTRL_ERS (1 << 23)
#define SYS_CNTRL_RTS (1 << 20)
#define SYS_CNTRL_RM2 (1 << 19)
#define SYS_CNTRL_RM1 (1 << 18)
#define SYS_CNTRL_RM0 (1 << 17)
#define SYS_CNTRL_RS (1 << 16)
#define SYS_CNTRL_BP (1 << 14)
#define SYS_CNTRL_REN (1 << 13)
#define SYS_CNTRL_BRT (1 << 12)
#define SYS_CNTRL_TEN (1 << 11)
#define SYS_CNTRL_BTT (1 << 10)
#define SYS_CNTRL_E0 (1 << 8)
#define SYS_CNTRL_ETS (1 << 7)
#define SYS_CNTRL_32S (1 << 5)
#define SYS_CNTRL_TTS (1 << 4)
#define SYS_CNTRL_TM2 (1 << 3)
#define SYS_CNTRL_TM1 (1 << 2)
#define SYS_CNTRL_TM0 (1 << 1)
#define SYS_CNTRL_TS (1 << 0)
/* Programmable Counter 0 Registers */
#define SYS_TOYTRIM (LS1X_RTC_REGS(0))
#define SYS_TOYWRITE0 (LS1X_RTC_REGS(4))
#define SYS_TOYWRITE1 (LS1X_RTC_REGS(8))
#define SYS_TOYREAD0 (LS1X_RTC_REGS(0xC))
#define SYS_TOYREAD1 (LS1X_RTC_REGS(0x10))
#define SYS_TOYMATCH0 (LS1X_RTC_REGS(0x14))
#define SYS_TOYMATCH1 (LS1X_RTC_REGS(0x18))
#define SYS_TOYMATCH2 (LS1X_RTC_REGS(0x1C))
/* Programmable Counter 1 Registers */
#define SYS_RTCTRIM (LS1X_RTC_REGS(0x40))
#define SYS_RTCWRITE0 (LS1X_RTC_REGS(0x44))
#define SYS_RTCREAD0 (LS1X_RTC_REGS(0x48))
#define SYS_RTCMATCH0 (LS1X_RTC_REGS(0x4C))
#define SYS_RTCMATCH1 (LS1X_RTC_REGS(0x50))
#define SYS_RTCMATCH2 (LS1X_RTC_REGS(0x54))
#define LS1X_SEC_OFFSET (4)
#define LS1X_MIN_OFFSET (10)
#define LS1X_HOUR_OFFSET (16)
#define LS1X_DAY_OFFSET (21)
#define LS1X_MONTH_OFFSET (26)
#define LS1X_SEC_MASK (0x3f)
#define LS1X_MIN_MASK (0x3f)
#define LS1X_HOUR_MASK (0x1f)
#define LS1X_DAY_MASK (0x1f)
#define LS1X_MONTH_MASK (0x3f)
#define LS1X_YEAR_MASK (0xffffffff)
#define ls1x_get_sec(t) (((t) >> LS1X_SEC_OFFSET) & LS1X_SEC_MASK)
#define ls1x_get_min(t) (((t) >> LS1X_MIN_OFFSET) & LS1X_MIN_MASK)
#define ls1x_get_hour(t) (((t) >> LS1X_HOUR_OFFSET) & LS1X_HOUR_MASK)
#define ls1x_get_day(t) (((t) >> LS1X_DAY_OFFSET) & LS1X_DAY_MASK)
#define ls1x_get_month(t) (((t) >> LS1X_MONTH_OFFSET) & LS1X_MONTH_MASK)
#define RTC_CNTR_OK (SYS_CNTRL_E0 | SYS_CNTRL_32S)
static int ls1x_rtc_read_time(struct device *dev, struct rtc_time *rtm)
{
unsigned long v;
time64_t t;
v = readl(SYS_TOYREAD0);
t = readl(SYS_TOYREAD1);
memset(rtm, 0, sizeof(struct rtc_time));
t = mktime64((t & LS1X_YEAR_MASK), ls1x_get_month(v),
ls1x_get_day(v), ls1x_get_hour(v),
ls1x_get_min(v), ls1x_get_sec(v));
rtc_time64_to_tm(t, rtm);
return 0;
}
static int ls1x_rtc_set_time(struct device *dev, struct rtc_time *rtm)
{
unsigned long v, t, c;
int ret = -ETIMEDOUT;
v = ((rtm->tm_mon + 1) << LS1X_MONTH_OFFSET)
| (rtm->tm_mday << LS1X_DAY_OFFSET)
| (rtm->tm_hour << LS1X_HOUR_OFFSET)
| (rtm->tm_min << LS1X_MIN_OFFSET)
| (rtm->tm_sec << LS1X_SEC_OFFSET);
writel(v, SYS_TOYWRITE0);
c = 0x10000;
/* add timeout check counter, for more safe */
while ((readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TS) && --c)
usleep_range(1000, 3000);
if (!c) {
dev_err(dev, "set time timeout!\n");
goto err;
}
t = rtm->tm_year + 1900;
writel(t, SYS_TOYWRITE1);
c = 0x10000;
while ((readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TS) && --c)
usleep_range(1000, 3000);
if (!c) {
dev_err(dev, "set time timeout!\n");
goto err;
}
return 0;
err:
return ret;
}
static const struct rtc_class_ops ls1x_rtc_ops = {
.read_time = ls1x_rtc_read_time,
.set_time = ls1x_rtc_set_time,
};
static int ls1x_rtc_probe(struct platform_device *pdev)
{
struct rtc_device *rtcdev;
unsigned long v;
v = readl(SYS_COUNTER_CNTRL);
if (!(v & RTC_CNTR_OK)) {
dev_err(&pdev->dev, "rtc counters not working\n");
return -ENODEV;
}
/* set to 1 HZ if needed */
if (readl(SYS_TOYTRIM) != 32767) {
v = 0x100000;
while ((readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TTS) && --v)
usleep_range(1000, 3000);
if (!v) {
dev_err(&pdev->dev, "time out\n");
return -ETIMEDOUT;
}
writel(32767, SYS_TOYTRIM);
}
/* this loop coundn't be endless */
while (readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_TTS)
usleep_range(1000, 3000);
rtcdev = devm_rtc_allocate_device(&pdev->dev);
if (IS_ERR(rtcdev))
return PTR_ERR(rtcdev);
platform_set_drvdata(pdev, rtcdev);
rtcdev->ops = &ls1x_rtc_ops;
rtcdev->range_min = RTC_TIMESTAMP_BEGIN_1900;
rtcdev->range_max = RTC_TIMESTAMP_END_2099;
return devm_rtc_register_device(rtcdev);
}
static struct platform_driver ls1x_rtc_driver = {
.driver = {
.name = "ls1x-rtc",
},
.probe = ls1x_rtc_probe,
};
module_platform_driver(ls1x_rtc_driver);
MODULE_AUTHOR("zhao zhang <zhzhl555@gmail.com>");
MODULE_LICENSE("GPL");

View File

@ -1013,7 +1013,7 @@ static struct i2c_driver m41t80_driver = {
.of_match_table = of_match_ptr(m41t80_of_match),
.pm = &m41t80_pm,
},
.probe_new = m41t80_probe,
.probe = m41t80_probe,
.remove = m41t80_remove,
.id_table = m41t80_id,
};

View File

@ -224,7 +224,7 @@ static struct i2c_driver max6900_driver = {
.driver = {
.name = "rtc-max6900",
},
.probe_new = max6900_probe,
.probe = max6900_probe,
.id_table = max6900_id,
};

View File

@ -540,7 +540,7 @@ static struct i2c_driver nct3018y_driver = {
.name = "rtc-nct3018y",
.of_match_table = of_match_ptr(nct3018y_of_match),
},
.probe_new = nct3018y_probe,
.probe = nct3018y_probe,
.id_table = nct3018y_id,
};

View File

@ -923,7 +923,7 @@ static struct i2c_driver pcf2127_i2c_driver = {
.name = "rtc-pcf2127-i2c",
.of_match_table = of_match_ptr(pcf2127_of_match),
},
.probe_new = pcf2127_i2c_probe,
.probe = pcf2127_i2c_probe,
.id_table = pcf2127_i2c_id,
};

View File

@ -681,7 +681,7 @@ static struct i2c_driver pcf85063_driver = {
.name = "rtc-pcf85063",
.of_match_table = of_match_ptr(pcf85063_of_match),
},
.probe_new = pcf85063_probe,
.probe = pcf85063_probe,
.id_table = pcf85063_ids,
};

View File

@ -488,7 +488,7 @@ static struct i2c_driver pcf8523_driver = {
.name = "rtc-pcf8523",
.of_match_table = pcf8523_of_match,
},
.probe_new = pcf8523_probe,
.probe = pcf8523_probe,
.id_table = pcf8523_id,
};
module_i2c_driver(pcf8523_driver);

View File

@ -475,7 +475,7 @@ static struct i2c_driver pcf85363_driver = {
.name = "pcf85363",
.of_match_table = of_match_ptr(dev_ids),
},
.probe_new = pcf85363_probe,
.probe = pcf85363_probe,
};
module_i2c_driver(pcf85363_driver);

View File

@ -612,7 +612,7 @@ static struct i2c_driver pcf8563_driver = {
.name = "rtc-pcf8563",
.of_match_table = of_match_ptr(pcf8563_of_match),
},
.probe_new = pcf8563_probe,
.probe = pcf8563_probe,
.id_table = pcf8563_id,
};

View File

@ -306,7 +306,7 @@ static struct i2c_driver pcf8583_driver = {
.driver = {
.name = "pcf8583",
},
.probe_new = pcf8583_probe,
.probe = pcf8583_probe,
.id_table = pcf8583_id,
};

View File

@ -921,7 +921,7 @@ static struct i2c_driver rs5c372_driver = {
.name = "rtc-rs5c372",
.of_match_table = of_match_ptr(rs5c372_of_match),
},
.probe_new = rs5c372_probe,
.probe = rs5c372_probe,
.remove = rs5c372_remove,
.id_table = rs5c372_id,
};

View File

@ -994,13 +994,20 @@ static const __maybe_unused struct of_device_id rv3028_of_match[] = {
};
MODULE_DEVICE_TABLE(of, rv3028_of_match);
static const struct i2c_device_id rv3028_id_table[] = {
{ .name = "rv3028", },
{ }
};
MODULE_DEVICE_TABLE(i2c, rv3028_id_table);
static struct i2c_driver rv3028_driver = {
.driver = {
.name = "rtc-rv3028",
.acpi_match_table = rv3028_i2c_acpi_match,
.of_match_table = of_match_ptr(rv3028_of_match),
},
.probe_new = rv3028_probe,
.id_table = rv3028_id_table,
.probe = rv3028_probe,
};
module_i2c_driver(rv3028_driver);

View File

@ -824,7 +824,7 @@ static struct i2c_driver rv3029_driver = {
.name = "rv3029",
.of_match_table = of_match_ptr(rv3029_of_match),
},
.probe_new = rv3029_i2c_probe,
.probe = rv3029_i2c_probe,
.id_table = rv3029_id,
};

View File

@ -842,7 +842,7 @@ static int rv3032_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
return err;
}
static const struct hwmon_channel_info *rv3032_hwmon_info[] = {
static const struct hwmon_channel_info * const 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
@ -998,7 +998,7 @@ static struct i2c_driver rv3032_driver = {
.acpi_match_table = rv3032_i2c_acpi_match,
.of_match_table = of_match_ptr(rv3032_of_match),
},
.probe_new = rv3032_probe,
.probe = rv3032_probe,
};
module_i2c_driver(rv3032_driver);

View File

@ -739,7 +739,7 @@ static struct i2c_driver rv8803_driver = {
.name = "rtc-rv8803",
.of_match_table = of_match_ptr(rv8803_of_match),
},
.probe_new = rv8803_probe,
.probe = rv8803_probe,
.id_table = rv8803_id,
};
module_i2c_driver(rv8803_driver);

View File

@ -462,7 +462,7 @@ static struct i2c_driver rx6110_i2c_driver = {
.name = RX6110_DRIVER_NAME,
.acpi_match_table = rx6110_i2c_acpi_match,
},
.probe_new = rx6110_i2c_probe,
.probe = rx6110_i2c_probe,
.id_table = rx6110_i2c_id,
};

View File

@ -424,7 +424,7 @@ static struct i2c_driver rx8010_driver = {
.name = "rtc-rx8010",
.of_match_table = of_match_ptr(rx8010_of_match),
},
.probe_new = rx8010_probe,
.probe = rx8010_probe,
.id_table = rx8010_id,
};

View File

@ -581,7 +581,7 @@ static struct i2c_driver rx8025_driver = {
.driver = {
.name = "rtc-rx8025",
},
.probe_new = rx8025_probe,
.probe = rx8025_probe,
.id_table = rx8025_id,
};

View File

@ -325,7 +325,7 @@ static struct i2c_driver rx8581_driver = {
.name = "rtc-rx8581",
.of_match_table = of_match_ptr(rx8581_of_match),
},
.probe_new = rx8581_probe,
.probe = rx8581_probe,
.id_table = rx8581_id,
};

View File

@ -499,7 +499,7 @@ static struct i2c_driver s35390a_driver = {
.name = "rtc-s35390a",
.of_match_table = of_match_ptr(s35390a_of_match),
},
.probe_new = s35390a_probe,
.probe = s35390a_probe,
.id_table = s35390a_id,
};

View File

@ -217,7 +217,7 @@ static struct i2c_driver sd3078_driver = {
.name = "sd3078",
.of_match_table = of_match_ptr(rtc_dt_match),
},
.probe_new = sd3078_probe,
.probe = sd3078_probe,
.id_table = sd3078_id,
};

View File

@ -228,17 +228,13 @@ static int st_rtc_probe(struct platform_device *pdev)
enable_irq_wake(rtc->irq);
disable_irq(rtc->irq);
rtc->clk = clk_get(&pdev->dev, NULL);
if (IS_ERR(rtc->clk)) {
dev_err(&pdev->dev, "Unable to request clock\n");
return PTR_ERR(rtc->clk);
}
clk_prepare_enable(rtc->clk);
rtc->clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(rtc->clk))
return dev_err_probe(&pdev->dev, PTR_ERR(rtc->clk),
"Unable to request clock\n");
rtc->clkrate = clk_get_rate(rtc->clk);
if (!rtc->clkrate) {
clk_disable_unprepare(rtc->clk);
dev_err(&pdev->dev, "Unable to fetch clock rate\n");
return -EINVAL;
}
@ -252,10 +248,8 @@ static int st_rtc_probe(struct platform_device *pdev)
do_div(rtc->rtc_dev->range_max, rtc->clkrate);
ret = devm_rtc_register_device(rtc->rtc_dev);
if (ret) {
clk_disable_unprepare(rtc->clk);
if (ret)
return ret;
}
return 0;
}

View File

@ -114,7 +114,6 @@ struct stm32_rtc_data {
void (*clear_events)(struct stm32_rtc *rtc, unsigned int flags);
bool has_pclk;
bool need_dbp;
bool has_wakeirq;
};
struct stm32_rtc {
@ -127,7 +126,6 @@ struct stm32_rtc {
struct clk *rtc_ck;
const struct stm32_rtc_data *data;
int irq_alarm;
int wakeirq_alarm;
};
static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc)
@ -547,7 +545,6 @@ static void stm32_rtc_clear_events(struct stm32_rtc *rtc,
static const struct stm32_rtc_data stm32_rtc_data = {
.has_pclk = false,
.need_dbp = true,
.has_wakeirq = false,
.regs = {
.tr = 0x00,
.dr = 0x04,
@ -569,7 +566,6 @@ static const struct stm32_rtc_data stm32_rtc_data = {
static const struct stm32_rtc_data stm32h7_rtc_data = {
.has_pclk = true,
.need_dbp = true,
.has_wakeirq = false,
.regs = {
.tr = 0x00,
.dr = 0x04,
@ -600,7 +596,6 @@ static void stm32mp1_rtc_clear_events(struct stm32_rtc *rtc,
static const struct stm32_rtc_data stm32mp1_data = {
.has_pclk = true,
.need_dbp = false,
.has_wakeirq = true,
.regs = {
.tr = 0x00,
.dr = 0x04,
@ -779,19 +774,12 @@ static int stm32_rtc_probe(struct platform_device *pdev)
}
ret = device_init_wakeup(&pdev->dev, true);
if (rtc->data->has_wakeirq) {
rtc->wakeirq_alarm = platform_get_irq(pdev, 1);
if (rtc->wakeirq_alarm > 0) {
ret = dev_pm_set_dedicated_wake_irq(&pdev->dev,
rtc->wakeirq_alarm);
} else {
ret = rtc->wakeirq_alarm;
if (rtc->wakeirq_alarm == -EPROBE_DEFER)
goto err;
}
}
if (ret)
dev_warn(&pdev->dev, "alarm can't wake up the system: %d", ret);
goto err;
ret = dev_pm_set_wake_irq(&pdev->dev, rtc->irq_alarm);
if (ret)
goto err;
platform_set_drvdata(pdev, rtc);
@ -879,9 +867,6 @@ static int stm32_rtc_suspend(struct device *dev)
if (rtc->data->has_pclk)
clk_disable_unprepare(rtc->pclk);
if (device_may_wakeup(dev))
return enable_irq_wake(rtc->irq_alarm);
return 0;
}
@ -903,9 +888,6 @@ static int stm32_rtc_resume(struct device *dev)
return ret;
}
if (device_may_wakeup(dev))
return disable_irq_wake(rtc->irq_alarm);
return ret;
}
#endif

View File

@ -679,7 +679,7 @@ static struct i2c_driver x1205_driver = {
.name = "rtc-x1205",
.of_match_table = x1205_dt_ids,
},
.probe_new = x1205_probe,
.probe = x1205_probe,
.remove = x1205_remove,
.id_table = x1205_id,
};