Skip to content
Snippets Groups Projects
Commit 13f6f62f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
  ...
parents f0718cea cee2cc21
No related branches found
No related tags found
No related merge requests found
Showing
with 1847 additions and 692 deletions
* 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 ...@@ -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 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 future, or if there is a leading +=, seconds ahead of the current
alarm. 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 IOCTL INTERFACE
--------------- ---------------
......
...@@ -35,8 +35,6 @@ ...@@ -35,8 +35,6 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/of.h> #include <linux/of.h>
#define I2C_ADDR_RTC (0x0C >> 1)
static const struct mfd_cell max77686_devs[] = { static const struct mfd_cell max77686_devs[] = {
{ .name = "max77686-pmic", }, { .name = "max77686-pmic", },
{ .name = "max77686-rtc", }, { .name = "max77686-rtc", },
...@@ -116,11 +114,6 @@ static const struct regmap_config max77686_regmap_config = { ...@@ -116,11 +114,6 @@ static const struct regmap_config max77686_regmap_config = {
.val_bits = 8, .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 = { static const struct regmap_config max77802_regmap_config = {
.reg_bits = 8, .reg_bits = 8,
.val_bits = 8, .val_bits = 8,
...@@ -156,25 +149,6 @@ static const struct regmap_irq_chip max77686_irq_chip = { ...@@ -156,25 +149,6 @@ static const struct regmap_irq_chip max77686_irq_chip = {
.num_irqs = ARRAY_SIZE(max77686_irqs), .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 = { static const struct regmap_irq_chip max77802_irq_chip = {
.name = "max77802-pmic", .name = "max77802-pmic",
.status_base = MAX77802_REG_INT1, .status_base = MAX77802_REG_INT1,
...@@ -184,15 +158,6 @@ static const struct regmap_irq_chip max77802_irq_chip = { ...@@ -184,15 +158,6 @@ static const struct regmap_irq_chip max77802_irq_chip = {
.num_irqs = ARRAY_SIZE(max77686_irqs), .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[] = { static const struct of_device_id max77686_pmic_dt_match[] = {
{ {
.compatible = "maxim,max77686", .compatible = "maxim,max77686",
...@@ -214,8 +179,6 @@ static int max77686_i2c_probe(struct i2c_client *i2c, ...@@ -214,8 +179,6 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
int ret = 0; int ret = 0;
const struct regmap_config *config; const struct regmap_config *config;
const struct regmap_irq_chip *irq_chip; const struct regmap_irq_chip *irq_chip;
const struct regmap_irq_chip *rtc_irq_chip;
struct regmap **rtc_regmap;
const struct mfd_cell *cells; const struct mfd_cell *cells;
int n_devs; int n_devs;
...@@ -242,15 +205,11 @@ static int max77686_i2c_probe(struct i2c_client *i2c, ...@@ -242,15 +205,11 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
if (max77686->type == TYPE_MAX77686) { if (max77686->type == TYPE_MAX77686) {
config = &max77686_regmap_config; config = &max77686_regmap_config;
irq_chip = &max77686_irq_chip; irq_chip = &max77686_irq_chip;
rtc_irq_chip = &max77686_rtc_irq_chip;
rtc_regmap = &max77686->rtc_regmap;
cells = max77686_devs; cells = max77686_devs;
n_devs = ARRAY_SIZE(max77686_devs); n_devs = ARRAY_SIZE(max77686_devs);
} else { } else {
config = &max77802_regmap_config; config = &max77802_regmap_config;
irq_chip = &max77802_irq_chip; irq_chip = &max77802_irq_chip;
rtc_irq_chip = &max77802_rtc_irq_chip;
rtc_regmap = &max77686->regmap;
cells = max77802_devs; cells = max77802_devs;
n_devs = ARRAY_SIZE(max77802_devs); n_devs = ARRAY_SIZE(max77802_devs);
} }
...@@ -270,60 +229,25 @@ static int max77686_i2c_probe(struct i2c_client *i2c, ...@@ -270,60 +229,25 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
return -ENODEV; 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, ret = regmap_add_irq_chip(max77686->regmap, max77686->irq,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT | IRQF_TRIGGER_FALLING | IRQF_ONESHOT |
IRQF_SHARED, 0, irq_chip, IRQF_SHARED, 0, irq_chip,
&max77686->irq_data); &max77686->irq_data);
if (ret) { if (ret < 0) {
dev_err(&i2c->dev, "failed to add PMIC irq chip: %d\n", ret); dev_err(&i2c->dev, "failed to add PMIC irq chip: %d\n", ret);
goto err_unregister_i2c; return ret;
}
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;
} }
ret = mfd_add_devices(max77686->dev, -1, cells, n_devs, NULL, 0, NULL); ret = mfd_add_devices(max77686->dev, -1, cells, n_devs, NULL, 0, NULL);
if (ret < 0) { if (ret < 0) {
dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret); dev_err(&i2c->dev, "failed to add MFD devices: %d\n", ret);
goto err_del_rtc_irqc; goto err_del_irqc;
} }
return 0; return 0;
err_del_rtc_irqc:
regmap_del_irq_chip(max77686->irq, max77686->rtc_irq_data);
err_del_irqc: err_del_irqc:
regmap_del_irq_chip(max77686->irq, max77686->irq_data); regmap_del_irq_chip(max77686->irq, max77686->irq_data);
err_unregister_i2c:
if (max77686->type == TYPE_MAX77686)
i2c_unregister_device(max77686->rtc);
return ret; return ret;
} }
...@@ -334,12 +258,8 @@ static int max77686_i2c_remove(struct i2c_client *i2c) ...@@ -334,12 +258,8 @@ static int max77686_i2c_remove(struct i2c_client *i2c)
mfd_remove_devices(max77686->dev); mfd_remove_devices(max77686->dev);
regmap_del_irq_chip(max77686->irq, max77686->rtc_irq_data);
regmap_del_irq_chip(max77686->irq, max77686->irq_data); regmap_del_irq_chip(max77686->irq, max77686->irq_data);
if (max77686->type == TYPE_MAX77686)
i2c_unregister_device(max77686->rtc);
return 0; return 0;
} }
......
...@@ -140,7 +140,6 @@ config RTC_DRV_TEST ...@@ -140,7 +140,6 @@ config RTC_DRV_TEST
will be called rtc-test. will be called rtc-test.
comment "I2C RTC drivers" comment "I2C RTC drivers"
depends on I2C
if I2C if I2C
...@@ -212,6 +211,15 @@ config RTC_DRV_DS1307 ...@@ -212,6 +211,15 @@ config RTC_DRV_DS1307
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-ds1307. 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 config RTC_DRV_DS1374
tristate "Dallas/Maxim DS1374" tristate "Dallas/Maxim DS1374"
help help
...@@ -239,16 +247,6 @@ config RTC_DRV_DS1672 ...@@ -239,16 +247,6 @@ config RTC_DRV_DS1672
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-ds1672. 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 config RTC_DRV_HYM8563
tristate "Haoyu Microelectronics HYM8563" tristate "Haoyu Microelectronics HYM8563"
depends on OF depends on OF
...@@ -317,10 +315,10 @@ config RTC_DRV_MAX8997 ...@@ -317,10 +315,10 @@ config RTC_DRV_MAX8997
config RTC_DRV_MAX77686 config RTC_DRV_MAX77686
tristate "Maxim MAX77686" tristate "Maxim MAX77686"
depends on MFD_MAX77686 depends on MFD_MAX77686 || MFD_MAX77620
help help
If you say yes here you will get support for the 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 This driver can also be built as a module. If so, the module
will be called rtc-max77686. will be called rtc-max77686.
...@@ -335,16 +333,6 @@ config RTC_DRV_RK808 ...@@ -335,16 +333,6 @@ config RTC_DRV_RK808
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rk808-rtc. 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 config RTC_DRV_RS5C372
tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A" tristate "Ricoh R2025S/D, RS5C372A/B, RV5C386, RV5C387A"
help help
...@@ -391,25 +379,6 @@ config RTC_DRV_X1205 ...@@ -391,25 +379,6 @@ config RTC_DRV_X1205
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-x1205. 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 config RTC_DRV_PCF8523
tristate "NXP PCF8523" tristate "NXP PCF8523"
help help
...@@ -419,6 +388,14 @@ config RTC_DRV_PCF8523 ...@@ -419,6 +388,14 @@ config RTC_DRV_PCF8523
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-pcf8523. 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 config RTC_DRV_PCF8563
tristate "Philips PCF8563/Epson RTC8564" tristate "Philips PCF8563/Epson RTC8564"
help help
...@@ -429,14 +406,6 @@ config RTC_DRV_PCF8563 ...@@ -429,14 +406,6 @@ config RTC_DRV_PCF8563
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-pcf8563. 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 config RTC_DRV_PCF8583
tristate "Philips PCF8583" tristate "Philips PCF8583"
help help
...@@ -501,6 +470,16 @@ config RTC_DRV_TWL4030 ...@@ -501,6 +470,16 @@ config RTC_DRV_TWL4030
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-twl. 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 config RTC_DRV_TPS6586X
tristate "TI TPS6586X RTC driver" tristate "TI TPS6586X RTC driver"
depends on MFD_TPS6586X depends on MFD_TPS6586X
...@@ -595,14 +574,23 @@ config RTC_DRV_EM3027 ...@@ -595,14 +574,23 @@ config RTC_DRV_EM3027
will be called rtc-em3027. will be called rtc-em3027.
config RTC_DRV_RV3029C2 config RTC_DRV_RV3029C2
tristate "Micro Crystal RTC" tristate "Micro Crystal RV3029"
help help
If you say yes here you get support for the Micro Crystal 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 This driver can also be built as a module. If so, the module
will be called rtc-rv3029c2. 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 config RTC_DRV_RV8803
tristate "Micro Crystal RV8803" tristate "Micro Crystal RV8803"
help help
...@@ -691,15 +679,6 @@ config RTC_DRV_DS1390 ...@@ -691,15 +679,6 @@ config RTC_DRV_DS1390
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-ds1390. 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 config RTC_DRV_R9701
tristate "Epson RTC-9701JE" tristate "Epson RTC-9701JE"
help help
...@@ -709,6 +688,23 @@ config RTC_DRV_R9701 ...@@ -709,6 +688,23 @@ config RTC_DRV_R9701
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-r9701. 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 config RTC_DRV_RS5C348
tristate "Ricoh RS5C348A/B" tristate "Ricoh RS5C348A/B"
help help
...@@ -718,14 +714,14 @@ config RTC_DRV_RS5C348 ...@@ -718,14 +714,14 @@ config RTC_DRV_RS5C348
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-rs5c348. will be called rtc-rs5c348.
config RTC_DRV_DS3234 config RTC_DRV_MAX6902
tristate "Maxim/Dallas DS3234" tristate "Maxim MAX6902"
help help
If you say yes here you get support for the If you say yes here you will get support for the
Maxim/Dallas DS3234 SPI RTC chip. Maxim MAX6902 SPI RTC chip.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-ds3234. will be called rtc-max6902.
config RTC_DRV_PCF2123 config RTC_DRV_PCF2123
tristate "NXP PCF2123" tristate "NXP PCF2123"
...@@ -736,14 +732,6 @@ config RTC_DRV_PCF2123 ...@@ -736,14 +732,6 @@ config RTC_DRV_PCF2123
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called rtc-pcf2123. 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 config RTC_DRV_MCP795
tristate "Microchip MCP795" tristate "Microchip MCP795"
help help
...@@ -754,6 +742,41 @@ config RTC_DRV_MCP795 ...@@ -754,6 +742,41 @@ config RTC_DRV_MCP795
endif # SPI_MASTER 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" comment "Platform RTC drivers"
# this 'CMOS' RTC driver is arch dependent because <asm-generic/rtc.h> # this 'CMOS' RTC driver is arch dependent because <asm-generic/rtc.h>
...@@ -1087,7 +1110,7 @@ config RTC_DRV_WM8350 ...@@ -1087,7 +1110,7 @@ config RTC_DRV_WM8350
config RTC_DRV_SPEAR config RTC_DRV_SPEAR
tristate "SPEAR ST RTC" tristate "SPEAR ST RTC"
depends on PLAT_SPEAR depends on PLAT_SPEAR || COMPILE_TEST
default y default y
help help
If you say Y here you will get support for the RTC found on If you say Y here you will get support for the RTC found on
...@@ -1119,7 +1142,7 @@ config RTC_DRV_AB8500 ...@@ -1119,7 +1142,7 @@ config RTC_DRV_AB8500
config RTC_DRV_NUC900 config RTC_DRV_NUC900
tristate "NUC910/NUC920 RTC driver" tristate "NUC910/NUC920 RTC driver"
depends on ARCH_W90X900 depends on ARCH_W90X900 || COMPILE_TEST
help help
If you say yes here you get support for the RTC subsystem of the If you say yes here you get support for the RTC subsystem of the
NUC910/NUC920 used in embedded systems. NUC910/NUC920 used in embedded systems.
...@@ -1144,9 +1167,19 @@ config RTC_DRV_ZYNQMP ...@@ -1144,9 +1167,19 @@ config RTC_DRV_ZYNQMP
comment "on-CPU RTC drivers" 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 config RTC_DRV_DAVINCI
tristate "TI DaVinci RTC" tristate "TI DaVinci RTC"
depends on ARCH_DAVINCI_DM365 depends on ARCH_DAVINCI_DM365 || COMPILE_TEST
help help
If you say yes here you get support for the RTC on the If you say yes here you get support for the RTC on the
DaVinci platforms (DM365). DaVinci platforms (DM365).
...@@ -1156,7 +1189,7 @@ config RTC_DRV_DAVINCI ...@@ -1156,7 +1189,7 @@ config RTC_DRV_DAVINCI
config RTC_DRV_DIGICOLOR config RTC_DRV_DIGICOLOR
tristate "Conexant Digicolor RTC" tristate "Conexant Digicolor RTC"
depends on ARCH_DIGICOLOR depends on ARCH_DIGICOLOR || COMPILE_TEST
help help
If you say yes here you get support for the RTC on Conexant If you say yes here you get support for the RTC on Conexant
Digicolor platforms. This currently includes the CX92755 SoC. Digicolor platforms. This currently includes the CX92755 SoC.
...@@ -1175,7 +1208,7 @@ config RTC_DRV_IMXDI ...@@ -1175,7 +1208,7 @@ config RTC_DRV_IMXDI
config RTC_DRV_OMAP config RTC_DRV_OMAP
tristate "TI OMAP Real Time Clock" tristate "TI OMAP Real Time Clock"
depends on ARCH_OMAP || ARCH_DAVINCI depends on ARCH_OMAP || ARCH_DAVINCI || COMPILE_TEST
help help
Say "yes" here to support the on chip real time clock Say "yes" here to support the on chip real time clock
present on TI OMAP1, AM33xx, DA8xx/OMAP-L13x, AM43xx and DRA7xx. present on TI OMAP1, AM33xx, DA8xx/OMAP-L13x, AM43xx and DRA7xx.
...@@ -1192,7 +1225,7 @@ config HAVE_S3C_RTC ...@@ -1192,7 +1225,7 @@ config HAVE_S3C_RTC
config RTC_DRV_S3C config RTC_DRV_S3C
tristate "Samsung S3C series SoC RTC" tristate "Samsung S3C series SoC RTC"
depends on ARCH_S3C64XX || HAVE_S3C_RTC depends on ARCH_S3C64XX || HAVE_S3C_RTC || COMPILE_TEST
help help
RTC (Realtime Clock) driver for the clock inbuilt into the RTC (Realtime Clock) driver for the clock inbuilt into the
Samsung S3C24XX series of SoCs. This can provide periodic Samsung S3C24XX series of SoCs. This can provide periodic
...@@ -1208,7 +1241,7 @@ config RTC_DRV_S3C ...@@ -1208,7 +1241,7 @@ config RTC_DRV_S3C
config RTC_DRV_EP93XX config RTC_DRV_EP93XX
tristate "Cirrus Logic EP93XX" tristate "Cirrus Logic EP93XX"
depends on ARCH_EP93XX depends on ARCH_EP93XX || COMPILE_TEST
help help
If you say yes here you get support for the If you say yes here you get support for the
RTC embedded in the Cirrus Logic EP93XX processors. RTC embedded in the Cirrus Logic EP93XX processors.
...@@ -1238,7 +1271,7 @@ config RTC_DRV_SH ...@@ -1238,7 +1271,7 @@ config RTC_DRV_SH
config RTC_DRV_VR41XX config RTC_DRV_VR41XX
tristate "NEC VR41XX" tristate "NEC VR41XX"
depends on CPU_VR41XX depends on CPU_VR41XX || COMPILE_TEST
help help
If you say Y here you will get access to the real time clock If you say Y here you will get access to the real time clock
built into your NEC VR41XX CPU. built into your NEC VR41XX CPU.
...@@ -1268,14 +1301,14 @@ config RTC_DRV_PL031 ...@@ -1268,14 +1301,14 @@ config RTC_DRV_PL031
config RTC_DRV_AT32AP700X config RTC_DRV_AT32AP700X
tristate "AT32AP700X series RTC" tristate "AT32AP700X series RTC"
depends on PLATFORM_AT32AP depends on PLATFORM_AT32AP || COMPILE_TEST
help help
Driver for the internal RTC (Realtime Clock) on Atmel AVR32 Driver for the internal RTC (Realtime Clock) on Atmel AVR32
AT32AP700x family processors. AT32AP700x family processors.
config RTC_DRV_AT91RM9200 config RTC_DRV_AT91RM9200
tristate "AT91RM9200 or some AT91SAM9 RTC" tristate "AT91RM9200 or some AT91SAM9 RTC"
depends on ARCH_AT91 depends on ARCH_AT91 || COMPILE_TEST
help help
Driver for the internal RTC (Realtime Clock) module found on Driver for the internal RTC (Realtime Clock) module found on
Atmel AT91RM9200's and some AT91SAM9 chips. On AT91SAM9 chips Atmel AT91RM9200's and some AT91SAM9 chips. On AT91SAM9 chips
...@@ -1283,7 +1316,7 @@ config RTC_DRV_AT91RM9200 ...@@ -1283,7 +1316,7 @@ config RTC_DRV_AT91RM9200
config RTC_DRV_AT91SAM9 config RTC_DRV_AT91SAM9
tristate "AT91SAM9 RTT as RTC" tristate "AT91SAM9 RTT as RTC"
depends on ARCH_AT91 depends on ARCH_AT91 || COMPILE_TEST
select MFD_SYSCON select MFD_SYSCON
help help
Some AT91SAM9 SoCs provide an RTT (Real Time Timer) block which Some AT91SAM9 SoCs provide an RTT (Real Time Timer) block which
...@@ -1325,17 +1358,17 @@ config RTC_DRV_GENERIC ...@@ -1325,17 +1358,17 @@ config RTC_DRV_GENERIC
tristate "Generic RTC support" tristate "Generic RTC support"
# Please consider writing a new RTC driver instead of using the generic # Please consider writing a new RTC driver instead of using the generic
# RTC abstraction # RTC abstraction
depends on PARISC || M68K || PPC || SUPERH32 depends on PARISC || M68K || PPC || SUPERH32 || COMPILE_TEST
help help
Say Y or M here to enable RTC support on systems using the generic 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 RTC abstraction. If you do not know what you are doing, you should
just say Y. just say Y.
config RTC_DRV_PXA config RTC_DRV_PXA
tristate "PXA27x/PXA3xx" tristate "PXA27x/PXA3xx"
depends on ARCH_PXA depends on ARCH_PXA
select RTC_DRV_SA1100 select RTC_DRV_SA1100
help help
If you say Y here you will get access to the real time clock 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 built into your PXA27x or PXA3xx CPU. This RTC is actually 2 RTCs
consisting of an SA1100 compatible RTC and the extended PXA RTC. consisting of an SA1100 compatible RTC and the extended PXA RTC.
...@@ -1345,7 +1378,7 @@ config RTC_DRV_PXA ...@@ -1345,7 +1378,7 @@ config RTC_DRV_PXA
config RTC_DRV_VT8500 config RTC_DRV_VT8500
tristate "VIA/WonderMedia 85xx SoC RTC" tristate "VIA/WonderMedia 85xx SoC RTC"
depends on ARCH_VT8500 depends on ARCH_VT8500 || COMPILE_TEST
help help
If you say Y here you will get access to the real time clock If you say Y here you will get access to the real time clock
built into your VIA VT8500 SoC or its relatives. built into your VIA VT8500 SoC or its relatives.
...@@ -1360,14 +1393,15 @@ config RTC_DRV_SUN4V ...@@ -1360,14 +1393,15 @@ config RTC_DRV_SUN4V
config RTC_DRV_SUN6I config RTC_DRV_SUN6I
tristate "Allwinner A31 RTC" tristate "Allwinner A31 RTC"
depends on MACH_SUN6I || MACH_SUN8I default MACH_SUN6I || MACH_SUN8I || COMPILE_TEST
depends on ARCH_SUNXI
help help
If you say Y here you will get support for the RTC found on If you say Y here you will get support for the RTC found in
Allwinner A31. some Allwinner SoCs like the A31 or the A64.
config RTC_DRV_SUNXI config RTC_DRV_SUNXI
tristate "Allwinner sun4i/sun7i RTC" tristate "Allwinner sun4i/sun7i RTC"
depends on MACH_SUN4I || MACH_SUN7I depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
help help
If you say Y here you will get support for the RTC found on If you say Y here you will get support for the RTC found on
Allwinner A10/A20. Allwinner A10/A20.
...@@ -1388,7 +1422,7 @@ config RTC_DRV_TX4939 ...@@ -1388,7 +1422,7 @@ config RTC_DRV_TX4939
config RTC_DRV_MV config RTC_DRV_MV
tristate "Marvell SoC RTC" tristate "Marvell SoC RTC"
depends on ARCH_DOVE || ARCH_MVEBU depends on ARCH_DOVE || ARCH_MVEBU || COMPILE_TEST
help help
If you say yes here you will get support for the in-chip RTC 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 that can be found in some of Marvell's SoC devices, such as
...@@ -1399,7 +1433,7 @@ config RTC_DRV_MV ...@@ -1399,7 +1433,7 @@ config RTC_DRV_MV
config RTC_DRV_ARMADA38X config RTC_DRV_ARMADA38X
tristate "Armada 38x Marvell SoC RTC" tristate "Armada 38x Marvell SoC RTC"
depends on ARCH_MVEBU depends on ARCH_MVEBU || COMPILE_TEST
help help
If you say yes here you will get support for the in-chip RTC 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 that can be found in the Armada 38x Marvell's SoC device
...@@ -1429,7 +1463,7 @@ config RTC_DRV_PS3 ...@@ -1429,7 +1463,7 @@ config RTC_DRV_PS3
config RTC_DRV_COH901331 config RTC_DRV_COH901331
tristate "ST-Ericsson COH 901 331 RTC" tristate "ST-Ericsson COH 901 331 RTC"
depends on ARCH_U300 depends on ARCH_U300 || COMPILE_TEST
help help
If you say Y here you will get access to ST-Ericsson If you say Y here you will get access to ST-Ericsson
COH 901 331 RTC clock found in some ST-Ericsson Mobile COH 901 331 RTC clock found in some ST-Ericsson Mobile
...@@ -1441,7 +1475,7 @@ config RTC_DRV_COH901331 ...@@ -1441,7 +1475,7 @@ config RTC_DRV_COH901331
config RTC_DRV_STMP config RTC_DRV_STMP
tristate "Freescale STMP3xxx/i.MX23/i.MX28 RTC" tristate "Freescale STMP3xxx/i.MX23/i.MX28 RTC"
depends on ARCH_MXS depends on ARCH_MXS || COMPILE_TEST
select STMP_DEVICE select STMP_DEVICE
help help
If you say yes here you will get support for the onboard If you say yes here you will get support for the onboard
...@@ -1476,7 +1510,7 @@ config RTC_DRV_MPC5121 ...@@ -1476,7 +1510,7 @@ config RTC_DRV_MPC5121
config RTC_DRV_JZ4740 config RTC_DRV_JZ4740
tristate "Ingenic JZ4740 SoC" tristate "Ingenic JZ4740 SoC"
depends on MACH_JZ4740 depends on MACH_JZ4740 || COMPILE_TEST
help help
If you say yes here you get support for the Ingenic JZ4740 SoC RTC If you say yes here you get support for the Ingenic JZ4740 SoC RTC
controller. controller.
...@@ -1497,7 +1531,7 @@ config RTC_DRV_LPC24XX ...@@ -1497,7 +1531,7 @@ config RTC_DRV_LPC24XX
so, the module will be called rtc-lpc24xx. so, the module will be called rtc-lpc24xx.
config RTC_DRV_LPC32XX config RTC_DRV_LPC32XX
depends on ARCH_LPC32XX depends on ARCH_LPC32XX || COMPILE_TEST
tristate "NXP LPC32XX RTC" tristate "NXP LPC32XX RTC"
help help
This enables support for the NXP RTC in the LPC32XX This enables support for the NXP RTC in the LPC32XX
...@@ -1507,7 +1541,7 @@ config RTC_DRV_LPC32XX ...@@ -1507,7 +1541,7 @@ config RTC_DRV_LPC32XX
config RTC_DRV_PM8XXX config RTC_DRV_PM8XXX
tristate "Qualcomm PMIC8XXX RTC" tristate "Qualcomm PMIC8XXX RTC"
depends on MFD_PM8XXX || MFD_SPMI_PMIC depends on MFD_PM8XXX || MFD_SPMI_PMIC || COMPILE_TEST
help help
If you say yes here you get support for the If you say yes here you get support for the
Qualcomm PMIC8XXX RTC. Qualcomm PMIC8XXX RTC.
...@@ -1517,7 +1551,7 @@ config RTC_DRV_PM8XXX ...@@ -1517,7 +1551,7 @@ config RTC_DRV_PM8XXX
config RTC_DRV_TEGRA config RTC_DRV_TEGRA
tristate "NVIDIA Tegra Internal RTC driver" tristate "NVIDIA Tegra Internal RTC driver"
depends on ARCH_TEGRA depends on ARCH_TEGRA || COMPILE_TEST
help help
If you say yes here you get support for the If you say yes here you get support for the
Tegra 200 series internal RTC module. Tegra 200 series internal RTC module.
...@@ -1603,7 +1637,7 @@ config RTC_DRV_MOXART ...@@ -1603,7 +1637,7 @@ config RTC_DRV_MOXART
config RTC_DRV_MT6397 config RTC_DRV_MT6397
tristate "Mediatek Real Time Clock driver" tristate "Mediatek Real Time Clock driver"
depends on MFD_MT6397 || COMPILE_TEST depends on MFD_MT6397 || (COMPILE_TEST && IRQ_DOMAIN)
help help
This selects the Mediatek(R) RTC driver. RTC is part of Mediatek This selects the Mediatek(R) RTC driver. RTC is part of Mediatek
MT6397 PMIC. You should enable MT6397 PMIC MFD before select MT6397 PMIC. You should enable MT6397 PMIC MFD before select
...@@ -1622,6 +1656,16 @@ config RTC_DRV_XGENE ...@@ -1622,6 +1656,16 @@ config RTC_DRV_XGENE
This driver can also be built as a module, if so, the module This driver can also be built as a module, if so, the module
will be called "rtc-xgene". 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" comment "HID Sensor RTC drivers"
config RTC_DRV_HID_SENSOR_TIME config RTC_DRV_HID_SENSOR_TIME
......
...@@ -28,6 +28,7 @@ obj-$(CONFIG_RTC_DRV_ABB5ZES3) += rtc-ab-b5ze-s3.o ...@@ -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_ABX80X) += rtc-abx80x.o
obj-$(CONFIG_RTC_DRV_ARMADA38X) += rtc-armada38x.o obj-$(CONFIG_RTC_DRV_ARMADA38X) += rtc-armada38x.o
obj-$(CONFIG_RTC_DRV_AS3722) += rtc-as3722.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_AT32AP700X)+= rtc-at32ap700x.o
obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o
...@@ -59,7 +60,6 @@ obj-$(CONFIG_RTC_DRV_DS1685_FAMILY) += rtc-ds1685.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_DS1742) += rtc-ds1742.o
obj-$(CONFIG_RTC_DRV_DS2404) += rtc-ds2404.o obj-$(CONFIG_RTC_DRV_DS2404) += rtc-ds2404.o
obj-$(CONFIG_RTC_DRV_DS3232) += rtc-ds3232.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_EFI) += rtc-efi.o
obj-$(CONFIG_RTC_DRV_EM3027) += rtc-em3027.o obj-$(CONFIG_RTC_DRV_EM3027) += rtc-em3027.o
obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o
...@@ -86,7 +86,6 @@ obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.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_MAX6900) += rtc-max6900.o
obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
obj-$(CONFIG_RTC_DRV_MAX77686) += rtc-max77686.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_MAX8907) += rtc-max8907.o
obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o
obj-$(CONFIG_RTC_DRV_MAX8997) += rtc-max8997.o obj-$(CONFIG_RTC_DRV_MAX8997) += rtc-max8997.o
...@@ -112,6 +111,7 @@ obj-$(CONFIG_RTC_DRV_PCF85063) += rtc-pcf85063.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_PCF8523) += rtc-pcf8523.o
obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o
obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o
obj-$(CONFIG_RTC_DRV_PIC32) += rtc-pic32.o
obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o
obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o
obj-$(CONFIG_RTC_DRV_PM8XXX) += rtc-pm8xxx.o obj-$(CONFIG_RTC_DRV_PM8XXX) += rtc-pm8xxx.o
...@@ -128,6 +128,7 @@ obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.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_RV3029C2) += rtc-rv3029c2.o
obj-$(CONFIG_RTC_DRV_RV8803) += rtc-rv8803.o obj-$(CONFIG_RTC_DRV_RV8803) += rtc-rv8803.o
obj-$(CONFIG_RTC_DRV_RX4581) += rtc-rx4581.o obj-$(CONFIG_RTC_DRV_RX4581) += rtc-rx4581.o
obj-$(CONFIG_RTC_DRV_RX6110) += rtc-rx6110.o
obj-$(CONFIG_RTC_DRV_RX8010) += rtc-rx8010.o obj-$(CONFIG_RTC_DRV_RX8010) += rtc-rx8010.o
obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o
obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o
......
...@@ -361,17 +361,4 @@ static int __init rtc_init(void) ...@@ -361,17 +361,4 @@ static int __init rtc_init(void)
rtc_dev_init(); rtc_dev_init();
return 0; return 0;
} }
static void __exit rtc_exit(void)
{
rtc_dev_exit();
class_destroy(rtc_class);
ida_destroy(&rtc_ida);
}
subsys_initcall(rtc_init); 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) ...@@ -939,4 +939,58 @@ void rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer *timer)
mutex_unlock(&rtc->ops_lock); 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) ...@@ -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); dev_info(&pdev->dev, "RTC interrupt %d\n", as3722_rtc->alarm_irq);
ret = devm_request_threaded_irq(&pdev->dev, as3722_rtc->alarm_irq, NULL, 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); "rtc-alarm", as3722_rtc);
if (ret < 0) { if (ret < 0) {
dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", 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, ...@@ -532,7 +532,7 @@ ds1305_nvram_read(struct file *filp, struct kobject *kobj,
struct spi_transfer x[2]; struct spi_transfer x[2];
int status; int status;
spi = container_of(kobj, struct spi_device, dev.kobj); spi = to_spi_device(kobj_to_dev(kobj));
addr = DS1305_NVRAM + off; addr = DS1305_NVRAM + off;
msg_init(&m, x, &addr, count, NULL, buf); msg_init(&m, x, &addr, count, NULL, buf);
...@@ -554,7 +554,7 @@ ds1305_nvram_write(struct file *filp, struct kobject *kobj, ...@@ -554,7 +554,7 @@ ds1305_nvram_write(struct file *filp, struct kobject *kobj,
struct spi_transfer x[2]; struct spi_transfer x[2];
int status; 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; addr = (DS1305_WRITE | DS1305_NVRAM) + off;
msg_init(&m, x, &addr, count, buf, NULL); msg_init(&m, x, &addr, count, buf, NULL);
......
...@@ -19,6 +19,9 @@ ...@@ -19,6 +19,9 @@
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.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 * We can't determine type by probing, but if we expect pre-Linux code
...@@ -89,6 +92,7 @@ enum ds_type { ...@@ -89,6 +92,7 @@ enum ds_type {
# define DS1340_BIT_OSF 0x80 # define DS1340_BIT_OSF 0x80
#define DS1337_REG_STATUS 0x0f #define DS1337_REG_STATUS 0x0f
# define DS1337_BIT_OSF 0x80 # define DS1337_BIT_OSF 0x80
# define DS3231_BIT_EN32KHZ 0x08
# define DS1337_BIT_A2I 0x02 # define DS1337_BIT_A2I 0x02
# define DS1337_BIT_A1I 0x01 # define DS1337_BIT_A1I 0x01
#define DS1339_REG_ALARM1_SECS 0x07 #define DS1339_REG_ALARM1_SECS 0x07
...@@ -118,6 +122,9 @@ struct ds1307 { ...@@ -118,6 +122,9 @@ struct ds1307 {
u8 length, u8 *values); u8 length, u8 *values);
s32 (*write_block_data)(const struct i2c_client *client, u8 command, s32 (*write_block_data)(const struct i2c_client *client, u8 command,
u8 length, const u8 *values); u8 length, const u8 *values);
#ifdef CONFIG_COMMON_CLK
struct clk_hw clks[2];
#endif
}; };
struct chip_desc { struct chip_desc {
...@@ -842,6 +849,378 @@ static void ds1307_trickle_of_init(struct i2c_client *client, ...@@ -842,6 +849,378 @@ static void ds1307_trickle_of_init(struct i2c_client *client,
return; 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, static int ds1307_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -851,6 +1230,7 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -851,6 +1230,7 @@ static int ds1307_probe(struct i2c_client *client,
struct chip_desc *chip = &chips[id->driver_data]; struct chip_desc *chip = &chips[id->driver_data];
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
bool want_irq = false; bool want_irq = false;
bool ds1307_can_wakeup_device = false;
unsigned char *buf; unsigned char *buf;
struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev); struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
irq_handler_t irq_handler = ds1307_irq; irq_handler_t irq_handler = ds1307_irq;
...@@ -898,6 +1278,20 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -898,6 +1278,20 @@ static int ds1307_probe(struct i2c_client *client,
ds1307->write_block_data = ds1307_write_block_data; 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) { switch (ds1307->type) {
case ds_1337: case ds_1337:
case ds_1339: case ds_1339:
...@@ -916,11 +1310,13 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -916,11 +1310,13 @@ static int ds1307_probe(struct i2c_client *client,
ds1307->regs[0] &= ~DS1337_BIT_nEOSC; 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 * For some variants, be sure alarms can trigger when we're
* running on Vbackup (BBSQI/BBSQW) * 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 ds1307->regs[0] |= DS1337_BIT_INTCN
| bbsqi_bitpos[ds1307->type]; | bbsqi_bitpos[ds1307->type];
ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE); ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE);
...@@ -1135,6 +1531,14 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -1135,6 +1531,14 @@ static int ds1307_probe(struct i2c_client *client,
return PTR_ERR(ds1307->rtc); 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) { if (want_irq) {
err = devm_request_threaded_irq(&client->dev, err = devm_request_threaded_irq(&client->dev,
client->irq, NULL, irq_handler, client->irq, NULL, irq_handler,
...@@ -1182,6 +1586,9 @@ static int ds1307_probe(struct i2c_client *client, ...@@ -1182,6 +1586,9 @@ static int ds1307_probe(struct i2c_client *client,
} }
} }
ds1307_hwmon_register(ds1307);
ds1307_clks_register(ds1307);
return 0; return 0;
exit: exit:
......
...@@ -187,9 +187,9 @@ ds1685_rtc_end_data_access(struct ds1685_priv *rtc) ...@@ -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. * Only use this where you are certain another lock will not be held.
*/ */
static inline void 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); ds1685_rtc_switch_to_bank1(rtc);
} }
...@@ -1300,7 +1300,7 @@ ds1685_rtc_sysfs_ctrl_regs_store(struct device *dev, ...@@ -1300,7 +1300,7 @@ ds1685_rtc_sysfs_ctrl_regs_store(struct device *dev,
{ {
struct ds1685_priv *rtc = dev_get_drvdata(dev); struct ds1685_priv *rtc = dev_get_drvdata(dev);
u8 reg = 0, bit = 0, tmp; u8 reg = 0, bit = 0, tmp;
unsigned long flags = 0; unsigned long flags;
long int val = 0; long int val = 0;
const struct ds1685_rtc_ctrl_regs *reg_info = const struct ds1685_rtc_ctrl_regs *reg_info =
ds1685_rtc_sysfs_ctrl_regs_lookup(attr->attr.name); ds1685_rtc_sysfs_ctrl_regs_lookup(attr->attr.name);
...@@ -1321,7 +1321,7 @@ ds1685_rtc_sysfs_ctrl_regs_store(struct device *dev, ...@@ -1321,7 +1321,7 @@ ds1685_rtc_sysfs_ctrl_regs_store(struct device *dev,
bit = reg_info->bit; bit = reg_info->bit;
/* Safe to spinlock during a write. */ /* 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); tmp = rtc->read(rtc, reg);
rtc->write(rtc, reg, (val ? (tmp | bit) : (tmp & ~(bit)))); rtc->write(rtc, reg, (val ? (tmp | bit) : (tmp & ~(bit))));
ds1685_rtc_end_ctrl_access(rtc, flags); ds1685_rtc_end_ctrl_access(rtc, flags);
...@@ -2161,6 +2161,7 @@ ds1685_rtc_poweroff(struct platform_device *pdev) ...@@ -2161,6 +2161,7 @@ ds1685_rtc_poweroff(struct platform_device *pdev)
/* Check for valid RTC data, else, spin forever. */ /* Check for valid RTC data, else, spin forever. */
if (unlikely(!pdev)) { if (unlikely(!pdev)) {
pr_emerg("platform device data not available, spinning forever ...\n"); pr_emerg("platform device data not available, spinning forever ...\n");
while(1);
unreachable(); unreachable();
} else { } else {
/* Get the rtc data. */ /* 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. * Copyright (C) 2009-2011 Freescale Semiconductor.
* Author: Jack Lan <jack.lan@freescale.com> * 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 * 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 * 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 * Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. * 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 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
...@@ -21,10 +17,11 @@ ...@@ -21,10 +17,11 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#include <linux/bcd.h> #include <linux/bcd.h>
#include <linux/workqueue.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/regmap.h>
#define DS3232_REG_SECONDS 0x00 #define DS3232_REG_SECONDS 0x00
#define DS3232_REG_MINUTES 0x01 #define DS3232_REG_MINUTES 0x01
...@@ -50,39 +47,33 @@ ...@@ -50,39 +47,33 @@
# define DS3232_REG_SR_A1F 0x01 # define DS3232_REG_SR_A1F 0x01
struct ds3232 { struct ds3232 {
struct i2c_client *client; struct device *dev;
struct regmap *regmap;
int irq;
struct rtc_device *rtc; 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; bool suspended;
int exiting;
}; };
static struct i2c_driver ds3232_driver; static int ds3232_check_rtc_status(struct device *dev)
static int ds3232_check_rtc_status(struct i2c_client *client)
{ {
struct ds3232 *ds3232 = dev_get_drvdata(dev);
int ret = 0; int ret = 0;
int control, stat; int control, stat;
stat = i2c_smbus_read_byte_data(client, DS3232_REG_SR); ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
if (stat < 0) if (ret)
return stat; return ret;
if (stat & DS3232_REG_SR_OSF) if (stat & DS3232_REG_SR_OSF)
dev_warn(&client->dev, dev_warn(dev,
"oscillator discontinuity flagged, " "oscillator discontinuity flagged, "
"time unreliable\n"); "time unreliable\n");
stat &= ~(DS3232_REG_SR_OSF | DS3232_REG_SR_A1F | DS3232_REG_SR_A2F); stat &= ~(DS3232_REG_SR_OSF | DS3232_REG_SR_A1F | DS3232_REG_SR_A2F);
ret = i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
if (ret < 0) if (ret)
return ret; return ret;
/* If the alarm is pending, clear it before requesting /* If the alarm is pending, clear it before requesting
...@@ -90,31 +81,28 @@ static int ds3232_check_rtc_status(struct i2c_client *client) ...@@ -90,31 +81,28 @@ static int ds3232_check_rtc_status(struct i2c_client *client)
* before everything is initialized. * before everything is initialized.
*/ */
control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
if (control < 0) if (ret)
return control; return ret;
control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE); control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE);
control |= DS3232_REG_CR_INTCN; 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) 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; int ret;
u8 buf[7]; u8 buf[7];
unsigned int year, month, day, hour, minute, second; unsigned int year, month, day, hour, minute, second;
unsigned int week, twelve_hr, am_pm; unsigned int week, twelve_hr, am_pm;
unsigned int century, add_century = 0; unsigned int century, add_century = 0;
ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_SECONDS, 7, buf); ret = regmap_bulk_read(ds3232->regmap, DS3232_REG_SECONDS, buf, 7);
if (ret)
if (ret < 0)
return ret; return ret;
if (ret < 7)
return -EIO;
second = buf[0]; second = buf[0];
minute = buf[1]; minute = buf[1];
...@@ -159,7 +147,7 @@ static int ds3232_read_time(struct device *dev, struct rtc_time *time) ...@@ -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) 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]; u8 buf[7];
/* Extract time from rtc_time and load into ds3232*/ /* 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) ...@@ -179,8 +167,7 @@ static int ds3232_set_time(struct device *dev, struct rtc_time *time)
buf[6] = bin2bcd(time->tm_year); buf[6] = bin2bcd(time->tm_year);
} }
return i2c_smbus_write_i2c_block_data(client, return regmap_bulk_write(ds3232->regmap, DS3232_REG_SECONDS, buf, 7);
DS3232_REG_SECONDS, 7, buf);
} }
/* /*
...@@ -190,24 +177,19 @@ static int ds3232_set_time(struct device *dev, struct rtc_time *time) ...@@ -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) static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{ {
struct i2c_client *client = to_i2c_client(dev); struct ds3232 *ds3232 = dev_get_drvdata(dev);
struct ds3232 *ds3232 = i2c_get_clientdata(client);
int control, stat; int control, stat;
int ret; int ret;
u8 buf[4]; u8 buf[4];
mutex_lock(&ds3232->mutex); ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
if (ret)
ret = i2c_smbus_read_byte_data(client, DS3232_REG_SR);
if (ret < 0)
goto out; goto out;
stat = ret; ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
ret = i2c_smbus_read_byte_data(client, DS3232_REG_CR); if (ret)
if (ret < 0)
goto out; goto out;
control = ret; ret = regmap_bulk_read(ds3232->regmap, DS3232_REG_ALARM1, buf, 4);
ret = i2c_smbus_read_i2c_block_data(client, DS3232_REG_ALARM1, 4, buf); if (ret)
if (ret < 0)
goto out; goto out;
alarm->time.tm_sec = bcd2bin(buf[0] & 0x7F); alarm->time.tm_sec = bcd2bin(buf[0] & 0x7F);
...@@ -226,7 +208,6 @@ static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) ...@@ -226,7 +208,6 @@ static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
ret = 0; ret = 0;
out: out:
mutex_unlock(&ds3232->mutex);
return ret; return ret;
} }
...@@ -236,166 +217,129 @@ static int ds3232_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) ...@@ -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) static int ds3232_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
{ {
struct i2c_client *client = to_i2c_client(dev); struct ds3232 *ds3232 = dev_get_drvdata(dev);
struct ds3232 *ds3232 = i2c_get_clientdata(client);
int control, stat; int control, stat;
int ret; int ret;
u8 buf[4]; u8 buf[4];
if (client->irq <= 0) if (ds3232->irq <= 0)
return -EINVAL; return -EINVAL;
mutex_lock(&ds3232->mutex);
buf[0] = bin2bcd(alarm->time.tm_sec); buf[0] = bin2bcd(alarm->time.tm_sec);
buf[1] = bin2bcd(alarm->time.tm_min); buf[1] = bin2bcd(alarm->time.tm_min);
buf[2] = bin2bcd(alarm->time.tm_hour); buf[2] = bin2bcd(alarm->time.tm_hour);
buf[3] = bin2bcd(alarm->time.tm_mday); buf[3] = bin2bcd(alarm->time.tm_mday);
/* clear alarm interrupt enable bit */ /* clear alarm interrupt enable bit */
ret = i2c_smbus_read_byte_data(client, DS3232_REG_CR); ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
if (ret < 0) if (ret)
goto out; goto out;
control = ret;
control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE); control &= ~(DS3232_REG_CR_A1IE | DS3232_REG_CR_A2IE);
ret = i2c_smbus_write_byte_data(client, DS3232_REG_CR, control); ret = regmap_write(ds3232->regmap, DS3232_REG_CR, control);
if (ret < 0) if (ret)
goto out; goto out;
/* clear any pending alarm flag */ /* clear any pending alarm flag */
ret = i2c_smbus_read_byte_data(client, DS3232_REG_SR); ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
if (ret < 0) if (ret)
goto out; goto out;
stat = ret;
stat &= ~(DS3232_REG_SR_A1F | DS3232_REG_SR_A2F); stat &= ~(DS3232_REG_SR_A1F | DS3232_REG_SR_A2F);
ret = i2c_smbus_write_byte_data(client, DS3232_REG_SR, stat); ret = regmap_write(ds3232->regmap, DS3232_REG_SR, stat);
if (ret < 0) if (ret)
goto out; 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) { if (alarm->enabled) {
control |= DS3232_REG_CR_A1IE; 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: out:
mutex_unlock(&ds3232->mutex);
return ret; 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 control;
int ret; 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); ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
if (control < 0) if (ret)
goto unlock; return ret;
if (ds3232->rtc->irq_data & (RTC_AF | RTC_UF)) if (enabled)
/* enable alarm1 interrupt */ /* enable alarm1 interrupt */
control |= DS3232_REG_CR_A1IE; control |= DS3232_REG_CR_A1IE;
else else
/* disable alarm1 interrupt */ /* disable alarm1 interrupt */
control &= ~(DS3232_REG_CR_A1IE); 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: return ret;
mutex_unlock(&ds3232->mutex);
} }
static int ds3232_alarm_irq_enable(struct device *dev, unsigned int enabled) static int ds3232_alarm_irq_enable(struct device *dev, unsigned int enabled)
{ {
struct i2c_client *client = to_i2c_client(dev); struct ds3232 *ds3232 = dev_get_drvdata(dev);
struct ds3232 *ds3232 = i2c_get_clientdata(client);
if (client->irq <= 0) if (ds3232->irq <= 0)
return -EINVAL; return -EINVAL;
if (enabled) return ds3232_update_alarm(dev, enabled);
ds3232->rtc->irq_data |= RTC_AF;
else
ds3232->rtc->irq_data &= ~RTC_AF;
ds3232_update_alarm(client);
return 0;
} }
static irqreturn_t ds3232_irq(int irq, void *dev_id) static irqreturn_t ds3232_irq(int irq, void *dev_id)
{ {
struct i2c_client *client = dev_id; struct device *dev = dev_id;
struct ds3232 *ds3232 = i2c_get_clientdata(client); struct ds3232 *ds3232 = dev_get_drvdata(dev);
struct mutex *lock = &ds3232->rtc->ops_lock;
disable_irq_nosync(irq); int ret;
/*
* 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;
int stat, control; int stat, control;
mutex_lock(&ds3232->mutex); mutex_lock(lock);
stat = i2c_smbus_read_byte_data(client, DS3232_REG_SR); ret = regmap_read(ds3232->regmap, DS3232_REG_SR, &stat);
if (stat < 0) if (ret)
goto unlock; goto unlock;
if (stat & DS3232_REG_SR_A1F) { if (stat & DS3232_REG_SR_A1F) {
control = i2c_smbus_read_byte_data(client, DS3232_REG_CR); ret = regmap_read(ds3232->regmap, DS3232_REG_CR, &control);
if (control < 0) { if (ret) {
pr_warn("Read Control Register error - Disable IRQ%d\n", dev_warn(ds3232->dev,
client->irq); "Read Control Register error %d\n", ret);
} else { } else {
/* disable alarm1 interrupt */ /* disable alarm1 interrupt */
control &= ~(DS3232_REG_CR_A1IE); control &= ~(DS3232_REG_CR_A1IE);
i2c_smbus_write_byte_data(client, DS3232_REG_CR, ret = regmap_write(ds3232->regmap, DS3232_REG_CR,
control); control);
if (ret) {
dev_warn(ds3232->dev,
"Write Control Register error %d\n",
ret);
goto unlock;
}
/* clear the alarm pend flag */ /* clear the alarm pend flag */
stat &= ~DS3232_REG_SR_A1F; 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); rtc_update_irq(ds3232->rtc, 1, RTC_AF | RTC_IRQF);
if (!ds3232->exiting)
enable_irq(client->irq);
} }
} }
unlock: unlock:
mutex_unlock(&ds3232->mutex); mutex_unlock(lock);
return IRQ_HANDLED;
} }
static const struct rtc_class_ops ds3232_rtc_ops = { static const struct rtc_class_ops ds3232_rtc_ops = {
...@@ -406,67 +350,50 @@ 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, .alarm_irq_enable = ds3232_alarm_irq_enable,
}; };
static int ds3232_probe(struct i2c_client *client, static int ds3232_probe(struct device *dev, struct regmap *regmap, int irq,
const struct i2c_device_id *id) const char *name)
{ {
struct ds3232 *ds3232; struct ds3232 *ds3232;
int ret; int ret;
ds3232 = devm_kzalloc(&client->dev, sizeof(struct ds3232), GFP_KERNEL); ds3232 = devm_kzalloc(dev, sizeof(*ds3232), GFP_KERNEL);
if (!ds3232) if (!ds3232)
return -ENOMEM; return -ENOMEM;
ds3232->client = client; ds3232->regmap = regmap;
i2c_set_clientdata(client, ds3232); ds3232->irq = irq;
ds3232->dev = dev;
INIT_WORK(&ds3232->work, ds3232_work); dev_set_drvdata(dev, ds3232);
mutex_init(&ds3232->mutex);
ret = ds3232_check_rtc_status(client); ret = ds3232_check_rtc_status(dev);
if (ret) if (ret)
return ret; return ret;
if (client->irq > 0) { if (ds3232->irq > 0) {
ret = devm_request_irq(&client->dev, client->irq, ds3232_irq, ret = devm_request_threaded_irq(dev, ds3232->irq, NULL,
IRQF_SHARED, "ds3232", client); ds3232_irq,
IRQF_SHARED | IRQF_ONESHOT,
name, dev);
if (ret) { if (ret) {
dev_err(&client->dev, "unable to request IRQ\n"); ds3232->irq = 0;
} dev_err(dev, "unable to request IRQ\n");
device_init_wakeup(&client->dev, 1); } else
} device_init_wakeup(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->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 #ifdef CONFIG_PM_SLEEP
static int ds3232_suspend(struct device *dev) static int ds3232_suspend(struct device *dev)
{ {
struct ds3232 *ds3232 = dev_get_drvdata(dev); struct ds3232 *ds3232 = dev_get_drvdata(dev);
struct i2c_client *client = to_i2c_client(dev);
if (device_can_wakeup(dev)) { if (device_may_wakeup(dev)) {
ds3232->suspended = true; if (enable_irq_wake(ds3232->irq))
if (irq_set_irq_wake(client->irq, 1)) {
dev_warn_once(dev, "Cannot set wakeup source\n"); dev_warn_once(dev, "Cannot set wakeup source\n");
ds3232->suspended = false;
}
} }
return 0; return 0;
...@@ -475,16 +402,9 @@ static int ds3232_suspend(struct device *dev) ...@@ -475,16 +402,9 @@ static int ds3232_suspend(struct device *dev)
static int ds3232_resume(struct device *dev) static int ds3232_resume(struct device *dev)
{ {
struct ds3232 *ds3232 = dev_get_drvdata(dev); struct ds3232 *ds3232 = dev_get_drvdata(dev);
struct i2c_client *client = to_i2c_client(dev);
if (ds3232->suspended) { if (device_may_wakeup(dev))
ds3232->suspended = false; disable_irq_wake(ds3232->irq);
/* Clear the hardware alarm pend flag */
schedule_work(&ds3232->work);
irq_set_irq_wake(client->irq, 0);
}
return 0; return 0;
} }
...@@ -494,6 +414,27 @@ static const struct dev_pm_ops ds3232_pm_ops = { ...@@ -494,6 +414,27 @@ static const struct dev_pm_ops ds3232_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(ds3232_suspend, ds3232_resume) 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[] = { static const struct i2c_device_id ds3232_id[] = {
{ "ds3232", 0 }, { "ds3232", 0 },
{ } { }
...@@ -505,13 +446,162 @@ static struct i2c_driver ds3232_driver = { ...@@ -505,13 +446,162 @@ static struct i2c_driver ds3232_driver = {
.name = "rtc-ds3232", .name = "rtc-ds3232",
.pm = &ds3232_pm_ops, .pm = &ds3232_pm_ops,
}, },
.probe = ds3232_probe, .probe = ds3232_i2c_probe,
.remove = ds3232_remove,
.id_table = ds3232_id, .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_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_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 @@ ...@@ -9,6 +9,8 @@
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/rtc.h> #include <linux/rtc.h>
#if defined(CONFIG_M68K) || defined(CONFIG_PARISC) || \
defined(CONFIG_PPC) || defined(CONFIG_SUPERH32)
#include <asm/rtc.h> #include <asm/rtc.h>
static int generic_get_time(struct device *dev, struct rtc_time *tm) 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 = { ...@@ -33,13 +35,21 @@ static const struct rtc_class_ops generic_rtc_ops = {
.read_time = generic_get_time, .read_time = generic_get_time,
.set_time = generic_set_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) static int __init generic_rtc_probe(struct platform_device *dev)
{ {
struct rtc_device *rtc; 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", rtc = devm_rtc_device_register(&dev->dev, "rtc-generic",
&generic_rtc_ops, THIS_MODULE); ops, THIS_MODULE);
if (IS_ERR(rtc)) if (IS_ERR(rtc))
return PTR_ERR(rtc); return PTR_ERR(rtc);
......
...@@ -144,7 +144,7 @@ static int hym8563_rtc_set_time(struct device *dev, struct rtc_time *tm) ...@@ -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. * 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. * 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, * CTL1 only contains TEST-mode bits apart from stop,
......
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment