Skip to contentSkip to conversation

RTC driver for i.MX25

PATCH New Baruch Siach 5 participants 20 messages Jan 27, 2010 – May 4, 2010

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

cover RTC driver for i.MX25

These patches add support for the RTC of the i.MX25 chip, which is based on the DryIce block. The driver is based on code from the Freescale i.MX BSP.

Also included platform code for i.MX25 chip, and the i.MX25 PDK board.

These patches have been tested on the i.MX25 PDK board.

Baruch Siach (3):
rtc: driver for the DryIce block found in i.MX25 chips
mx25: add support for the DryIce rtc
mx25pdk: platform code for the DryIce RTC module

 arch/arm/mach-mx25/clock.c            |    2 +
 arch/arm/mach-mx25/devices.c          |   19 ++
 arch/arm/mach-mx25/devices.h          |    1 +
 arch/arm/mach-mx25/mx25pdk.c          |    1 +
 arch/arm/plat-mxc/include/mach/mx25.h |    2 +
 drivers/rtc/Kconfig                   |   10 +
 drivers/rtc/Makefile                  |    1 +
 drivers/rtc/rtc-imxdi.c               |  559 +++++++++++++++++++++++++++++++++
 8 files changed, 595 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/rtc-imxdi.c
#1 lore raw

PATCH 1/3 rtc: driver for the DryIce block found in i.MX25 chips

This driver is based on code from Freescale which accompanies their i.MX25 PDK board, with some cleanup.

---
 drivers/rtc/Kconfig     |   10 +
 drivers/rtc/Makefile    |    1 +
 drivers/rtc/rtc-imxdi.c |  559 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 570 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/rtc-imxdi.c
drivers/rtc/Kconfig +10 -0
index 8167e9e..83bd602 100644
@@ -527,6 +527,16 @@ config RTC_DRV_MSM6242
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-msm6242.
 
+config RTC_DRV_IMXDI
+	tristate "Freescale IMX DryIce Real Time Clock"
+	depends on ARCH_MX25
+	depends on RTC_CLASS
+	help
+	   Support for Freescale IMX DryIce RTC
+
+	   This driver can also be built as a module, if so, the module
+	   will be called "rtc-imxdi".
+
 config RTC_MXC
 	tristate "Freescale MXC Real Time Clock"
 	depends on ARCH_MXC
drivers/rtc/Makefile +1 -0
index e5160fd..f2d3420 100644
@@ -44,6 +44,7 @@ obj-$(CONFIG_RTC_DRV_EFI)	+= rtc-efi.o
 obj-$(CONFIG_RTC_DRV_EP93XX)	+= rtc-ep93xx.o
 obj-$(CONFIG_RTC_DRV_FM3130)	+= rtc-fm3130.o
 obj-$(CONFIG_RTC_DRV_GENERIC)	+= rtc-generic.o
+obj-$(CONFIG_RTC_DRV_IMXDI)	+= rtc-imxdi.o
 obj-$(CONFIG_RTC_DRV_ISL1208)	+= rtc-isl1208.o
 obj-$(CONFIG_RTC_DRV_M41T80)	+= rtc-m41t80.o
 obj-$(CONFIG_RTC_DRV_M41T94)	+= rtc-m41t94.o
drivers/rtc/rtc-imxdi.c new file +559 -0

559 lines not on this page · raw message

Signature · 1 line
1.6.5
#17 lore raw

PATCH 2/3 mx25: add support for the DryIce rtc

In reply to Baruch Siach
---
 arch/arm/mach-mx25/clock.c            |    2 ++
 arch/arm/mach-mx25/devices.c          |   19 +++++++++++++++++++
 arch/arm/mach-mx25/devices.h          |    1 +
 arch/arm/plat-mxc/include/mach/mx25.h |    2 ++
 4 files changed, 24 insertions(+), 0 deletions(-)
arch/arm/mach-mx25/clock.c +2 -0
index 6acc88b..744b52a 100644
@@ -182,6 +182,7 @@ DEFINE_CLOCK(kpp_clk,	 0, CCM_CGCR1, 28, get_rate_ipg, NULL, NULL);
 DEFINE_CLOCK(tsc_clk,	 0, CCM_CGCR2, 13, get_rate_ipg, NULL, NULL);
 DEFINE_CLOCK(i2c_clk,	 0, CCM_CGCR0,  6, get_rate_i2c, NULL, NULL);
 DEFINE_CLOCK(fec_clk,	 0, CCM_CGCR1, 15, get_rate_ipg, NULL, &fec_ahb_clk);
+DEFINE_CLOCK(dryice_clk, 0, CCM_CGCR1,  8, get_rate_ipg, NULL, NULL);
 
 #define _REGISTER_CLOCK(d, n, c)	\
 	{				\
@@ -214,6 +215,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk)
 	_REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk)
 	_REGISTER_CLOCK("fec.0", NULL, fec_clk)
+	_REGISTER_CLOCK("imxdi_rtc.0", NULL, dryice_clk)
 };
 
 int __init mx25_clocks_init(void)
arch/arm/mach-mx25/devices.c +19 -0
index dd40697..b0b75fc 100644
@@ -458,3 +458,22 @@ struct platform_device mxc_nand_device = {
 	.num_resources	= ARRAY_SIZE(mxc_nand_resources),
 	.resource	= mxc_nand_resources,
 };
+
+static struct resource mx25_rtc_resources[] = {
+	{
+		.start	= MX25_DRYICE_BASE_ADDR,
+		.end	= MX25_DRYICE_BASE_ADDR + 0x40,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MX25_INT_DRYICE,
+		.flags	= IORESOURCE_IRQ
+	},
+};
+
+struct platform_device mx25_rtc_device = {
+	.name	= "imxdi_rtc",
+	.id	= 0,
+	.num_resources	= ARRAY_SIZE(mx25_rtc_resources),
+	.resource	= mx25_rtc_resources,
+};
arch/arm/mach-mx25/devices.h +1 -0
index 8f55300..37e6a08 100644
@@ -19,3 +19,4 @@ extern struct platform_device mxc_i2c_device1;
 extern struct platform_device mxc_i2c_device2;
 extern struct platform_device mx25_fec_device;
 extern struct platform_device mxc_nand_device;
+extern struct platform_device mx25_rtc_device;
arch/arm/plat-mxc/include/mach/mx25.h +2 -0
index 58e0bd3..215c4d8 100644
@@ -43,7 +43,9 @@
 
 #define MX25_FEC_BASE_ADDR		0x50038000
 #define MX25_NFC_BASE_ADDR		0xbb000000
+#define MX25_DRYICE_BASE_ADDR		0x53ffc000
 
+#define MX25_INT_DRYICE	25
 #define MX25_INT_FEC	57
 #define MX25_INT_NANDFC	33
 
Signature · 1 line
1.6.5
#18 lore raw

PATCH 3/3 mx25pdk: platform code for the DryIce RTC module

In reply to Baruch Siach
---
 arch/arm/mach-mx25/mx25pdk.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)
arch/arm/mach-mx25/mx25pdk.c +1 -0
index 232f9ca..f4e8b98 100644
@@ -91,6 +91,7 @@ static void __init mx25pdk_init(void)
 	mxc_register_device(&mxc_uart_device0, &uart_pdata);
 	mxc_register_device(&mxc_usbh2, NULL);
 	mxc_register_device(&mxc_nand_device, &mx25pdk_nand_board_info);
+	mxc_register_device(&mx25_rtc_device, NULL);
 
 	mx25pdk_fec_reset();
 	mxc_register_device(&mx25_fec_device, &mx25_fec_pdata);
Signature · 1 line
1.6.5
#2 lore raw

PATCH 1/3 rtc: driver for the DryIce block found in i.MX25 chips

In reply to Baruch Siach

Hi,

Quoted 49 lines · Baruch Siach

This driver is based on code from Freescale which accompanies their i.MX25 PDK board, with some cleanup.

---
 drivers/rtc/Kconfig     |   10 +
 drivers/rtc/Makefile    |    1 +
 drivers/rtc/rtc-imxdi.c |  559 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 570 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/rtc-imxdi.c
drivers/rtc/Kconfig +10 -0
index 8167e9e..83bd602 100644
@@ -527,6 +527,16 @@ config RTC_DRV_MSM6242
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-msm6242.
 
+config RTC_DRV_IMXDI
+	tristate "Freescale IMX DryIce Real Time Clock"
+	depends on ARCH_MX25
+	depends on RTC_CLASS
+	help
+	   Support for Freescale IMX DryIce RTC
+
+	   This driver can also be built as a module, if so, the module
+	   will be called "rtc-imxdi".
+
 config RTC_MXC
 	tristate "Freescale MXC Real Time Clock"
 	depends on ARCH_MXC
drivers/rtc/Makefile +1 -0
index e5160fd..f2d3420 100644
@@ -44,6 +44,7 @@ obj-$(CONFIG_RTC_DRV_EFI)	+= rtc-efi.o
 obj-$(CONFIG_RTC_DRV_EP93XX)	+= rtc-ep93xx.o
 obj-$(CONFIG_RTC_DRV_FM3130)	+= rtc-fm3130.o
 obj-$(CONFIG_RTC_DRV_GENERIC)	+= rtc-generic.o
+obj-$(CONFIG_RTC_DRV_IMXDI)	+= rtc-imxdi.o
 obj-$(CONFIG_RTC_DRV_ISL1208)	+= rtc-isl1208.o
 obj-$(CONFIG_RTC_DRV_M41T80)	+= rtc-m41t80.o
 obj-$(CONFIG_RTC_DRV_M41T94)	+= rtc-m41t94.o
drivers/rtc/rtc-imxdi.c new file +0 -0
new file mode 100644
index 0000000..12a6df5

[...]

Quoted 29 lines
drivers/rtc/rtc-imxdi.c new file +28 -0
+static int dryice_rtc_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct imxdi_dev *imxdi = NULL;
+	int rc = 0;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	imxdi = kzalloc(sizeof(*imxdi), GFP_KERNEL);
+	if (!imxdi)
+		return -ENOMEM;
+
+	imxdi->pdev = pdev;
+	imxdi->irq = -1;
+
+	if (!request_mem_region(res->start, resource_size(res),
+				pdev->name)) {
+		rc = -EBUSY;
+		goto err_free_mem;
+	}
+	imxdi->ioaddr = ioremap(res->start, resource_size(res));
+	if (imxdi->ioaddr == NULL) {
+		rc = -ENOMEM;
+		goto err_release_region;
+	}
+	imxdi->irq = platform_get_irq(pdev, 0);

drivers/rtc/rtc-imxdi.c line 421

Quoted 10 lines
drivers/rtc/rtc-imxdi.c new file +10 -0
+
+	init_waitqueue_head(&imxdi->write_wait);
+
+	INIT_WORK(&imxdi->work, dryice_work);
+
+	mutex_init(&imxdi->write_mutex);
+
+	imxdi->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(imxdi->clk)) {
+		rc = -ENODEV;

rc = PTR_ERR(imxdi->clk);

Lothar Wa?mann

Signature · 9 lines
___________________________________________________________

Ka-Ro electronics GmbH | Pascalstra?e 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Gesch?ftsf?hrer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | info at karo-electronics.de
___________________________________________________________
#3 lore raw

PATCH 1/3 rtc: driver for the DryIce block found in i.MX25 chips

Quoted 8 lines · Lothar Wa?mann

Hi,

drivers/rtc/rtc-imxdi.c line 421

Quoted 4 lines · Baruch Siach
drivers/rtc/rtc-imxdi.c new file +3 -0
+	imxdi->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(imxdi->clk)) {
+		rc = -ENODEV;

rc = PTR_ERR(imxdi->clk);

Grr.

Why do people find the general principle that "if you have an error code, propagate it upwards" is soo difficult to deal with?

We seem to have stuff like the above constantly appearing, or the evil "lets return -1 because we can't be bothered to find an appropriate error value" sillyness.

Why is this?

A suggestion - try thinking like this: "If I find myself typing 'return -1', immediate stop typing and take the time to find a better value. If I find myself typing IS_ERR() make sure I use PTR_ERR to assign an error code."

Simples.

maintainer
#19 lore raw

cover RTC driver for i.MX25

In reply to Baruch Siach
Quoted 6 lines · Baruch Siach

These patches add support for the RTC of the i.MX25 chip, which is based on the DryIce block. The driver is based on code from the Freescale i.MX BSP.

Also included platform code for i.MX25 chip, and the i.MX25 PDK board.

These patches have been tested on the i.MX25 PDK board.

I added 2/3 and 3/3 to mxc-master. The rtc guys should take care of the rest.

Sascha

Quoted 18 lines

Baruch Siach (3):
rtc: driver for the DryIce block found in i.MX25 chips
mx25: add support for the DryIce rtc
mx25pdk: platform code for the DryIce RTC module

 arch/arm/mach-mx25/clock.c            |    2 +
 arch/arm/mach-mx25/devices.c          |   19 ++
 arch/arm/mach-mx25/devices.h          |    1 +
 arch/arm/mach-mx25/mx25pdk.c          |    1 +
 arch/arm/plat-mxc/include/mach/mx25.h |    2 +
 drivers/rtc/Kconfig                   |   10 +
 drivers/rtc/Makefile                  |    1 +
 drivers/rtc/rtc-imxdi.c               |  559 +++++++++++++++++++++++++++++++++
 8 files changed, 595 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/rtc-imxdi.c
Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
#4 lore raw

PATCH 1/3 rtc: driver for the DryIce block found in i.MX25 chips

In reply to Baruch Siach
Quoted 5 lines · On Wed, 27 Jan 2010 15:00:47 +0200 Baruch Siach <[email protected]> wrote:

This driver is based on code from Freescale which accompanies their i.MX25 PDK board, with some cleanup.

Hi Baruch, please find a few comments below and be sure to read http://groups.google.com/group/rtc-linux/web/checklist

Quoted 228 lines
---
 drivers/rtc/Kconfig     |   10 +
 drivers/rtc/Makefile    |    1 +
 drivers/rtc/rtc-imxdi.c |  559 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 570 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/rtc-imxdi.c
drivers/rtc/Kconfig +10 -0
index 8167e9e..83bd602 100644
@@ -527,6 +527,16 @@ config RTC_DRV_MSM6242
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-msm6242.
 
+config RTC_DRV_IMXDI
+	tristate "Freescale IMX DryIce Real Time Clock"
+	depends on ARCH_MX25
+	depends on RTC_CLASS
+	help
+	   Support for Freescale IMX DryIce RTC
+
+	   This driver can also be built as a module, if so, the module
+	   will be called "rtc-imxdi".
+
 config RTC_MXC
 	tristate "Freescale MXC Real Time Clock"
 	depends on ARCH_MXC
drivers/rtc/Makefile +1 -0
index e5160fd..f2d3420 100644
@@ -44,6 +44,7 @@ obj-$(CONFIG_RTC_DRV_EFI)	+= rtc-efi.o
 obj-$(CONFIG_RTC_DRV_EP93XX)	+= rtc-ep93xx.o
 obj-$(CONFIG_RTC_DRV_FM3130)	+= rtc-fm3130.o
 obj-$(CONFIG_RTC_DRV_GENERIC)	+= rtc-generic.o
+obj-$(CONFIG_RTC_DRV_IMXDI)	+= rtc-imxdi.o
 obj-$(CONFIG_RTC_DRV_ISL1208)	+= rtc-isl1208.o
 obj-$(CONFIG_RTC_DRV_M41T80)	+= rtc-m41t80.o
 obj-$(CONFIG_RTC_DRV_M41T94)	+= rtc-m41t94.o
drivers/rtc/rtc-imxdi.c new file +182 -0
new file mode 100644
index 0000000..12a6df5
@@ -0,0 +1,559 @@
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2010 Orex Computed Radiography
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/* based on rtc-mc13892.c */
+
+/*
+ * This driver uses the 47-bit 32 kHz counter in the Freescale DryIce block
+ * to implement a Linux RTC. Times and alarms are truncated to seconds.
+ * Since the RTC framework performs API locking via rtc->ops_lock the
+ * only simultaneous accesses we need to deal with is updating DryIce
+ * registers while servicing an alarm.
+ *
+ * Note that reading the DSR (DryIce Status Register) automatically clears
+ * the WCF (Write Complete Flag). All DryIce writes are synchronized to the
+ * LP (Low Power) domain and set the WCF upon completion. Writes to the
+ * DIER (DryIce Interrupt Enable Register) are the only exception. These
+ * occur at normal bus speeds and do not set WCF.  Periodic interrupts are
+ * not supported by the hardware.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/workqueue.h>
+
+/* DryIce Register Definitions */
+
+#define DTCMR     0x00           /* Time Counter MSB Reg */
+#define DTCLR     0x04           /* Time Counter LSB Reg */
+
+#define DCAMR     0x08           /* Clock Alarm MSB Reg */
+#define DCALR     0x0c           /* Clock Alarm LSB Reg */
+#define DCAMR_UNSET  0xFFFFFFFF  /* doomsday - 1 sec */
+
+#define DCR       0x10           /* Control Reg */
+#define DCR_TCE   (1 << 3)       /* Time Counter Enable */
+
+#define DSR       0x14           /* Status Reg */
+#define DSR_WBF   (1 << 10)      /* Write Busy Flag */
+#define DSR_WNF   (1 << 9)       /* Write Next Flag */
+#define DSR_WCF   (1 << 8)       /* Write Complete Flag */
+#define DSR_WEF   (1 << 7)       /* Write Error Flag */
+#define DSR_CAF   (1 << 4)       /* Clock Alarm Flag */
+#define DSR_NVF   (1 << 1)       /* Non-Valid Flag */
+#define DSR_SVF   (1 << 0)       /* Security Violation Flag */
+
+#define DIER      0x18           /* Interrupt Enable Reg */
+#define DIER_WNIE (1 << 9)       /* Write Next Interrupt Enable */
+#define DIER_WCIE (1 << 8)       /* Write Complete Interrupt Enable */
+#define DIER_WEIE (1 << 7)       /* Write Error Interrupt Enable */
+#define DIER_CAIE (1 << 4)       /* Clock Alarm Interrupt Enable */
+
+/**
+ * struct imxdi_dev - private imxdi rtc data
+ * @pdev: pionter to platform dev
+ * @rtc: pointer to rtc struct
+ * @ioaddr: IO registers pointer
+ * @irq: dryice normal interrupt
+ * @clk: input reference clock
+ * @dsr: copy of the DSR register
+ * @irq_lock: interrupt enable register (DIER) lock
+ * @write_wait: registers write complete queue
+ * @write_mutex: serialize registers write
+ * @work: schedule alarm work
+ */
+struct imxdi_dev {
+	struct platform_device *pdev;
+	struct rtc_device *rtc;
+	void __iomem *ioaddr;
+	int irq;
+	struct clk *clk;
+	u32 dsr;
+	spinlock_t irq_lock;
+	wait_queue_head_t write_wait;
+	struct mutex write_mutex;
+	struct work_struct work;
+};
+
+/*
+ * enable a dryice interrupt
+ */
+static inline void di_int_enable(struct imxdi_dev *imxdi, u32 intr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&imxdi->irq_lock, flags);
+	__raw_writel(__raw_readl(imxdi->ioaddr+DIER) | intr,
+			imxdi->ioaddr+DIER);
+	spin_unlock_irqrestore(&imxdi->irq_lock, flags);
+}
+
+/*
+ * disable a dryice interrupt
+ */
+static inline void di_int_disable(struct imxdi_dev *imxdi, u32 intr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&imxdi->irq_lock, flags);
+	__raw_writel(__raw_readl(imxdi->ioaddr+DIER) & ~intr,
+			imxdi->ioaddr+DIER);
+	spin_unlock_irqrestore(&imxdi->irq_lock, flags);
+}
+
+/*
+ * This function attempts to clear the dryice write-error flag.
+ *
+ * A dryice write error is similar to a bus fault and should not occur in
+ * normal operation.  Clearing the flag requires another write, so the root
+ * cause of the problem may need to be fixed before the flag can be cleared.
+ */
+static void clear_write_error(struct imxdi_dev *imxdi)
+{
+	int cnt;
+
+	dev_warn(&imxdi->pdev->dev, "WARNING: Register write error!\n");
+
+	for (;;) {
+		/* clear the write error flag */
+		__raw_writel(DSR_WEF, imxdi->ioaddr+DSR);
+
+		/* wait for it to take effect */
+		for (cnt = 0; cnt < 100; cnt++) {
+			if ((__raw_readl(imxdi->ioaddr+DSR) & DSR_WEF) == 0)
+				return;
+			udelay(10);
+		}
+		dev_err(&imxdi->pdev->dev,
+			"ERROR: Cannot clear write-error flag!\n");
+	}
+}
+
+/*
+ * Write a dryice register and wait until it completes.
+ *
+ * This function uses interrupts to determine when the
+ * write has completed.
+ */
+static int di_write_wait(struct imxdi_dev *imxdi, u32 val, int reg)
+{
+	int ret;
+	int rc = 0;
+
+	/* serialize register writes */
+	mutex_lock(&imxdi->write_mutex);
+
+	/* enable the write-complete interrupt */
+	di_int_enable(imxdi, DIER_WCIE);
+
+	imxdi->dsr = 0;
+
+	/* do the register write */
+	__raw_writel(val, imxdi->ioaddr+reg);
+
+	/* wait for the write to finish */
+	ret = wait_event_interruptible_timeout(imxdi->write_wait,
+			imxdi->dsr & (DSR_WCF | DSR_WEF), 1 * HZ);
+	if (ret == 0)
+		dev_warn(&imxdi->pdev->dev,
+				"Write-wait timeout "
+				"val = 0x%08x reg = 0x%08x\n", val, reg);
+
+	/* check for write error */
+	if (imxdi->dsr & DSR_WEF) {
+		clear_write_error(imxdi);
+		rc = -EIO;
+	}
+	mutex_unlock(&imxdi->write_mutex);

drivers/rtc/rtc-imxdi.c line 192

Quoted 10 lines
drivers/rtc/rtc-imxdi.c new file +10 -0
+	return rc;
+}
+
+/*
+ * rtc device ioctl
+ *
+ * The rtc framework handles the basic rtc ioctls on behalf
+ * of the driver by calling the functions registered in the
+ * rtc_ops structure.
+ */

there are ops for alarm handling too, ioctl is not needed

Quoted 38 lines
drivers/rtc/rtc-imxdi.c new file +38 -0
+static int dryice_rtc_ioctl(struct device *dev, unsigned int cmd,
+			    unsigned long arg)
+{
+	struct imxdi_dev *imxdi = dev_get_drvdata(dev);
+
+	dev_dbg(dev, "%s(0x%x)\n", __func__, cmd);
+	switch (cmd) {
+	case RTC_AIE_OFF:  /* alarm disable */
+		di_int_disable(imxdi, DIER_CAIE);
+		return 0;
+
+	case RTC_AIE_ON:  /* alarm enable */
+		di_int_enable(imxdi, DIER_CAIE);
+		return 0;
+	}
+	return -ENOIOCTLCMD;
+}
+
+/*
+ * read the seconds portion of the current time from the dryice time counter
+ */
+static int dryice_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct imxdi_dev *imxdi = dev_get_drvdata(dev);
+	unsigned long now;
+
+	now = __raw_readl(imxdi->ioaddr+DTCMR);
+	rtc_time_to_tm(now, tm);
+
+	return 0;
+}
+
+/*
+ * set the seconds portion of dryice time counter and clear the
+ * fractional part.
+ */
+static int dryice_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{

drivers/rtc/rtc-imxdi.c line 240

Quoted 10 lines
drivers/rtc/rtc-imxdi.c new file +10 -0
+	struct imxdi_dev *imxdi = dev_get_drvdata(dev);
+	unsigned long now;
+	int rc;
+
+	rc = rtc_tm_to_time(tm, &now);
+	if (rc == 0)
+		/* zero the fractional part first */
+		rc = di_write_wait(imxdi, 0, DTCLR);
+	if (rc == 0)
+		rc = di_write_wait(imxdi, now, DTCMR);

two if ?

please implement set_mmss instead of set_time

Quoted 162 lines
drivers/rtc/rtc-imxdi.c new file +162 -0
+
+	return rc;
+}
+
+/*
+ * read the seconds portion of the alarm register.
+ * the fractional part of the alarm register is always zero.
+ */
+static int dryice_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	struct imxdi_dev *imxdi = dev_get_drvdata(dev);
+	u32 dcamr;
+
+	dcamr = __raw_readl(imxdi->ioaddr+DCAMR);
+	rtc_time_to_tm(dcamr, &alarm->time);
+
+	/* alarm is enabled if the interrupt is enabled */
+	alarm->enabled = (__raw_readl(imxdi->ioaddr+DIER) & DIER_CAIE) != 0;
+
+	/* don't allow the DSR read to mess up DSR_WCF */
+	mutex_lock(&imxdi->write_mutex);
+
+	/* alarm is pending if the alarm flag is set */
+	alarm->pending = (__raw_readl(imxdi->ioaddr+DSR) & DSR_CAF) != 0;
+
+	mutex_unlock(&imxdi->write_mutex);
+
+	return 0;
+}
+
+/*
+ * set the seconds portion of dryice alarm register
+ */
+static int dryice_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	struct imxdi_dev *imxdi = dev_get_drvdata(dev);
+	unsigned long now;
+	unsigned long alarm_time;
+	int rc;
+
+	rc = rtc_tm_to_time(&alarm->time, &alarm_time);
+	if (rc)
+		return rc;
+
+	/* don't allow setting alarm in the past */
+	now = __raw_readl(imxdi->ioaddr+DTCMR);
+	if (alarm_time < now)
+		return -EINVAL;
+
+	/* write the new alarm time */
+	rc = di_write_wait(imxdi, (u32)alarm_time, DCAMR);
+	if (rc)
+		return rc;
+
+	if (alarm->enabled)
+		di_int_enable(imxdi, DIER_CAIE);  /* enable alarm intr */
+	else
+		di_int_disable(imxdi, DIER_CAIE); /* disable alarm intr */
+
+	return 0;
+}
+
+static struct rtc_class_ops dryice_rtc_ops = {
+	.ioctl = dryice_rtc_ioctl,
+	.read_time = dryice_rtc_read_time,
+	.set_time = dryice_rtc_set_time,
+	.read_alarm = dryice_rtc_read_alarm,
+	.set_alarm = dryice_rtc_set_alarm,
+};
+
+/*
+ * dryice "normal" interrupt handler
+ */
+static irqreturn_t dryice_norm_irq(int irq, void *dev_id)
+{
+	struct imxdi_dev *imxdi = dev_id;
+	u32 dsr, dier;
+	irqreturn_t rc = IRQ_NONE;
+
+	dier = __raw_readl(imxdi->ioaddr+DIER);
+
+	/* handle write complete and write error cases */
+	if ((dier & DIER_WCIE)) {
+		/*If the write wait queue is empty then there is no pending
+		  operations. It means the interrupt is for DryIce -Security.
+		  IRQ must be returned as none.*/
+		if (list_empty_careful(&imxdi->write_wait.task_list))
+			return rc;
+
+		/* DSR_WCF clears itself on DSR read */
+		dsr = __raw_readl(imxdi->ioaddr+DSR);
+		if ((dsr & (DSR_WCF | DSR_WEF))) {
+			/* mask the interrupt */
+			di_int_disable(imxdi, DIER_WCIE);
+
+			/* save the dsr value for the wait queue */
+			imxdi->dsr |= dsr;
+
+			wake_up_interruptible(&imxdi->write_wait);
+			rc = IRQ_HANDLED;
+		}
+	}
+
+	/* handle the alarm case */
+	if ((dier & DIER_CAIE)) {
+		/* DSR_WCF clears itself on DSR read */
+		dsr = __raw_readl(imxdi->ioaddr+DSR);
+		if (dsr & DSR_CAF) {
+			/* mask the interrupt */
+			di_int_disable(imxdi, DIER_CAIE);
+
+			/* finish alarm in user context */
+			schedule_work(&imxdi->work);
+			rc = IRQ_HANDLED;
+		}
+	}
+	return rc;
+}
+
+/*
+ * post the alarm event from user context so it can sleep
+ * on the write completion.
+ */
+static void dryice_work(struct work_struct *work)
+{
+	struct imxdi_dev *imxdi = container_of(work,
+			struct imxdi_dev, work);
+
+	/* dismiss the interrupt (ignore error) */
+	di_write_wait(imxdi, DSR_CAF, DSR);
+
+	/*
+	 * pass the alarm event to the rtc framework. note that
+	 * rtc_update_irq expects to be called with interrupts off.
+	 */
+	local_irq_disable();
+	rtc_update_irq(imxdi->rtc, 1, RTC_AF | RTC_IRQF);
+	local_irq_enable();
+}
+
+/*
+ * probe for dryice rtc device
+ */
+static int dryice_rtc_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct imxdi_dev *imxdi = NULL;
+	int rc = 0;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	imxdi = kzalloc(sizeof(*imxdi), GFP_KERNEL);
+	if (!imxdi)
+		return -ENOMEM;
+
+	imxdi->pdev = pdev;
+	imxdi->irq = -1;
+
+	if (!request_mem_region(res->start, resource_size(res),
+				pdev->name)) {

drivers/rtc/rtc-imxdi.c line 413

Quoted 10 lines
drivers/rtc/rtc-imxdi.c new file +10 -0
+		rc = -EBUSY;
+		goto err_free_mem;
+	}
+	imxdi->ioaddr = ioremap(res->start, resource_size(res));
+	if (imxdi->ioaddr == NULL) {
+		rc = -ENOMEM;
+		goto err_release_region;
+	}
+	imxdi->irq = platform_get_irq(pdev, 0);
+	init_waitqueue_head(&imxdi->write_wait);

this routine has initialization and error sequence issues, I'd suggest to move to the resource manager

Documentation/driver-model/devres.txt

Quoted 9 lines
drivers/rtc/rtc-imxdi.c new file +9 -0
+	INIT_WORK(&imxdi->work, dryice_work);
+
+	mutex_init(&imxdi->write_mutex);
+
+	imxdi->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(imxdi->clk)) {
+		rc = -ENODEV;
+		goto err;
+	}

drivers/rtc/rtc-imxdi.c line 433

Quoted 10 lines
drivers/rtc/rtc-imxdi.c new file +10 -0
+	clk_enable(imxdi->clk);
+
+	if (imxdi->irq >= 0) {
+		if (request_irq(imxdi->irq, dryice_norm_irq, IRQF_SHARED,
+				pdev->name, imxdi) < 0) {
+			dev_warn(&pdev->dev, "interrupt not available.\n");
+			imxdi->irq = -1;
+			goto err;
+		}
+	}

be sure no irq is enabled prior to registration of the rtc device.

Quoted 77 lines
drivers/rtc/rtc-imxdi.c new file +77 -0
+
+	/*
+	 * Initialize dryice hardware
+	 */
+
+	/* put dryice into valid state */
+	if (__raw_readl(imxdi->ioaddr+DSR) & DSR_NVF)
+		rc = di_write_wait(imxdi, DSR_NVF | DSR_SVF, DSR);
+	if (rc)
+		goto err;
+
+	/* mask alarm interrupt */
+	di_int_disable(imxdi, DIER_CAIE);
+
+	/* initialize alarm */
+	rc = di_write_wait(imxdi, DCAMR_UNSET, DCAMR);
+	if (rc == 0)
+		rc = di_write_wait(imxdi, 0, DCALR);
+	if (rc)
+		goto err;
+
+	/* clear alarm flag */
+	if (__raw_readl(imxdi->ioaddr+DSR) & DSR_CAF)
+		rc = di_write_wait(imxdi, DSR_CAF, DSR);
+	if (rc)
+		goto err;
+
+	/* the timer won't count if it has never been written to */
+	if (__raw_readl(imxdi->ioaddr+DTCMR) == 0)
+		rc = di_write_wait(imxdi, 0, DTCMR);
+	if (rc)
+		goto err;
+
+	/* start keeping time */
+	if (!(__raw_readl(imxdi->ioaddr+DCR) & DCR_TCE))
+		rc = di_write_wait(imxdi,
+				__raw_readl(imxdi->ioaddr+DCR) | DCR_TCE, DCR);
+	if (rc)
+		goto err;
+
+	imxdi->rtc = rtc_device_register(pdev->name, &pdev->dev,
+				  &dryice_rtc_ops, THIS_MODULE);
+	if (IS_ERR(imxdi->rtc)) {
+		rc = PTR_ERR(imxdi->rtc);
+		goto err;
+	}
+	platform_set_drvdata(pdev, imxdi);
+
+	return 0;
+err:
+	if (imxdi->rtc && !IS_ERR(imxdi->rtc))
+		rtc_device_unregister(imxdi->rtc);
+
+	if (imxdi->irq >= 0)
+		free_irq(imxdi->irq, imxdi);
+
+	if (imxdi->clk && !IS_ERR(imxdi->clk)) {
+		clk_disable(imxdi->clk);
+		clk_put(imxdi->clk);
+	}
+
+	if (imxdi->ioaddr)
+		iounmap(imxdi->ioaddr);
+
+err_release_region:
+	release_mem_region(res->start, resource_size(res));
+
+err_free_mem:
+	kfree(imxdi);
+
+	return rc;
+}
+
+static int __exit dryice_rtc_remove(struct platform_device *pdev)
+{
+	struct imxdi_dev *imxdi = platform_get_drvdata(pdev);
+	struct resource *mem;

drivers/rtc/rtc-imxdi.c line 520

Quoted 10 lines
drivers/rtc/rtc-imxdi.c new file +10 -0
+
+	flush_scheduled_work();
+
+	rtc_device_unregister(imxdi->rtc);
+
+	/* mask alarm interrupt */
+	di_int_disable(imxdi, DIER_CAIE);
+
+	if (imxdi->irq >= 0)
+		free_irq(imxdi->irq, imxdi);

bbzt, wrong. disable prior to unregistration

Quoted 26 lines
drivers/rtc/rtc-imxdi.c new file +26 -0
+	clk_disable(imxdi->clk);
+	clk_put(imxdi->clk);
+
+	iounmap(imxdi->ioaddr);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+
+	kfree(imxdi);
+
+	return 0;
+}
+
+static struct platform_driver dryice_rtc_driver = {
+	.driver = {
+		   .name = "imxdi_rtc",
+		   .owner = THIS_MODULE,
+		   },
+	.probe = dryice_rtc_probe,
+	.remove = __exit_p(dryice_rtc_remove),
+};
+
+static int __init dryice_rtc_init(void)
+{
+	return platform_driver_register(&dryice_rtc_driver);
+}

drivers/rtc/rtc-imxdi.c line 557

Quoted 10 lines
drivers/rtc/rtc-imxdi.c new file +10 -0
+
+static void __exit dryice_rtc_exit(void)
+{
+	platform_driver_unregister(&dryice_rtc_driver);
+}
+
+module_init(dryice_rtc_init);
+module_exit(dryice_rtc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");

email here please or you will not be
notified of changes to the driver (not by me, at least ).

Quoted 10 lines
drivers/rtc/rtc-imxdi.c new file +2 -0
+MODULE_DESCRIPTION("IMXDI Realtime Clock Driver (RTC)");
+MODULE_LICENSE("GPL");
Signature · 7 lines
1.6.5

-- 
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
Signature · 6 lines
 Best regards,

 Alessandro Zummo,
  Tower Technologies - Torino, Italy

  http://www.towertech.it
#5 lore raw

PATCH 1/1 rtc: driver for the DryIce block found in i.MX25 chips

This driver is based on code from Freescale which accompanies their i.MX25 PDK board, with some cleanup.

---
 drivers/rtc/Kconfig     |   10 +
 drivers/rtc/Makefile    |    1 +
 drivers/rtc/rtc-imxdi.c |  532 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 543 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/rtc-imxdi.c

Changes v1 -> v2:

Address the comments of Alessandro Zummo:

* remove the .ioctl implementation
* implement .set_mmss instead of .set_time
* reorder the .probe implementation
* make sure not to have enabled interrupts when registering or unregistering the rtc device
* add MODULE_AUTHOR() with my email

Address the comment of Lothar Wa??mann:

* return PTR_ERR on clk_get failure

Slightly change MODULE_DESCRIPTION().
Use timeout which is independent of HZ for wait_event_interruptible_timeout().

drivers/rtc/Kconfig +10 -0
index 8167e9e..83bd602 100644
@@ -527,6 +527,16 @@ config RTC_DRV_MSM6242
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-msm6242.
 
+config RTC_DRV_IMXDI
+	tristate "Freescale IMX DryIce Real Time Clock"
+	depends on ARCH_MX25
+	depends on RTC_CLASS
+	help
+	   Support for Freescale IMX DryIce RTC
+
+	   This driver can also be built as a module, if so, the module
+	   will be called "rtc-imxdi".
+
 config RTC_MXC
 	tristate "Freescale MXC Real Time Clock"
 	depends on ARCH_MXC
drivers/rtc/Makefile +1 -0
index e5160fd..f2d3420 100644
@@ -44,6 +44,7 @@ obj-$(CONFIG_RTC_DRV_EFI)	+= rtc-efi.o
 obj-$(CONFIG_RTC_DRV_EP93XX)	+= rtc-ep93xx.o
 obj-$(CONFIG_RTC_DRV_FM3130)	+= rtc-fm3130.o
 obj-$(CONFIG_RTC_DRV_GENERIC)	+= rtc-generic.o
+obj-$(CONFIG_RTC_DRV_IMXDI)	+= rtc-imxdi.o
 obj-$(CONFIG_RTC_DRV_ISL1208)	+= rtc-isl1208.o
 obj-$(CONFIG_RTC_DRV_M41T80)	+= rtc-m41t80.o
 obj-$(CONFIG_RTC_DRV_M41T94)	+= rtc-m41t94.o
drivers/rtc/rtc-imxdi.c new file +532 -0

532 lines not on this page · raw message

Signature · 1 line
1.6.5
#6 lore raw

PATCH 1/1 rtc: driver for the DryIce block found in i.MX25 chips

Hi,

Just one nitpick, I didn't notice when replying to your first mail... Baruch Siach writes:
[...]

drivers/rtc/rtc-imxdi.c line 101

Quoted 6 lines
drivers/rtc/rtc-imxdi.c new file +6 -0
+static inline void di_int_enable(struct imxdi_dev *imxdi, u32 intr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&imxdi->irq_lock, flags);
+	__raw_writel(__raw_readl(imxdi->ioaddr+DIER) | intr,
                                              ^

Review

Quoted 1 line
(quoted diff) +1 -0
+			imxdi->ioaddr+DIER);
                                     ^
Quoted 1 line

Spaces around operators are welcome in the kernel.

Lothar Wa?mann

Signature · 9 lines
___________________________________________________________

Ka-Ro electronics GmbH | Pascalstra?e 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Gesch?ftsf?hrer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | info at karo-electronics.de
___________________________________________________________
#7 lore raw

PATCH 1/1 rtc: driver for the DryIce block found in i.MX25 chips

Hi Lothar,

Quoted 10 lines · Lothar Wa?mann

Just one nitpick, I didn't notice when replying to your first mail... Baruch Siach writes:
[...]

drivers/rtc/rtc-imxdi.c line 101

Quoted 6 lines
drivers/rtc/rtc-imxdi.c new file +6 -0
+static inline void di_int_enable(struct imxdi_dev *imxdi, u32 intr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&imxdi->irq_lock, flags);
+	__raw_writel(__raw_readl(imxdi->ioaddr+DIER) | intr,
                                            ^
Quoted 4 lines

Review

Quoted 1 line
(quoted diff) +1 -0
+			imxdi->ioaddr+DIER);
                           ^
Quoted 1 line

Spaces around operators are welcome in the kernel.

Thanks for your review.
Will fix in the next version.

baruch

Signature · 3 lines
                                                     ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
#8 lore raw

PATCH 1/1 rtc: driver for the DryIce block found in i.MX25 chips

In reply to Baruch Siach
Quoted 3 lines · On Mon, 1 Feb 2010 09:36:51 +0200 Baruch Siach <[email protected]> wrote:

Address the comments of Alessandro Zummo:

* remove the .ioctl implementation

you did not add the ops for alarm irq handling... ?

more below.

drivers/rtc/rtc-imxdi.c line 358

Quoted 4 lines
drivers/rtc/rtc-imxdi.c new file +4 -0
+static int dryice_rtc_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct imxdi_dev *imxdi = NULL;

= NULL is not necessary

Review

Quoted 1 line
(quoted diff) +1 -0
+	int rc = 0;

idem for = 0

drivers/rtc/rtc-imxdi.c line 369

Quoted 9 lines
drivers/rtc/rtc-imxdi.c new file +9 -0
+	imxdi = kzalloc(sizeof(*imxdi), GFP_KERNEL);
+	if (!imxdi)
+		return -ENOMEM;
+
+	imxdi->pdev = pdev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;

you forgot to release imxdi here. I still suggest to use devm.

Quoted 6 lines
drivers/rtc/rtc-imxdi.c new file +6 -0
+
+	if (!request_mem_region(res->start, resource_size(res),
+				pdev->name)) {
+		rc = -EBUSY;
+		goto err_free_mem;
+	}

drivers/rtc/rtc-imxdi.c line 385

Quoted 10 lines
drivers/rtc/rtc-imxdi.c new file +10 -0
+	imxdi->ioaddr = ioremap(res->start, resource_size(res));
+	if (imxdi->ioaddr == NULL) {
+		rc = -ENOMEM;
+		goto err_release_region;
+	}
+
+	if ((imxdi->irq = platform_get_irq(pdev, 0)) < 0) {
+		rc = imxdi->irq;
+		goto err;
+	}

no if inline with the assignment please, it's not readable.

Quoted 22 lines
drivers/rtc/rtc-imxdi.c new file +22 -0
+	init_waitqueue_head(&imxdi->write_wait);
+
+	INIT_WORK(&imxdi->work, dryice_work);
+
+	mutex_init(&imxdi->write_mutex);
+
+	imxdi->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(imxdi->clk)) {
+		rc = PTR_ERR(imxdi->clk);
+		goto err;
+	}
+	clk_enable(imxdi->clk);
+
+	/*
+	 * Initialize dryice hardware
+	 */
+
+	/* put dryice into valid state */
+	if (__raw_readl(imxdi->ioaddr+DSR) & DSR_NVF)
+		rc = di_write_wait(imxdi, DSR_NVF | DSR_SVF, DSR);
+	if (rc)
+		goto err;

drivers/rtc/rtc-imxdi.c line 418

Quoted 10 lines
drivers/rtc/rtc-imxdi.c new file +10 -0
+
+	/* mask all interrupts */
+	__raw_writel(0, imxdi->ioaddr+DIER);
+
+	if (request_irq(imxdi->irq, dryice_norm_irq, IRQF_SHARED,
+				pdev->name, imxdi) < 0) {
+		dev_warn(&pdev->dev, "interrupt not available.\n");
+		imxdi->irq = -1;
+		goto err;
+	}

ditto for the if. what's the value of rc here?

Quoted 15 lines
drivers/rtc/rtc-imxdi.c new file +15 -0
+	/* initialize alarm */
+	rc = di_write_wait(imxdi, DCAMR_UNSET, DCAMR);
+	if (rc == 0)
+		rc = di_write_wait(imxdi, 0, DCALR);
+	if (rc)
+		goto err;
+
+	/* clear alarm flag */
+	if (__raw_readl(imxdi->ioaddr+DSR) & DSR_CAF)
+		rc = di_write_wait(imxdi, DSR_CAF, DSR);
+	if (rc)
+		goto err;
+
+	/* the timer won't count if it has never been written to */
+	if (__raw_readl(imxdi->ioaddr+DTCMR) == 0)

drivers/rtc/rtc-imxdi.c line 444

Quoted 10 lines
drivers/rtc/rtc-imxdi.c new file +10 -0
+		rc = di_write_wait(imxdi, 0, DTCMR);
+	if (rc)
+		goto err;
+
+	/* start keeping time */
+	if (!(__raw_readl(imxdi->ioaddr+DCR) & DCR_TCE))
+		rc = di_write_wait(imxdi,
+				__raw_readl(imxdi->ioaddr+DCR) | DCR_TCE, DCR);
+	if (rc)
+		goto err;

spaces are welcomed around the +

Quoted 24 lines
drivers/rtc/rtc-imxdi.c new file +24 -0
+	imxdi->rtc = rtc_device_register(pdev->name, &pdev->dev,
+				  &dryice_rtc_ops, THIS_MODULE);
+	if (IS_ERR(imxdi->rtc)) {
+		rc = PTR_ERR(imxdi->rtc);
+		goto err;
+	}
+	platform_set_drvdata(pdev, imxdi);
+
+	return 0;
+err:
+	if (imxdi->rtc && !IS_ERR(imxdi->rtc))
+		rtc_device_unregister(imxdi->rtc);
+
+	if (imxdi->irq >= 0)
+		free_irq(imxdi->irq, imxdi);
+
+	if (imxdi->clk && !IS_ERR(imxdi->clk)) {
+		clk_disable(imxdi->clk);
+		clk_put(imxdi->clk);
+	}
+
+	if (imxdi->ioaddr)
+		iounmap(imxdi->ioaddr);
+

drivers/rtc/rtc-imxdi.c line 479

Quoted 10 lines
drivers/rtc/rtc-imxdi.c new file +10 -0
+err_release_region:
+	release_mem_region(res->start, resource_size(res));
+
+err_free_mem:
+	kfree(imxdi);
+
+	return rc;
+}
+
+static int __exit dryice_rtc_remove(struct platform_device *pdev)

no __devexit?

Quoted 24 lines
drivers/rtc/rtc-imxdi.c new file +24 -0
+{
+	struct imxdi_dev *imxdi = platform_get_drvdata(pdev);
+	struct resource *mem;
+
+	flush_scheduled_work();
+
+	/* mask alarm interrupt */
+	di_int_disable(imxdi, DIER_CAIE);
+
+	if (imxdi->irq >= 0)
+		free_irq(imxdi->irq, imxdi);
+
+	rtc_device_unregister(imxdi->rtc);
+
+	clk_disable(imxdi->clk);
+	clk_put(imxdi->clk);
+
+	iounmap(imxdi->ioaddr);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+
+	kfree(imxdi);
+

drivers/rtc/rtc-imxdi.c line 513

Quoted 10 lines
drivers/rtc/rtc-imxdi.c new file +10 -0
+	return 0;
+}
+
+static struct platform_driver dryice_rtc_driver = {
+	.driver = {
+		   .name = "imxdi_rtc",
+		   .owner = THIS_MODULE,
+		   },
+	.probe = dryice_rtc_probe,
+	.remove = __exit_p(dryice_rtc_remove),

__devexit_p ?

Quoted 22 lines
drivers/rtc/rtc-imxdi.c new file +19 -0
+};
+
+static int __init dryice_rtc_init(void)
+{
+	return platform_driver_register(&dryice_rtc_driver);
+}
+
+static void __exit dryice_rtc_exit(void)
+{
+	platform_driver_unregister(&dryice_rtc_driver);
+}
+
+module_init(dryice_rtc_init);
+module_exit(dryice_rtc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_AUTHOR("Baruch Siach <[email protected]>");
+MODULE_DESCRIPTION("IMX DryIce Realtime Clock Driver (RTC)");
+MODULE_LICENSE("GPL");
Signature · 1 line
1.6.5
Signature · 6 lines
 Best regards,

 Alessandro Zummo,
  Tower Technologies - Torino, Italy

  http://www.towertech.it
#9 lore raw

PATCH v3 1/1 rtc: driver for the DryIce block found in i.MX25 chips

This driver is based on code from Freescale which accompanies their i.MX25 PDK board, with some cleanup.

---
 drivers/rtc/Kconfig     |   10 +
 drivers/rtc/Makefile    |    1 +
 drivers/rtc/rtc-imxdi.c |  532 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 543 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/rtc-imxdi.c

Changes v2 -> v3:

Add spaces around the '+' operator as suggested by Alessandro Zummo and Lothar Wa??mann.

Address other comments of Alessandro Zummo:

* add implementation of the alarm_irq_enable rtc op
* use devres in .probe
* remove unneeded initializations

Changes v1 -> v2:

Address the comments of Alessandro Zummo:

* remove the .ioctl implementation
* implement .set_mmss instead of .set_time
* reorder the .probe implementation
* make sure not to have enabled interrupts when registering or unregistering the rtc device
* add MODULE_AUTHOR() with my email

Address the comment of Lothar Wa??mann:

* return PTR_ERR on clk_get failure

Slightly change MODULE_DESCRIPTION().
Use timeout which is independent of HZ for wait_event_interruptible_timeout().

drivers/rtc/Kconfig +10 -0
index 8167e9e..83bd602 100644
@@ -527,6 +527,16 @@ config RTC_DRV_MSM6242
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-msm6242.
 
+config RTC_DRV_IMXDI
+	tristate "Freescale IMX DryIce Real Time Clock"
+	depends on ARCH_MX25
+	depends on RTC_CLASS
+	help
+	   Support for Freescale IMX DryIce RTC
+
+	   This driver can also be built as a module, if so, the module
+	   will be called "rtc-imxdi".
+
 config RTC_MXC
 	tristate "Freescale MXC Real Time Clock"
 	depends on ARCH_MXC
drivers/rtc/Makefile +1 -0
index e5160fd..f2d3420 100644
@@ -44,6 +44,7 @@ obj-$(CONFIG_RTC_DRV_EFI)	+= rtc-efi.o
 obj-$(CONFIG_RTC_DRV_EP93XX)	+= rtc-ep93xx.o
 obj-$(CONFIG_RTC_DRV_FM3130)	+= rtc-fm3130.o
 obj-$(CONFIG_RTC_DRV_GENERIC)	+= rtc-generic.o
+obj-$(CONFIG_RTC_DRV_IMXDI)	+= rtc-imxdi.o
 obj-$(CONFIG_RTC_DRV_ISL1208)	+= rtc-isl1208.o
 obj-$(CONFIG_RTC_DRV_M41T80)	+= rtc-m41t80.o
 obj-$(CONFIG_RTC_DRV_M41T94)	+= rtc-m41t94.o
drivers/rtc/rtc-imxdi.c new file +532 -0

532 lines not on this page · raw message

Signature · 1 line
1.6.5
#10 lore raw

PATCH v3 1/1 rtc: driver for the DryIce block found in i.MX25 chips

Quoted 11 lines · On Tue, 2 Feb 2010 08:47:04 +0200 Baruch Siach <[email protected]> wrote:

Changes v2 -> v3:

Add spaces around the '+' operator as suggested by Alessandro Zummo and Lothar Wa?mann.

Address other comments of Alessandro Zummo:

* add implementation of the alarm_irq_enable rtc op
* use devres in .probe
* remove unneeded initializations

I believe you sent the old version ;)

Signature · 6 lines
 Best regards,

 Alessandro Zummo,
  Tower Technologies - Torino, Italy

  http://www.towertech.it
#11 lore raw

PATCH v3 1/1 rtc: driver for the DryIce block found in i.MX25 chips

Hi Alessandro,

Quoted 8 lines · Alessandro Zummo
Quoted 6 lines · On Tue, 2 Feb 2010 08:47:04 +0200 Baruch Siach <[email protected]> wrote:

Changes v2 -> v3:

Add spaces around the '+' operator as suggested by Alessandro Zummo and Lothar Wa?mann.

Quoted 7 lines
Quoted 5 lines

Address other comments of Alessandro Zummo:

* add implementation of the alarm_irq_enable rtc op
* use devres in .probe
* remove unneeded initializations

I believe you sent the old version ;)

Oops. Sending again.

baruch

Signature · 3 lines
                                                     ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
#12 lore raw

PATCH v3 1/1 rtc: driver for the DryIce block found in i.MX25 chips

In reply to Alessandro Zummo

This driver is based on code from Freescale which accompanies their i.MX25 PDK board, with some cleanup.

---
 drivers/rtc/Kconfig     |   10 +
 drivers/rtc/Makefile    |    1 +
 drivers/rtc/rtc-imxdi.c |  520 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 531 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/rtc-imxdi.c

Changes v2 -> v3:

Add spaces around the '+' operator as suggested by Alessandro Zummo and Lothar Wa??mann.

Address other comments of Alessandro Zummo:

* add implementation of the alarm_irq_enable rtc op
* use devres in .probe
* remove unneeded initializations

Changes v1 -> v2:

Address the comments of Alessandro Zummo:

* remove the .ioctl implementation
* implement .set_mmss instead of .set_time
* reorder the .probe implementation
* make sure not to have enabled interrupts when registering or unregistering the rtc device
* add MODULE_AUTHOR() with my email

Address the comment of Lothar Wa??mann:

* return PTR_ERR on clk_get failure

Slightly change MODULE_DESCRIPTION().
Use timeout which is independent of HZ for wait_event_interruptible_timeout().

drivers/rtc/Kconfig +10 -0
index 8167e9e..83bd602 100644
@@ -527,6 +527,16 @@ config RTC_DRV_MSM6242
 	  This driver can also be built as a module. If so, the module
 	  will be called rtc-msm6242.
 
+config RTC_DRV_IMXDI
+	tristate "Freescale IMX DryIce Real Time Clock"
+	depends on ARCH_MX25
+	depends on RTC_CLASS
+	help
+	   Support for Freescale IMX DryIce RTC
+
+	   This driver can also be built as a module, if so, the module
+	   will be called "rtc-imxdi".
+
 config RTC_MXC
 	tristate "Freescale MXC Real Time Clock"
 	depends on ARCH_MXC
drivers/rtc/Makefile +1 -0
index e5160fd..f2d3420 100644
@@ -44,6 +44,7 @@ obj-$(CONFIG_RTC_DRV_EFI)	+= rtc-efi.o
 obj-$(CONFIG_RTC_DRV_EP93XX)	+= rtc-ep93xx.o
 obj-$(CONFIG_RTC_DRV_FM3130)	+= rtc-fm3130.o
 obj-$(CONFIG_RTC_DRV_GENERIC)	+= rtc-generic.o
+obj-$(CONFIG_RTC_DRV_IMXDI)	+= rtc-imxdi.o
 obj-$(CONFIG_RTC_DRV_ISL1208)	+= rtc-isl1208.o
 obj-$(CONFIG_RTC_DRV_M41T80)	+= rtc-m41t80.o
 obj-$(CONFIG_RTC_DRV_M41T94)	+= rtc-m41t94.o
drivers/rtc/rtc-imxdi.c new file +520 -0

520 lines not on this page · raw message

Signature · 1 line
1.6.5
#13 lore raw

PATCH v3 1/1 rtc: driver for the DryIce block found in i.MX25 chips

Hi Alessandro,

Quoted 10 lines · Baruch Siach

This driver is based on code from Freescale which accompanies their i.MX25 PDK board, with some cleanup.

---
 drivers/rtc/Kconfig     |   10 +
 drivers/rtc/Makefile    |    1 +
 drivers/rtc/rtc-imxdi.c |  520 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 531 insertions(+), 0 deletions(-)
 create mode 100644 drivers/rtc/rtc-imxdi.c

Ping?

Since .34-rc1 has already been released, I guess this is not going to get into 2.6.34. Are there any remaining issues to resolve in order to merge this upstream?

baruch

Signature · 3 lines
                                                     ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
#14 lore raw

[rtc-linux] Re: [PATCH v3] rtc: driver for the DryIce block found in i.MX25 chips

Quoted 5 lines · On Tue, 9 Mar 2010 09:41:14 +0200 Baruch Siach <[email protected]> wrote:

Ping?

Since .34-rc1 has already been released, I guess this is not going to get into 2.6.34. Are there any remaining issues to resolve in order to merge this upstream?

I just have to find some time to review it. don't worry, since is a completely new driver it could go upstream at any time.

Signature · 6 lines
 Best regards,

 Alessandro Zummo,
  Tower Technologies - Torino, Italy

  http://www.towertech.it
#15 lore raw

[rtc-linux] Re: [PATCH v3] rtc: driver for the DryIce block found in i.MX25 chips

Hi Alessandro,

Quoted 9 lines · Alessandro Zummo
Quoted 5 lines · On Tue, 9 Mar 2010 09:41:14 +0200 Baruch Siach <[email protected]> wrote:

Ping?

Since .34-rc1 has already been released, I guess this is not going to get into 2.6.34. Are there any remaining issues to resolve in order to merge this upstream?

I just have to find some time to review it. don't worry, since is a completely new driver it could go upstream at any time.

Thanks. Please note another patch against this one fixing an irq related bug:

http://groups.google.com/group/rtc-linux/browse_thread/thread/2847baa17905dfc3#

baruch

Signature · 3 lines
                                                     ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
#16 lore raw

[rtc-linux] Re: [PATCH v3] rtc: driver for the DryIce block found in i.MX25 chips

In reply to Alessandro Zummo

Hi Alessandro,

Quoted 10 lines · Alessandro Zummo
Quoted 5 lines · On Tue, 9 Mar 2010 09:41:14 +0200 Baruch Siach <[email protected]> wrote:

Ping?

Since .34-rc1 has already been released, I guess this is not going to get into 2.6.34. Are there any remaining issues to resolve in order to merge this upstream?

I just have to find some time to review it. don't worry, since is a completely new driver it could go upstream at any time.

Any news about this driver?

baruch

Signature · 3 lines
                                                     ~. .~   Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
   - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -