Skip to contentSkip to conversation

RTC: Add driver for DS1685 family of real time clocks

PATCH RESEND Superseded Joshua Kinard 2 participants 4 messages Dec 12, 2014 – Feb 10, 2015

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH RESEND 1/2 RTC: Add driver for DS1685 family of real time clocks

From: Joshua Kinard <[email protected]>

This adds a driver for the Dallas/Maxim DS1685-family of RTC chips. It supports the DS1685/DS1687, DS1688/DS1691, DS1689/DS1693, DS17285/DS17287, DS17485/DS17487, and DS17885/DS17887 RTC chips. These chips are commonly found in SGI O2 and SGI Octane systems. It was originally derived from a driver patch submitted by Matthias Fuchs many years ago for use in EPPC-405-UC modules, which also used these RTCs. In addition to the time-keeping functions, this RTC also handles the shutdown mechanism of the O2 and Octane and acts as a partial NVRAM for the boot PROMS in these systems.

Verified on both an SGI O2 and an SGI Octane.

---
 MAINTAINERS                |    6
 drivers/rtc/Kconfig        |   90 +
 drivers/rtc/Makefile       |    1
 drivers/rtc/rtc-ds1685.c   | 2252 +++++++++++++++++++++++++++++++++++
 include/linux/rtc/ds1685.h |  375 +++++
 5 files changed, 2724 insertions(+)
 create mode 100644 drivers/rtc/rtc-ds1685.c
 create mode 100644 include/linux/rtc/ds1685.h

The checkpatch errors regarding "Macros with complex values should be enclosed in parenthesis" should be fine. That macro construct I copied from elsewhere in the kernel, and I don't think wrapping them in parenthesis helps at all. Please let me know of any problems, thanks!

linux-rtc-ds1685.patch

MAINTAINERS +6 -0
index e186bf9..d081504 100644
@@ -2915,6 +2915,12 @@ S:	Supported
 F:	drivers/input/touchscreen/cyttsp*
 F:	include/linux/input/cyttsp.h
 
+DALLAS/MAXIM DS1685-FAMILY REAL TIME CLOCK
+M:	Joshua Kinard <[email protected]>
+S:	Maintained
+F:	drivers/rtc/rtc-ds1685.c
+F:	include/linux/rtc/ds1685.h
+
 DAMA SLAVE for AX.25
 M:	Joerg Reuter <[email protected]>
 W:	http://yaina.de/jreuter/
drivers/rtc/Kconfig +90 -0

96 lines not on this page · raw message

drivers/rtc/Makefile +1 -0
index c8ef3e1..1b45334 100644
@@ -52,6 +52,7 @@ obj-$(CONFIG_RTC_DRV_DS1390)	+= rtc-ds1390.o
 obj-$(CONFIG_RTC_DRV_DS1511)	+= rtc-ds1511.o
 obj-$(CONFIG_RTC_DRV_DS1553)	+= rtc-ds1553.o
 obj-$(CONFIG_RTC_DRV_DS1672)	+= rtc-ds1672.o
+obj-$(CONFIG_RTC_DRV_DS1685_FAMILY)	+= rtc-ds1685.o
 obj-$(CONFIG_RTC_DRV_DS1742)	+= rtc-ds1742.o
 obj-$(CONFIG_RTC_DRV_DS2404)    += rtc-ds2404.o
 obj-$(CONFIG_RTC_DRV_DS3232)	+= rtc-ds3232.o
drivers/rtc/rtc-ds1685.c new file +2252 -0

2,252 lines not on this page · raw message

include/linux/rtc/ds1685.h new file +375 -0

375 lines not on this page · raw message

#1 lore raw
Quoted 18 lines · On Fri, 12 Dec 2014 17:13:38 -0500 Joshua Kinard <[email protected]> wrote:

From: Joshua Kinard <[email protected]>

This adds a driver for the Dallas/Maxim DS1685-family of RTC chips. It supports the DS1685/DS1687, DS1688/DS1691, DS1689/DS1693, DS17285/DS17287, DS17485/DS17487, and DS17885/DS17887 RTC chips. These chips are commonly found in SGI O2 and SGI Octane systems. It was originally derived from a driver patch submitted by Matthias Fuchs many years ago for use in EPPC-405-UC modules, which also used these RTCs. In addition to the time-keeping functions, this RTC also handles the shutdown mechanism of the O2 and Octane and acts as a partial NVRAM for the boot PROMS in these systems.

Verified on both an SGI O2 and an SGI Octane.

...

drivers/rtc/rtc-ds1685.c new file +3 -0
+static int
+ds1685_rtc_probe(struct platform_device *pdev)
+{

drivers/rtc/rtc-ds1685.c line 1837

Quoted 10 lines
drivers/rtc/rtc-ds1685.c new file +10 -0
+	struct rtc_device *rtc_dev;
+	struct resource *res;
+	struct ds1685_priv *rtc;
+	struct ds1685_rtc_platform_data *pdata;
+	u8 ctrla, ctrlb, hours;
+	unsigned char am_pm;
+	int ret = 0;
+
+	/* Get the platform data. */
+	pdata = (struct ds1685_rtc_platform_data *) pdev->dev.platform_data;

That cast isn't needed.

Quoted 37 lines
drivers/rtc/rtc-ds1685.c new file +37 -0
+	if (!pdata)
+		return -ENODEV;
+
+	/* Allocate memory for the rtc device. */
+	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+	if (!rtc)
+		return -ENOMEM;
+
+	/*
+	 * Allocate/setup any IORESOURCE_MEM resources, if required.  Not all
+	 * platforms put the RTC in an easy-access place.  Like the SGI Octane,
+	 * which attaches the RTC to a "ByteBus", hooked to a SuperIO chip
+	 * that sits behind the IOC3 PCI metadevice.
+	 */
+	if (pdata->alloc_io_resources) {
+		/* Get the platform resources. */
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (!res)
+			return -ENXIO;
+		rtc->size = resource_size(res);
+
+		/* Request a memory region. */
+		/* XXX: mmio-only for now. */
+		if (!devm_request_mem_region(&pdev->dev, res->start, rtc->size,
+					     pdev->name))
+			return -EBUSY;
+
+		/*
+		 * Set the base address for the rtc, and ioremap its
+		 * registers.
+		 */
+		rtc->baseaddr = res->start;
+		rtc->regs = devm_ioremap(&pdev->dev, res->start, rtc->size);
+		if (!rtc->regs)
+			return -ENOMEM;
+	}
+	rtc->alloc_io_resources = pdata->alloc_io_resources;

drivers/rtc/rtc-ds1685.c line 1884

Quoted 10 lines
drivers/rtc/rtc-ds1685.c new file +10 -0
+
+	/* Get the register step size. */
+	if (pdata->regstep > 0)
+		rtc->regstep = pdata->regstep;
+	else
+		rtc->regstep = 1;
+
+	/* Platform read function, else default if mmio setup */
+	if (pdata->plat_read)
+		rtc->read = pdata->plat_read;

I'm trying to understand how this works and I'm not getting very far. Perhaps it is the intention that some code(?) is to allocate and populate a ds1685_rtc_platform_data and use platform_device_add_data() on it, but no such code exists.

Or something. What's going on here?

Quoted 34 lines
drivers/rtc/rtc-ds1685.c new file +31 -0
+	else
+		if (pdata->alloc_io_resources)
+			rtc->read = ds1685_read;
+		else
+			return -ENXIO;
+
+	/* Platform write function, else default if mmio setup */
+	if (pdata->plat_write)
+		rtc->write = pdata->plat_write;
+	else
+		if (pdata->alloc_io_resources)
+			rtc->write = ds1685_write;
+		else
+			return -ENXIO;
+
+	/* Platform pre-shutdown function, if defined. */
+	if (pdata->plat_prepare_poweroff)
+		rtc->prepare_poweroff = pdata->plat_prepare_poweroff;
+
+	/* Platform wake_alarm function, if defined. */
+	if (pdata->plat_wake_alarm)
+		rtc->wake_alarm = pdata->plat_wake_alarm;
+
+	/* Platform post_ram_clear function, if defined. */
+	if (pdata->plat_post_ram_clear)
+		rtc->post_ram_clear = pdata->plat_post_ram_clear;
+
+	/* Init the spinlock, workqueue, & set the driver data. */
+	spin_lock_init(&rtc->lock);
+	INIT_WORK(&rtc->work, ds1685_rtc_work_queue);
+	platform_set_drvdata(pdev, rtc);
 
...
#2 lore raw
Quoted 5 lines · On Mon, 9 Feb 2015 16:18:44 -0800 Andrew Morton <[email protected]>…

drivers/rtc/rtc-ds1685.c line 1884

Quoted 3 lines
drivers/rtc/rtc-ds1685.c new file +3 -0
+	/* Platform read function, else default if mmio setup */
+	if (pdata->plat_read)
+		rtc->read = pdata->plat_read;

I'm trying to understand how this works and I'm not getting very far.

oop, never mind, it's there in patch 2/2.

#3 lore raw
In reply to Andrew Morton
Quoted 17 lines · Andrew Morton
Quoted 15 lines · On Fri, 12 Dec 2014 17:13:38 -0500 Joshua Kinard <[email protected]> wrote:

From: Joshua Kinard <[email protected]>

This adds a driver for the Dallas/Maxim DS1685-family of RTC chips. It supports the DS1685/DS1687, DS1688/DS1691, DS1689/DS1693, DS17285/DS17287, DS17485/DS17487, and DS17885/DS17887 RTC chips. These chips are commonly found in SGI O2 and SGI Octane systems. It was originally derived from a driver patch submitted by Matthias Fuchs many years ago for use in EPPC-405-UC modules, which also used these RTCs. In addition to the time-keeping functions, this RTC also handles the shutdown mechanism of the O2 and Octane and acts as a partial NVRAM for the boot PROMS in these systems.

Verified on both an SGI O2 and an SGI Octane.

...

Quoted 15 lines

drivers/rtc/rtc-ds1685.c line 1837

Quoted 13 lines
drivers/rtc/rtc-ds1685.c new file +13 -0
+static int
+ds1685_rtc_probe(struct platform_device *pdev)
+{
+	struct rtc_device *rtc_dev;
+	struct resource *res;
+	struct ds1685_priv *rtc;
+	struct ds1685_rtc_platform_data *pdata;
+	u8 ctrla, ctrlb, hours;
+	unsigned char am_pm;
+	int ret = 0;
+
+	/* Get the platform data. */
+	pdata = (struct ds1685_rtc_platform_data *) pdev->dev.platform_data;

That cast isn't needed.

Huh, I thought GCC complained about that once, but it doesn't now (gcc-4.7.4).
Would you like me to remove it and re-send the patch, even though it looks
like you've added it to -mm?

Quoted 53 lines
Quoted 37 lines
drivers/rtc/rtc-ds1685.c new file +37 -0
+	if (!pdata)
+		return -ENODEV;
+
+	/* Allocate memory for the rtc device. */
+	rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+	if (!rtc)
+		return -ENOMEM;
+
+	/*
+	 * Allocate/setup any IORESOURCE_MEM resources, if required.  Not all
+	 * platforms put the RTC in an easy-access place.  Like the SGI Octane,
+	 * which attaches the RTC to a "ByteBus", hooked to a SuperIO chip
+	 * that sits behind the IOC3 PCI metadevice.
+	 */
+	if (pdata->alloc_io_resources) {
+		/* Get the platform resources. */
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (!res)
+			return -ENXIO;
+		rtc->size = resource_size(res);
+
+		/* Request a memory region. */
+		/* XXX: mmio-only for now. */
+		if (!devm_request_mem_region(&pdev->dev, res->start, rtc->size,
+					     pdev->name))
+			return -EBUSY;
+
+		/*
+		 * Set the base address for the rtc, and ioremap its
+		 * registers.
+		 */
+		rtc->baseaddr = res->start;
+		rtc->regs = devm_ioremap(&pdev->dev, res->start, rtc->size);
+		if (!rtc->regs)
+			return -ENOMEM;
+	}
+	rtc->alloc_io_resources = pdata->alloc_io_resources;

drivers/rtc/rtc-ds1685.c line 1884

Quoted 10 lines
drivers/rtc/rtc-ds1685.c new file +10 -0
+
+	/* Get the register step size. */
+	if (pdata->regstep > 0)
+		rtc->regstep = pdata->regstep;
+	else
+		rtc->regstep = 1;
+
+	/* Platform read function, else default if mmio setup */
+	if (pdata->plat_read)
+		rtc->read = pdata->plat_read;

I'm trying to understand how this works and I'm not getting very far. Perhaps it is the intention that some code(?) is to allocate and populate a ds1685_rtc_platform_data and use platform_device_add_data() on it, but no such code exists.

Quoted 1 line

Or something. What's going on here?

Yeah, as you saw in the second patch, this is a mechanism to keep arch or machine-specific code out of a general driver. SGI O2's use MMIO to read/set the RTC (which are the default methods in this patch), but SGI Octane's, whose code is not in-tree yet, use this same RTC (DS1687-5) via PIO access because the RTC is tucked behind the IOC3 PCI Metadevice's "ByteBus" (write an address port, read a data port). Thus, two different methods are needed by each machine to talk to the same RTC driver, so this looked like the best approach, after I looked at a few other drivers.

Quoted 23 lines
Quoted 23 lines
drivers/rtc/rtc-ds1685.c new file +23 -0
+	else
+		if (pdata->alloc_io_resources)
+			rtc->read = ds1685_read;
+		else
+			return -ENXIO;
+
+	/* Platform write function, else default if mmio setup */
+	if (pdata->plat_write)
+		rtc->write = pdata->plat_write;
+	else
+		if (pdata->alloc_io_resources)
+			rtc->write = ds1685_write;
+		else
+			return -ENXIO;
+
+	/* Platform pre-shutdown function, if defined. */
+	if (pdata->plat_prepare_poweroff)
+		rtc->prepare_poweroff = pdata->plat_prepare_poweroff;
+
+	/* Platform wake_alarm function, if defined. */
+	if (pdata->plat_wake_alarm)
+		rtc->wake_alarm = pdata->plat_wake_alarm;
+
Quoted 8 lines

drivers/rtc/rtc-ds1685.c line 1915

Quoted 8 lines
drivers/rtc/rtc-ds1685.c new file +8 -0
+	/* Platform post_ram_clear function, if defined. */
+	if (pdata->plat_post_ram_clear)
+		rtc->post_ram_clear = pdata->plat_post_ram_clear;
+
+	/* Init the spinlock, workqueue, & set the driver data. */
+	spin_lock_init(&rtc->lock);
+	INIT_WORK(&rtc->work, ds1685_rtc_work_queue);
+	platform_set_drvdata(pdev, rtc);

--J