9
0
Fork 0

rtc: ds1307: Add support for configuring external clock pin

The DS1307 has a square wave output pin, which can be used to output a
clock signal from the DS1307.  Additionally, the DS1308 supports
configuring this pin as an input from an external clock source to
which it should sync itself.

Add support with OF device tree properties to configure these
settings.  Supported features are using the clock pin as an output, an
input, the rate of the pin, and if it should be enabled on battery
backup power.

The driver does not check that the selected features are supported by
the clock chip being used.  It is the designer's responsibility to
create a valid device tree node; the bootloader does not attempt to be
a device tree validator.

Signed-off-by: Trent Piepho <tpiepho@kymetacorp.com>
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
Trent Piepho 2016-05-19 23:39:32 +00:00 committed by Sascha Hauer
parent 61ddbd3520
commit 24fcf5fcee
2 changed files with 77 additions and 1 deletions

View File

@ -0,0 +1,33 @@
Dallas DS1307 I2C Serial Real-Time Clock
========================================
Required properties:
* ``compatible``: ``dallas,ds1307``, ``dallas,ds1308``, ``dallas,ds1338``
"maxim" can be used in place of "dallas"
* ``reg``: I2C address for chip
Optional properties:
* ``ext-clock-input``: Enable external clock input pin
* ``ext-clock-output``: Enable square wave output. The above two
properties are mutually exclusive
* ``ext-clock-bb``: Enable external clock on battery power
* ``ext-clock-rate``: Expected/Generated rate on external clock pin
in Hz. Allowable values are 1, 50, 60, 4096, 8192, and 32768 Hz.
Not all values are valid for all configurations.
The default is ext-clock-input, ext-clock-output, and ext-clock-bb
disabled and ext-clock-rate of 1 Hz.
Example::
ds1307: rtc@68 {
compatible = "dallas,ds1307";
reg = <0x68>;
};
ds1308: rtc@68 {
compatible = "maxim,ds1308";
reg = <0x68>;
ext-clock-output;
ext-clock-rate = <32768>;
};

View File

@ -59,10 +59,13 @@ enum ds_type {
* start at 7, and they differ a LOT. Only control and status matter for
* basic RTC date and time functionality; be careful using them.
*/
#define DS1307_REG_CONTROL 0x07 /* or ds1338 */
#define DS1307_REG_CONTROL 0x07 /* or ds1338, 1308 */
# define DS1307_BIT_OUT 0x80
# define DS1308_BIT_ECLK 0x40
# define DS1338_BIT_OSF 0x20
# define DS1307_BIT_SQWE 0x10
# define DS1308_BIT_LOS 0x08
# define DS1308_BIT_BBCLK 0x04
# define DS1307_BIT_RS1 0x02
# define DS1307_BIT_RS0 0x01
#define DS1337_REG_CONTROL 0x0e
@ -288,6 +291,7 @@ static int ds1307_probe(struct device_d *dev)
int tmp;
unsigned char *buf;
unsigned long driver_data;
const struct device_node *np = dev->device_node;
ds1307 = xzalloc(sizeof(struct ds1307));
@ -377,6 +381,45 @@ read_rtc:
goto exit;
}
/* Configure clock using OF data if available */
if (IS_ENABLED(CONFIG_OFDEVICE) && np) {
u8 control = ds1307->regs[DS1307_REG_CONTROL];
u32 rate = 0;
if (of_property_read_bool(np, "ext-clock-input"))
control |= DS1308_BIT_ECLK;
else
control &= ~DS1308_BIT_ECLK;
if (of_property_read_bool(np, "ext-clock-output"))
control |= DS1307_BIT_SQWE;
else
control &= ~DS1307_BIT_SQWE;
if (of_property_read_bool(np, "ext-clock-bb"))
control |= DS1308_BIT_BBCLK;
else
control &= ~DS1308_BIT_BBCLK;
control &= ~(DS1307_BIT_RS1 | DS1307_BIT_RS0);
of_property_read_u32(np, "ext-clock-rate", &rate);
switch (rate) {
default:
case 1: control |= 0; break;
case 50: control |= 1; break;
case 60: control |= 2; break;
case 4096: control |= 1; break;
case 8192: control |= 2; break;
case 32768: control |= 3; break;
}
dev_dbg(&client->dev, "control reg: 0x%02x\n", control);
if (ds1307->regs[DS1307_REG_CONTROL] != control) {
i2c_smbus_write_byte_data(client, DS1307_REG_CONTROL, control);
ds1307->regs[DS1307_REG_CONTROL] = control;
}
}
/*
* minimal sanity checking; some chips (like DS1340) don't
* specify the extra bits as must-be-zero, but there are