mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
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:
commit
b349de4c91
@ -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>;
|
||||
};
|
||||
|
100
Documentation/devicetree/bindings/rtc/isil,isl1208.yaml
Normal file
100
Documentation/devicetree/bindings/rtc/isil,isl1208.yaml
Normal 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>;
|
||||
};
|
||||
};
|
57
Documentation/devicetree/bindings/rtc/loongson,rtc.yaml
Normal file
57
Documentation/devicetree/bindings/rtc/loongson,rtc.yaml
Normal 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>;
|
||||
};
|
||||
|
||||
...
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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
397
drivers/rtc/rtc-loongson.c
Normal 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");
|
@ -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");
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -306,7 +306,7 @@ static struct i2c_driver pcf8583_driver = {
|
||||
.driver = {
|
||||
.name = "pcf8583",
|
||||
},
|
||||
.probe_new = pcf8583_probe,
|
||||
.probe = pcf8583_probe,
|
||||
.id_table = pcf8583_id,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user