提交 13f6f62f 编写于 作者: L Linus Torvalds

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

Pull RTC updates from Alexandre Belloni:
 "Core:
   - New sysfs interface to set and read clock offset
   - Drivers can now be both I2C and SPI (see pcf2127 and ds3232)

  New drivers:
   - Alphascale ASM9260
   - Epson RX6110SA
   - Maxim max20024 and max77620 (in max77686)
   - Microchip PIC32
   - NXP pcf2129 (in pcf2127)

  Subsystem wide cleanups:
   - remove IRQF_EARLY_RESUME when unecessary

  Drivers:
   - ds1307: clock output, temperature sensor and wakeup-source support
   - ds1685: actually spin forever in poweroff error path
   - ds3232: many cleanups
   - ds3234: merged in ds3232
   - hym8563: fix invalid year calculation
   - max77686: many cleanups
   - max77802 merged in max77686
   - pcf2123: cleanups and offset support
   - pcf85063: cleanups
   - pcf8523: propely handle oscillator stop bit
   - rv3029: many cleanups, trickle charger and temperature sensor support
   - rv8803: convert spin_lock to mutex_lock
   - rx8025: many fixes
   - vr41xx: restore alarm_irq_enable"

* tag 'rtc-4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (86 commits)
  rtc: pcf2127: add pcf2129 device id
  rtc: pcf2127: add support for spi interface
  rtc: pcf2127: convert to use regmap
  rtc: rv3029: Add thermometer hwmon support
  rtc: rv3029: Add update_bits helper for eeprom access
  rtc: ds1685: actually spin forever in poweroff error path
  rtc: hym8563: fix invalid year calculation
  rtc: ds3232: use rtc->ops_lock to protect alarm operations
  rtc: ds3232: fix issue when irq is shared several devices
  rtc: ds3232: remove unused UIE code
  rtc: ds3232: add register access error checks
  rtc: ds3232: fix read on /dev/rtc after RTC_AIE_ON
  rtc: merge ds3232 and ds3234
  rtc: ds3232: convert to use regmap
  rtc: pxa: fix Kconfig indentation
  rtc: rv3029: Add device tree property for trickle charger
  rtc: rv3029: Add functions for EEPROM access
  rtc: rv3029: Add i2c register update-bits helper
  rtc: rv3029: Add missing register definitions
  rtc: rv3029: Add "rv3029" I2C device id
  ...
* Alphascale asm9260 SoC Real Time Clock
Required properties:
- compatible: Should be "alphascale,asm9260-rtc"
- reg: Physical base address of the controller and length
of memory mapped region.
- interrupts: IRQ line for the RTC.
- clocks: Reference to the clock entry.
- clock-names: should contain:
* "ahb" for the SoC RTC clock
Example:
rtc0: rtc@800a0000 {
compatible = "alphascale,asm9260-rtc";
reg = <0x800a0000 0x100>;
clocks = <&acc CLKID_AHB_RTC>;
clock-names = "ahb";
interrupts = <2>;
};
Epson RX6110 Real Time Clock
============================
The Epson RX6110 can be used with SPI or I2C busses. The kind of
bus depends on the SPISEL pin and can not be configured via software.
I2C mode
--------
Required properties:
- compatible: should be: "epson,rx6110"
- reg : the I2C address of the device for I2C
Example:
rtc: rtc@32 {
compatible = "epson,rx6110"
reg = <0x32>;
};
SPI mode
--------
Required properties:
- compatible: should be: "epson,rx6110"
- reg: chip select number
- spi-cs-high: RX6110 needs chipselect high
- spi-cpha: RX6110 works with SPI shifted clock phase
- spi-cpol: RX6110 works with SPI inverse clock polarity
Example:
rtc: rtc@3 {
compatible = "epson,rx6110"
reg = <3>
spi-cs-high;
spi-cpha;
spi-cpol;
};
* Maxim DS3231 Real Time Clock
Required properties:
see: Documentation/devicetree/bindings/i2c/trivial-devices.txt
Optional property:
- #clock-cells: Should be 1.
- clock-output-names:
overwrite the default clock names "ds3231_clk_sqw" and "ds3231_clk_32khz".
Each clock is assigned an identifier and client nodes can use this identifier
to specify the clock which they consume. Following indices are allowed:
- 0: square-wave output on the SQW pin
- 1: square-wave output on the 32kHz pin
- interrupts: rtc alarm/event interrupt. When this property is selected,
clock on the SQW pin cannot be used.
Example:
ds3231: ds3231@51 {
compatible = "maxim,ds3231";
reg = <0x68>;
#clock-cells = <1>;
};
device1 {
...
clocks = <&ds3231 0>;
...
};
device2 {
...
clocks = <&ds3231 1>;
...
};
* Microchip PIC32 Real Time Clock and Calendar
The RTCC keeps time in hours, minutes, and seconds, and one half second. It
provides a calendar in weekday, date, month, and year. It also provides a
configurable alarm.
Required properties:
- compatible: should be: "microchip,pic32mzda-rtc"
- reg: physical base address of the controller and length of memory mapped
region.
- interrupts: RTC alarm/event interrupt
- clocks: clock phandle
Example:
rtc: rtc@1f8c0000 {
compatible = "microchip,pic32mzda-rtc";
reg = <0x1f8c0000 0x60>;
interrupts = <166 IRQ_TYPE_EDGE_RISING>;
clocks = <&PBCLK6>;
};
......@@ -157,6 +157,12 @@ wakealarm: The time at which the clock will generate a system wakeup
the epoch by default, or if there's a leading +, seconds in the
future, or if there is a leading +=, seconds ahead of the current
alarm.
offset: The amount which the rtc clock has been adjusted in firmware.
Visible only if the driver supports clock offset adjustment.
The unit is parts per billion, i.e. The number of clock ticks
which are added to or removed from the rtc's base clock per
billion ticks. A positive value makes a day pass more slowly,
longer, and a negative value makes a day pass more quickly.
IOCTL INTERFACE
---------------
......
......@@ -35,8 +35,6 @@
#include <linux/err.h>
#include <linux/of.h>
#define I2C_ADDR_RTC (0x0C >> 1)
static const struct mfd_cell max77686_devs[] = {
{ .name = "max77686-pmic", },
{ .name = "max77686-rtc", },
......@@ -116,11 +114,6 @@ static const struct regmap_config max77686_regmap_config = {
.val_bits = 8,
};
static const struct regmap_config max77686_rtc_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
static const struct regmap_config max77802_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
......@@ -156,25 +149,6 @@ static const struct regmap_irq_chip max77686_irq_chip = {
.num_irqs = ARRAY_SIZE(max77686_irqs),
};
static const struct regmap_irq max77686_rtc_irqs[] = {
/* RTC interrupts */
{ .reg_offset = 0, .mask = MAX77686_RTCINT_RTC60S_MSK, },
{ .reg_offset = 0, .mask = MAX77686_RTCINT_RTCA1_MSK, },
{ .reg_offset = 0, .mask = MAX77686_RTCINT_RTCA2_MSK, },
{ .reg_offset = 0, .mask = MAX77686_RTCINT_SMPL_MSK, },
{ .reg_offset = 0, .mask = MAX77686_RTCINT_RTC1S_MSK, },
{ .reg_offset = 0, .mask = MAX77686_RTCINT_WTSR_MSK, },
};
static const struct regmap_irq_chip max77686_rtc_irq_chip = {
.name = "max77686-rtc",
.status_base = MAX77686_RTC_INT,
.mask_base = MAX77686_RTC_INTM,
.num_regs = 1,
.irqs = max77686_rtc_irqs,
.num_irqs = ARRAY_SIZE(max77686_rtc_irqs),
};
static const struct regmap_irq_chip max77802_irq_chip = {
.name = "max77802-pmic",
.status_base = MAX77802_REG_INT1,
......@@ -184,15 +158,6 @@ static const struct regmap_irq_chip max77802_irq_chip = {
.num_irqs = ARRAY_SIZE(max77686_irqs),
};
static const struct regmap_irq_chip max77802_rtc_irq_chip = {
.name = "max77802-rtc",
.status_base = MAX77802_RTC_INT,
.mask_base = MAX77802_RTC_INTM,
.num_regs = 1,
.irqs = max77686_rtc_irqs, /* same masks as 77686 */
.num_irqs = ARRAY_SIZE(max77686_rtc_irqs),
};
static const struct of_device_id max77686_pmic_dt_match[] = {
{
.compatible = "maxim,max77686",
......@@ -214,8 +179,6 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
int ret = 0;
const struct regmap_config *config;
const struct regmap_irq_chip *irq_chip;
const struct regmap_irq_chip *rtc_irq_chip;
struct regmap **rtc_regmap;
const struct mfd_cell *cells;
int n_devs;
......@@ -242,15 +205,11 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
if (max77686->type == TYPE_MAX77686) {
config = &max77686_regmap_config;
irq_chip = &max77686_irq_chip;
rtc_irq_chip = &max77686_rtc_irq_chip;
rtc_regmap = &max77686->rtc_regmap;
cells = max77686_devs;
n_devs = ARRAY_SIZE(max77686_devs);
} else {
config = &max77802_regmap_config;
irq_chip = &max77802_irq_chip;
rtc_irq_chip = &max77802_rtc_irq_chip;
rtc_regmap = &max77686->regmap;
cells = max77802_devs;
n_devs = ARRAY_SIZE(max77802_devs);
}
......@@ -270,60 +229,25 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
return -ENODEV;
}
if (max77686->type == TYPE_MAX77686) {
max77686->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
if (!max77686->rtc) {
dev_err(max77686->dev,
"Failed to allocate I2C device for RTC\n");
return -ENODEV;
}
i2c_set_clientdata(max77686->rtc, max77686);
max77686->rtc_regmap =
devm_regmap_init_i2c(max77686->rtc,
&max77686_rtc_regmap_config);
if (IS_ERR(max77686->rtc_regmap)) {
ret = PTR_ERR(max77686->rtc_regmap);
dev_err(max77686->dev,
"failed to allocate RTC regmap: %d\n",
ret);
goto err_unregister_i2c;
}
}
ret = regmap_add_irq_chip(max77686->regmap, max77686->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
IRQF_SHARED, 0, irq_chip,
&max77686->irq_data);
if (ret) {
if (ret < 0) {
dev_err(&i2c->dev, "failed to add PMIC irq chip: %d\n", ret);
goto err_unregister_i2c;
}
ret = regmap_add_irq_chip(*rtc_regmap, max77686->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
IRQF_SHARED, 0, rtc_irq_chip,
&max77686->rtc_irq_data);
if (ret) {
dev_err(&i2c->dev, "failed to add RTC irq chip: %d\n", ret);
goto err_del_irqc;
return ret;
}
ret = mfd_add_devices(max77686->dev, -1, cells, n_devs, NULL, 0, NULL);
if (ret < 0) {
dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
goto err_del_rtc_irqc;
goto err_del_irqc;
}
return 0;
err_del_rtc_irqc:
regmap_del_irq_chip(max77686->irq, max77686->rtc_irq_data);
err_del_irqc:
regmap_del_irq_chip(max77686->irq, max77686->irq_data);
err_unregister_i2c:
if (max77686->type == TYPE_MAX77686)
i2c_unregister_device(max77686->rtc);
return ret;
}
......@@ -334,12 +258,8 @@ static int max77686_i2c_remove(struct i2c_client *i2c)
mfd_remove_devices(max77686->dev);
regmap_del_irq_chip(max77686->irq, max77686->rtc_irq_data);
regmap_del_irq_chip(max77686->irq, max77686->irq_data);
if (max77686->type == TYPE_MAX77686)
i2c_unregister_device(max77686->rtc);
return 0;
}
......
......@@ -140,7 +140,6 @@ config RTC_DRV_TEST
will be called rtc-test.
comment "I2C RTC drivers"
depends on I2C
if I2C
......@@ -212,6 +211,15 @@ config RTC_DRV_DS1307
This driver can also be built as a module. If so, the module
will be called rtc-ds1307.
config RTC_DRV_DS1307_HWMON
bool "HWMON support for rtc-ds1307"
depends on RTC_DRV_DS1307 && HWMON
depends on !(RTC_DRV_DS1307=y && HWMON=m)
default y
help
Say Y here if you want to expose temperature sensor data on
rtc-ds1307 (only DS3231)
config RTC_DRV_DS1374
tristate "Dallas/Maxim DS1374"
help
......@@ -239,16 +247,6 @@ config RTC_DRV_DS1672
This driver can also be built as a module. If so, the module
will be called rtc-ds1672.
config RTC_DRV_DS3232
tristate "Dallas/Maxim DS3232"
help
If you say yes here you get support for Dallas Semiconductor
DS3232 real-time clock chips. If an interrupt is associated
with the device, the alarm functionality is supported.
This driver can also be built as a module. If so, the module
will be called rtc-ds3232.
config RTC_DRV_HYM8563
tristate "Haoyu Microelectronics HYM8563"
depends on OF
......@@ -317,10 +315,10 @@ config RTC_DRV_MAX8997
config RTC_DRV_MAX77686
tristate "Maxim MAX77686"
depends on MFD_MAX77686
depends on MFD_MAX77686 || MFD_MAX77620
help
If you say yes here you will get support for the
RTC of Maxim MAX77686 PMIC.
RTC of Maxim MAX77686/MAX77620/MAX77802 PMIC.
This driver can also be built as a module. If so, the module
will be called rtc-max77686.
......@@ -335,16 +333,6 @@ config RTC_DRV_RK808
This driver can also be built as a module. If so, the module
will be called rk808-rtc.
config RTC_DRV_MAX77802
tristate "Maxim 77802 RTC"
depends on MFD_MAX77686
help
If you say yes here you will get support for the
RTC of Maxim MAX77802 PMIC.
This driver can also be built as a module. If so, the module
will be called rtc-max77802.
config RTC_DRV_RS5C372
tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A"
help
......@@ -391,25 +379,6 @@ config RTC_DRV_X1205
This driver can also be built as a module. If so, the module
will be called rtc-x1205.
config RTC_DRV_PALMAS
tristate "TI Palmas RTC driver"
depends on MFD_PALMAS
help
If you say yes here you get support for the RTC of TI PALMA series PMIC
chips.
This driver can also be built as a module. If so, the module
will be called rtc-palma.
config RTC_DRV_PCF2127
tristate "NXP PCF2127"
help
If you say yes here you get support for the NXP PCF2127/29 RTC
chips.
This driver can also be built as a module. If so, the module
will be called rtc-pcf2127.
config RTC_DRV_PCF8523
tristate "NXP PCF8523"
help
......@@ -419,6 +388,14 @@ config RTC_DRV_PCF8523
This driver can also be built as a module. If so, the module
will be called rtc-pcf8523.
config RTC_DRV_PCF85063
tristate "NXP PCF85063"
help
If you say yes here you get support for the PCF85063 RTC chip
This driver can also be built as a module. If so, the module
will be called rtc-pcf85063.
config RTC_DRV_PCF8563
tristate "Philips PCF8563/Epson RTC8564"
help
......@@ -429,14 +406,6 @@ config RTC_DRV_PCF8563
This driver can also be built as a module. If so, the module
will be called rtc-pcf8563.
config RTC_DRV_PCF85063
tristate "nxp PCF85063"
help
If you say yes here you get support for the PCF85063 RTC chip
This driver can also be built as a module. If so, the module
will be called rtc-pcf85063.
config RTC_DRV_PCF8583
tristate "Philips PCF8583"
help
......@@ -501,6 +470,16 @@ config RTC_DRV_TWL4030
This driver can also be built as a module. If so, the module
will be called rtc-twl.
config RTC_DRV_PALMAS
tristate "TI Palmas RTC driver"
depends on MFD_PALMAS
help
If you say yes here you get support for the RTC of TI PALMA series PMIC
chips.
This driver can also be built as a module. If so, the module
will be called rtc-palma.
config RTC_DRV_TPS6586X
tristate "TI TPS6586X RTC driver"
depends on MFD_TPS6586X
......@@ -595,14 +574,23 @@ config RTC_DRV_EM3027
will be called rtc-em3027.
config RTC_DRV_RV3029C2
tristate "Micro Crystal RTC"
tristate "Micro Crystal RV3029"
help
If you say yes here you get support for the Micro Crystal
RV3029-C2 RTC chips.
RV3029 RTC chips.
This driver can also be built as a module. If so, the module
will be called rtc-rv3029c2.
config RTC_DRV_RV3029_HWMON
bool "HWMON support for RV3029"
depends on RTC_DRV_RV3029C2 && HWMON
depends on !(RTC_DRV_RV3029C2=y && HWMON=m)
default y
help
Say Y here if you want to expose temperature sensor data on
rtc-rv3029c2.
config RTC_DRV_RV8803
tristate "Micro Crystal RV8803"
help
......@@ -691,15 +679,6 @@ config RTC_DRV_DS1390
This driver can also be built as a module. If so, the module
will be called rtc-ds1390.
config RTC_DRV_MAX6902
tristate "Maxim MAX6902"
help
If you say yes here you will get support for the
Maxim MAX6902 SPI RTC chip.
This driver can also be built as a module. If so, the module
will be called rtc-max6902.
config RTC_DRV_R9701
tristate "Epson RTC-9701JE"
help
......@@ -709,6 +688,23 @@ config RTC_DRV_R9701
This driver can also be built as a module. If so, the module
will be called rtc-r9701.
config RTC_DRV_RX4581
tristate "Epson RX-4581"
help
If you say yes here you will get support for the Epson RX-4581.
This driver can also be built as a module. If so the module
will be called rtc-rx4581.
config RTC_DRV_RX6110
tristate "Epson RX-6110"
select REGMAP_SPI
help
If you say yes here you will get support for the Epson RX-6610.
This driver can also be built as a module. If so the module
will be called rtc-rx6110.
config RTC_DRV_RS5C348
tristate "Ricoh RS5C348A/B"
help
......@@ -718,14 +714,14 @@ config RTC_DRV_RS5C348
This driver can also be built as a module. If so, the module
will be called rtc-rs5c348.
config RTC_DRV_DS3234
tristate "Maxim/Dallas DS3234"
config RTC_DRV_MAX6902
tristate "Maxim MAX6902"
help
If you say yes here you get support for the
Maxim/Dallas DS3234 SPI RTC chip.
If you say yes here you will get support for the
Maxim MAX6902 SPI RTC chip.
This driver can also be built as a module. If so, the module
will be called rtc-ds3234.
will be called rtc-max6902.
config RTC_DRV_PCF2123
tristate "NXP PCF2123"
......@@ -736,14 +732,6 @@ config RTC_DRV_PCF2123
This driver can also be built as a module. If so, the module
will be called rtc-pcf2123.
config RTC_DRV_RX4581
tristate "Epson RX-4581"
help
If you say yes here you will get support for the Epson RX-4581.
This driver can also be built as a module. If so the module
will be called rtc-rx4581.
config RTC_DRV_MCP795
tristate "Microchip MCP795"
help
......@@ -754,6 +742,41 @@ config RTC_DRV_MCP795
endif # SPI_MASTER
#
# Helper to resolve issues with configs that have SPI enabled but I2C
# modular. See SND_SOC_I2C_AND_SPI for more information
#
config RTC_I2C_AND_SPI
tristate
default m if I2C=m
default y if I2C=y
default y if SPI_MASTER=y
select REGMAP_I2C if I2C
select REGMAP_SPI if SPI_MASTER
comment "SPI and I2C RTC drivers"
config RTC_DRV_DS3232
tristate "Dallas/Maxim DS3232/DS3234"
depends on RTC_I2C_AND_SPI
help
If you say yes here you get support for Dallas Semiconductor
DS3232 and DS3234 real-time clock chips. If an interrupt is associated
with the device, the alarm functionality is supported.
This driver can also be built as a module. If so, the module
will be called rtc-ds3232.
config RTC_DRV_PCF2127
tristate "NXP PCF2127"
depends on RTC_I2C_AND_SPI
help
If you say yes here you get support for the NXP PCF2127/29 RTC
chips.
This driver can also be built as a module. If so, the module
will be called rtc-pcf2127.
comment "Platform RTC drivers"
# this 'CMOS' RTC driver is arch dependent because <asm-generic/rtc.h>
......@@ -1087,7 +1110,7 @@ config RTC_DRV_WM8350
config RTC_DRV_SPEAR
tristate "SPEAR ST RTC"
depends on PLAT_SPEAR
depends on PLAT_SPEAR || COMPILE_TEST
default y
help
If you say Y here you will get support for the RTC found on
......@@ -1119,7 +1142,7 @@ config RTC_DRV_AB8500
config RTC_DRV_NUC900
tristate "NUC910/NUC920 RTC driver"
depends on ARCH_W90X900
depends on ARCH_W90X900 || COMPILE_TEST
help
If you say yes here you get support for the RTC subsystem of the
NUC910/NUC920 used in embedded systems.
......@@ -1144,9 +1167,19 @@ config RTC_DRV_ZYNQMP
comment "on-CPU RTC drivers"
config RTC_DRV_ASM9260
tristate "Alphascale asm9260 RTC"
depends on MACH_ASM9260
help
If you say yes here you get support for the RTC on the
Alphascale asm9260 SoC.
This driver can also be built as a module. If so, the module
will be called rtc-asm9260.
config RTC_DRV_DAVINCI
tristate "TI DaVinci RTC"
depends on ARCH_DAVINCI_DM365
depends on ARCH_DAVINCI_DM365 || COMPILE_TEST
help
If you say yes here you get support for the RTC on the
DaVinci platforms (DM365).
......@@ -1156,7 +1189,7 @@ config RTC_DRV_DAVINCI
config RTC_DRV_DIGICOLOR
tristate "Conexant Digicolor RTC"
depends on ARCH_DIGICOLOR
depends on ARCH_DIGICOLOR || COMPILE_TEST
help
If you say yes here you get support for the RTC on Conexant
Digicolor platforms. This currently includes the CX92755 SoC.
......@@ -1175,7 +1208,7 @@ config RTC_DRV_IMXDI
config RTC_DRV_OMAP
tristate "TI OMAP Real Time Clock"
depends on ARCH_OMAP || ARCH_DAVINCI
depends on ARCH_OMAP || ARCH_DAVINCI || COMPILE_TEST
help
Say "yes" here to support the on chip real time clock
present on TI OMAP1, AM33xx, DA8xx/OMAP-L13x, AM43xx and DRA7xx.
......@@ -1192,7 +1225,7 @@ config HAVE_S3C_RTC
config RTC_DRV_S3C
tristate "Samsung S3C series SoC RTC"
depends on ARCH_S3C64XX || HAVE_S3C_RTC
depends on ARCH_S3C64XX || HAVE_S3C_RTC || COMPILE_TEST
help
RTC (Realtime Clock) driver for the clock inbuilt into the
Samsung S3C24XX series of SoCs. This can provide periodic
......@@ -1208,7 +1241,7 @@ config RTC_DRV_S3C
config RTC_DRV_EP93XX
tristate "Cirrus Logic EP93XX"
depends on ARCH_EP93XX
depends on ARCH_EP93XX || COMPILE_TEST
help
If you say yes here you get support for the
RTC embedded in the Cirrus Logic EP93XX processors.
......@@ -1238,7 +1271,7 @@ config RTC_DRV_SH
config RTC_DRV_VR41XX
tristate "NEC VR41XX"
depends on CPU_VR41XX
depends on CPU_VR41XX || COMPILE_TEST
help
If you say Y here you will get access to the real time clock
built into your NEC VR41XX CPU.
......@@ -1268,14 +1301,14 @@ config RTC_DRV_PL031
config RTC_DRV_AT32AP700X
tristate "AT32AP700X series RTC"
depends on PLATFORM_AT32AP
depends on PLATFORM_AT32AP || COMPILE_TEST
help
Driver for the internal RTC (Realtime Clock) on Atmel AVR32
AT32AP700x family processors.
config RTC_DRV_AT91RM9200
tristate "AT91RM9200 or some AT91SAM9 RTC"
depends on ARCH_AT91
depends on ARCH_AT91 || COMPILE_TEST
help
Driver for the internal RTC (Realtime Clock) module found on
Atmel AT91RM9200's and some AT91SAM9 chips. On AT91SAM9 chips
......@@ -1283,7 +1316,7 @@ config RTC_DRV_AT91RM9200
config RTC_DRV_AT91SAM9
tristate "AT91SAM9 RTT as RTC"
depends on ARCH_AT91
depends on ARCH_AT91 || COMPILE_TEST
select MFD_SYSCON
help
Some AT91SAM9 SoCs provide an RTT (Real Time Timer) block which
......@@ -1325,17 +1358,17 @@ config RTC_DRV_GENERIC
tristate "Generic RTC support"
# Please consider writing a new RTC driver instead of using the generic
# RTC abstraction
depends on PARISC || M68K || PPC || SUPERH32
depends on PARISC || M68K || PPC || SUPERH32 || COMPILE_TEST
help
Say Y or M here to enable RTC support on systems using the generic
RTC abstraction. If you do not know what you are doing, you should
just say Y.
config RTC_DRV_PXA
tristate "PXA27x/PXA3xx"
depends on ARCH_PXA
select RTC_DRV_SA1100
help
tristate "PXA27x/PXA3xx"
depends on ARCH_PXA
select RTC_DRV_SA1100
help
If you say Y here you will get access to the real time clock
built into your PXA27x or PXA3xx CPU. This RTC is actually 2 RTCs
consisting of an SA1100 compatible RTC and the extended PXA RTC.
......@@ -1345,7 +1378,7 @@ config RTC_DRV_PXA
config RTC_DRV_VT8500
tristate "VIA/WonderMedia 85xx SoC RTC"
depends on ARCH_VT8500
depends on ARCH_VT8500 || COMPILE_TEST
help
If you say Y here you will get access to the real time clock
built into your VIA VT8500 SoC or its relatives.
......@@ -1360,14 +1393,15 @@ config RTC_DRV_SUN4V
config RTC_DRV_SUN6I
tristate "Allwinner A31 RTC"
depends on MACH_SUN6I || MACH_SUN8I
default MACH_SUN6I || MACH_SUN8I || COMPILE_TEST
depends on ARCH_SUNXI
help
If you say Y here you will get support for the RTC found on
Allwinner A31.
If you say Y here you will get support for the RTC found in
some Allwinner SoCs like the A31 or the A64.
config RTC_DRV_SUNXI
tristate "Allwinner sun4i/sun7i RTC"
depends on MACH_SUN4I || MACH_SUN7I
depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
help
If you say Y here you will get support for the RTC found on
Allwinner A10/A20.
......@@ -1388,7 +1422,7 @@ config RTC_DRV_TX4939
config RTC_DRV_MV
tristate "Marvell SoC RTC"
depends on ARCH_DOVE || ARCH_MVEBU
depends on ARCH_DOVE || ARCH_MVEBU || COMPILE_TEST
help
If you say yes here you will get support for the in-chip RTC
that can be found in some of Marvell's SoC devices, such as
......@@ -1399,7 +1433,7 @@ config RTC_DRV_MV
config RTC_DRV_ARMADA38X
tristate "Armada 38x Marvell SoC RTC"
depends on ARCH_MVEBU
depends on ARCH_MVEBU || COMPILE_TEST
help
If you say yes here you will get support for the in-chip RTC
that can be found in the Armada 38x Marvell's SoC device
......@@ -1429,7 +1463,7 @@ config RTC_DRV_PS3
config RTC_DRV_COH901331
tristate "ST-Ericsson COH 901 331 RTC"
depends on ARCH_U300
depends on ARCH_U300 || COMPILE_TEST
help
If you say Y here you will get access to ST-Ericsson
COH 901 331 RTC clock found in some ST-Ericsson Mobile
......@@ -1441,7 +1475,7 @@ config RTC_DRV_COH901331
config RTC_DRV_STMP
tristate "Freescale STMP3xxx/i.MX23/i.MX28 RTC"
depends on ARCH_MXS
depends on ARCH_MXS || COMPILE_TEST
select STMP_DEVICE
help
If you say yes here you will get support for the onboard
......@@ -1476,7 +1510,7 @@ config RTC_DRV_MPC5121
config RTC_DRV_JZ4740
tristate "Ingenic JZ4740 SoC"
depends on MACH_JZ4740
depends on MACH_JZ4740 || COMPILE_TEST
help
If you say yes here you get support for the Ingenic JZ4740 SoC RTC
controller.
......@@ -1497,7 +1531,7 @@ config RTC_DRV_LPC24XX
so, the module will be called rtc-lpc24xx.
config RTC_DRV_LPC32XX
depends on ARCH_LPC32XX
depends on ARCH_LPC32XX || COMPILE_TEST
tristate "NXP LPC32XX RTC"
help
This enables support for the NXP RTC in the LPC32XX
......@@ -1507,7 +1541,7 @@ config RTC_DRV_LPC32XX
config RTC_DRV_PM8XXX
tristate "Qualcomm PMIC8XXX RTC"
depends on MFD_PM8XXX || MFD_SPMI_PMIC
depends on MFD_PM8XXX || MFD_SPMI_PMIC || COMPILE_TEST
help
If you say yes here you get support for the
Qualcomm PMIC8XXX RTC.
......@@ -1517,7 +1551,7 @@ config RTC_DRV_PM8XXX
config RTC_DRV_TEGRA
tristate "NVIDIA Tegra Internal RTC driver"
depends on ARCH_TEGRA
depends on ARCH_TEGRA || COMPILE_TEST
help
If you say yes here you get support for the
Tegra 200 series internal RTC module.
......@@ -1603,7 +1637,7 @@ config RTC_DRV_MOXART
config RTC_DRV_MT6397
tristate "Mediatek Real Time Clock driver"
depends on MFD_MT6397 || COMPILE_TEST
depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN)
help
This selects the Mediatek(R) RTC driver. RTC is part of Mediatek
MT6397 PMIC. You should enable MT6397 PMIC MFD before select
......@@ -1622,6 +1656,16 @@ config RTC_DRV_XGENE
This driver can also be built as a module, if so, the module
will be called "rtc-xgene".
config RTC_DRV_PIC32
tristate "Microchip PIC32 RTC"
depends on MACH_PIC32
default y
help
If you say yes here you get support for the PIC32 RTC module.
This driver can also be built as a module. If so, the module
will be called rtc-pic32
comment "HID Sensor RTC drivers"
config RTC_DRV_HID_SENSOR_TIME
......
......@@ -28,6 +28,7 @@ obj-$(CONFIG_RTC_DRV_ABB5ZES3) += rtc-ab-b5ze-s3.o
obj-$(CONFIG_RTC_DRV_ABX80X) += rtc-abx80x.o
obj-$(CONFIG_RTC_DRV_ARMADA38X) += rtc-armada38x.o
obj-$(CONFIG_RTC_DRV_AS3722) += rtc-as3722.o
obj-$(CONFIG_RTC_DRV_ASM9260) += rtc-asm9260.o
obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o
......@@ -59,7 +60,6 @@ obj-$(CONFIG_RTC_DRV_DS1685_FAMILY) += rtc-ds1685.o
obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds1742.o
obj-$(CONFIG_RTC_DRV_DS2404) += rtc-ds2404.o
obj-$(CONFIG_RTC_DRV_DS3232) += rtc-ds3232.o
obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o
obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o
obj-$(CONFIG_RTC_DRV_EM3027) += rtc-em3027.o
obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o
......@@ -86,7 +86,6 @@ obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o
obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.o
obj-$(CONFIG_RTC_DRV_MAX77802) += rtc-max77802.o
obj-$(CONFIG_RTC_DRV_MAX8907) += rtc-max8907.o
obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o
obj-$(CONFIG_RTC_DRV_MAX8997) += rtc-max8997.o
......@@ -112,6 +111,7 @@ obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.o
obj-$(CONFIG_RTC_DRV_PCF8523) += rtc-pcf8523.o
obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o
obj-$(CONFIG_RTC_DRV_PIC32) += rtc-pic32.o
obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o
obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o
obj-$(CONFIG_RTC_DRV_PM8XXX) += rtc-pm8xxx.o
......@@ -128,6 +128,7 @@ obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o
obj-$(CONFIG_RTC_DRV_RV3029C2) += rtc-rv3029c2.o
obj-$(CONFIG_RTC_DRV_RV8803) += rtc-rv8803.o
obj-$(CONFIG_RTC_DRV_RX4581) += rtc-rx4581.o
obj-$(CONFIG_RTC_DRV_RX6110) += rtc-rx6110.o
obj-$(CONFIG_RTC_DRV_RX8010) += rtc-rx8010.o
obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o
obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o
......
......@@ -361,17 +361,4 @@ static int __init rtc_init(void)
rtc_dev_init();
return 0;
}
static void __exit rtc_exit(void)
{
rtc_dev_exit();
class_destroy(rtc_class);
ida_destroy(&rtc_ida);
}
subsys_initcall(rtc_init);
module_exit(rtc_exit);
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
MODULE_DESCRIPTION("RTC class support");
MODULE_LICENSE("GPL");
......@@ -939,4 +939,58 @@ void rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer *timer)
mutex_unlock(&rtc->ops_lock);
}
/**
* rtc_read_offset - Read the amount of rtc offset in parts per billion
* @ rtc: rtc device to be used
* @ offset: the offset in parts per billion
*
* see below for details.
*
* Kernel interface to read rtc clock offset
* Returns 0 on success, or a negative number on error.
* If read_offset() is not implemented for the rtc, return -EINVAL
*/
int rtc_read_offset(struct rtc_device *rtc, long *offset)
{
int ret;
if (!rtc->ops)
return -ENODEV;
if (!rtc->ops->read_offset)
return -EINVAL;
mutex_lock(&rtc->ops_lock);
ret = rtc->ops->read_offset(rtc->dev.parent, offset);
mutex_unlock(&rtc->ops_lock);
return ret;
}
/**
* rtc_set_offset - Adjusts the duration of the average second
* @ rtc: rtc device to be used
* @ offset: the offset in parts per billion
*
* Some rtc's allow an adjustment to the average duration of a second
* to compensate for differences in the actual clock rate due to temperature,
* the crystal, capacitor, etc.
*
* Kernel interface to adjust an rtc clock offset.
* Return 0 on success, or a negative number on error.
* If the rtc offset is not setable (or not implemented), return -EINVAL
*/
int rtc_set_offset(struct rtc_device *rtc, long offset)
{
int ret;
if (!rtc->ops)
return -ENODEV;
if (!rtc->ops->set_offset)
return -EINVAL;
mutex_lock(&rtc->ops_lock);
ret = rtc->ops->set_offset(rtc->dev.parent, offset);
mutex_unlock(&rtc->ops_lock);
return ret;
}
......@@ -210,7 +210,7 @@ static int as3722_rtc_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "RTC interrupt %d\n", as3722_rtc->alarm_irq);
ret = devm_request_threaded_irq(&pdev->dev, as3722_rtc->alarm_irq, NULL,
as3722_alarm_irq, IRQF_ONESHOT | IRQF_EARLY_RESUME,
as3722_alarm_irq, IRQF_ONESHOT,
"rtc-alarm", as3722_rtc);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n",
......
/*
* Copyright (C) 2016 Oleksij Rempel <linux@rempel-privat.de>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*/
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
/* Miscellaneous registers */
/* Interrupt Location Register */
#define HW_ILR 0x00
#define BM_RTCALF BIT(1)
#define BM_RTCCIF BIT(0)
/* Clock Control Register */
#define HW_CCR 0x08
/* Calibration counter disable */
#define BM_CCALOFF BIT(4)
/* Reset internal oscillator divider */
#define BM_CTCRST BIT(1)
/* Clock Enable */
#define BM_CLKEN BIT(0)
/* Counter Increment Interrupt Register */
#define HW_CIIR 0x0C
#define BM_CIIR_IMYEAR BIT(7)
#define BM_CIIR_IMMON BIT(6)
#define BM_CIIR_IMDOY BIT(5)
#define BM_CIIR_IMDOW BIT(4)
#define BM_CIIR_IMDOM BIT(3)
#define BM_CIIR_IMHOUR BIT(2)
#define BM_CIIR_IMMIN BIT(1)
#define BM_CIIR_IMSEC BIT(0)
/* Alarm Mask Register */
#define HW_AMR 0x10
#define BM_AMR_IMYEAR BIT(7)
#define BM_AMR_IMMON BIT(6)
#define BM_AMR_IMDOY BIT(5)
#define BM_AMR_IMDOW BIT(4)
#define BM_AMR_IMDOM BIT(3)
#define BM_AMR_IMHOUR BIT(2)
#define BM_AMR_IMMIN BIT(1)
#define BM_AMR_IMSEC BIT(0)
#define BM_AMR_OFF 0xff
/* Consolidated time registers */
#define HW_CTIME0 0x14
#define BM_CTIME0_DOW_S 24
#define BM_CTIME0_DOW_M 0x7
#define BM_CTIME0_HOUR_S 16
#define BM_CTIME0_HOUR_M 0x1f
#define BM_CTIME0_MIN_S 8
#define BM_CTIME0_MIN_M 0x3f
#define BM_CTIME0_SEC_S 0
#define BM_CTIME0_SEC_M 0x3f
#define HW_CTIME1 0x18
#define BM_CTIME1_YEAR_S 16
#define BM_CTIME1_YEAR_M 0xfff
#define BM_CTIME1_MON_S 8
#define BM_CTIME1_MON_M 0xf
#define BM_CTIME1_DOM_S 0
#define BM_CTIME1_DOM_M 0x1f
#define HW_CTIME2 0x1C
#define BM_CTIME2_DOY_S 0
#define BM_CTIME2_DOY_M 0xfff
/* Time counter registers */
#define HW_SEC 0x20
#define HW_MIN 0x24
#define HW_HOUR 0x28
#define HW_DOM 0x2C
#define HW_DOW 0x30
#define HW_DOY 0x34
#define HW_MONTH 0x38
#define HW_YEAR 0x3C
#define HW_CALIBRATION 0x40
#define BM_CALDIR_BACK BIT(17)
#define BM_CALVAL_M 0x1ffff
/* General purpose registers */
#define HW_GPREG0 0x44
#define HW_GPREG1 0x48
#define HW_GPREG2 0x4C
#define HW_GPREG3 0x50
#define HW_GPREG4 0x54
/* Alarm register group */
#define HW_ALSEC 0x60
#define HW_ALMIN 0x64
#define HW_ALHOUR 0x68
#define HW_ALDOM 0x6C
#define HW_ALDOW 0x70
#define HW_ALDOY 0x74
#define HW_ALMON 0x78
#define HW_ALYEAR 0x7C
struct asm9260_rtc_priv {
struct device *dev;
void __iomem *iobase;
struct rtc_device *rtc;
struct clk *clk;
/* io lock */
spinlock_t lock;
};
static irqreturn_t asm9260_rtc_irq(int irq, void *dev_id)
{
struct asm9260_rtc_priv *priv = dev_id;
u32 isr;
unsigned long events = 0;
isr = ioread32(priv->iobase + HW_CIIR);
if (!isr)
return IRQ_NONE;
iowrite32(0, priv->iobase + HW_CIIR);
events |= RTC_AF | RTC_IRQF;
rtc_update_irq(priv->rtc, 1, events);
return IRQ_HANDLED;
}
static int asm9260_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
u32 ctime0, ctime1, ctime2;
unsigned long irq_flags;
spin_lock_irqsave(&priv->lock, irq_flags);
ctime0 = ioread32(priv->iobase + HW_CTIME0);
ctime1 = ioread32(priv->iobase + HW_CTIME1);
ctime2 = ioread32(priv->iobase + HW_CTIME2);
if (ctime1 != ioread32(priv->iobase + HW_CTIME1)) {
/*
* woops, counter flipped right now. Now we are safe
* to reread.
*/
ctime0 = ioread32(priv->iobase + HW_CTIME0);
ctime1 = ioread32(priv->iobase + HW_CTIME1);
ctime2 = ioread32(priv->iobase + HW_CTIME2);
}
spin_unlock_irqrestore(&priv->lock, irq_flags);
tm->tm_sec = (ctime0 >> BM_CTIME0_SEC_S) & BM_CTIME0_SEC_M;
tm->tm_min = (ctime0 >> BM_CTIME0_MIN_S) & BM_CTIME0_MIN_M;
tm->tm_hour = (ctime0 >> BM_CTIME0_HOUR_S) & BM_CTIME0_HOUR_M;
tm->tm_wday = (ctime0 >> BM_CTIME0_DOW_S) & BM_CTIME0_DOW_M;
tm->tm_mday = (ctime1 >> BM_CTIME1_DOM_S) & BM_CTIME1_DOM_M;
tm->tm_mon = (ctime1 >> BM_CTIME1_MON_S) & BM_CTIME1_MON_M;
tm->tm_year = (ctime1 >> BM_CTIME1_YEAR_S) & BM_CTIME1_YEAR_M;
tm->tm_yday = (ctime2 >> BM_CTIME2_DOY_S) & BM_CTIME2_DOY_M;
return 0;
}
static int asm9260_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
unsigned long irq_flags;
spin_lock_irqsave(&priv->lock, irq_flags);
/*
* make sure SEC counter will not flip other counter on write time,
* real value will be written at the enf of sequence.
*/
iowrite32(0, priv->iobase + HW_SEC);
iowrite32(tm->tm_year, priv->iobase + HW_YEAR);
iowrite32(tm->tm_mon, priv->iobase + HW_MONTH);
iowrite32(tm->tm_mday, priv->iobase + HW_DOM);
iowrite32(tm->tm_wday, priv->iobase + HW_DOW);
iowrite32(tm->tm_yday, priv->iobase + HW_DOY);
iowrite32(tm->tm_hour, priv->iobase + HW_HOUR);
iowrite32(tm->tm_min, priv->iobase + HW_MIN);
iowrite32(tm->tm_sec, priv->iobase + HW_SEC);
spin_unlock_irqrestore(&priv->lock, irq_flags);
return 0;
}
static int asm9260_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
unsigned long irq_flags;
spin_lock_irqsave(&priv->lock, irq_flags);
alrm->time.tm_year = ioread32(priv->iobase + HW_ALYEAR);
alrm->time.tm_mon = ioread32(priv->iobase + HW_ALMON);
alrm->time.tm_mday = ioread32(priv->iobase + HW_ALDOM);
alrm->time.tm_wday = ioread32(priv->iobase + HW_ALDOW);
alrm->time.tm_yday = ioread32(priv->iobase + HW_ALDOY);
alrm->time.tm_hour = ioread32(priv->iobase + HW_ALHOUR);
alrm->time.tm_min = ioread32(priv->iobase + HW_ALMIN);
alrm->time.tm_sec = ioread32(priv->iobase + HW_ALSEC);
alrm->enabled = ioread32(priv->iobase + HW_AMR) ? 1 : 0;
alrm->pending = ioread32(priv->iobase + HW_CIIR) ? 1 : 0;
spin_unlock_irqrestore(&priv->lock, irq_flags);
return rtc_valid_tm(&alrm->time);
}
static int asm9260_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
unsigned long irq_flags;
spin_lock_irqsave(&priv->lock, irq_flags);
iowrite32(alrm->time.tm_year, priv->iobase + HW_ALYEAR);
iowrite32(alrm->time.tm_mon, priv->iobase + HW_ALMON);
iowrite32(alrm->time.tm_mday, priv->iobase + HW_ALDOM);
iowrite32(alrm->time.tm_wday, priv->iobase + HW_ALDOW);
iowrite32(alrm->time.tm_yday, priv->iobase + HW_ALDOY);
iowrite32(alrm->time.tm_hour, priv->iobase + HW_ALHOUR);
iowrite32(alrm->time.tm_min, priv->iobase + HW_ALMIN);
iowrite32(alrm->time.tm_sec, priv->iobase + HW_ALSEC);
iowrite32(alrm->enabled ? 0 : BM_AMR_OFF, priv->iobase + HW_AMR);
spin_unlock_irqrestore(&priv->lock, irq_flags);
return 0;
}
static int asm9260_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
struct asm9260_rtc_priv *priv = dev_get_drvdata(dev);
iowrite32(enabled ? 0 : BM_AMR_OFF, priv->iobase + HW_AMR);
return 0;
}
static const struct rtc_class_ops asm9260_rtc_ops = {
.read_time = asm9260_rtc_read_time,
.set_time = asm9260_rtc_set_time,
.read_alarm = asm9260_rtc_read_alarm,
.set_alarm = asm9260_rtc_set_alarm,
.alarm_irq_enable = asm9260_alarm_irq_enable,
};
static int __init asm9260_rtc_probe(struct platform_device *pdev)
{
struct asm9260_rtc_priv *priv;
struct device *dev = &pdev->dev;
struct resource *res;
int irq_alarm, ret;
u32 ccr;
priv = devm_kzalloc(dev, sizeof(struct asm9260_rtc_priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->dev = &pdev->dev;
platform_set_drvdata(pdev, priv);
irq_alarm = platform_get_irq(pdev, 0);
if (irq_alarm < 0) {
dev_err(dev, "No alarm IRQ resource defined\n");
return irq_alarm;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->iobase = devm_ioremap_resource(dev, res);
if (IS_ERR(priv->iobase))
return PTR_ERR(priv->iobase);
priv->clk = devm_clk_get(dev, "ahb");
ret = clk_prepare_enable(priv->clk);
if (ret) {
dev_err(dev, "Failed to enable clk!\n");
return ret;
}
ccr = ioread32(priv->iobase + HW_CCR);
/* if dev is not enabled, reset it */
if ((ccr & (BM_CLKEN | BM_CTCRST)) != BM_CLKEN) {
iowrite32(BM_CTCRST, priv->iobase + HW_CCR);
ccr = 0;
}
iowrite32(BM_CLKEN | ccr, priv->iobase + HW_CCR);
iowrite32(0, priv->iobase + HW_CIIR);
iowrite32(BM_AMR_OFF, priv->iobase + HW_AMR);
priv->rtc = devm_rtc_device_register(dev, dev_name(dev),
&asm9260_rtc_ops, THIS_MODULE);
if (IS_ERR(priv->rtc)) {
ret = PTR_ERR(priv->rtc);
dev_err(dev, "Failed to register RTC device: %d\n", ret);
goto err_return;
}
ret = devm_request_threaded_irq(dev, irq_alarm, NULL,
asm9260_rtc_irq, IRQF_ONESHOT,
dev_name(dev), priv);
if (ret < 0) {
dev_err(dev, "can't get irq %i, err %d\n",
irq_alarm, ret);
goto err_return;
}
return 0;
err_return:
clk_disable_unprepare(priv->clk);
return ret;
}
static int __exit asm9260_rtc_remove(struct platform_device *pdev)
{
struct asm9260_rtc_priv *priv = platform_get_drvdata(pdev);
/* Disable alarm matching */
iowrite32(BM_AMR_OFF, priv->iobase + HW_AMR);
clk_disable_unprepare(priv->clk);
return 0;
}
static const struct of_device_id asm9260_dt_ids[] = {
{ .compatible = "alphascale,asm9260-rtc", },
{}
};
static struct platform_driver asm9260_rtc_driver = {
.probe = asm9260_rtc_probe,
.remove = asm9260_rtc_remove,
.driver = {
.name = "asm9260-rtc",
.owner = THIS_MODULE,
.of_match_table = asm9260_dt_ids,
},
};
module_platform_driver(asm9260_rtc_driver);
MODULE_AUTHOR("Oleksij Rempel <linux@rempel-privat.de>");
MODULE_DESCRIPTION("Alphascale asm9260 SoC Realtime Clock Driver (RTC)");
MODULE_LICENSE("GPL");
......@@ -532,7 +532,7 @@ ds1305_nvram_read(struct file *filp, struct kobject *kobj,
struct spi_transfer x[2];
int status;
spi = container_of(kobj, struct spi_device, dev.kobj);
spi = to_spi_device(kobj_to_dev(kobj));
addr = DS1305_NVRAM + off;
msg_init(&m, x, &addr, count, NULL, buf);
......@@ -554,7 +554,7 @@ ds1305_nvram_write(struct file *filp, struct kobject *kobj,
struct spi_transfer x[2];
int status;
spi = container_of(kobj, struct spi_device, dev.kobj);
spi = to_spi_device(kobj_to_dev(kobj));
addr = (DS1305_WRITE | DS1305_NVRAM) + off;
msg_init(&m, x, &addr, count, buf, NULL);
......
......@@ -19,6 +19,9 @@
#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/clk-provider.h>
/*
* We can't determine type by probing, but if we expect pre-Linux code
......@@ -89,6 +92,7 @@ enum ds_type {
# define DS1340_BIT_OSF 0x80
#define DS1337_REG_STATUS 0x0f
# define DS1337_BIT_OSF 0x80
# define DS3231_BIT_EN32KHZ 0x08
# define DS1337_BIT_A2I 0x02
# define DS1337_BIT_A1I 0x01
#define DS1339_REG_ALARM1_SECS 0x07
......@@ -118,6 +122,9 @@ struct ds1307 {
u8 length, u8 *values);
s32 (*write_block_data)(const struct i2c_client *client, u8 command,
u8 length, const u8 *values);
#ifdef CONFIG_COMMON_CLK
struct clk_hw clks[2];
#endif
};
struct chip_desc {
......@@ -842,6 +849,378 @@ static void ds1307_trickle_of_init(struct i2c_client *client,
return;
}
/*----------------------------------------------------------------------*/
#ifdef CONFIG_RTC_DRV_DS1307_HWMON
/*
* Temperature sensor support for ds3231 devices.
*/
#define DS3231_REG_TEMPERATURE 0x11
/*
* A user-initiated temperature conversion is not started by this function,
* so the temperature is updated once every 64 seconds.
*/
static int ds3231_hwmon_read_temp(struct device *dev, s16 *mC)
{
struct ds1307 *ds1307 = dev_get_drvdata(dev);
u8 temp_buf[2];
s16 temp;
int ret;
ret = ds1307->read_block_data(ds1307->client, DS3231_REG_TEMPERATURE,
sizeof(temp_buf), temp_buf);
if (ret < 0)
return ret;
if (ret != sizeof(temp_buf))
return -EIO;
/*
* Temperature is represented as a 10-bit code with a resolution of
* 0.25 degree celsius and encoded in two's complement format.
*/
temp = (temp_buf[0] << 8) | temp_buf[1];
temp >>= 6;
*mC = temp * 250;
return 0;
}
static ssize_t ds3231_hwmon_show_temp(struct device *dev,
struct device_attribute *attr, char *buf)
{
int ret;
s16 temp;
ret = ds3231_hwmon_read_temp(dev, &temp);
if (ret)
return ret;
return sprintf(buf, "%d\n", temp);
}
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ds3231_hwmon_show_temp,
NULL, 0);
static struct attribute *ds3231_hwmon_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(ds3231_hwmon);
static void ds1307_hwmon_register(struct ds1307 *ds1307)
{
struct device *dev;
if (ds1307->type != ds_3231)
return;
dev = devm_hwmon_device_register_with_groups(&ds1307->client->dev,
ds1307->client->name,
ds1307, ds3231_hwmon_groups);
if (IS_ERR(dev)) {
dev_warn(&ds1307->client->dev,
"unable to register hwmon device %ld\n", PTR_ERR(dev));
}
}
#else
static void ds1307_hwmon_register(struct ds1307 *ds1307)
{
}
#endif /* CONFIG_RTC_DRV_DS1307_HWMON */
/*----------------------------------------------------------------------*/
/*
* Square-wave output support for DS3231
* Datasheet: https://datasheets.maximintegrated.com/en/ds/DS3231.pdf
*/
#ifdef CONFIG_COMMON_CLK
enum {
DS3231_CLK_SQW = 0,
DS3231_CLK_32KHZ,
};
#define clk_sqw_to_ds1307(clk) \
container_of(clk, struct ds1307, clks[DS3231_CLK_SQW])
#define clk_32khz_to_ds1307(clk) \
container_of(clk, struct ds1307, clks[DS3231_CLK_32KHZ])
static int ds3231_clk_sqw_rates[] = {
1,
1024,
4096,
8192,
};
static int ds1337_write_control(struct ds1307 *ds1307, u8 mask, u8 value)
{
struct i2c_client *client = ds1307->client;
struct mutex *lock = &ds1307->rtc->ops_lock;
int control;
int ret;
mutex_lock(lock);
control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
if (control < 0) {
ret = control;
goto out;
}
control &= ~mask;
control |= value;
ret = i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, control);
out:
mutex_unlock(lock);
return ret;
}
static unsigned long ds3231_clk_sqw_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
int control;
int rate_sel = 0;
control = i2c_smbus_read_byte_data(ds1307->client, DS1337_REG_CONTROL);
if (control < 0)
return control;
if (control & DS1337_BIT_RS1)
rate_sel += 1;
if (control & DS1337_BIT_RS2)
rate_sel += 2;
return ds3231_clk_sqw_rates[rate_sel];
}
static long ds3231_clk_sqw_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
int i;
for (i = ARRAY_SIZE(ds3231_clk_sqw_rates) - 1; i >= 0; i--) {
if (ds3231_clk_sqw_rates[i] <= rate)
return ds3231_clk_sqw_rates[i];
}
return 0;
}
static int ds3231_clk_sqw_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
int control = 0;
int rate_sel;
for (rate_sel = 0; rate_sel < ARRAY_SIZE(ds3231_clk_sqw_rates);
rate_sel++) {
if (ds3231_clk_sqw_rates[rate_sel] == rate)
break;
}
if (rate_sel == ARRAY_SIZE(ds3231_clk_sqw_rates))
return -EINVAL;
if (rate_sel & 1)
control |= DS1337_BIT_RS1;
if (rate_sel & 2)
control |= DS1337_BIT_RS2;
return ds1337_write_control(ds1307, DS1337_BIT_RS1 | DS1337_BIT_RS2,
control);
}
static int ds3231_clk_sqw_prepare(struct clk_hw *hw)
{
struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
return ds1337_write_control(ds1307, DS1337_BIT_INTCN, 0);
}
static void ds3231_clk_sqw_unprepare(struct clk_hw *hw)
{
struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
ds1337_write_control(ds1307, DS1337_BIT_INTCN, DS1337_BIT_INTCN);
}
static int ds3231_clk_sqw_is_prepared(struct clk_hw *hw)
{
struct ds1307 *ds1307 = clk_sqw_to_ds1307(hw);
int control;
control = i2c_smbus_read_byte_data(ds1307->client, DS1337_REG_CONTROL);
if (control < 0)
return control;
return !(control & DS1337_BIT_INTCN);
}
static const struct clk_ops ds3231_clk_sqw_ops = {
.prepare = ds3231_clk_sqw_prepare,
.unprepare = ds3231_clk_sqw_unprepare,
.is_prepared = ds3231_clk_sqw_is_prepared,
.recalc_rate = ds3231_clk_sqw_recalc_rate,
.round_rate = ds3231_clk_sqw_round_rate,
.set_rate = ds3231_clk_sqw_set_rate,
};
static unsigned long ds3231_clk_32khz_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
return 32768;
}
static int ds3231_clk_32khz_control(struct ds1307 *ds1307, bool enable)
{
struct i2c_client *client = ds1307->client;
struct mutex *lock = &ds1307->rtc->ops_lock;
int status;
int ret;
mutex_lock(lock);
status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
if (status < 0) {
ret = status;
goto out;
}
if (enable)
status |= DS3231_BIT_EN32KHZ;
else
status &= ~DS3231_BIT_EN32KHZ;
ret = i2c_smbus_write_byte_data(client, DS1337_REG_STATUS, status);
out:
mutex_unlock(lock);
return ret;
}
static int ds3231_clk_32khz_prepare(struct clk_hw *hw)
{
struct ds1307 *ds1307 = clk_32khz_to_ds1307(hw);
return ds3231_clk_32khz_control(ds1307, true);
}
static void ds3231_clk_32khz_unprepare(struct clk_hw *hw)
{
struct ds1307 *ds1307 = clk_32khz_to_ds1307(hw);
ds3231_clk_32khz_control(ds1307, false);
}
static int ds3231_clk_32khz_is_prepared(struct clk_hw *hw)
{
struct ds1307 *ds1307 = clk_32khz_to_ds1307(hw);
int status;
status = i2c_smbus_read_byte_data(ds1307->client, DS1337_REG_STATUS);
if (status < 0)
return status;
return !!(status & DS3231_BIT_EN32KHZ);
}
static const struct clk_ops ds3231_clk_32khz_ops = {
.prepare = ds3231_clk_32khz_prepare,
.unprepare = ds3231_clk_32khz_unprepare,
.is_prepared = ds3231_clk_32khz_is_prepared,
.recalc_rate = ds3231_clk_32khz_recalc_rate,
};
static struct clk_init_data ds3231_clks_init[] = {
[DS3231_CLK_SQW] = {
.name = "ds3231_clk_sqw",
.ops = &ds3231_clk_sqw_ops,
.flags = CLK_IS_ROOT,
},
[DS3231_CLK_32KHZ] = {
.name = "ds3231_clk_32khz",
.ops = &ds3231_clk_32khz_ops,
.flags = CLK_IS_ROOT,
},
};
static int ds3231_clks_register(struct ds1307 *ds1307)
{
struct i2c_client *client = ds1307->client;
struct device_node *node = client->dev.of_node;
struct clk_onecell_data *onecell;
int i;
onecell = devm_kzalloc(&client->dev, sizeof(*onecell), GFP_KERNEL);
if (!onecell)
return -ENOMEM;
onecell->clk_num = ARRAY_SIZE(ds3231_clks_init);
onecell->clks = devm_kcalloc(&client->dev, onecell->clk_num,
sizeof(onecell->clks[0]), GFP_KERNEL);
if (!onecell->clks)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(ds3231_clks_init); i++) {
struct clk_init_data init = ds3231_clks_init[i];
/*
* Interrupt signal due to alarm conditions and square-wave
* output share same pin, so don't initialize both.
*/
if (i == DS3231_CLK_SQW && test_bit(HAS_ALARM, &ds1307->flags))
continue;
/* optional override of the clockname */
of_property_read_string_index(node, "clock-output-names", i,
&init.name);
ds1307->clks[i].init = &init;
onecell->clks[i] = devm_clk_register(&client->dev,
&ds1307->clks[i]);
if (IS_ERR(onecell->clks[i]))
return PTR_ERR(onecell->clks[i]);
}
if (!node)
return 0;
of_clk_add_provider(node, of_clk_src_onecell_get, onecell);
return 0;
}
static void ds1307_clks_register(struct ds1307 *ds1307)
{
int ret;
if (ds1307->type != ds_3231)
return;
ret = ds3231_clks_register(ds1307);
if (ret) {
dev_warn(&ds1307->client->dev,
"unable to register clock device %d\n", ret);
}
}
#else
static void ds1307_clks_register(struct ds1307 *ds1307)
{
}
#endif /* CONFIG_COMMON_CLK */
static int ds1307_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
......@@ -851,6 +1230,7 @@ static int ds1307_probe(struct i2c_client *client,
struct chip_desc *chip = &chips[id->driver_data];
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
bool want_irq = false;
bool ds1307_can_wakeup_device = false;
unsigned char *buf;
struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
irq_handler_t irq_handler = ds1307_irq;
......@@ -898,6 +1278,20 @@ static int ds1307_probe(struct i2c_client *client,
ds1307->write_block_data = ds1307_write_block_data;
}
#ifdef CONFIG_OF
/*
* For devices with no IRQ directly connected to the SoC, the RTC chip
* can be forced as a wakeup source by stating that explicitly in
* the device's .dts file using the "wakeup-source" boolean property.
* If the "wakeup-source" property is set, don't request an IRQ.
* This will guarantee the 'wakealarm' sysfs entry is available on the device,
* if supported by the RTC.
*/
if (of_property_read_bool(client->dev.of_node, "wakeup-source")) {
ds1307_can_wakeup_device = true;
}
#endif
switch (ds1307->type) {
case ds_1337:
case ds_1339:
......@@ -916,11 +1310,13 @@ static int ds1307_probe(struct i2c_client *client,
ds1307->regs[0] &= ~DS1337_BIT_nEOSC;
/*
* Using IRQ? Disable the square wave and both alarms.
* Using IRQ or defined as wakeup-source?
* Disable the square wave and both alarms.
* For some variants, be sure alarms can trigger when we're
* running on Vbackup (BBSQI/BBSQW)
*/
if (ds1307->client->irq > 0 && chip->alarm) {
if (chip->alarm && (ds1307->client->irq > 0 ||
ds1307_can_wakeup_device)) {
ds1307->regs[0] |= DS1337_BIT_INTCN
| bbsqi_bitpos[ds1307->type];
ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE);
......@@ -1135,6 +1531,14 @@ static int ds1307_probe(struct i2c_client *client,
return PTR_ERR(ds1307->rtc);
}
if (ds1307_can_wakeup_device) {
/* Disable request for an IRQ */
want_irq = false;
dev_info(&client->dev, "'wakeup-source' is set, request for an IRQ is disabled!\n");
/* We cannot support UIE mode if we do not have an IRQ line */
ds1307->rtc->uie_unsupported = 1;
}
if (want_irq) {
err = devm_request_threaded_irq(&client->dev,
client->irq, NULL, irq_handler,
......@@ -1182,6 +1586,9 @@ static int ds1307_probe(struct i2c_client *client,
}
}
ds1307_hwmon_register(ds1307);
ds1307_clks_register(ds1307);
return 0;
exit:
......
......@@ -187,9 +187,9 @@ ds1685_rtc_end_data_access(struct ds1685_priv *rtc)
* Only use this where you are certain another lock will not be held.
*/
static inline void
ds1685_rtc_begin_ctrl_access(struct ds1685_priv *rtc, unsigned long flags)
ds1685_rtc_begin_ctrl_access(struct ds1685_priv *rtc, unsigned long *flags)
{
spin_lock_irqsave(&rtc->lock, flags);
spin_lock_irqsave(&rtc->lock, *flags);
ds1685_rtc_switch_to_bank1(rtc);
}
......@@ -1300,7 +1300,7 @@ ds1685_rtc_sysfs_ctrl_regs_store(struct device *dev,
{
struct ds1685_priv *rtc = dev_get_drvdata(dev);
u8 reg = 0, bit = 0, tmp;
unsigned long flags = 0;
unsigned long flags;
long int val = 0;
const struct ds1685_rtc_ctrl_regs *reg_info =
ds1685_rtc_sysfs_ctrl_regs_lookup(attr->attr.name);
......@@ -1321,7 +1321,7 @@ ds1685_rtc_sysfs_ctrl_regs_store(struct device *dev,
bit = reg_info->bit;
/* Safe to spinlock during a write. */
ds1685_rtc_begin_ctrl_access(rtc, flags);
ds1685_rtc_begin_ctrl_access(rtc, &flags);
tmp = rtc->read(rtc, reg);
rtc->write(rtc, reg, (val ? (tmp | bit) : (tmp & ~(bit))));
ds1685_rtc_end_ctrl_access(rtc, flags);
......@@ -2161,6 +2161,7 @@ ds1685_rtc_poweroff(struct platform_device *pdev)
/* Check for valid RTC data, else, spin forever. */
if (unlikely(!pdev)) {
pr_emerg("platform device data not available, spinning forever ...\n");
while(1);
unreachable();
} else {
/* Get the rtc data. */
......
/*
* RTC client/driver for the Maxim/Dallas DS3232 Real-Time Clock over I2C
* RTC client/driver for the Maxim/Dallas DS3232/DS3234 Real-Time Clock
*
* Copyright (C) 2009-2011 Freescale Semiconductor.
* Author: Jack Lan <jack.lan@freescale.com>
* Copyright (C) 2008 MIMOMax Wireless Ltd.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
/*
* It would be more efficient to use i2c msgs/i2c_transfer directly but, as
* recommened in .../Documentation/i2c/writing-clients section
* "Sending and receiving", using SMBus level communication is preferred.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
......@@ -21,10 +17,11 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/regmap.h>
#define DS3232_REG_SECONDS 0x00
#define DS3232_REG_MINUTES 0x01
......@@ -50,39 +47,33 @@
# define DS3232_REG_SR_A1F 0x01
struct ds3232 {
struct i2c_client *client;
struct device *dev;
struct regmap *regmap;
int irq;
struct rtc_device *rtc;
struct work_struct work;
/* The mutex protects alarm operations, and prevents a race
* between the enable_irq() in the workqueue and the free_irq()
* in the remove function.
*/
struct mutex mutex;
bool suspended;
int exiting;
};
static struct i2c_driver ds3232_driver;
static int ds3232_check_rtc_status(struct i2c_client *client)
static int ds3232_check_rtc_status(struct device *dev)
{
struct ds3232 *ds3232 = dev_get_drvdata(dev);
int ret = 0;
int control, stat;
stat = i2c_smbus_read_byte_data(client, DS3232_REG_SR);
if (stat < 0)
return stat;
ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
if (ret)
return ret;
if (stat & DS3232_REG_SR_OSF)
dev_warn(&client->dev,
dev_warn(dev,
"oscillator discontinuity flagged, "
"time unreliable\n");
stat &= ~(DS3232_REG_SR_OSF | DS3232_REG_SR_A1F | DS3232_REG_SR_A2F);
ret = i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat);
if (ret < 0)
ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
if (ret)
return ret;
/* If the alarm is pending, clear it before requesting
......@@ -90,31 +81,28 @@ static int ds3232_check_rtc_status(struct i2c_client *client)
* before everything is initialized.
*/
control = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
if (control < 0)
return control;
ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
if (ret)
return ret;
control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE);
control |= DS3232_REG_CR_INTCN;
return i2c_smbus_write_byte_data(client, DS3232_REG_CR, control);
return regmap_write(ds3232->regmap, DS3232_REG_CR, control);
}
static int ds3232_read_time(struct device *dev, struct rtc_time *time)
{
struct i2c_client *client = to_i2c_client(dev);
struct ds3232 *ds3232 = dev_get_drvdata(dev);
int ret;
u8 buf[7];
unsigned int year, month, day, hour, minute, second;
unsigned int week, twelve_hr, am_pm;
unsigned int century, add_century = 0;
ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_SECONDS, 7, buf);
if (ret < 0)
ret = regmap_bulk_read(ds3232->regmap, DS3232_REG_SECONDS, buf, 7);
if (ret)
return ret;
if (ret < 7)
return -EIO;
second = buf[0];
minute = buf[1];
......@@ -159,7 +147,7 @@ static int ds3232_read_time(struct device *dev, struct rtc_time *time)
static int ds3232_set_time(struct device *dev, struct rtc_time *time)
{
struct i2c_client *client = to_i2c_client(dev);
struct ds3232 *ds3232 = dev_get_drvdata(dev);
u8 buf[7];
/* Extract time from rtc_time and load into ds3232*/
......@@ -179,8 +167,7 @@ static int ds3232_set_time(struct device *dev, struct rtc_time *time)
buf[6] = bin2bcd(time->tm_year);
}
return i2c_smbus_write_i2c_block_data(client,
DS3232_REG_SECONDS, 7, buf);
return regmap_bulk_write(ds3232->regmap, DS3232_REG_SECONDS, buf, 7);
}
/*
......@@ -190,24 +177,19 @@ static int ds3232_set_time(struct device *dev, struct rtc_time *time)
*/
static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
struct i2c_client *client = to_i2c_client(dev);
struct ds3232 *ds3232 = i2c_get_clientdata(client);
struct ds3232 *ds3232 = dev_get_drvdata(dev);
int control, stat;
int ret;
u8 buf[4];
mutex_lock(&ds3232->mutex);
ret = i2c_smbus_read_byte_data(client, DS3232_REG_SR);
if (ret < 0)
ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
if (ret)
goto out;
stat = ret;
ret = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
if (ret < 0)
ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
if (ret)
goto out;
control = ret;
ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf);
if (ret < 0)
ret = regmap_bulk_read(ds3232->regmap, DS3232_REG_ALARM1, buf, 4);
if (ret)
goto out;
alarm->time.tm_sec = bcd2bin(buf[0] & 0x7F);
......@@ -226,7 +208,6 @@ static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
ret = 0;
out:
mutex_unlock(&ds3232->mutex);
return ret;
}
......@@ -236,166 +217,129 @@ static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
*/
static int ds3232_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{
struct i2c_client *client = to_i2c_client(dev);
struct ds3232 *ds3232 = i2c_get_clientdata(client);
struct ds3232 *ds3232 = dev_get_drvdata(dev);
int control, stat;
int ret;
u8 buf[4];
if (client->irq <= 0)
if (ds3232->irq <= 0)
return -EINVAL;
mutex_lock(&ds3232->mutex);
buf[0] = bin2bcd(alarm->time.tm_sec);
buf[1] = bin2bcd(alarm->time.tm_min);
buf[2] = bin2bcd(alarm->time.tm_hour);
buf[3] = bin2bcd(alarm->time.tm_mday);
/* clear alarm interrupt enable bit */
ret = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
if (ret < 0)
ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
if (ret)
goto out;
control = ret;
control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE);
ret = i2c_smbus_write_byte_data(client, DS3232_REG_CR, control);
if (ret < 0)
ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
if (ret)
goto out;
/* clear any pending alarm flag */
ret = i2c_smbus_read_byte_data(client, DS3232_REG_SR);
if (ret < 0)
ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
if (ret)
goto out;
stat = ret;
stat &= ~(DS3232_REG_SR_A1F | DS3232_REG_SR_A2F);
ret = i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat);
if (ret < 0)
ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
if (ret)
goto out;
ret = i2c_smbus_write_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf);
ret = regmap_bulk_write(ds3232->regmap, DS3232_REG_ALARM1, buf, 4);
if (ret)
goto out;
if (alarm->enabled) {
control |= DS3232_REG_CR_A1IE;
ret = i2c_smbus_write_byte_data(client, DS3232_REG_CR, control);
ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
}
out:
mutex_unlock(&ds3232->mutex);
return ret;
}
static void ds3232_update_alarm(struct i2c_client *client)
static int ds3232_update_alarm(struct device *dev, unsigned int enabled)
{
struct ds3232 *ds3232 = i2c_get_clientdata(client);
struct ds3232 *ds3232 = dev_get_drvdata(dev);
int control;
int ret;
u8 buf[4];
mutex_lock(&ds3232->mutex);
ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf);
if (ret < 0)
goto unlock;
buf[0] = bcd2bin(buf[0]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ?
0x80 : buf[0];
buf[1] = bcd2bin(buf[1]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ?
0x80 : buf[1];
buf[2] = bcd2bin(buf[2]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ?
0x80 : buf[2];
buf[3] = bcd2bin(buf[3]) < 0 || (ds3232->rtc->irq_data & RTC_UF) ?
0x80 : buf[3];
ret = i2c_smbus_write_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf);
if (ret < 0)
goto unlock;
control = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
if (control < 0)
goto unlock;
ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
if (ret)
return ret;
if (ds3232->rtc->irq_data & (RTC_AF | RTC_UF))
if (enabled)
/* enable alarm1 interrupt */
control |= DS3232_REG_CR_A1IE;
else
/* disable alarm1 interrupt */
control &= ~(DS3232_REG_CR_A1IE);
i2c_smbus_write_byte_data(client, DS3232_REG_CR, control);
ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
unlock:
mutex_unlock(&ds3232->mutex);
return ret;
}
static int ds3232_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
struct i2c_client *client = to_i2c_client(dev);
struct ds3232 *ds3232 = i2c_get_clientdata(client);
struct ds3232 *ds3232 = dev_get_drvdata(dev);
if (client->irq <= 0)
if (ds3232->irq <= 0)
return -EINVAL;
if (enabled)
ds3232->rtc->irq_data |= RTC_AF;
else
ds3232->rtc->irq_data &= ~RTC_AF;
ds3232_update_alarm(client);
return 0;
return ds3232_update_alarm(dev, enabled);
}
static irqreturn_t ds3232_irq(int irq, void *dev_id)
{
struct i2c_client *client = dev_id;
struct ds3232 *ds3232 = i2c_get_clientdata(client);
disable_irq_nosync(irq);
/*
* If rtc as a wakeup source, can't schedule the work
* at system resume flow, because at this time the i2c bus
* has not been resumed.
*/
if (!ds3232->suspended)
schedule_work(&ds3232->work);
return IRQ_HANDLED;
}
static void ds3232_work(struct work_struct *work)
{
struct ds3232 *ds3232 = container_of(work, struct ds3232, work);
struct i2c_client *client = ds3232->client;
struct device *dev = dev_id;
struct ds3232 *ds3232 = dev_get_drvdata(dev);
struct mutex *lock = &ds3232->rtc->ops_lock;
int ret;
int stat, control;
mutex_lock(&ds3232->mutex);
mutex_lock(lock);
stat = i2c_smbus_read_byte_data(client, DS3232_REG_SR);
if (stat < 0)
ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
if (ret)
goto unlock;
if (stat & DS3232_REG_SR_A1F) {
control = i2c_smbus_read_byte_data(client, DS3232_REG_CR);
if (control < 0) {
pr_warn("Read Control Register error - Disable IRQ%d\n",
client->irq);
ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
if (ret) {
dev_warn(ds3232->dev,
"Read Control Register error %d\n", ret);
} else {
/* disable alarm1 interrupt */
control &= ~(DS3232_REG_CR_A1IE);
i2c_smbus_write_byte_data(client, DS3232_REG_CR,
control);
ret = regmap_write(ds3232->regmap, DS3232_REG_CR,
control);
if (ret) {
dev_warn(ds3232->dev,
"Write Control Register error %d\n",
ret);
goto unlock;
}
/* clear the alarm pend flag */
stat &= ~DS3232_REG_SR_A1F;
i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat);
ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
if (ret) {
dev_warn(ds3232->dev,
"Write Status Register error %d\n",
ret);
goto unlock;
}
rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF);
if (!ds3232->exiting)
enable_irq(client->irq);
}
}
unlock:
mutex_unlock(&ds3232->mutex);
mutex_unlock(lock);
return IRQ_HANDLED;
}
static const struct rtc_class_ops ds3232_rtc_ops = {
......@@ -406,67 +350,50 @@ static const struct rtc_class_ops ds3232_rtc_ops = {
.alarm_irq_enable = ds3232_alarm_irq_enable,
};
static int ds3232_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq,
const char *name)
{
struct ds3232 *ds3232;
int ret;
ds3232 = devm_kzalloc(&client->dev, sizeof(struct ds3232), GFP_KERNEL);
ds3232 = devm_kzalloc(dev, sizeof(*ds3232), GFP_KERNEL);
if (!ds3232)
return -ENOMEM;
ds3232->client = client;
i2c_set_clientdata(client, ds3232);
INIT_WORK(&ds3232->work, ds3232_work);
mutex_init(&ds3232->mutex);
ds3232->regmap = regmap;
ds3232->irq = irq;
ds3232->dev = dev;
dev_set_drvdata(dev, ds3232);
ret = ds3232_check_rtc_status(client);
ret = ds3232_check_rtc_status(dev);
if (ret)
return ret;
if (client->irq > 0) {
ret = devm_request_irq(&client->dev, client->irq, ds3232_irq,
IRQF_SHARED, "ds3232", client);
if (ds3232->irq > 0) {
ret = devm_request_threaded_irq(dev, ds3232->irq, NULL,
ds3232_irq,
IRQF_SHARED | IRQF_ONESHOT,
name, dev);
if (ret) {
dev_err(&client->dev, "unable to request IRQ\n");
}
device_init_wakeup(&client->dev, 1);
}
ds3232->rtc = devm_rtc_device_register(&client->dev, client->name,
&ds3232_rtc_ops, THIS_MODULE);
return PTR_ERR_OR_ZERO(ds3232->rtc);
}
static int ds3232_remove(struct i2c_client *client)
{
struct ds3232 *ds3232 = i2c_get_clientdata(client);
if (client->irq > 0) {
mutex_lock(&ds3232->mutex);
ds3232->exiting = 1;
mutex_unlock(&ds3232->mutex);
devm_free_irq(&client->dev, client->irq, client);
cancel_work_sync(&ds3232->work);
ds3232->irq = 0;
dev_err(dev, "unable to request IRQ\n");
} else
device_init_wakeup(dev, 1);
}
ds3232->rtc = devm_rtc_device_register(dev, name, &ds3232_rtc_ops,
THIS_MODULE);
return 0;
return PTR_ERR_OR_ZERO(ds3232->rtc);
}
#ifdef CONFIG_PM_SLEEP
static int ds3232_suspend(struct device *dev)
{
struct ds3232 *ds3232 = dev_get_drvdata(dev);
struct i2c_client *client = to_i2c_client(dev);
if (device_can_wakeup(dev)) {
ds3232->suspended = true;
if (irq_set_irq_wake(client->irq, 1)) {
if (device_may_wakeup(dev)) {
if (enable_irq_wake(ds3232->irq))
dev_warn_once(dev, "Cannot set wakeup source\n");
ds3232->suspended = false;
}
}
return 0;
......@@ -475,16 +402,9 @@ static int ds3232_suspend(struct device *dev)
static int ds3232_resume(struct device *dev)
{
struct ds3232 *ds3232 = dev_get_drvdata(dev);
struct i2c_client *client = to_i2c_client(dev);
if (ds3232->suspended) {
ds3232->suspended = false;
/* Clear the hardware alarm pend flag */
schedule_work(&ds3232->work);
irq_set_irq_wake(client->irq, 0);
}
if (device_may_wakeup(dev))
disable_irq_wake(ds3232->irq);
return 0;
}
......@@ -494,6 +414,27 @@ static const struct dev_pm_ops ds3232_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(ds3232_suspend, ds3232_resume)
};
#if IS_ENABLED(CONFIG_I2C)
static int ds3232_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct regmap *regmap;
static const struct regmap_config config = {
.reg_bits = 8,
.val_bits = 8,
};
regmap = devm_regmap_init_i2c(client, &config);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "%s: regmap allocation failed: %ld\n",
__func__, PTR_ERR(regmap));
return PTR_ERR(regmap);
}
return ds3232_probe(&client->dev, regmap, client->irq, client->name);
}
static const struct i2c_device_id ds3232_id[] = {
{ "ds3232", 0 },
{ }
......@@ -505,13 +446,162 @@ static struct i2c_driver ds3232_driver = {
.name = "rtc-ds3232",
.pm = &ds3232_pm_ops,
},
.probe = ds3232_probe,
.remove = ds3232_remove,
.probe = ds3232_i2c_probe,
.id_table = ds3232_id,
};
module_i2c_driver(ds3232_driver);
static int ds3232_register_driver(void)
{
return i2c_add_driver(&ds3232_driver);
}
static void ds3232_unregister_driver(void)
{
i2c_del_driver(&ds3232_driver);
}
#else
static int ds3232_register_driver(void)
{
return 0;
}
static void ds3232_unregister_driver(void)
{
}
#endif
#if IS_ENABLED(CONFIG_SPI_MASTER)
static int ds3234_probe(struct spi_device *spi)
{
int res;
unsigned int tmp;
static const struct regmap_config config = {
.reg_bits = 8,
.val_bits = 8,
.write_flag_mask = 0x80,
};
struct regmap *regmap;
regmap = devm_regmap_init_spi(spi, &config);
if (IS_ERR(regmap)) {
dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n",
__func__, PTR_ERR(regmap));
return PTR_ERR(regmap);
}
spi->mode = SPI_MODE_3;
spi->bits_per_word = 8;
spi_setup(spi);
res = regmap_read(regmap, DS3232_REG_SECONDS, &tmp);
if (res)
return res;
/* Control settings
*
* CONTROL_REG
* BIT 7 6 5 4 3 2 1 0
* EOSC BBSQW CONV RS2 RS1 INTCN A2IE A1IE
*
* 0 0 0 1 1 1 0 0
*
* CONTROL_STAT_REG
* BIT 7 6 5 4 3 2 1 0
* OSF BB32kHz CRATE1 CRATE0 EN32kHz BSY A2F A1F
*
* 1 0 0 0 1 0 0 0
*/
res = regmap_read(regmap, DS3232_REG_CR, &tmp);
if (res)
return res;
res = regmap_write(regmap, DS3232_REG_CR, tmp & 0x1c);
if (res)
return res;
res = regmap_read(regmap, DS3232_REG_SR, &tmp);
if (res)
return res;
res = regmap_write(regmap, DS3232_REG_SR, tmp & 0x88);
if (res)
return res;
/* Print our settings */
res = regmap_read(regmap, DS3232_REG_CR, &tmp);
if (res)
return res;
dev_info(&spi->dev, "Control Reg: 0x%02x\n", tmp);
res = regmap_read(regmap, DS3232_REG_SR, &tmp);
if (res)
return res;
dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp);
return ds3232_probe(&spi->dev, regmap, spi->irq, "ds3234");
}
static struct spi_driver ds3234_driver = {
.driver = {
.name = "ds3234",
},
.probe = ds3234_probe,
};
static int ds3234_register_driver(void)
{
return spi_register_driver(&ds3234_driver);
}
static void ds3234_unregister_driver(void)
{
spi_unregister_driver(&ds3234_driver);
}
#else
static int ds3234_register_driver(void)
{
return 0;
}
static void ds3234_unregister_driver(void)
{
}
#endif
static int __init ds323x_init(void)
{
int ret;
ret = ds3232_register_driver();
if (ret) {
pr_err("Failed to register ds3232 driver: %d\n", ret);
return ret;
}
ret = ds3234_register_driver();
if (ret) {
pr_err("Failed to register ds3234 driver: %d\n", ret);
ds3232_unregister_driver();
}
return ret;
}
module_init(ds323x_init)
static void __exit ds323x_exit(void)
{
ds3234_unregister_driver();
ds3232_unregister_driver();
}
module_exit(ds323x_exit)
MODULE_AUTHOR("Srikanth Srinivasan <srikanth.srinivasan@freescale.com>");
MODULE_DESCRIPTION("Maxim/Dallas DS3232 RTC Driver");
MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>");
MODULE_DESCRIPTION("Maxim/Dallas DS3232/DS3234 RTC Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("spi:ds3234");
/* rtc-ds3234.c
*
* Driver for Dallas Semiconductor (DS3234) SPI RTC with Integrated Crystal
* and SRAM.
*
* Copyright (C) 2008 MIMOMax Wireless Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/spi/spi.h>
#include <linux/bcd.h>
#define DS3234_REG_SECONDS 0x00
#define DS3234_REG_MINUTES 0x01
#define DS3234_REG_HOURS 0x02
#define DS3234_REG_DAY 0x03
#define DS3234_REG_DATE 0x04
#define DS3234_REG_MONTH 0x05
#define DS3234_REG_YEAR 0x06
#define DS3234_REG_CENTURY (1 << 7) /* Bit 7 of the Month register */
#define DS3234_REG_CONTROL 0x0E
#define DS3234_REG_CONT_STAT 0x0F
static int ds3234_set_reg(struct device *dev, unsigned char address,
unsigned char data)
{
struct spi_device *spi = to_spi_device(dev);
unsigned char buf[2];
/* MSB must be '1' to indicate write */
buf[0] = address | 0x80;
buf[1] = data;
return spi_write_then_read(spi, buf, 2, NULL, 0);
}
static int ds3234_get_reg(struct device *dev, unsigned char address,
unsigned char *data)
{
struct spi_device *spi = to_spi_device(dev);
*data = address & 0x7f;
return spi_write_then_read(spi, data, 1, data, 1);
}
static int ds3234_read_time(struct device *dev, struct rtc_time *dt)
{
int err;
unsigned char buf[8];
struct spi_device *spi = to_spi_device(dev);
buf[0] = 0x00; /* Start address */
err = spi_write_then_read(spi, buf, 1, buf, 8);
if (err != 0)
return err;
/* Seconds, Minutes, Hours, Day, Date, Month, Year */
dt->tm_sec = bcd2bin(buf[0]);
dt->tm_min = bcd2bin(buf[1]);
dt->tm_hour = bcd2bin(buf[2] & 0x3f);
dt->tm_wday = bcd2bin(buf[3]) - 1; /* 0 = Sun */
dt->tm_mday = bcd2bin(buf[4]);
dt->tm_mon = bcd2bin(buf[5] & 0x1f) - 1; /* 0 = Jan */
dt->tm_year = bcd2bin(buf[6] & 0xff) + 100; /* Assume 20YY */
return rtc_valid_tm(dt);
}
static int ds3234_set_time(struct device *dev, struct rtc_time *dt)
{
ds3234_set_reg(dev, DS3234_REG_SECONDS, bin2bcd(dt->tm_sec));
ds3234_set_reg(dev, DS3234_REG_MINUTES, bin2bcd(dt->tm_min));
ds3234_set_reg(dev, DS3234_REG_HOURS, bin2bcd(dt->tm_hour) & 0x3f);
/* 0 = Sun */
ds3234_set_reg(dev, DS3234_REG_DAY, bin2bcd(dt->tm_wday + 1));
ds3234_set_reg(dev, DS3234_REG_DATE, bin2bcd(dt->tm_mday));
/* 0 = Jan */
ds3234_set_reg(dev, DS3234_REG_MONTH, bin2bcd(dt->tm_mon + 1));
/* Assume 20YY although we just want to make sure not to go negative. */
if (dt->tm_year > 100)
dt->tm_year -= 100;
ds3234_set_reg(dev, DS3234_REG_YEAR, bin2bcd(dt->tm_year));
return 0;
}
static const struct rtc_class_ops ds3234_rtc_ops = {
.read_time = ds3234_read_time,
.set_time = ds3234_set_time,
};
static int ds3234_probe(struct spi_device *spi)
{
struct rtc_device *rtc;
unsigned char tmp;
int res;
spi->mode = SPI_MODE_3;
spi->bits_per_word = 8;
spi_setup(spi);
res = ds3234_get_reg(&spi->dev, DS3234_REG_SECONDS, &tmp);
if (res != 0)
return res;
/* Control settings
*
* CONTROL_REG
* BIT 7 6 5 4 3 2 1 0
* EOSC BBSQW CONV RS2 RS1 INTCN A2IE A1IE
*
* 0 0 0 1 1 1 0 0
*
* CONTROL_STAT_REG
* BIT 7 6 5 4 3 2 1 0
* OSF BB32kHz CRATE1 CRATE0 EN32kHz BSY A2F A1F
*
* 1 0 0 0 1 0 0 0
*/
ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp);
ds3234_set_reg(&spi->dev, DS3234_REG_CONTROL, tmp & 0x1c);
ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp);
ds3234_set_reg(&spi->dev, DS3234_REG_CONT_STAT, tmp & 0x88);
/* Print our settings */
ds3234_get_reg(&spi->dev, DS3234_REG_CONTROL, &tmp);
dev_info(&spi->dev, "Control Reg: 0x%02x\n", tmp);
ds3234_get_reg(&spi->dev, DS3234_REG_CONT_STAT, &tmp);
dev_info(&spi->dev, "Ctrl/Stat Reg: 0x%02x\n", tmp);
rtc = devm_rtc_device_register(&spi->dev, "ds3234",
&ds3234_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
spi_set_drvdata(spi, rtc);
return 0;
}
static struct spi_driver ds3234_driver = {
.driver = {
.name = "ds3234",
},
.probe = ds3234_probe,
};
module_spi_driver(ds3234_driver);
MODULE_DESCRIPTION("DS3234 SPI RTC driver");
MODULE_AUTHOR("Dennis Aberilla <denzzzhome@yahoo.com>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("spi:ds3234");
......@@ -9,6 +9,8 @@
#include <linux/platform_device.h>
#include <linux/rtc.h>
#if defined(CONFIG_M68K) || defined(CONFIG_PARISC) || \
defined(CONFIG_PPC) || defined(CONFIG_SUPERH32)
#include <asm/rtc.h>
static int generic_get_time(struct device *dev, struct rtc_time *tm)
......@@ -33,13 +35,21 @@ static const struct rtc_class_ops generic_rtc_ops = {
.read_time = generic_get_time,
.set_time = generic_set_time,
};
#else
#define generic_rtc_ops *(struct rtc_class_ops*)NULL
#endif
static int __init generic_rtc_probe(struct platform_device *dev)
{
struct rtc_device *rtc;
const struct rtc_class_ops *ops;
ops = dev_get_platdata(&dev->dev);
if (!ops)
ops = &generic_rtc_ops;
rtc = devm_rtc_device_register(&dev->dev, "rtc-generic",
&generic_rtc_ops, THIS_MODULE);
ops, THIS_MODULE);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
......
......@@ -144,7 +144,7 @@ static int hym8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
* it does not seem to carry it over a subsequent write/read.
* So we'll limit ourself to 100 years, starting at 2000 for now.
*/
buf[6] = tm->tm_year - 100;
buf[6] = bin2bcd(tm->tm_year - 100);
/*
* CTL1 only contains TEST-mode bits apart from stop,
......
此差异已折叠。
/*
* RTC driver for Maxim MAX77802
*
* Copyright (C) 2013 Google, Inc
*
* Copyright (C) 2012 Samsung Electronics Co.Ltd
*
* based on rtc-max8997.c
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#include <linux/slab.h>
#include <linux/rtc.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mfd/max77686-private.h>
#include <linux/irqdomain.h>
#include <linux/regmap.h>
/* RTC Control Register */
#define BCD_EN_SHIFT 0
#define BCD_EN_MASK (1 << BCD_EN_SHIFT)
#define MODEL24_SHIFT 1
#define MODEL24_MASK (1 << MODEL24_SHIFT)
/* RTC Update Register1 */
#define RTC_UDR_SHIFT 0
#define RTC_UDR_MASK (1 << RTC_UDR_SHIFT)
#define RTC_RBUDR_SHIFT 4
#define RTC_RBUDR_MASK (1 << RTC_RBUDR_SHIFT)
/* RTC Hour register */
#define HOUR_PM_SHIFT 6
#define HOUR_PM_MASK (1 << HOUR_PM_SHIFT)
/* RTC Alarm Enable */
#define ALARM_ENABLE_SHIFT 7
#define ALARM_ENABLE_MASK (1 << ALARM_ENABLE_SHIFT)
/* For the RTCAE1 register, we write this value to enable the alarm */
#define ALARM_ENABLE_VALUE 0x77
#define MAX77802_RTC_UPDATE_DELAY_US 200
enum {
RTC_SEC = 0,
RTC_MIN,
RTC_HOUR,
RTC_WEEKDAY,
RTC_MONTH,
RTC_YEAR,
RTC_DATE,
RTC_NR_TIME
};
struct max77802_rtc_info {
struct device *dev;
struct max77686_dev *max77802;
struct i2c_client *rtc;
struct rtc_device *rtc_dev;
struct mutex lock;
struct regmap *regmap;
int virq;
int rtc_24hr_mode;
};
enum MAX77802_RTC_OP {
MAX77802_RTC_WRITE,
MAX77802_RTC_READ,
};
static void max77802_rtc_data_to_tm(u8 *data, struct rtc_time *tm,
int rtc_24hr_mode)
{
tm->tm_sec = data[RTC_SEC] & 0xff;
tm->tm_min = data[RTC_MIN] & 0xff;
if (rtc_24hr_mode)
tm->tm_hour = data[RTC_HOUR] & 0x1f;
else {
tm->tm_hour = data[RTC_HOUR] & 0x0f;
if (data[RTC_HOUR] & HOUR_PM_MASK)
tm->tm_hour += 12;
}
/* Only a single bit is set in data[], so fls() would be equivalent */
tm->tm_wday = ffs(data[RTC_WEEKDAY] & 0xff) - 1;
tm->tm_mday = data[RTC_DATE] & 0x1f;
tm->tm_mon = (data[RTC_MONTH] & 0x0f) - 1;
tm->tm_year = data[RTC_YEAR] & 0xff;
tm->tm_yday = 0;
tm->tm_isdst = 0;
}
static int max77802_rtc_tm_to_data(struct rtc_time *tm, u8 *data)
{
data[RTC_SEC] = tm->tm_sec;
data[RTC_MIN] = tm->tm_min;
data[RTC_HOUR] = tm->tm_hour;
data[RTC_WEEKDAY] = 1 << tm->tm_wday;
data[RTC_DATE] = tm->tm_mday;
data[RTC_MONTH] = tm->tm_mon + 1;
data[RTC_YEAR] = tm->tm_year;
return 0;
}
static int max77802_rtc_update(struct max77802_rtc_info *info,
enum MAX77802_RTC_OP op)
{
int ret;
unsigned int data;
if (op == MAX77802_RTC_WRITE)
data = 1 << RTC_UDR_SHIFT;
else
data = 1 << RTC_RBUDR_SHIFT;
ret = regmap_update_bits(info->max77802->regmap,
MAX77802_RTC_UPDATE0, data, data);
if (ret < 0)
dev_err(info->dev, "%s: fail to write update reg(ret=%d, data=0x%x)\n",
__func__, ret, data);
else {
/* Minimum delay required before RTC update. */
usleep_range(MAX77802_RTC_UPDATE_DELAY_US,
MAX77802_RTC_UPDATE_DELAY_US * 2);
}
return ret;
}
static int max77802_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct max77802_rtc_info *info = dev_get_drvdata(dev);
u8 data[RTC_NR_TIME];
int ret;
mutex_lock(&info->lock);
ret = max77802_rtc_update(info, MAX77802_RTC_READ);
if (ret < 0)
goto out;
ret = regmap_bulk_read(info->max77802->regmap,
MAX77802_RTC_SEC, data, RTC_NR_TIME);
if (ret < 0) {
dev_err(info->dev, "%s: fail to read time reg(%d)\n", __func__,
ret);
goto out;
}
max77802_rtc_data_to_tm(data, tm, info->rtc_24hr_mode);
ret = rtc_valid_tm(tm);
out:
mutex_unlock(&info->lock);
return ret;
}
static int max77802_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct max77802_rtc_info *info = dev_get_drvdata(dev);
u8 data[RTC_NR_TIME];
int ret;
ret = max77802_rtc_tm_to_data(tm, data);
if (ret < 0)
return ret;
mutex_lock(&info->lock);
ret = regmap_bulk_write(info->max77802->regmap,
MAX77802_RTC_SEC, data, RTC_NR_TIME);
if (ret < 0) {
dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
ret);
goto out;
}
ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
out:
mutex_unlock(&info->lock);
return ret;
}
static int max77802_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct max77802_rtc_info *info = dev_get_drvdata(dev);
u8 data[RTC_NR_TIME];
unsigned int val;
int ret;
mutex_lock(&info->lock);
ret = max77802_rtc_update(info, MAX77802_RTC_READ);
if (ret < 0)
goto out;
ret = regmap_bulk_read(info->max77802->regmap,
MAX77802_ALARM1_SEC, data, RTC_NR_TIME);
if (ret < 0) {
dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
__func__, __LINE__, ret);
goto out;
}
max77802_rtc_data_to_tm(data, &alrm->time, info->rtc_24hr_mode);
alrm->enabled = 0;
ret = regmap_read(info->max77802->regmap,
MAX77802_RTC_AE1, &val);
if (ret < 0) {
dev_err(info->dev, "%s:%d fail to read alarm enable(%d)\n",
__func__, __LINE__, ret);
goto out;
}
if (val)
alrm->enabled = 1;
alrm->pending = 0;
ret = regmap_read(info->max77802->regmap, MAX77802_REG_STATUS2, &val);
if (ret < 0) {
dev_err(info->dev, "%s:%d fail to read status2 reg(%d)\n",
__func__, __LINE__, ret);
goto out;
}
if (val & (1 << 2)) /* RTCA1 */
alrm->pending = 1;
out:
mutex_unlock(&info->lock);
return 0;
}
static int max77802_rtc_stop_alarm(struct max77802_rtc_info *info)
{
int ret;
if (!mutex_is_locked(&info->lock))
dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
ret = max77802_rtc_update(info, MAX77802_RTC_READ);
if (ret < 0)
goto out;
ret = regmap_write(info->max77802->regmap,
MAX77802_RTC_AE1, 0);
if (ret < 0) {
dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
__func__, ret);
goto out;
}
ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
out:
return ret;
}
static int max77802_rtc_start_alarm(struct max77802_rtc_info *info)
{
int ret;
if (!mutex_is_locked(&info->lock))
dev_warn(info->dev, "%s: should have mutex locked\n",
__func__);
ret = max77802_rtc_update(info, MAX77802_RTC_READ);
if (ret < 0)
goto out;
ret = regmap_write(info->max77802->regmap,
MAX77802_RTC_AE1,
ALARM_ENABLE_VALUE);
if (ret < 0) {
dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
__func__, ret);
goto out;
}
ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
out:
return ret;
}
static int max77802_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct max77802_rtc_info *info = dev_get_drvdata(dev);
u8 data[RTC_NR_TIME];
int ret;
ret = max77802_rtc_tm_to_data(&alrm->time, data);
if (ret < 0)
return ret;
mutex_lock(&info->lock);
ret = max77802_rtc_stop_alarm(info);
if (ret < 0)
goto out;
ret = regmap_bulk_write(info->max77802->regmap,
MAX77802_ALARM1_SEC, data, RTC_NR_TIME);
if (ret < 0) {
dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
__func__, ret);
goto out;
}
ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
if (ret < 0)
goto out;
if (alrm->enabled)
ret = max77802_rtc_start_alarm(info);
out:
mutex_unlock(&info->lock);
return ret;
}
static int max77802_rtc_alarm_irq_enable(struct device *dev,
unsigned int enabled)
{
struct max77802_rtc_info *info = dev_get_drvdata(dev);
int ret;
mutex_lock(&info->lock);
if (enabled)
ret = max77802_rtc_start_alarm(info);
else
ret = max77802_rtc_stop_alarm(info);
mutex_unlock(&info->lock);
return ret;
}
static irqreturn_t max77802_rtc_alarm_irq(int irq, void *data)
{
struct max77802_rtc_info *info = data;
dev_dbg(info->dev, "%s:irq(%d)\n", __func__, irq);
rtc_update_irq(info->rtc_dev, 1, RTC_IRQF | RTC_AF);
return IRQ_HANDLED;
}
static const struct rtc_class_ops max77802_rtc_ops = {
.read_time = max77802_rtc_read_time,
.set_time = max77802_rtc_set_time,
.read_alarm = max77802_rtc_read_alarm,
.set_alarm = max77802_rtc_set_alarm,
.alarm_irq_enable = max77802_rtc_alarm_irq_enable,
};
static int max77802_rtc_init_reg(struct max77802_rtc_info *info)
{
u8 data[2];
int ret;
max77802_rtc_update(info, MAX77802_RTC_READ);
/* Set RTC control register : Binary mode, 24hour mdoe */
data[0] = (1 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
data[1] = (0 << BCD_EN_SHIFT) | (1 << MODEL24_SHIFT);
info->rtc_24hr_mode = 1;
ret = regmap_bulk_write(info->max77802->regmap,
MAX77802_RTC_CONTROLM, data, ARRAY_SIZE(data));
if (ret < 0) {
dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
__func__, ret);
return ret;
}
ret = max77802_rtc_update(info, MAX77802_RTC_WRITE);
return ret;
}
static int max77802_rtc_probe(struct platform_device *pdev)
{
struct max77686_dev *max77802 = dev_get_drvdata(pdev->dev.parent);
struct max77802_rtc_info *info;
int ret;
dev_dbg(&pdev->dev, "%s\n", __func__);
info = devm_kzalloc(&pdev->dev, sizeof(struct max77802_rtc_info),
GFP_KERNEL);
if (!info)
return -ENOMEM;
mutex_init(&info->lock);
info->dev = &pdev->dev;
info->max77802 = max77802;
info->rtc = max77802->i2c;
platform_set_drvdata(pdev, info);
ret = max77802_rtc_init_reg(info);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to initialize RTC reg:%d\n", ret);
return ret;
}
device_init_wakeup(&pdev->dev, 1);
info->rtc_dev = devm_rtc_device_register(&pdev->dev, "max77802-rtc",
&max77802_rtc_ops, THIS_MODULE);
if (IS_ERR(info->rtc_dev)) {
ret = PTR_ERR(info->rtc_dev);
dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret);
if (ret == 0)
ret = -EINVAL;
return ret;
}
if (!max77802->rtc_irq_data) {
dev_err(&pdev->dev, "No RTC regmap IRQ chip\n");
return -EINVAL;
}
info->virq = regmap_irq_get_virq(max77802->rtc_irq_data,
MAX77686_RTCIRQ_RTCA1);
if (info->virq <= 0) {
dev_err(&pdev->dev, "Failed to get virtual IRQ %d\n",
MAX77686_RTCIRQ_RTCA1);
return -EINVAL;
}
ret = devm_request_threaded_irq(&pdev->dev, info->virq, NULL,
max77802_rtc_alarm_irq, 0, "rtc-alarm1",
info);
if (ret < 0)
dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
info->virq, ret);
return ret;
}
#ifdef CONFIG_PM_SLEEP
static int max77802_rtc_suspend(struct device *dev)
{
if (device_may_wakeup(dev)) {
struct max77802_rtc_info *info = dev_get_drvdata(dev);
return enable_irq_wake(info->virq);
}
return 0;
}
static int max77802_rtc_resume(struct device *dev)
{
if (device_may_wakeup(dev)) {
struct max77802_rtc_info *info = dev_get_drvdata(dev);
return disable_irq_wake(info->virq);
}
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(max77802_rtc_pm_ops,
max77802_rtc_suspend, max77802_rtc_resume);
static const struct platform_device_id rtc_id[] = {
{ "max77802-rtc", 0 },
{},
};
MODULE_DEVICE_TABLE(platform, rtc_id);
static struct platform_driver max77802_rtc_driver = {
.driver = {
.name = "max77802-rtc",
.pm = &max77802_rtc_pm_ops,
},
.probe = max77802_rtc_probe,
.id_table = rtc_id,
};
module_platform_driver(max77802_rtc_driver);
MODULE_DESCRIPTION("Maxim MAX77802 RTC driver");
MODULE_AUTHOR("Simon Glass <sjg@chromium.org>");
MODULE_LICENSE("GPL");
......@@ -419,4 +419,3 @@ module_platform_driver(mtk_rtc_driver);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Tianping Fang <tianping.fang@mediatek.com>");
MODULE_DESCRIPTION("RTC Driver for MediaTek MT6397 PMIC");
MODULE_ALIAS("platform:mt6397-rtc");
......@@ -311,8 +311,7 @@ static int palmas_rtc_probe(struct platform_device *pdev)
ret = devm_request_threaded_irq(&pdev->dev, palmas_rtc->irq, NULL,
palmas_rtc_interrupt,
IRQF_TRIGGER_LOW | IRQF_ONESHOT |
IRQF_EARLY_RESUME,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
dev_name(&pdev->dev), palmas_rtc);
if (ret < 0) {
dev_err(&pdev->dev, "IRQ request failed, err = %d\n", ret);
......
......@@ -48,6 +48,7 @@
#define DRV_VERSION "0.6"
/* REGISTERS */
#define PCF2123_REG_CTRL1 (0x00) /* Control Register 1 */
#define PCF2123_REG_CTRL2 (0x01) /* Control Register 2 */
#define PCF2123_REG_SC (0x02) /* datetime */
......@@ -57,10 +58,54 @@
#define PCF2123_REG_DW (0x06)
#define PCF2123_REG_MO (0x07)
#define PCF2123_REG_YR (0x08)
#define PCF2123_REG_ALRM_MN (0x09) /* Alarm Registers */
#define PCF2123_REG_ALRM_HR (0x0a)
#define PCF2123_REG_ALRM_DM (0x0b)
#define PCF2123_REG_ALRM_DW (0x0c)
#define PCF2123_REG_OFFSET (0x0d) /* Clock Rate Offset Register */
#define PCF2123_REG_TMR_CLKOUT (0x0e) /* Timer Registers */
#define PCF2123_REG_CTDWN_TMR (0x0f)
/* PCF2123_REG_CTRL1 BITS */
#define CTRL1_CLEAR (0) /* Clear */
#define CTRL1_CORR_INT BIT(1) /* Correction irq enable */
#define CTRL1_12_HOUR BIT(2) /* 12 hour time */
#define CTRL1_SW_RESET (BIT(3) | BIT(4) | BIT(6)) /* Software reset */
#define CTRL1_STOP BIT(5) /* Stop the clock */
#define CTRL1_EXT_TEST BIT(7) /* External clock test mode */
/* PCF2123_REG_CTRL2 BITS */
#define CTRL2_TIE BIT(0) /* Countdown timer irq enable */
#define CTRL2_AIE BIT(1) /* Alarm irq enable */
#define CTRL2_TF BIT(2) /* Countdown timer flag */
#define CTRL2_AF BIT(3) /* Alarm flag */
#define CTRL2_TI_TP BIT(4) /* Irq pin generates pulse */
#define CTRL2_MSF BIT(5) /* Minute or second irq flag */
#define CTRL2_SI BIT(6) /* Second irq enable */
#define CTRL2_MI BIT(7) /* Minute irq enable */
/* PCF2123_REG_SC BITS */
#define OSC_HAS_STOPPED BIT(7) /* Clock has been stopped */
/* PCF2123_REG_ALRM_XX BITS */
#define ALRM_ENABLE BIT(7) /* MN, HR, DM, or DW alarm enable */
/* PCF2123_REG_TMR_CLKOUT BITS */
#define CD_TMR_4096KHZ (0) /* 4096 KHz countdown timer */
#define CD_TMR_64HZ (1) /* 64 Hz countdown timer */
#define CD_TMR_1HZ (2) /* 1 Hz countdown timer */
#define CD_TMR_60th_HZ (3) /* 60th Hz countdown timer */
#define CD_TMR_TE BIT(3) /* Countdown timer enable */
/* PCF2123_REG_OFFSET BITS */
#define OFFSET_SIGN_BIT BIT(6) /* 2's complement sign bit */
#define OFFSET_COARSE BIT(7) /* Coarse mode offset */
#define OFFSET_STEP (2170) /* Offset step in parts per billion */
/* READ/WRITE ADDRESS BITS */
#define PCF2123_WRITE BIT(4)
#define PCF2123_READ (BIT(4) | BIT(7))
#define PCF2123_SUBADDR (1 << 4)
#define PCF2123_WRITE ((0 << 7) | PCF2123_SUBADDR)
#define PCF2123_READ ((1 << 7) | PCF2123_SUBADDR)
static struct spi_driver pcf2123_driver;
......@@ -84,12 +129,44 @@ static inline void pcf2123_delay_trec(void)
ndelay(30);
}
static int pcf2123_read(struct device *dev, u8 reg, u8 *rxbuf, size_t size)
{
struct spi_device *spi = to_spi_device(dev);
int ret;
reg |= PCF2123_READ;
ret = spi_write_then_read(spi, &reg, 1, rxbuf, size);
pcf2123_delay_trec();
return ret;
}
static int pcf2123_write(struct device *dev, u8 *txbuf, size_t size)
{
struct spi_device *spi = to_spi_device(dev);
int ret;
txbuf[0] |= PCF2123_WRITE;
ret = spi_write(spi, txbuf, size);
pcf2123_delay_trec();
return ret;
}
static int pcf2123_write_reg(struct device *dev, u8 reg, u8 val)
{
u8 txbuf[2];
txbuf[0] = reg;
txbuf[1] = val;
return pcf2123_write(dev, txbuf, sizeof(txbuf));
}
static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr,
char *buffer)
{
struct spi_device *spi = to_spi_device(dev);
struct pcf2123_sysfs_reg *r;
u8 txbuf[1], rxbuf[1];
u8 rxbuf[1];
unsigned long reg;
int ret;
......@@ -99,19 +176,16 @@ static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr,
if (ret)
return ret;
txbuf[0] = PCF2123_READ | reg;
ret = spi_write_then_read(spi, txbuf, 1, rxbuf, 1);
ret = pcf2123_read(dev, reg, rxbuf, 1);
if (ret < 0)
return -EIO;
pcf2123_delay_trec();
return sprintf(buffer, "0x%x\n", rxbuf[0]);
}
static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,
const char *buffer, size_t count) {
struct spi_device *spi = to_spi_device(dev);
struct pcf2123_sysfs_reg *r;
u8 txbuf[2];
unsigned long reg;
unsigned long val;
......@@ -127,27 +201,78 @@ static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr,
if (ret)
return ret;
txbuf[0] = PCF2123_WRITE | reg;
txbuf[1] = val;
ret = spi_write(spi, txbuf, sizeof(txbuf));
pcf2123_write_reg(dev, reg, val);
if (ret < 0)
return -EIO;
pcf2123_delay_trec();
return count;
}
static int pcf2123_read_offset(struct device *dev, long *offset)
{
int ret;
s8 reg;
ret = pcf2123_read(dev, PCF2123_REG_OFFSET, &reg, 1);
if (ret < 0)
return ret;
if (reg & OFFSET_COARSE)
reg <<= 1; /* multiply by 2 and sign extend */
else
reg |= (reg & OFFSET_SIGN_BIT) << 1; /* sign extend only */
*offset = ((long)reg) * OFFSET_STEP;
return 0;
}
/*
* The offset register is a 7 bit signed value with a coarse bit in bit 7.
* The main difference between the two is normal offset adjusts the first
* second of n minutes every other hour, with 61, 62 and 63 being shoved
* into the 60th minute.
* The coarse adjustment does the same, but every hour.
* the two overlap, with every even normal offset value corresponding
* to a coarse offset. Based on this algorithm, it seems that despite the
* name, coarse offset is a better fit for overlapping values.
*/
static int pcf2123_set_offset(struct device *dev, long offset)
{
s8 reg;
if (offset > OFFSET_STEP * 127)
reg = 127;
else if (offset < OFFSET_STEP * -128)
reg = -128;
else
reg = (s8)((offset + (OFFSET_STEP >> 1)) / OFFSET_STEP);
/* choose fine offset only for odd values in the normal range */
if (reg & 1 && reg <= 63 && reg >= -64) {
/* Normal offset. Clear the coarse bit */
reg &= ~OFFSET_COARSE;
} else {
/* Coarse offset. Divide by 2 and set the coarse bit */
reg >>= 1;
reg |= OFFSET_COARSE;
}
return pcf2123_write_reg(dev, PCF2123_REG_OFFSET, reg);
}
static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct spi_device *spi = to_spi_device(dev);
u8 txbuf[1], rxbuf[7];
u8 rxbuf[7];
int ret;
txbuf[0] = PCF2123_READ | PCF2123_REG_SC;
ret = spi_write_then_read(spi, txbuf, sizeof(txbuf),
rxbuf, sizeof(rxbuf));
ret = pcf2123_read(dev, PCF2123_REG_SC, rxbuf, sizeof(rxbuf));
if (ret < 0)
return ret;
pcf2123_delay_trec();
if (rxbuf[0] & OSC_HAS_STOPPED) {
dev_info(dev, "clock was stopped. Time is not valid\n");
return -EINVAL;
}
tm->tm_sec = bcd2bin(rxbuf[0] & 0x7F);
tm->tm_min = bcd2bin(rxbuf[1] & 0x7F);
......@@ -170,7 +295,6 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct spi_device *spi = to_spi_device(dev);
u8 txbuf[8];
int ret;
......@@ -181,15 +305,12 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
/* Stop the counter first */
txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
txbuf[1] = 0x20;
ret = spi_write(spi, txbuf, 2);
ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_STOP);
if (ret < 0)
return ret;
pcf2123_delay_trec();
/* Set the new time */
txbuf[0] = PCF2123_WRITE | PCF2123_REG_SC;
txbuf[0] = PCF2123_REG_SC;
txbuf[1] = bin2bcd(tm->tm_sec & 0x7F);
txbuf[2] = bin2bcd(tm->tm_min & 0x7F);
txbuf[3] = bin2bcd(tm->tm_hour & 0x3F);
......@@ -198,18 +319,48 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
txbuf[6] = bin2bcd((tm->tm_mon + 1) & 0x1F); /* rtc mn 1-12 */
txbuf[7] = bin2bcd(tm->tm_year < 100 ? tm->tm_year : tm->tm_year - 100);
ret = spi_write(spi, txbuf, sizeof(txbuf));
ret = pcf2123_write(dev, txbuf, sizeof(txbuf));
if (ret < 0)
return ret;
pcf2123_delay_trec();
/* Start the counter */
txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
txbuf[1] = 0x00;
ret = spi_write(spi, txbuf, 2);
ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_CLEAR);
if (ret < 0)
return ret;
return 0;
}
static int pcf2123_reset(struct device *dev)
{
int ret;
u8 rxbuf[2];
ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_SW_RESET);
if (ret < 0)
return ret;
/* Stop the counter */
dev_dbg(dev, "stopping RTC\n");
ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_STOP);
if (ret < 0)
return ret;
/* See if the counter was actually stopped */
dev_dbg(dev, "checking for presence of RTC\n");
ret = pcf2123_read(dev, PCF2123_REG_CTRL1, rxbuf, sizeof(rxbuf));
if (ret < 0)
return ret;
dev_dbg(dev, "received data from RTC (0x%02X 0x%02X)\n",
rxbuf[0], rxbuf[1]);
if (!(rxbuf[0] & CTRL1_STOP))
return -ENODEV;
/* Start the counter */
ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_CLEAR);
if (ret < 0)
return ret;
pcf2123_delay_trec();
return 0;
}
......@@ -217,13 +368,16 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
static const struct rtc_class_ops pcf2123_rtc_ops = {
.read_time = pcf2123_rtc_read_time,
.set_time = pcf2123_rtc_set_time,
.read_offset = pcf2123_read_offset,
.set_offset = pcf2123_set_offset,
};
static int pcf2123_probe(struct spi_device *spi)
{
struct rtc_device *rtc;
struct rtc_time tm;
struct pcf2123_plat_data *pdata;
u8 txbuf[2], rxbuf[2];
int ret, i;
pdata = devm_kzalloc(&spi->dev, sizeof(struct pcf2123_plat_data),
......@@ -232,56 +386,19 @@ static int pcf2123_probe(struct spi_device *spi)
return -ENOMEM;
spi->dev.platform_data = pdata;
/* Send a software reset command */
txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
txbuf[1] = 0x58;
dev_dbg(&spi->dev, "resetting RTC (0x%02X 0x%02X)\n",
txbuf[0], txbuf[1]);
ret = spi_write(spi, txbuf, 2 * sizeof(u8));
if (ret < 0)
goto kfree_exit;
pcf2123_delay_trec();
/* Stop the counter */
txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
txbuf[1] = 0x20;
dev_dbg(&spi->dev, "stopping RTC (0x%02X 0x%02X)\n",
txbuf[0], txbuf[1]);
ret = spi_write(spi, txbuf, 2 * sizeof(u8));
if (ret < 0)
goto kfree_exit;
pcf2123_delay_trec();
/* See if the counter was actually stopped */
txbuf[0] = PCF2123_READ | PCF2123_REG_CTRL1;
dev_dbg(&spi->dev, "checking for presence of RTC (0x%02X)\n",
txbuf[0]);
ret = spi_write_then_read(spi, txbuf, 1 * sizeof(u8),
rxbuf, 2 * sizeof(u8));
dev_dbg(&spi->dev, "received data from RTC (0x%02X 0x%02X)\n",
rxbuf[0], rxbuf[1]);
if (ret < 0)
goto kfree_exit;
pcf2123_delay_trec();
if (!(rxbuf[0] & 0x20)) {
dev_err(&spi->dev, "chip not found\n");
ret = -ENODEV;
goto kfree_exit;
ret = pcf2123_rtc_read_time(&spi->dev, &tm);
if (ret < 0) {
ret = pcf2123_reset(&spi->dev);
if (ret < 0) {
dev_err(&spi->dev, "chip not found\n");
goto kfree_exit;
}
}
dev_info(&spi->dev, "chip found, driver version " DRV_VERSION "\n");
dev_info(&spi->dev, "spiclk %u KHz.\n",
(spi->max_speed_hz + 500) / 1000);
/* Start the counter */
txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1;
txbuf[1] = 0x00;
ret = spi_write(spi, txbuf, sizeof(txbuf));
if (ret < 0)
goto kfree_exit;
pcf2123_delay_trec();
/* Finalize the initialization */
rtc = devm_rtc_device_register(&spi->dev, pcf2123_driver.driver.name,
&pcf2123_rtc_ops, THIS_MODULE);
......
/*
* An I2C driver for the NXP PCF2127 RTC
* An I2C and SPI driver for the NXP PCF2127/29 RTC
* Copyright 2013 Til-Technologies
*
* Author: Renaud Cerrato <r.cerrato@til-technologies.fr>
*
* based on the other drivers in this same directory.
*
* http://www.nxp.com/documents/data_sheet/PCF2127AT.pdf
* Datasheet: http://cache.nxp.com/documents/data_sheet/PCF2127.pdf
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
......@@ -14,11 +14,13 @@
*/
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/bcd.h>
#include <linux/rtc.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/regmap.h>
#define PCF2127_REG_CTRL1 (0x00) /* Control Register 1 */
#define PCF2127_REG_CTRL2 (0x01) /* Control Register 2 */
......@@ -36,29 +38,30 @@
#define PCF2127_OSF BIT(7) /* Oscillator Fail flag */
static struct i2c_driver pcf2127_driver;
struct pcf2127 {
struct rtc_device *rtc;
struct regmap *regmap;
};
/*
* In the routines that deal directly with the pcf2127 hardware, we use
* rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch.
*/
static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
unsigned char buf[10] = { PCF2127_REG_CTRL1 };
struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
unsigned char buf[10];
int ret;
/* read registers */
if (i2c_master_send(client, buf, 1) != 1 ||
i2c_master_recv(client, buf, sizeof(buf)) != sizeof(buf)) {
dev_err(&client->dev, "%s: read error\n", __func__);
return -EIO;
ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_CTRL1, buf,
sizeof(buf));
if (ret) {
dev_err(dev, "%s: read error\n", __func__);
return ret;
}
if (buf[PCF2127_REG_CTRL3] & PCF2127_REG_CTRL3_BLF)
dev_info(&client->dev,
dev_info(dev,
"low voltage detected, check/replace RTC battery.\n");
if (buf[PCF2127_REG_SC] & PCF2127_OSF) {
......@@ -66,12 +69,12 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
* no need clear the flag here,
* it will be cleared once the new date is saved
*/
dev_warn(&client->dev,
dev_warn(dev,
"oscillator stop detected, date/time is not reliable\n");
return -EINVAL;
}
dev_dbg(&client->dev,
dev_dbg(dev,
"%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, "
"sec=%02x, min=%02x, hr=%02x, "
"mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
......@@ -91,7 +94,7 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
if (tm->tm_year < 70)
tm->tm_year += 100; /* assume we are in 1970...2069 */
dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
__func__,
tm->tm_sec, tm->tm_min, tm->tm_hour,
......@@ -100,20 +103,18 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
return rtc_valid_tm(tm);
}
static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
unsigned char buf[8];
struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
unsigned char buf[7];
int i = 0, err;
dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
__func__,
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
/* start register address */
buf[i++] = PCF2127_REG_SC;
/* hours, minutes and seconds */
buf[i++] = bin2bcd(tm->tm_sec); /* this will also clear OSF flag */
buf[i++] = bin2bcd(tm->tm_min);
......@@ -128,11 +129,11 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
buf[i++] = bin2bcd(tm->tm_year % 100);
/* write register's data */
err = i2c_master_send(client, buf, i);
if (err != i) {
dev_err(&client->dev,
err = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_SC, buf, i);
if (err) {
dev_err(dev,
"%s: err=%d", __func__, err);
return -EIO;
return err;
}
return 0;
......@@ -142,26 +143,17 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
static int pcf2127_rtc_ioctl(struct device *dev,
unsigned int cmd, unsigned long arg)
{
struct i2c_client *client = to_i2c_client(dev);
unsigned char buf = PCF2127_REG_CTRL3;
struct pcf2127 *pcf2127 = dev_get_drvdata(dev);
int touser;
int ret;
switch (cmd) {
case RTC_VL_READ:
ret = i2c_master_send(client, &buf, 1);
if (!ret)
ret = -EIO;
if (ret < 0)
return ret;
ret = i2c_master_recv(client, &buf, 1);
if (!ret)
ret = -EIO;
if (ret < 0)
ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &touser);
if (ret)
return ret;
touser = buf & PCF2127_REG_CTRL3_BLF ? 1 : 0;
touser = touser & PCF2127_REG_CTRL3_BLF ? 1 : 0;
if (copy_to_user((void __user *)arg, &touser, sizeof(int)))
return -EFAULT;
......@@ -174,71 +166,270 @@ static int pcf2127_rtc_ioctl(struct device *dev,
#define pcf2127_rtc_ioctl NULL
#endif
static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
return pcf2127_get_datetime(to_i2c_client(dev), tm);
}
static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
return pcf2127_set_datetime(to_i2c_client(dev), tm);
}
static const struct rtc_class_ops pcf2127_rtc_ops = {
.ioctl = pcf2127_rtc_ioctl,
.read_time = pcf2127_rtc_read_time,
.set_time = pcf2127_rtc_set_time,
};
static int pcf2127_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int pcf2127_probe(struct device *dev, struct regmap *regmap,
const char *name)
{
struct pcf2127 *pcf2127;
dev_dbg(&client->dev, "%s\n", __func__);
dev_dbg(dev, "%s\n", __func__);
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
pcf2127 = devm_kzalloc(&client->dev, sizeof(struct pcf2127),
GFP_KERNEL);
pcf2127 = devm_kzalloc(dev, sizeof(*pcf2127), GFP_KERNEL);
if (!pcf2127)
return -ENOMEM;
i2c_set_clientdata(client, pcf2127);
pcf2127->regmap = regmap;
dev_set_drvdata(dev, pcf2127);
pcf2127->rtc = devm_rtc_device_register(&client->dev,
pcf2127_driver.driver.name,
&pcf2127_rtc_ops, THIS_MODULE);
pcf2127->rtc = devm_rtc_device_register(dev, name, &pcf2127_rtc_ops,
THIS_MODULE);
return PTR_ERR_OR_ZERO(pcf2127->rtc);
}
static const struct i2c_device_id pcf2127_id[] = {
{ "pcf2127", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcf2127_id);
#ifdef CONFIG_OF
static const struct of_device_id pcf2127_of_match[] = {
{ .compatible = "nxp,pcf2127" },
{ .compatible = "nxp,pcf2129" },
{}
};
MODULE_DEVICE_TABLE(of, pcf2127_of_match);
#endif
static struct i2c_driver pcf2127_driver = {
#if IS_ENABLED(CONFIG_I2C)
static int pcf2127_i2c_write(void *context, const void *data, size_t count)
{
struct device *dev = context;
struct i2c_client *client = to_i2c_client(dev);
int ret;
ret = i2c_master_send(client, data, count);
if (ret != count)
return ret < 0 ? ret : -EIO;
return 0;
}
static int pcf2127_i2c_gather_write(void *context,
const void *reg, size_t reg_size,
const void *val, size_t val_size)
{
struct device *dev = context;
struct i2c_client *client = to_i2c_client(dev);
int ret;
void *buf;
if (WARN_ON(reg_size != 1))
return -EINVAL;
buf = kmalloc(val_size + 1, GFP_KERNEL);
if (!buf)
return -ENOMEM;
memcpy(buf, reg, 1);
memcpy(buf + 1, val, val_size);
ret = i2c_master_send(client, buf, val_size + 1);
if (ret != val_size + 1)
return ret < 0 ? ret : -EIO;
return 0;
}
static int pcf2127_i2c_read(void *context, const void *reg, size_t reg_size,
void *val, size_t val_size)
{
struct device *dev = context;
struct i2c_client *client = to_i2c_client(dev);
int ret;
if (WARN_ON(reg_size != 1))
return -EINVAL;
ret = i2c_master_send(client, reg, 1);
if (ret != 1)
return ret < 0 ? ret : -EIO;
ret = i2c_master_recv(client, val, val_size);
if (ret != val_size)
return ret < 0 ? ret : -EIO;
return 0;
}
/*
* The reason we need this custom regmap_bus instead of using regmap_init_i2c()
* is that the STOP condition is required between set register address and
* read register data when reading from registers.
*/
static const struct regmap_bus pcf2127_i2c_regmap = {
.write = pcf2127_i2c_write,
.gather_write = pcf2127_i2c_gather_write,
.read = pcf2127_i2c_read,
};
static struct i2c_driver pcf2127_i2c_driver;
static int pcf2127_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct regmap *regmap;
static const struct regmap_config config = {
.reg_bits = 8,
.val_bits = 8,
};
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
regmap = devm_regmap_init(&client->dev, &pcf2127_i2c_regmap,
&client->dev, &config);
if (IS_ERR(regmap)) {
dev_err(&client->dev, "%s: regmap allocation failed: %ld\n",
__func__, PTR_ERR(regmap));
return PTR_ERR(regmap);
}
return pcf2127_probe(&client->dev, regmap,
pcf2127_i2c_driver.driver.name);
}
static const struct i2c_device_id pcf2127_i2c_id[] = {
{ "pcf2127", 0 },
{ "pcf2129", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcf2127_i2c_id);
static struct i2c_driver pcf2127_i2c_driver = {
.driver = {
.name = "rtc-pcf2127-i2c",
.of_match_table = of_match_ptr(pcf2127_of_match),
},
.probe = pcf2127_i2c_probe,
.id_table = pcf2127_i2c_id,
};
static int pcf2127_i2c_register_driver(void)
{
return i2c_add_driver(&pcf2127_i2c_driver);
}
static void pcf2127_i2c_unregister_driver(void)
{
i2c_del_driver(&pcf2127_i2c_driver);
}
#else
static int pcf2127_i2c_register_driver(void)
{
return 0;
}
static void pcf2127_i2c_unregister_driver(void)
{
}
#endif
#if IS_ENABLED(CONFIG_SPI_MASTER)
static struct spi_driver pcf2127_spi_driver;
static int pcf2127_spi_probe(struct spi_device *spi)
{
static const struct regmap_config config = {
.reg_bits = 8,
.val_bits = 8,
.read_flag_mask = 0xa0,
.write_flag_mask = 0x20,
};
struct regmap *regmap;
regmap = devm_regmap_init_spi(spi, &config);
if (IS_ERR(regmap)) {
dev_err(&spi->dev, "%s: regmap allocation failed: %ld\n",
__func__, PTR_ERR(regmap));
return PTR_ERR(regmap);
}
return pcf2127_probe(&spi->dev, regmap, pcf2127_spi_driver.driver.name);
}
static const struct spi_device_id pcf2127_spi_id[] = {
{ "pcf2127", 0 },
{ "pcf2129", 0 },
{ }
};
MODULE_DEVICE_TABLE(spi, pcf2127_spi_id);
static struct spi_driver pcf2127_spi_driver = {
.driver = {
.name = "rtc-pcf2127",
.name = "rtc-pcf2127-spi",
.of_match_table = of_match_ptr(pcf2127_of_match),
},
.probe = pcf2127_probe,
.id_table = pcf2127_id,
.probe = pcf2127_spi_probe,
.id_table = pcf2127_spi_id,
};
module_i2c_driver(pcf2127_driver);
static int pcf2127_spi_register_driver(void)
{
return spi_register_driver(&pcf2127_spi_driver);
}
static void pcf2127_spi_unregister_driver(void)
{
spi_unregister_driver(&pcf2127_spi_driver);
}
#else
static int pcf2127_spi_register_driver(void)
{
return 0;
}
static void pcf2127_spi_unregister_driver(void)
{
}
#endif
static int __init pcf2127_init(void)
{
int ret;
ret = pcf2127_i2c_register_driver();
if (ret) {
pr_err("Failed to register pcf2127 i2c driver: %d\n", ret);
return ret;
}
ret = pcf2127_spi_register_driver();
if (ret) {
pr_err("Failed to register pcf2127 spi driver: %d\n", ret);
pcf2127_i2c_unregister_driver();
}
return ret;
}
module_init(pcf2127_init)
static void __exit pcf2127_exit(void)
{
pcf2127_spi_unregister_driver();
pcf2127_i2c_unregister_driver();
}
module_exit(pcf2127_exit)
MODULE_AUTHOR("Renaud Cerrato <r.cerrato@til-technologies.fr>");
MODULE_DESCRIPTION("NXP PCF2127 RTC driver");
MODULE_DESCRIPTION("NXP PCF2127/29 RTC driver");
MODULE_LICENSE("GPL v2");
此差异已折叠。
......@@ -178,28 +178,8 @@ static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm)
if (err < 0)
return err;
if (regs[0] & REG_SECONDS_OS) {
/*
* If the oscillator was stopped, try to clear the flag. Upon
* power-up the flag is always set, but if we cannot clear it
* the oscillator isn't running properly for some reason. The
* sensible thing therefore is to return an error, signalling
* that the clock cannot be assumed to be correct.
*/
regs[0] &= ~REG_SECONDS_OS;
err = pcf8523_write(client, REG_SECONDS, regs[0]);
if (err < 0)
return err;
err = pcf8523_read(client, REG_SECONDS, &regs[0]);
if (err < 0)
return err;
if (regs[0] & REG_SECONDS_OS)
return -EAGAIN;
}
if (regs[0] & REG_SECONDS_OS)
return -EINVAL;
tm->tm_sec = bcd2bin(regs[0] & 0x7f);
tm->tm_min = bcd2bin(regs[1] & 0x7f);
......@@ -235,6 +215,7 @@ static int pcf8523_rtc_set_time(struct device *dev, struct rtc_time *tm)
return err;
regs[0] = REG_SECONDS;
/* This will purposely overwrite REG_SECONDS_OS */
regs[1] = bin2bcd(tm->tm_sec);
regs[2] = bin2bcd(tm->tm_min);
regs[3] = bin2bcd(tm->tm_hour);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -65,7 +65,6 @@
static const struct i2c_device_id rx8025_id[] = {
{ "rx8025", 0 },
{ "rv8803", 1 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rx8025_id);
......@@ -147,8 +146,10 @@ static irqreturn_t rx8025_handle_irq(int irq, void *dev_id)
{
struct i2c_client *client = dev_id;
struct rx8025_data *rx8025 = i2c_get_clientdata(client);
struct mutex *lock = &rx8025->rtc->ops_lock;
int status;
mutex_lock(lock);
status = rx8025_read_reg(client, RX8025_REG_CTRL2);
if (status < 0)
goto out;
......@@ -173,6 +174,8 @@ static irqreturn_t rx8025_handle_irq(int irq, void *dev_id)
}
out:
mutex_unlock(lock);
return IRQ_HANDLED;
}
......@@ -341,7 +344,17 @@ static int rx8025_set_alarm(struct device *dev, struct rtc_wkalrm *t)
if (client->irq <= 0)
return -EINVAL;
/* Hardware alarm precision is 1 minute! */
/*
* Hardware alarm precision is 1 minute!
* round up to nearest minute
*/
if (t->time.tm_sec) {
time64_t alarm_time = rtc_tm_to_time64(&t->time);
alarm_time += 60 - t->time.tm_sec;
rtc_time64_to_tm(alarm_time, &t->time);
}
ald[0] = bin2bcd(t->time.tm_min);
if (rx8025->ctrl1 & RX8025_BIT_CTRL1_1224)
ald[1] = bin2bcd(t->time.tm_hour);
......@@ -539,8 +552,9 @@ static int rx8025_probe(struct i2c_client *client,
if (client->irq > 0) {
dev_info(&client->dev, "IRQ %d supplied\n", client->irq);
err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
rx8025_handle_irq, 0, "rx8025",
client);
rx8025_handle_irq,
IRQF_ONESHOT,
"rx8025", client);
if (err) {
dev_err(&client->dev, "unable to request IRQ, alarms disabled\n");
client->irq = 0;
......@@ -549,6 +563,9 @@ static int rx8025_probe(struct i2c_client *client,
rx8025->rtc->max_user_freq = 1;
/* the rx8025 alarm only supports a minute accuracy */
rx8025->rtc->uie_unsupported = 1;
err = rx8025_sysfs_register(&client->dev);
return err;
}
......
此差异已折叠。
此差异已折叠。
......@@ -286,7 +286,7 @@ static int tps6586x_rtc_probe(struct platform_device *pdev)
ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
tps6586x_rtc_irq,
IRQF_ONESHOT | IRQF_EARLY_RESUME,
IRQF_ONESHOT,
dev_name(&pdev->dev), rtc);
if (ret < 0) {
dev_err(&pdev->dev, "request IRQ(%d) failed with ret %d\n",
......
......@@ -268,7 +268,7 @@ static int tps65910_rtc_probe(struct platform_device *pdev)
}
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
tps65910_rtc_interrupt, IRQF_TRIGGER_LOW | IRQF_EARLY_RESUME,
tps65910_rtc_interrupt, IRQF_TRIGGER_LOW,
dev_name(&pdev->dev), &pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "IRQ is not free.\n");
......
......@@ -287,7 +287,7 @@ static int tps80031_rtc_probe(struct platform_device *pdev)
ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
tps80031_rtc_irq,
IRQF_ONESHOT | IRQF_EARLY_RESUME,
IRQF_ONESHOT,
dev_name(&pdev->dev), rtc);
if (ret < 0) {
dev_err(&pdev->dev, "request IRQ:%d failed, err = %d\n",
......
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册