* [PATCHv2 0/6] add devicetree bindings for rtc-m48t86
@ 2013-04-01 23:22 Alexander Clouter
2013-04-01 23:22 ` [PATCH 1/6] rtc: rtc-m48t86: move m48t86.h to platform_data Alexander Clouter
` (5 more replies)
0 siblings, 6 replies; 14+ messages in thread
From: Alexander Clouter @ 2013-04-01 23:22 UTC (permalink / raw)
To: linux-arm-kernel
Currently there are two users of rtc-m48t86 (mach-ep93xx/ts72xx.c and
mach-orion5x/ts78xx-setup.c) and both just use {read,write}b against
a memory mapped region. As I am devicetree'ing the TS-7800, this
driver needs converting and thats what this patchset does.
The patch does the following:
* moves m48t86.h to include/linux/platform_data/rtc-m48t86.h
* adds a new additional interface to rtc-m48t86 via named
resources that move the ioremap and {read,write}byte
functionality into the driver (usable by ts7[28]xx)
* moves the RTC detection routine from ts78xx-setup.c into rtc-m48t86.c
* converts both ts7[28]xx to use the new interface
* enable devicetree hooks and include documentation
Alexander Clouter (6):
rtc: rtc-m48t86: move m48t86.h to platform_data
rtc: rtc-m48t86: add hooks to support driver side memory mapping
rtc: rtc-m48t86: add detect method for RTC
arm: orion5x: move ts78xx to use rtc-m48t86 driver side memory
interface
arm: ep93xx: move ts72xx to use rtc-m48t86 driver side memory
interface
rtc: rtc-m48t86: add devicetree bindings
.../devicetree/bindings/rtc/rtc-m48t86.txt | 17 ++
arch/arm/mach-ep93xx/ts72xx.c | 38 +--
arch/arm/mach-orion5x/ts78xx-setup.c | 78 ++----
drivers/rtc/rtc-m48t86.c | 285 ++++++++++++++++----
.../linux/{m48t86.h => platform_data/rtc-m48t86.h} | 0
5 files changed, 267 insertions(+), 151 deletions(-)
create mode 100644 Documentation/devicetree/bindings/rtc/rtc-m48t86.txt
rename include/linux/{m48t86.h => platform_data/rtc-m48t86.h} (100%)
--
1.7.10.4
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/6] rtc: rtc-m48t86: move m48t86.h to platform_data
2013-04-01 23:22 [PATCHv2 0/6] add devicetree bindings for rtc-m48t86 Alexander Clouter
@ 2013-04-01 23:22 ` Alexander Clouter
2013-04-01 23:22 ` [PATCH 2/6] rtc: rtc-m48t86: add hooks to support driver side memory mapping Alexander Clouter
` (4 subsequent siblings)
5 siblings, 0 replies; 14+ messages in thread
From: Alexander Clouter @ 2013-04-01 23:22 UTC (permalink / raw)
To: linux-arm-kernel
The header for the rtc-m48t86 platform-data should be in
include/linux/platform_data.
Signed-off-by: Alexander Clouter <alex@digriz.org.uk>
---
arch/arm/mach-ep93xx/ts72xx.c | 2 +-
arch/arm/mach-orion5x/ts78xx-setup.c | 2 +-
drivers/rtc/rtc-m48t86.c | 2 +-
include/linux/{m48t86.h => platform_data/rtc-m48t86.h} | 0
4 files changed, 3 insertions(+), 3 deletions(-)
rename include/linux/{m48t86.h => platform_data/rtc-m48t86.h} (100%)
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 61f4b5d..a278639 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -16,7 +16,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
-#include <linux/m48t86.h>
+#include <linux/platform_data/rtc-m48t86.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c
index e960855..ffe3603 100644
--- a/arch/arm/mach-orion5x/ts78xx-setup.c
+++ b/arch/arm/mach-orion5x/ts78xx-setup.c
@@ -16,7 +16,7 @@
#include <linux/platform_device.h>
#include <linux/mv643xx_eth.h>
#include <linux/ata_platform.h>
-#include <linux/m48t86.h>
+#include <linux/platform_data/rtc-m48t86.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/timeriomem-rng.h>
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
index 2ffbcac..25e0116 100644
--- a/drivers/rtc/rtc-m48t86.c
+++ b/drivers/rtc/rtc-m48t86.c
@@ -16,7 +16,7 @@
#include <linux/module.h>
#include <linux/rtc.h>
#include <linux/platform_device.h>
-#include <linux/m48t86.h>
+#include <linux/platform_data/rtc-m48t86.h>
#include <linux/bcd.h>
#define M48T86_REG_SEC 0x00
diff --git a/include/linux/m48t86.h b/include/linux/platform_data/rtc-m48t86.h
similarity index 100%
rename from include/linux/m48t86.h
rename to include/linux/platform_data/rtc-m48t86.h
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/6] rtc: rtc-m48t86: add hooks to support driver side memory mapping
2013-04-01 23:22 [PATCHv2 0/6] add devicetree bindings for rtc-m48t86 Alexander Clouter
2013-04-01 23:22 ` [PATCH 1/6] rtc: rtc-m48t86: move m48t86.h to platform_data Alexander Clouter
@ 2013-04-01 23:22 ` Alexander Clouter
2013-04-01 23:36 ` Ryan Mallon
` (3 more replies)
2013-04-01 23:22 ` [PATCH 3/6] rtc: rtc-m48t86: add detect method for RTC Alexander Clouter
` (3 subsequent siblings)
5 siblings, 4 replies; 14+ messages in thread
From: Alexander Clouter @ 2013-04-01 23:22 UTC (permalink / raw)
To: linux-arm-kernel
If platform_data is not defined (as before), then named memory io
ranges need to be defined ("rtc_index" and "rtc_data"). The driver
then maps those regions and uses them as the RTC index and data
addresses.
Does compile with the following warnings, I cannot see the codepath
affected myself:
----
drivers/rtc/rtc-m48t86.c: In function ?m48t86_rtc_probe?:
drivers/rtc/rtc-m48t86.c:180: warning: ?res_index? may be used uninitialized in this function
drivers/rtc/rtc-m48t86.c:180: warning: ?res_data? may be used uninitialized in this function
----
Signed-off-by: Alexander Clouter <alex@digriz.org.uk>
---
drivers/rtc/rtc-m48t86.c | 230 ++++++++++++++++++++++++++++++++++------------
1 file changed, 173 insertions(+), 57 deletions(-)
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
index 25e0116..6f99e64 100644
--- a/drivers/rtc/rtc-m48t86.c
+++ b/drivers/rtc/rtc-m48t86.c
@@ -18,6 +18,8 @@
#include <linux/platform_device.h>
#include <linux/platform_data/rtc-m48t86.h>
#include <linux/bcd.h>
+#include <linux/slab.h>
+#include <linux/io.h>
#define M48T86_REG_SEC 0x00
#define M48T86_REG_SECALRM 0x01
@@ -41,40 +43,71 @@
#define DRV_VERSION "0.1"
+struct m48t86_rtc_private_data {
+ void __iomem *io_index;
+ void __iomem *io_data;
+
+ struct rtc_device *rtc;
+ struct m48t86_ops *ops;
+};
+
+static void m48t86_rtc_writebyte(struct device *dev,
+ unsigned char value, unsigned long addr)
+{
+ struct m48t86_rtc_private_data *priv = dev_get_drvdata(dev);
+
+ if (priv->ops) {
+ priv->ops->writebyte(value, addr);
+ return;
+ }
+
+ writeb(addr, priv->io_index);
+ writeb(value, priv->io_data);
+}
+
+static unsigned char m48t86_rtc_readbyte(struct device *dev,
+ unsigned long addr)
+{
+ struct m48t86_rtc_private_data *priv = dev_get_drvdata(dev);
+
+ if (priv->ops)
+ return priv->ops->readbyte(addr);
+
+ writeb(addr, priv->io_index);
+ return readb(priv->io_data);
+}
static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
unsigned char reg;
- struct platform_device *pdev = to_platform_device(dev);
- struct m48t86_ops *ops = pdev->dev.platform_data;
- reg = ops->readbyte(M48T86_REG_B);
+ reg = m48t86_rtc_readbyte(dev, M48T86_REG_B);
if (reg & M48T86_REG_B_DM) {
/* data (binary) mode */
- tm->tm_sec = ops->readbyte(M48T86_REG_SEC);
- tm->tm_min = ops->readbyte(M48T86_REG_MIN);
- tm->tm_hour = ops->readbyte(M48T86_REG_HOUR) & 0x3F;
- tm->tm_mday = ops->readbyte(M48T86_REG_DOM);
+ tm->tm_sec = m48t86_rtc_readbyte(dev, M48T86_REG_SEC);
+ tm->tm_min = m48t86_rtc_readbyte(dev, M48T86_REG_MIN);
+ tm->tm_hour = m48t86_rtc_readbyte(dev, M48T86_REG_HOUR) & 0x3F;
+ tm->tm_mday = m48t86_rtc_readbyte(dev, M48T86_REG_DOM);
/* tm_mon is 0-11 */
- tm->tm_mon = ops->readbyte(M48T86_REG_MONTH) - 1;
- tm->tm_year = ops->readbyte(M48T86_REG_YEAR) + 100;
- tm->tm_wday = ops->readbyte(M48T86_REG_DOW);
+ tm->tm_mon = m48t86_rtc_readbyte(dev, M48T86_REG_MONTH) - 1;
+ tm->tm_year = m48t86_rtc_readbyte(dev, M48T86_REG_YEAR) + 100;
+ tm->tm_wday = m48t86_rtc_readbyte(dev, M48T86_REG_DOW);
} else {
/* bcd mode */
- tm->tm_sec = bcd2bin(ops->readbyte(M48T86_REG_SEC));
- tm->tm_min = bcd2bin(ops->readbyte(M48T86_REG_MIN));
- tm->tm_hour = bcd2bin(ops->readbyte(M48T86_REG_HOUR) & 0x3F);
- tm->tm_mday = bcd2bin(ops->readbyte(M48T86_REG_DOM));
+ tm->tm_sec = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_SEC));
+ tm->tm_min = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_MIN));
+ tm->tm_hour = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_HOUR) & 0x3F);
+ tm->tm_mday = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_DOM));
/* tm_mon is 0-11 */
- tm->tm_mon = bcd2bin(ops->readbyte(M48T86_REG_MONTH)) - 1;
- tm->tm_year = bcd2bin(ops->readbyte(M48T86_REG_YEAR)) + 100;
- tm->tm_wday = bcd2bin(ops->readbyte(M48T86_REG_DOW));
+ tm->tm_mon = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_MONTH)) - 1;
+ tm->tm_year = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_YEAR)) + 100;
+ tm->tm_wday = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_DOW));
}
/* correct the hour if the clock is in 12h mode */
if (!(reg & M48T86_REG_B_H24))
- if (ops->readbyte(M48T86_REG_HOUR) & 0x80)
+ if (m48t86_rtc_readbyte(dev, M48T86_REG_HOUR) & 0x80)
tm->tm_hour += 12;
return rtc_valid_tm(tm);
@@ -83,38 +116,36 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
unsigned char reg;
- struct platform_device *pdev = to_platform_device(dev);
- struct m48t86_ops *ops = pdev->dev.platform_data;
- reg = ops->readbyte(M48T86_REG_B);
+ reg = m48t86_rtc_readbyte(dev, M48T86_REG_B);
/* update flag and 24h mode */
reg |= M48T86_REG_B_SET | M48T86_REG_B_H24;
- ops->writebyte(reg, M48T86_REG_B);
+ m48t86_rtc_writebyte(dev, reg, M48T86_REG_B);
if (reg & M48T86_REG_B_DM) {
/* data (binary) mode */
- ops->writebyte(tm->tm_sec, M48T86_REG_SEC);
- ops->writebyte(tm->tm_min, M48T86_REG_MIN);
- ops->writebyte(tm->tm_hour, M48T86_REG_HOUR);
- ops->writebyte(tm->tm_mday, M48T86_REG_DOM);
- ops->writebyte(tm->tm_mon + 1, M48T86_REG_MONTH);
- ops->writebyte(tm->tm_year % 100, M48T86_REG_YEAR);
- ops->writebyte(tm->tm_wday, M48T86_REG_DOW);
+ m48t86_rtc_writebyte(dev, tm->tm_sec, M48T86_REG_SEC);
+ m48t86_rtc_writebyte(dev, tm->tm_min, M48T86_REG_MIN);
+ m48t86_rtc_writebyte(dev, tm->tm_hour, M48T86_REG_HOUR);
+ m48t86_rtc_writebyte(dev, tm->tm_mday, M48T86_REG_DOM);
+ m48t86_rtc_writebyte(dev, tm->tm_mon + 1, M48T86_REG_MONTH);
+ m48t86_rtc_writebyte(dev, tm->tm_year % 100, M48T86_REG_YEAR);
+ m48t86_rtc_writebyte(dev, tm->tm_wday, M48T86_REG_DOW);
} else {
/* bcd mode */
- ops->writebyte(bin2bcd(tm->tm_sec), M48T86_REG_SEC);
- ops->writebyte(bin2bcd(tm->tm_min), M48T86_REG_MIN);
- ops->writebyte(bin2bcd(tm->tm_hour), M48T86_REG_HOUR);
- ops->writebyte(bin2bcd(tm->tm_mday), M48T86_REG_DOM);
- ops->writebyte(bin2bcd(tm->tm_mon + 1), M48T86_REG_MONTH);
- ops->writebyte(bin2bcd(tm->tm_year % 100), M48T86_REG_YEAR);
- ops->writebyte(bin2bcd(tm->tm_wday), M48T86_REG_DOW);
+ m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_sec), M48T86_REG_SEC);
+ m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_min), M48T86_REG_MIN);
+ m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_hour), M48T86_REG_HOUR);
+ m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_mday), M48T86_REG_DOM);
+ m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_mon + 1), M48T86_REG_MONTH);
+ m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_year % 100), M48T86_REG_YEAR);
+ m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_wday), M48T86_REG_DOW);
}
/* update ended */
reg &= ~M48T86_REG_B_SET;
- ops->writebyte(reg, M48T86_REG_B);
+ m48t86_rtc_writebyte(dev, reg, M48T86_REG_B);
return 0;
}
@@ -122,15 +153,13 @@ static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq)
{
unsigned char reg;
- struct platform_device *pdev = to_platform_device(dev);
- struct m48t86_ops *ops = pdev->dev.platform_data;
- reg = ops->readbyte(M48T86_REG_B);
+ reg = m48t86_rtc_readbyte(dev, M48T86_REG_B);
seq_printf(seq, "mode\t\t: %s\n",
(reg & M48T86_REG_B_DM) ? "binary" : "bcd");
- reg = ops->readbyte(M48T86_REG_D);
+ reg = m48t86_rtc_readbyte(dev, M48T86_REG_D);
seq_printf(seq, "battery\t\t: %s\n",
(reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
@@ -144,34 +173,121 @@ static const struct rtc_class_ops m48t86_rtc_ops = {
.proc = m48t86_rtc_proc,
};
-static int m48t86_rtc_probe(struct platform_device *dev)
+static int m48t86_rtc_probe(struct platform_device *pdev)
{
unsigned char reg;
- struct m48t86_ops *ops = dev->dev.platform_data;
- struct rtc_device *rtc = rtc_device_register("m48t86",
- &dev->dev, &m48t86_rtc_ops, THIS_MODULE);
-
- if (IS_ERR(rtc))
- return PTR_ERR(rtc);
-
- platform_set_drvdata(dev, rtc);
+ int err;
+ struct resource *res_index, *res_data;
+ struct m48t86_rtc_private_data *priv;
+
+ /* Allocate memory for the device structure (and zero it) */
+ priv = kzalloc(sizeof(struct m48t86_rtc_private_data), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, priv);
+
+ if (!pdev->dev.platform_data) {
+ res_index = platform_get_resource_byname(
+ pdev, IORESOURCE_MEM, "rtc_index");
+ if (!res_index) {
+ err = -ENXIO;
+ goto out_free;
+ }
+
+ res_data = platform_get_resource_byname(
+ pdev, IORESOURCE_MEM, "rtc_data");
+ if (!res_data) {
+ err = -ENXIO;
+ goto out_free;
+ }
+
+ if (!request_mem_region(res_index->start,
+ resource_size(res_index),
+ dev_name(&pdev->dev))) {
+ err = -EBUSY;
+ goto out_free;
+ }
+
+ if (!request_mem_region(res_data->start,
+ resource_size(res_data),
+ dev_name(&pdev->dev))) {
+ err = -EBUSY;
+ goto out_release_index;
+ }
+
+ priv->io_index = ioremap(res_index->start,
+ resource_size(res_index));
+ if (!priv->io_index) {
+ err = -EIO;
+ goto out_release_data;
+ }
+
+ priv->io_data = ioremap(res_data->start,
+ resource_size(res_data));
+ if (!priv->io_data) {
+ err = -EIO;
+ goto out_io_index;
+ }
+ } else
+ priv->ops = pdev->dev.platform_data;
+
+ priv->rtc = rtc_device_register("m48t86",
+ &pdev->dev, &m48t86_rtc_ops, THIS_MODULE);
+ if (IS_ERR(priv->rtc)) {
+ err = PTR_ERR(priv->rtc);
+ if (!pdev->dev.platform_data)
+ goto out_io_data;
+ else
+ goto out_free;
+ }
/* read battery status */
- reg = ops->readbyte(M48T86_REG_D);
- dev_info(&dev->dev, "battery %s\n",
+ reg = m48t86_rtc_readbyte(&pdev->dev, M48T86_REG_D);
+ dev_info(&pdev->dev, "battery %s\n",
(reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
return 0;
+
+out_io_data:
+ iounmap(priv->io_data);
+out_io_index:
+ iounmap(priv->io_index);
+out_release_data:
+ release_mem_region(res_data->start, resource_size(res_data));
+out_release_index:
+ release_mem_region(res_index->start, resource_size(res_index));
+out_free:
+ platform_set_drvdata(pdev, NULL);
+ kfree(priv);
+ return err;
}
-static int m48t86_rtc_remove(struct platform_device *dev)
+static int m48t86_rtc_remove(struct platform_device *pdev)
{
- struct rtc_device *rtc = platform_get_drvdata(dev);
+ struct resource *res;
+ struct m48t86_rtc_private_data *priv = platform_get_drvdata(pdev);
+
+ if (priv->rtc)
+ rtc_device_unregister(priv->rtc);
+
+ if (priv->io_data) {
+ iounmap(priv->io_data);
+ res = platform_get_resource_byname(
+ pdev, IORESOURCE_MEM, "rtc_data");
+ release_mem_region(res->start, resource_size(res));
+ }
+
+ if (priv->io_index) {
+ iounmap(priv->io_index);
+ res = platform_get_resource_byname(
+ pdev, IORESOURCE_MEM, "rtc_index");
+ release_mem_region(res->start, resource_size(res));
+ }
- if (rtc)
- rtc_device_unregister(rtc);
+ platform_set_drvdata(pdev, NULL);
- platform_set_drvdata(dev, NULL);
+ kfree(priv);
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 3/6] rtc: rtc-m48t86: add detect method for RTC
2013-04-01 23:22 [PATCHv2 0/6] add devicetree bindings for rtc-m48t86 Alexander Clouter
2013-04-01 23:22 ` [PATCH 1/6] rtc: rtc-m48t86: move m48t86.h to platform_data Alexander Clouter
2013-04-01 23:22 ` [PATCH 2/6] rtc: rtc-m48t86: add hooks to support driver side memory mapping Alexander Clouter
@ 2013-04-01 23:22 ` Alexander Clouter
2013-04-01 23:22 ` [PATCH 4/6] arm: orion5x: move ts78xx to use rtc-m48t86 driver side memory interface Alexander Clouter
` (2 subsequent siblings)
5 siblings, 0 replies; 14+ messages in thread
From: Alexander Clouter @ 2013-04-01 23:22 UTC (permalink / raw)
To: linux-arm-kernel
The m48t86 has 114 bytes of user space available, so we can use this
space to detect for the presence of the RTC.
Signed-off-by: Alexander Clouter <alex@digriz.org.uk>
---
drivers/rtc/rtc-m48t86.c | 43 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
index 6f99e64..b8edf73 100644
--- a/drivers/rtc/rtc-m48t86.c
+++ b/drivers/rtc/rtc-m48t86.c
@@ -173,6 +173,41 @@ static const struct rtc_class_ops m48t86_rtc_ops = {
.proc = m48t86_rtc_proc,
};
+/*
+ * The RTC chip has 114 bytes upper bytes that can be used as user storage
+ * space which we can use to test if the chip is present; for example it is
+ * an optional feature and not all boards will have it present.
+ *
+ * I've used the method Technologic Systems use in their rtc7800.c example
+ * for the detection.
+ *
+ * TODO: track down a guinea pig without an RTC to see if we can work out a
+ * better RTC detection routine
+ */
+static int m48t86_rtc_detect(struct device *dev)
+{
+ unsigned char tmp_rtc0, tmp_rtc1;
+
+ tmp_rtc0 = m48t86_rtc_readbyte(dev, 126);
+ tmp_rtc1 = m48t86_rtc_readbyte(dev, 127);
+
+ m48t86_rtc_writebyte(dev, 0x00, 126);
+ m48t86_rtc_writebyte(dev, 0x55, 127);
+ if (m48t86_rtc_readbyte(dev, 127) == 0x55) {
+ m48t86_rtc_writebyte(dev, 0xaa, 127);
+ if (m48t86_rtc_readbyte(dev, 127) == 0xaa
+ && m48t86_rtc_readbyte(dev, 126) == 0x00) {
+ m48t86_rtc_writebyte(dev, tmp_rtc0, 126);
+ m48t86_rtc_writebyte(dev, tmp_rtc1, 127);
+
+ return 0;
+ }
+ }
+
+ dev_info(dev, "RTC not found\n");
+ return -ENODEV;
+}
+
static int m48t86_rtc_probe(struct platform_device *pdev)
{
unsigned char reg;
@@ -232,6 +267,14 @@ static int m48t86_rtc_probe(struct platform_device *pdev)
} else
priv->ops = pdev->dev.platform_data;
+ err = m48t86_rtc_detect(&pdev->dev);
+ if (err) {
+ if (!pdev->dev.platform_data)
+ goto out_io_data;
+ else
+ goto out_free;
+ }
+
priv->rtc = rtc_device_register("m48t86",
&pdev->dev, &m48t86_rtc_ops, THIS_MODULE);
if (IS_ERR(priv->rtc)) {
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 4/6] arm: orion5x: move ts78xx to use rtc-m48t86 driver side memory interface
2013-04-01 23:22 [PATCHv2 0/6] add devicetree bindings for rtc-m48t86 Alexander Clouter
` (2 preceding siblings ...)
2013-04-01 23:22 ` [PATCH 3/6] rtc: rtc-m48t86: add detect method for RTC Alexander Clouter
@ 2013-04-01 23:22 ` Alexander Clouter
2013-04-02 11:50 ` Jason Cooper
2013-04-01 23:22 ` [PATCH 5/6] arm: ep93xx: move ts72xx " Alexander Clouter
2013-04-01 23:22 ` [PATCH 6/6] rtc: rtc-m48t86: add devicetree bindings Alexander Clouter
5 siblings, 1 reply; 14+ messages in thread
From: Alexander Clouter @ 2013-04-01 23:22 UTC (permalink / raw)
To: linux-arm-kernel
Remove platform_data hooks into rtc-m48t86 and use named resource regions.
Signed-off-by: Alexander Clouter <alex@digriz.org.uk>
---
arch/arm/mach-orion5x/ts78xx-setup.c | 78 ++++++++--------------------------
1 file changed, 17 insertions(+), 61 deletions(-)
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c
index ffe3603..613216f 100644
--- a/arch/arm/mach-orion5x/ts78xx-setup.c
+++ b/arch/arm/mach-orion5x/ts78xx-setup.c
@@ -16,7 +16,6 @@
#include <linux/platform_device.h>
#include <linux/mv643xx_eth.h>
#include <linux/ata_platform.h>
-#include <linux/platform_data/rtc-m48t86.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/timeriomem-rng.h>
@@ -80,78 +79,35 @@ static struct mv_sata_platform_data ts78xx_sata_data = {
/*****************************************************************************
* RTC M48T86 - nicked^Wborrowed from arch/arm/mach-ep93xx/ts72xx.c
****************************************************************************/
-#define TS_RTC_CTRL (TS78XX_FPGA_REGS_VIRT_BASE + 0x808)
-#define TS_RTC_DATA (TS78XX_FPGA_REGS_VIRT_BASE + 0x80c)
+#define TS_RTC_INDEX (TS78XX_FPGA_REGS_PHYS_BASE + 0x808)
+#define TS_RTC_DATA (TS78XX_FPGA_REGS_PHYS_BASE + 0x80c)
-static unsigned char ts78xx_ts_rtc_readbyte(unsigned long addr)
-{
- writeb(addr, TS_RTC_CTRL);
- return readb(TS_RTC_DATA);
-}
-
-static void ts78xx_ts_rtc_writebyte(unsigned char value, unsigned long addr)
-{
- writeb(addr, TS_RTC_CTRL);
- writeb(value, TS_RTC_DATA);
-}
-
-static struct m48t86_ops ts78xx_ts_rtc_ops = {
- .readbyte = ts78xx_ts_rtc_readbyte,
- .writebyte = ts78xx_ts_rtc_writebyte,
+static struct resource ts78xx_ts_rtc_resource[] = {
+ DEFINE_RES_NAMED(TS_RTC_INDEX, 4, "rtc_index", IORESOURCE_MEM),
+ DEFINE_RES_NAMED(TS_RTC_DATA, 4, "rtc_data", IORESOURCE_MEM),
};
static struct platform_device ts78xx_ts_rtc_device = {
.name = "rtc-m48t86",
.id = -1,
- .dev = {
- .platform_data = &ts78xx_ts_rtc_ops,
- },
- .num_resources = 0,
+ .resource = ts78xx_ts_rtc_resource,
+ .num_resources = ARRAY_SIZE(ts78xx_ts_rtc_resource),
};
-/*
- * TS uses some of the user storage space on the RTC chip so see if it is
- * present; as it's an optional feature at purchase time and not all boards
- * will have it present
- *
- * I've used the method TS use in their rtc7800.c example for the detection
- *
- * TODO: track down a guinea pig without an RTC to see if we can work out a
- * better RTC detection routine
- */
static int ts78xx_ts_rtc_load(void)
{
int rc;
- unsigned char tmp_rtc0, tmp_rtc1;
-
- tmp_rtc0 = ts78xx_ts_rtc_readbyte(126);
- tmp_rtc1 = ts78xx_ts_rtc_readbyte(127);
-
- ts78xx_ts_rtc_writebyte(0x00, 126);
- ts78xx_ts_rtc_writebyte(0x55, 127);
- if (ts78xx_ts_rtc_readbyte(127) == 0x55) {
- ts78xx_ts_rtc_writebyte(0xaa, 127);
- if (ts78xx_ts_rtc_readbyte(127) == 0xaa
- && ts78xx_ts_rtc_readbyte(126) == 0x00) {
- ts78xx_ts_rtc_writebyte(tmp_rtc0, 126);
- ts78xx_ts_rtc_writebyte(tmp_rtc1, 127);
-
- if (ts78xx_fpga.supports.ts_rtc.init == 0) {
- rc = platform_device_register(&ts78xx_ts_rtc_device);
- if (!rc)
- ts78xx_fpga.supports.ts_rtc.init = 1;
- } else
- rc = platform_device_add(&ts78xx_ts_rtc_device);
-
- if (rc)
- pr_info("RTC could not be registered: %d\n",
- rc);
- return rc;
- }
- }
- pr_info("RTC not found\n");
- return -ENODEV;
+ if (ts78xx_fpga.supports.ts_rtc.init == 0) {
+ rc = platform_device_register(&ts78xx_ts_rtc_device);
+ if (!rc)
+ ts78xx_fpga.supports.ts_rtc.init = 1;
+ } else
+ rc = platform_device_add(&ts78xx_ts_rtc_device);
+
+ if (rc)
+ pr_info("RTC could not be registered: %d\n", rc);
+ return rc;
};
static void ts78xx_ts_rtc_unload(void)
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 5/6] arm: ep93xx: move ts72xx to use rtc-m48t86 driver side memory interface
2013-04-01 23:22 [PATCHv2 0/6] add devicetree bindings for rtc-m48t86 Alexander Clouter
` (3 preceding siblings ...)
2013-04-01 23:22 ` [PATCH 4/6] arm: orion5x: move ts78xx to use rtc-m48t86 driver side memory interface Alexander Clouter
@ 2013-04-01 23:22 ` Alexander Clouter
2013-04-01 23:22 ` [PATCH 6/6] rtc: rtc-m48t86: add devicetree bindings Alexander Clouter
5 siblings, 0 replies; 14+ messages in thread
From: Alexander Clouter @ 2013-04-01 23:22 UTC (permalink / raw)
To: linux-arm-kernel
Remove platform_data hooks into rtc-m48t86 and use named resource regions.
Signed-off-by: Alexander Clouter <alex@digriz.org.uk>
---
arch/arm/mach-ep93xx/ts72xx.c | 38 +++++++-------------------------------
1 file changed, 7 insertions(+), 31 deletions(-)
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index a278639..baadffd 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -16,7 +16,6 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
-#include <linux/platform_data/rtc-m48t86.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
@@ -45,16 +44,6 @@ static struct map_desc ts72xx_io_desc[] __initdata = {
.pfn = __phys_to_pfn(TS72XX_OPTIONS2_PHYS_BASE),
.length = TS72XX_OPTIONS2_SIZE,
.type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)TS72XX_RTC_INDEX_VIRT_BASE,
- .pfn = __phys_to_pfn(TS72XX_RTC_INDEX_PHYS_BASE),
- .length = TS72XX_RTC_INDEX_SIZE,
- .type = MT_DEVICE,
- }, {
- .virtual = (unsigned long)TS72XX_RTC_DATA_VIRT_BASE,
- .pfn = __phys_to_pfn(TS72XX_RTC_DATA_PHYS_BASE),
- .length = TS72XX_RTC_DATA_SIZE,
- .type = MT_DEVICE,
}
};
@@ -179,31 +168,18 @@ static void __init ts72xx_register_flash(void)
}
}
-
-static unsigned char ts72xx_rtc_readbyte(unsigned long addr)
-{
- __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
- return __raw_readb(TS72XX_RTC_DATA_VIRT_BASE);
-}
-
-static void ts72xx_rtc_writebyte(unsigned char value, unsigned long addr)
-{
- __raw_writeb(addr, TS72XX_RTC_INDEX_VIRT_BASE);
- __raw_writeb(value, TS72XX_RTC_DATA_VIRT_BASE);
-}
-
-static struct m48t86_ops ts72xx_rtc_ops = {
- .readbyte = ts72xx_rtc_readbyte,
- .writebyte = ts72xx_rtc_writebyte,
+static struct resource ts72xx_rtc_resource[] = {
+ DEFINE_RES_NAMED(TS72XX_RTC_INDEX_PHYS_BASE, 4,
+ "rtc_index", IORESOURCE_MEM),
+ DEFINE_RES_NAMED(TS72XX_RTC_DATA_PHYS_BASE, 4,
+ "rtc_data", IORESOURCE_MEM),
};
static struct platform_device ts72xx_rtc_device = {
.name = "rtc-m48t86",
.id = -1,
- .dev = {
- .platform_data = &ts72xx_rtc_ops,
- },
- .num_resources = 0,
+ .resource = ts72xx_rtc_resource,
+ .num_resources = ARRAY_SIZE(ts72xx_rtc_resource),
};
static struct resource ts72xx_wdt_resources[] = {
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 6/6] rtc: rtc-m48t86: add devicetree bindings
2013-04-01 23:22 [PATCHv2 0/6] add devicetree bindings for rtc-m48t86 Alexander Clouter
` (4 preceding siblings ...)
2013-04-01 23:22 ` [PATCH 5/6] arm: ep93xx: move ts72xx " Alexander Clouter
@ 2013-04-01 23:22 ` Alexander Clouter
5 siblings, 0 replies; 14+ messages in thread
From: Alexander Clouter @ 2013-04-01 23:22 UTC (permalink / raw)
To: linux-arm-kernel
Add devicetree bindings (and documentation) for rtc-m48t86.
Signed-off-by: Alexander Clouter <alex@digriz.org.uk>
---
Documentation/devicetree/bindings/rtc/rtc-m48t86.txt | 17 +++++++++++++++++
drivers/rtc/rtc-m48t86.c | 12 ++++++++++--
2 files changed, 27 insertions(+), 2 deletions(-)
create mode 100644 Documentation/devicetree/bindings/rtc/rtc-m48t86.txt
diff --git a/Documentation/devicetree/bindings/rtc/rtc-m48t86.txt b/Documentation/devicetree/bindings/rtc/rtc-m48t86.txt
new file mode 100644
index 0000000..375ea56
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-m48t86.txt
@@ -0,0 +1,17 @@
+RTC support for the rtc-m48t86 driver
+
+Required properties:
+- compatible : "rtc-m48t86"
+- reg : Array of base physical addresses for the RTC control and data
+- reg-names : must have "rtc_index" and "rtc_data"
+
+Example:
+
+rtc at 808 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "rtc-m48t86";
+ reg = <0x808 0x04>,
+ <0x80c 0x04>;
+ reg-names = "rtc_index", "rtc_data";
+};
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
index b8edf73..9395126 100644
--- a/drivers/rtc/rtc-m48t86.c
+++ b/drivers/rtc/rtc-m48t86.c
@@ -20,6 +20,7 @@
#include <linux/bcd.h>
#include <linux/slab.h>
#include <linux/io.h>
+#include <linux/of.h>
#define M48T86_REG_SEC 0x00
#define M48T86_REG_SECALRM 0x01
@@ -335,10 +336,17 @@ static int m48t86_rtc_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id m48t86_rtc_match[] = {
+ { .compatible = "rtc-m48t86" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, m48t86_rtc_match);
+
static struct platform_driver m48t86_rtc_platform_driver = {
.driver = {
- .name = "rtc-m48t86",
- .owner = THIS_MODULE,
+ .name = "rtc-m48t86",
+ .owner = THIS_MODULE,
+ .of_match_table = m48t86_rtc_match,
},
.probe = m48t86_rtc_probe,
.remove = m48t86_rtc_remove,
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/6] rtc: rtc-m48t86: add hooks to support driver side memory mapping
2013-04-01 23:22 ` [PATCH 2/6] rtc: rtc-m48t86: add hooks to support driver side memory mapping Alexander Clouter
@ 2013-04-01 23:36 ` Ryan Mallon
2013-04-01 23:42 ` Alexander Clouter
2013-04-02 5:34 ` Ryan Mallon
` (2 subsequent siblings)
3 siblings, 1 reply; 14+ messages in thread
From: Ryan Mallon @ 2013-04-01 23:36 UTC (permalink / raw)
To: linux-arm-kernel
On 02/04/13 10:22, Alexander Clouter wrote:
> If platform_data is not defined (as before), then named memory io
> ranges need to be defined ("rtc_index" and "rtc_data"). The driver
> then maps those regions and uses them as the RTC index and data
> addresses.
>
> Does compile with the following warnings, I cannot see the codepath
> affected myself:
> ----
> drivers/rtc/rtc-m48t86.c: In function ?m48t86_rtc_probe?:
> drivers/rtc/rtc-m48t86.c:180: warning: ?res_index? may be used uninitialized in this function
> drivers/rtc/rtc-m48t86.c:180: warning: ?res_data? may be used uninitialized in this function
It is caused by the exit paths. If pdev->dev.platform_data is set, the
res_index and res_data are never initialised, but in the error case you
still for rtc_device_register you jump to out_io_data, which will then
dereference res_index/res_data. You need to make the exit paths
conditional on pdev->dev.platform_data (or init res_index/data to NULL
and make the release_mem_regions conditional on that).
~Ryan
> ----
>
> Signed-off-by: Alexander Clouter <alex@digriz.org.uk>
> ---
> drivers/rtc/rtc-m48t86.c | 230 ++++++++++++++++++++++++++++++++++------------
> 1 file changed, 173 insertions(+), 57 deletions(-)
>
> diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
> index 25e0116..6f99e64 100644
> --- a/drivers/rtc/rtc-m48t86.c
> +++ b/drivers/rtc/rtc-m48t86.c
> @@ -18,6 +18,8 @@
> #include <linux/platform_device.h>
> #include <linux/platform_data/rtc-m48t86.h>
> #include <linux/bcd.h>
> +#include <linux/slab.h>
> +#include <linux/io.h>
>
> #define M48T86_REG_SEC 0x00
> #define M48T86_REG_SECALRM 0x01
> @@ -41,40 +43,71 @@
>
> #define DRV_VERSION "0.1"
>
> +struct m48t86_rtc_private_data {
> + void __iomem *io_index;
> + void __iomem *io_data;
> +
> + struct rtc_device *rtc;
> + struct m48t86_ops *ops;
> +};
> +
> +static void m48t86_rtc_writebyte(struct device *dev,
> + unsigned char value, unsigned long addr)
> +{
> + struct m48t86_rtc_private_data *priv = dev_get_drvdata(dev);
> +
> + if (priv->ops) {
> + priv->ops->writebyte(value, addr);
> + return;
> + }
> +
> + writeb(addr, priv->io_index);
> + writeb(value, priv->io_data);
> +}
> +
> +static unsigned char m48t86_rtc_readbyte(struct device *dev,
> + unsigned long addr)
> +{
> + struct m48t86_rtc_private_data *priv = dev_get_drvdata(dev);
> +
> + if (priv->ops)
> + return priv->ops->readbyte(addr);
> +
> + writeb(addr, priv->io_index);
> + return readb(priv->io_data);
> +}
>
> static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
> {
> unsigned char reg;
> - struct platform_device *pdev = to_platform_device(dev);
> - struct m48t86_ops *ops = pdev->dev.platform_data;
>
> - reg = ops->readbyte(M48T86_REG_B);
> + reg = m48t86_rtc_readbyte(dev, M48T86_REG_B);
>
> if (reg & M48T86_REG_B_DM) {
> /* data (binary) mode */
> - tm->tm_sec = ops->readbyte(M48T86_REG_SEC);
> - tm->tm_min = ops->readbyte(M48T86_REG_MIN);
> - tm->tm_hour = ops->readbyte(M48T86_REG_HOUR) & 0x3F;
> - tm->tm_mday = ops->readbyte(M48T86_REG_DOM);
> + tm->tm_sec = m48t86_rtc_readbyte(dev, M48T86_REG_SEC);
> + tm->tm_min = m48t86_rtc_readbyte(dev, M48T86_REG_MIN);
> + tm->tm_hour = m48t86_rtc_readbyte(dev, M48T86_REG_HOUR) & 0x3F;
> + tm->tm_mday = m48t86_rtc_readbyte(dev, M48T86_REG_DOM);
> /* tm_mon is 0-11 */
> - tm->tm_mon = ops->readbyte(M48T86_REG_MONTH) - 1;
> - tm->tm_year = ops->readbyte(M48T86_REG_YEAR) + 100;
> - tm->tm_wday = ops->readbyte(M48T86_REG_DOW);
> + tm->tm_mon = m48t86_rtc_readbyte(dev, M48T86_REG_MONTH) - 1;
> + tm->tm_year = m48t86_rtc_readbyte(dev, M48T86_REG_YEAR) + 100;
> + tm->tm_wday = m48t86_rtc_readbyte(dev, M48T86_REG_DOW);
> } else {
> /* bcd mode */
> - tm->tm_sec = bcd2bin(ops->readbyte(M48T86_REG_SEC));
> - tm->tm_min = bcd2bin(ops->readbyte(M48T86_REG_MIN));
> - tm->tm_hour = bcd2bin(ops->readbyte(M48T86_REG_HOUR) & 0x3F);
> - tm->tm_mday = bcd2bin(ops->readbyte(M48T86_REG_DOM));
> + tm->tm_sec = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_SEC));
> + tm->tm_min = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_MIN));
> + tm->tm_hour = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_HOUR) & 0x3F);
> + tm->tm_mday = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_DOM));
> /* tm_mon is 0-11 */
> - tm->tm_mon = bcd2bin(ops->readbyte(M48T86_REG_MONTH)) - 1;
> - tm->tm_year = bcd2bin(ops->readbyte(M48T86_REG_YEAR)) + 100;
> - tm->tm_wday = bcd2bin(ops->readbyte(M48T86_REG_DOW));
> + tm->tm_mon = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_MONTH)) - 1;
> + tm->tm_year = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_YEAR)) + 100;
> + tm->tm_wday = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_DOW));
> }
>
> /* correct the hour if the clock is in 12h mode */
> if (!(reg & M48T86_REG_B_H24))
> - if (ops->readbyte(M48T86_REG_HOUR) & 0x80)
> + if (m48t86_rtc_readbyte(dev, M48T86_REG_HOUR) & 0x80)
> tm->tm_hour += 12;
>
> return rtc_valid_tm(tm);
> @@ -83,38 +116,36 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
> static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
> {
> unsigned char reg;
> - struct platform_device *pdev = to_platform_device(dev);
> - struct m48t86_ops *ops = pdev->dev.platform_data;
>
> - reg = ops->readbyte(M48T86_REG_B);
> + reg = m48t86_rtc_readbyte(dev, M48T86_REG_B);
>
> /* update flag and 24h mode */
> reg |= M48T86_REG_B_SET | M48T86_REG_B_H24;
> - ops->writebyte(reg, M48T86_REG_B);
> + m48t86_rtc_writebyte(dev, reg, M48T86_REG_B);
>
> if (reg & M48T86_REG_B_DM) {
> /* data (binary) mode */
> - ops->writebyte(tm->tm_sec, M48T86_REG_SEC);
> - ops->writebyte(tm->tm_min, M48T86_REG_MIN);
> - ops->writebyte(tm->tm_hour, M48T86_REG_HOUR);
> - ops->writebyte(tm->tm_mday, M48T86_REG_DOM);
> - ops->writebyte(tm->tm_mon + 1, M48T86_REG_MONTH);
> - ops->writebyte(tm->tm_year % 100, M48T86_REG_YEAR);
> - ops->writebyte(tm->tm_wday, M48T86_REG_DOW);
> + m48t86_rtc_writebyte(dev, tm->tm_sec, M48T86_REG_SEC);
> + m48t86_rtc_writebyte(dev, tm->tm_min, M48T86_REG_MIN);
> + m48t86_rtc_writebyte(dev, tm->tm_hour, M48T86_REG_HOUR);
> + m48t86_rtc_writebyte(dev, tm->tm_mday, M48T86_REG_DOM);
> + m48t86_rtc_writebyte(dev, tm->tm_mon + 1, M48T86_REG_MONTH);
> + m48t86_rtc_writebyte(dev, tm->tm_year % 100, M48T86_REG_YEAR);
> + m48t86_rtc_writebyte(dev, tm->tm_wday, M48T86_REG_DOW);
> } else {
> /* bcd mode */
> - ops->writebyte(bin2bcd(tm->tm_sec), M48T86_REG_SEC);
> - ops->writebyte(bin2bcd(tm->tm_min), M48T86_REG_MIN);
> - ops->writebyte(bin2bcd(tm->tm_hour), M48T86_REG_HOUR);
> - ops->writebyte(bin2bcd(tm->tm_mday), M48T86_REG_DOM);
> - ops->writebyte(bin2bcd(tm->tm_mon + 1), M48T86_REG_MONTH);
> - ops->writebyte(bin2bcd(tm->tm_year % 100), M48T86_REG_YEAR);
> - ops->writebyte(bin2bcd(tm->tm_wday), M48T86_REG_DOW);
> + m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_sec), M48T86_REG_SEC);
> + m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_min), M48T86_REG_MIN);
> + m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_hour), M48T86_REG_HOUR);
> + m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_mday), M48T86_REG_DOM);
> + m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_mon + 1), M48T86_REG_MONTH);
> + m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_year % 100), M48T86_REG_YEAR);
> + m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_wday), M48T86_REG_DOW);
> }
>
> /* update ended */
> reg &= ~M48T86_REG_B_SET;
> - ops->writebyte(reg, M48T86_REG_B);
> + m48t86_rtc_writebyte(dev, reg, M48T86_REG_B);
>
> return 0;
> }
> @@ -122,15 +153,13 @@ static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
> static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq)
> {
> unsigned char reg;
> - struct platform_device *pdev = to_platform_device(dev);
> - struct m48t86_ops *ops = pdev->dev.platform_data;
>
> - reg = ops->readbyte(M48T86_REG_B);
> + reg = m48t86_rtc_readbyte(dev, M48T86_REG_B);
>
> seq_printf(seq, "mode\t\t: %s\n",
> (reg & M48T86_REG_B_DM) ? "binary" : "bcd");
>
> - reg = ops->readbyte(M48T86_REG_D);
> + reg = m48t86_rtc_readbyte(dev, M48T86_REG_D);
>
> seq_printf(seq, "battery\t\t: %s\n",
> (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
> @@ -144,34 +173,121 @@ static const struct rtc_class_ops m48t86_rtc_ops = {
> .proc = m48t86_rtc_proc,
> };
>
> -static int m48t86_rtc_probe(struct platform_device *dev)
> +static int m48t86_rtc_probe(struct platform_device *pdev)
> {
> unsigned char reg;
> - struct m48t86_ops *ops = dev->dev.platform_data;
> - struct rtc_device *rtc = rtc_device_register("m48t86",
> - &dev->dev, &m48t86_rtc_ops, THIS_MODULE);
> -
> - if (IS_ERR(rtc))
> - return PTR_ERR(rtc);
> -
> - platform_set_drvdata(dev, rtc);
> + int err;
> + struct resource *res_index, *res_data;
> + struct m48t86_rtc_private_data *priv;
> +
> + /* Allocate memory for the device structure (and zero it) */
> + priv = kzalloc(sizeof(struct m48t86_rtc_private_data), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + platform_set_drvdata(pdev, priv);
> +
> + if (!pdev->dev.platform_data) {
> + res_index = platform_get_resource_byname(
> + pdev, IORESOURCE_MEM, "rtc_index");
> + if (!res_index) {
> + err = -ENXIO;
> + goto out_free;
> + }
> +
> + res_data = platform_get_resource_byname(
> + pdev, IORESOURCE_MEM, "rtc_data");
> + if (!res_data) {
> + err = -ENXIO;
> + goto out_free;
> + }
> +
> + if (!request_mem_region(res_index->start,
> + resource_size(res_index),
> + dev_name(&pdev->dev))) {
> + err = -EBUSY;
> + goto out_free;
> + }
> +
> + if (!request_mem_region(res_data->start,
> + resource_size(res_data),
> + dev_name(&pdev->dev))) {
> + err = -EBUSY;
> + goto out_release_index;
> + }
> +
> + priv->io_index = ioremap(res_index->start,
> + resource_size(res_index));
> + if (!priv->io_index) {
> + err = -EIO;
> + goto out_release_data;
> + }
> +
> + priv->io_data = ioremap(res_data->start,
> + resource_size(res_data));
> + if (!priv->io_data) {
> + err = -EIO;
> + goto out_io_index;
> + }
> + } else
> + priv->ops = pdev->dev.platform_data;
> +
> + priv->rtc = rtc_device_register("m48t86",
> + &pdev->dev, &m48t86_rtc_ops, THIS_MODULE);
> + if (IS_ERR(priv->rtc)) {
> + err = PTR_ERR(priv->rtc);
> + if (!pdev->dev.platform_data)
> + goto out_io_data;
> + else
> + goto out_free;
> + }
>
> /* read battery status */
> - reg = ops->readbyte(M48T86_REG_D);
> - dev_info(&dev->dev, "battery %s\n",
> + reg = m48t86_rtc_readbyte(&pdev->dev, M48T86_REG_D);
> + dev_info(&pdev->dev, "battery %s\n",
> (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
>
> return 0;
> +
> +out_io_data:
> + iounmap(priv->io_data);
> +out_io_index:
> + iounmap(priv->io_index);
> +out_release_data:
> + release_mem_region(res_data->start, resource_size(res_data));
> +out_release_index:
> + release_mem_region(res_index->start, resource_size(res_index));
> +out_free:
> + platform_set_drvdata(pdev, NULL);
> + kfree(priv);
> + return err;
> }
>
> -static int m48t86_rtc_remove(struct platform_device *dev)
> +static int m48t86_rtc_remove(struct platform_device *pdev)
> {
> - struct rtc_device *rtc = platform_get_drvdata(dev);
> + struct resource *res;
> + struct m48t86_rtc_private_data *priv = platform_get_drvdata(pdev);
> +
> + if (priv->rtc)
> + rtc_device_unregister(priv->rtc);
> +
> + if (priv->io_data) {
> + iounmap(priv->io_data);
> + res = platform_get_resource_byname(
> + pdev, IORESOURCE_MEM, "rtc_data");
> + release_mem_region(res->start, resource_size(res));
> + }
> +
> + if (priv->io_index) {
> + iounmap(priv->io_index);
> + res = platform_get_resource_byname(
> + pdev, IORESOURCE_MEM, "rtc_index");
> + release_mem_region(res->start, resource_size(res));
> + }
>
> - if (rtc)
> - rtc_device_unregister(rtc);
> + platform_set_drvdata(pdev, NULL);
>
> - platform_set_drvdata(dev, NULL);
> + kfree(priv);
>
> return 0;
> }
>
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/6] rtc: rtc-m48t86: add hooks to support driver side memory mapping
2013-04-01 23:36 ` Ryan Mallon
@ 2013-04-01 23:42 ` Alexander Clouter
2013-04-02 5:37 ` Ryan Mallon
0 siblings, 1 reply; 14+ messages in thread
From: Alexander Clouter @ 2013-04-01 23:42 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Apr 02, 2013 at 10:36:43AM +1100, Ryan Mallon wrote:
>On 02/04/13 10:22, Alexander Clouter wrote:
>> If platform_data is not defined (as before), then named memory io
>> ranges need to be defined ("rtc_index" and "rtc_data"). The driver
>> then maps those regions and uses them as the RTC index and data
>> addresses.
>>
>> Does compile with the following warnings, I cannot see the codepath
>> affected myself:
>> ----
>> drivers/rtc/rtc-m48t86.c: In function ?m48t86_rtc_probe?:
>> drivers/rtc/rtc-m48t86.c:180: warning: ?res_index? may be used uninitialized in this function
>> drivers/rtc/rtc-m48t86.c:180: warning: ?res_data? may be used uninitialized in this function
>
>It is caused by the exit paths. If pdev->dev.platform_data is set, the
>res_index and res_data are never initialised, but in the error case you
>still for rtc_device_register you jump to out_io_data, which will then
>dereference res_index/res_data. You need to make the exit paths
>conditional on pdev->dev.platform_data (or init res_index/data to NULL
>and make the release_mem_regions conditional on that).
However, the 'goto out_io_data' in the 'IS_ERR(priv->rtc)' is wrapped in a 'if
(!pdev->dev.platform_data)', else we jump to out_free.
I suspect I am probably missing something *too* obvious here for it to click?
Cheers
>> + priv->rtc = rtc_device_register("m48t86",
>> + &pdev->dev, &m48t86_rtc_ops, THIS_MODULE);
>> + if (IS_ERR(priv->rtc)) { <--------------
>> + err = PTR_ERR(priv->rtc);
>> + if (!pdev->dev.platform_data) <--------------
>> + goto out_io_data;
>> + else
>> + goto out_free;
>> + }
>>
>> /* read battery status */
>> - reg = ops->readbyte(M48T86_REG_D);
>> - dev_info(&dev->dev, "battery %s\n",
>> + reg = m48t86_rtc_readbyte(&pdev->dev, M48T86_REG_D);
>> + dev_info(&pdev->dev, "battery %s\n",
>> (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
>>
>> return 0;
>> +
>> +out_io_data:
>> + iounmap(priv->io_data);
>> +out_io_index:
>> + iounmap(priv->io_index);
>> +out_release_data:
>> + release_mem_region(res_data->start, resource_size(res_data));
>> +out_release_index:
>> + release_mem_region(res_index->start, resource_size(res_index));
>> +out_free:
>> + platform_set_drvdata(pdev, NULL);
>> + kfree(priv);
>> + return err;
>> }
--
Alexander Clouter
.sigmonster says: Zeus gave Leda the bird.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/6] rtc: rtc-m48t86: add hooks to support driver side memory mapping
2013-04-01 23:22 ` [PATCH 2/6] rtc: rtc-m48t86: add hooks to support driver side memory mapping Alexander Clouter
2013-04-01 23:36 ` Ryan Mallon
@ 2013-04-02 5:34 ` Ryan Mallon
2013-04-02 11:04 ` [PATCHv2 " Alexander Clouter
2013-04-04 7:25 ` [PATCH " Andrew Lunn
3 siblings, 0 replies; 14+ messages in thread
From: Ryan Mallon @ 2013-04-02 5:34 UTC (permalink / raw)
To: linux-arm-kernel
On 02/04/13 10:22, Alexander Clouter wrote:
> If platform_data is not defined (as before), then named memory io
> ranges need to be defined ("rtc_index" and "rtc_data"). The driver
> then maps those regions and uses them as the RTC index and data
> addresses.
>
> Does compile with the following warnings, I cannot see the codepath
> affected myself:
> ----
> drivers/rtc/rtc-m48t86.c: In function ?m48t86_rtc_probe?:
> drivers/rtc/rtc-m48t86.c:180: warning: ?res_index? may be used uninitialized in this function
> drivers/rtc/rtc-m48t86.c:180: warning: ?res_data? may be used uninitialized in this function
> ----
>
> Signed-off-by: Alexander Clouter <alex@digriz.org.uk>
> ---
> drivers/rtc/rtc-m48t86.c | 230 ++++++++++++++++++++++++++++++++++------------
> 1 file changed, 173 insertions(+), 57 deletions(-)
>
> diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
> index 25e0116..6f99e64 100644
> --- a/drivers/rtc/rtc-m48t86.c
> +++ b/drivers/rtc/rtc-m48t86.c
> @@ -18,6 +18,8 @@
> #include <linux/platform_device.h>
> #include <linux/platform_data/rtc-m48t86.h>
> #include <linux/bcd.h>
> +#include <linux/slab.h>
> +#include <linux/io.h>
>
> #define M48T86_REG_SEC 0x00
> #define M48T86_REG_SECALRM 0x01
> @@ -41,40 +43,71 @@
>
> #define DRV_VERSION "0.1"
>
> +struct m48t86_rtc_private_data {
> + void __iomem *io_index;
> + void __iomem *io_data;
> +
> + struct rtc_device *rtc;
> + struct m48t86_ops *ops;
> +};
> +
> +static void m48t86_rtc_writebyte(struct device *dev,
> + unsigned char value, unsigned long addr)
> +{
> + struct m48t86_rtc_private_data *priv = dev_get_drvdata(dev);
> +
> + if (priv->ops) {
> + priv->ops->writebyte(value, addr);
> + return;
> + }
> +
> + writeb(addr, priv->io_index);
> + writeb(value, priv->io_data);
> +}
> +
> +static unsigned char m48t86_rtc_readbyte(struct device *dev,
> + unsigned long addr)
The read/writebyte functions should return a u8 and take a u8 for the
address (since you are using readb/writeb). For the temporary step which
still has the ops structure, you can explicitly cast addr to unsigned
long if you want to make it obvious that the old api was silly.
~Ryan
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/6] rtc: rtc-m48t86: add hooks to support driver side memory mapping
2013-04-01 23:42 ` Alexander Clouter
@ 2013-04-02 5:37 ` Ryan Mallon
0 siblings, 0 replies; 14+ messages in thread
From: Ryan Mallon @ 2013-04-02 5:37 UTC (permalink / raw)
To: linux-arm-kernel
On 02/04/13 10:42, Alexander Clouter wrote:
> On Tue, Apr 02, 2013 at 10:36:43AM +1100, Ryan Mallon wrote:
>> On 02/04/13 10:22, Alexander Clouter wrote:
>>> If platform_data is not defined (as before), then named memory io
>>> ranges need to be defined ("rtc_index" and "rtc_data"). The driver
>>> then maps those regions and uses them as the RTC index and data
>>> addresses.
>>>
>>> Does compile with the following warnings, I cannot see the codepath
>>> affected myself:
>>> ----
>>> drivers/rtc/rtc-m48t86.c: In function ?m48t86_rtc_probe?:
>>> drivers/rtc/rtc-m48t86.c:180: warning: ?res_index? may be used
>>> uninitialized in this function
>>> drivers/rtc/rtc-m48t86.c:180: warning: ?res_data? may be used
>>> uninitialized in this function
>>
>> It is caused by the exit paths. If pdev->dev.platform_data is set, the
>> res_index and res_data are never initialised, but in the error case you
>> still for rtc_device_register you jump to out_io_data, which will then
>> dereference res_index/res_data. You need to make the exit paths
>> conditional on pdev->dev.platform_data (or init res_index/data to NULL
>> and make the release_mem_regions conditional on that).
>
> However, the 'goto out_io_data' in the 'IS_ERR(priv->rtc)' is wrapped in
> a 'if (!pdev->dev.platform_data)', else we jump to out_free.
Ah right, I missed that. In that case, I can't see the problem either :-/.
>
> I suspect I am probably missing something *too* obvious here for it to
> click?
It could be gcc being dumb, though this does seem a straight-forward
enough case for gcc to get it correct. It would be nice to get rid of
the warning though. Doing:
struct resource *res_index = NULL; /* Avoid GCC warning */
Isn't too costly.
~Ryan
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCHv2 2/6] rtc: rtc-m48t86: add hooks to support driver side memory mapping
2013-04-01 23:22 ` [PATCH 2/6] rtc: rtc-m48t86: add hooks to support driver side memory mapping Alexander Clouter
2013-04-01 23:36 ` Ryan Mallon
2013-04-02 5:34 ` Ryan Mallon
@ 2013-04-02 11:04 ` Alexander Clouter
2013-04-04 7:25 ` [PATCH " Andrew Lunn
3 siblings, 0 replies; 14+ messages in thread
From: Alexander Clouter @ 2013-04-02 11:04 UTC (permalink / raw)
To: linux-arm-kernel
If platform_data is not defined (as before), then named memory io
ranges need to be defined ("rtc_index" and "rtc_data"). The driver
then maps those regions and uses them as the RTC index and data
addresses.
Changelog:
v2 - mute GCC warnings (seems to be GCC being dumb)
- amend the {read,write}byte driver functions to use u8
Signed-off-by: Alexander Clouter <alex@digriz.org.uk>
---
drivers/rtc/rtc-m48t86.c | 230 ++++++++++++++++++++++++++++++++++------------
1 file changed, 173 insertions(+), 57 deletions(-)
diff --git a/drivers/rtc/rtc-m48t86.c b/drivers/rtc/rtc-m48t86.c
index 25e0116..b2cabf9 100644
--- a/drivers/rtc/rtc-m48t86.c
+++ b/drivers/rtc/rtc-m48t86.c
@@ -18,6 +18,8 @@
#include <linux/platform_device.h>
#include <linux/platform_data/rtc-m48t86.h>
#include <linux/bcd.h>
+#include <linux/slab.h>
+#include <linux/io.h>
#define M48T86_REG_SEC 0x00
#define M48T86_REG_SECALRM 0x01
@@ -41,40 +43,70 @@
#define DRV_VERSION "0.1"
+struct m48t86_rtc_private_data {
+ void __iomem *io_index;
+ void __iomem *io_data;
+
+ struct rtc_device *rtc;
+ struct m48t86_ops *ops;
+};
+
+static void m48t86_rtc_writebyte(struct device *dev, u8 value, u8 reg)
+{
+ struct m48t86_rtc_private_data *priv = dev_get_drvdata(dev);
+
+ if (priv->ops) {
+ priv->ops->writebyte((unsigned char)value,
+ (unsigned long)reg);
+ return;
+ }
+
+ writeb(reg, priv->io_index);
+ writeb(value, priv->io_data);
+}
+
+static u8 m48t86_rtc_readbyte(struct device *dev, u8 reg)
+{
+ struct m48t86_rtc_private_data *priv = dev_get_drvdata(dev);
+
+ if (priv->ops)
+ return priv->ops->readbyte((unsigned long)reg);
+
+ writeb(reg, priv->io_index);
+ return readb(priv->io_data);
+}
static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
unsigned char reg;
- struct platform_device *pdev = to_platform_device(dev);
- struct m48t86_ops *ops = pdev->dev.platform_data;
- reg = ops->readbyte(M48T86_REG_B);
+ reg = m48t86_rtc_readbyte(dev, M48T86_REG_B);
if (reg & M48T86_REG_B_DM) {
/* data (binary) mode */
- tm->tm_sec = ops->readbyte(M48T86_REG_SEC);
- tm->tm_min = ops->readbyte(M48T86_REG_MIN);
- tm->tm_hour = ops->readbyte(M48T86_REG_HOUR) & 0x3F;
- tm->tm_mday = ops->readbyte(M48T86_REG_DOM);
+ tm->tm_sec = m48t86_rtc_readbyte(dev, M48T86_REG_SEC);
+ tm->tm_min = m48t86_rtc_readbyte(dev, M48T86_REG_MIN);
+ tm->tm_hour = m48t86_rtc_readbyte(dev, M48T86_REG_HOUR) & 0x3F;
+ tm->tm_mday = m48t86_rtc_readbyte(dev, M48T86_REG_DOM);
/* tm_mon is 0-11 */
- tm->tm_mon = ops->readbyte(M48T86_REG_MONTH) - 1;
- tm->tm_year = ops->readbyte(M48T86_REG_YEAR) + 100;
- tm->tm_wday = ops->readbyte(M48T86_REG_DOW);
+ tm->tm_mon = m48t86_rtc_readbyte(dev, M48T86_REG_MONTH) - 1;
+ tm->tm_year = m48t86_rtc_readbyte(dev, M48T86_REG_YEAR) + 100;
+ tm->tm_wday = m48t86_rtc_readbyte(dev, M48T86_REG_DOW);
} else {
/* bcd mode */
- tm->tm_sec = bcd2bin(ops->readbyte(M48T86_REG_SEC));
- tm->tm_min = bcd2bin(ops->readbyte(M48T86_REG_MIN));
- tm->tm_hour = bcd2bin(ops->readbyte(M48T86_REG_HOUR) & 0x3F);
- tm->tm_mday = bcd2bin(ops->readbyte(M48T86_REG_DOM));
+ tm->tm_sec = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_SEC));
+ tm->tm_min = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_MIN));
+ tm->tm_hour = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_HOUR) & 0x3F);
+ tm->tm_mday = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_DOM));
/* tm_mon is 0-11 */
- tm->tm_mon = bcd2bin(ops->readbyte(M48T86_REG_MONTH)) - 1;
- tm->tm_year = bcd2bin(ops->readbyte(M48T86_REG_YEAR)) + 100;
- tm->tm_wday = bcd2bin(ops->readbyte(M48T86_REG_DOW));
+ tm->tm_mon = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_MONTH)) - 1;
+ tm->tm_year = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_YEAR)) + 100;
+ tm->tm_wday = bcd2bin(m48t86_rtc_readbyte(dev, M48T86_REG_DOW));
}
/* correct the hour if the clock is in 12h mode */
if (!(reg & M48T86_REG_B_H24))
- if (ops->readbyte(M48T86_REG_HOUR) & 0x80)
+ if (m48t86_rtc_readbyte(dev, M48T86_REG_HOUR) & 0x80)
tm->tm_hour += 12;
return rtc_valid_tm(tm);
@@ -83,38 +115,36 @@ static int m48t86_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
unsigned char reg;
- struct platform_device *pdev = to_platform_device(dev);
- struct m48t86_ops *ops = pdev->dev.platform_data;
- reg = ops->readbyte(M48T86_REG_B);
+ reg = m48t86_rtc_readbyte(dev, M48T86_REG_B);
/* update flag and 24h mode */
reg |= M48T86_REG_B_SET | M48T86_REG_B_H24;
- ops->writebyte(reg, M48T86_REG_B);
+ m48t86_rtc_writebyte(dev, reg, M48T86_REG_B);
if (reg & M48T86_REG_B_DM) {
/* data (binary) mode */
- ops->writebyte(tm->tm_sec, M48T86_REG_SEC);
- ops->writebyte(tm->tm_min, M48T86_REG_MIN);
- ops->writebyte(tm->tm_hour, M48T86_REG_HOUR);
- ops->writebyte(tm->tm_mday, M48T86_REG_DOM);
- ops->writebyte(tm->tm_mon + 1, M48T86_REG_MONTH);
- ops->writebyte(tm->tm_year % 100, M48T86_REG_YEAR);
- ops->writebyte(tm->tm_wday, M48T86_REG_DOW);
+ m48t86_rtc_writebyte(dev, tm->tm_sec, M48T86_REG_SEC);
+ m48t86_rtc_writebyte(dev, tm->tm_min, M48T86_REG_MIN);
+ m48t86_rtc_writebyte(dev, tm->tm_hour, M48T86_REG_HOUR);
+ m48t86_rtc_writebyte(dev, tm->tm_mday, M48T86_REG_DOM);
+ m48t86_rtc_writebyte(dev, tm->tm_mon + 1, M48T86_REG_MONTH);
+ m48t86_rtc_writebyte(dev, tm->tm_year % 100, M48T86_REG_YEAR);
+ m48t86_rtc_writebyte(dev, tm->tm_wday, M48T86_REG_DOW);
} else {
/* bcd mode */
- ops->writebyte(bin2bcd(tm->tm_sec), M48T86_REG_SEC);
- ops->writebyte(bin2bcd(tm->tm_min), M48T86_REG_MIN);
- ops->writebyte(bin2bcd(tm->tm_hour), M48T86_REG_HOUR);
- ops->writebyte(bin2bcd(tm->tm_mday), M48T86_REG_DOM);
- ops->writebyte(bin2bcd(tm->tm_mon + 1), M48T86_REG_MONTH);
- ops->writebyte(bin2bcd(tm->tm_year % 100), M48T86_REG_YEAR);
- ops->writebyte(bin2bcd(tm->tm_wday), M48T86_REG_DOW);
+ m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_sec), M48T86_REG_SEC);
+ m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_min), M48T86_REG_MIN);
+ m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_hour), M48T86_REG_HOUR);
+ m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_mday), M48T86_REG_DOM);
+ m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_mon + 1), M48T86_REG_MONTH);
+ m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_year % 100), M48T86_REG_YEAR);
+ m48t86_rtc_writebyte(dev, bin2bcd(tm->tm_wday), M48T86_REG_DOW);
}
/* update ended */
reg &= ~M48T86_REG_B_SET;
- ops->writebyte(reg, M48T86_REG_B);
+ m48t86_rtc_writebyte(dev, reg, M48T86_REG_B);
return 0;
}
@@ -122,15 +152,13 @@ static int m48t86_rtc_set_time(struct device *dev, struct rtc_time *tm)
static int m48t86_rtc_proc(struct device *dev, struct seq_file *seq)
{
unsigned char reg;
- struct platform_device *pdev = to_platform_device(dev);
- struct m48t86_ops *ops = pdev->dev.platform_data;
- reg = ops->readbyte(M48T86_REG_B);
+ reg = m48t86_rtc_readbyte(dev, M48T86_REG_B);
seq_printf(seq, "mode\t\t: %s\n",
(reg & M48T86_REG_B_DM) ? "binary" : "bcd");
- reg = ops->readbyte(M48T86_REG_D);
+ reg = m48t86_rtc_readbyte(dev, M48T86_REG_D);
seq_printf(seq, "battery\t\t: %s\n",
(reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
@@ -144,34 +172,122 @@ static const struct rtc_class_ops m48t86_rtc_ops = {
.proc = m48t86_rtc_proc,
};
-static int m48t86_rtc_probe(struct platform_device *dev)
+static int m48t86_rtc_probe(struct platform_device *pdev)
{
unsigned char reg;
- struct m48t86_ops *ops = dev->dev.platform_data;
- struct rtc_device *rtc = rtc_device_register("m48t86",
- &dev->dev, &m48t86_rtc_ops, THIS_MODULE);
-
- if (IS_ERR(rtc))
- return PTR_ERR(rtc);
-
- platform_set_drvdata(dev, rtc);
+ int err;
+ struct m48t86_rtc_private_data *priv;
+ struct resource *res_index = NULL; /* Avoid GCC warning */
+ struct resource *res_data = NULL; /* Avoid GCC warning */
+
+ /* Allocate memory for the device structure (and zero it) */
+ priv = kzalloc(sizeof(struct m48t86_rtc_private_data), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, priv);
+
+ if (!pdev->dev.platform_data) {
+ res_index = platform_get_resource_byname(
+ pdev, IORESOURCE_MEM, "rtc_index");
+ if (!res_index) {
+ err = -ENXIO;
+ goto out_free;
+ }
+
+ res_data = platform_get_resource_byname(
+ pdev, IORESOURCE_MEM, "rtc_data");
+ if (!res_data) {
+ err = -ENXIO;
+ goto out_free;
+ }
+
+ if (!request_mem_region(res_index->start,
+ resource_size(res_index),
+ dev_name(&pdev->dev))) {
+ err = -EBUSY;
+ goto out_free;
+ }
+
+ if (!request_mem_region(res_data->start,
+ resource_size(res_data),
+ dev_name(&pdev->dev))) {
+ err = -EBUSY;
+ goto out_release_index;
+ }
+
+ priv->io_index = ioremap(res_index->start,
+ resource_size(res_index));
+ if (!priv->io_index) {
+ err = -EIO;
+ goto out_release_data;
+ }
+
+ priv->io_data = ioremap(res_data->start,
+ resource_size(res_data));
+ if (!priv->io_data) {
+ err = -EIO;
+ goto out_io_index;
+ }
+ } else
+ priv->ops = pdev->dev.platform_data;
+
+ priv->rtc = rtc_device_register("m48t86",
+ &pdev->dev, &m48t86_rtc_ops, THIS_MODULE);
+ if (IS_ERR(priv->rtc)) {
+ err = PTR_ERR(priv->rtc);
+ if (!pdev->dev.platform_data)
+ goto out_io_data;
+ else
+ goto out_free;
+ }
/* read battery status */
- reg = ops->readbyte(M48T86_REG_D);
- dev_info(&dev->dev, "battery %s\n",
+ reg = m48t86_rtc_readbyte(&pdev->dev, M48T86_REG_D);
+ dev_info(&pdev->dev, "battery %s\n",
(reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
return 0;
+
+out_io_data:
+ iounmap(priv->io_data);
+out_io_index:
+ iounmap(priv->io_index);
+out_release_data:
+ release_mem_region(res_data->start, resource_size(res_data));
+out_release_index:
+ release_mem_region(res_index->start, resource_size(res_index));
+out_free:
+ platform_set_drvdata(pdev, NULL);
+ kfree(priv);
+ return err;
}
-static int m48t86_rtc_remove(struct platform_device *dev)
+static int m48t86_rtc_remove(struct platform_device *pdev)
{
- struct rtc_device *rtc = platform_get_drvdata(dev);
+ struct resource *res;
+ struct m48t86_rtc_private_data *priv = platform_get_drvdata(pdev);
+
+ if (priv->rtc)
+ rtc_device_unregister(priv->rtc);
+
+ if (priv->io_data) {
+ iounmap(priv->io_data);
+ res = platform_get_resource_byname(
+ pdev, IORESOURCE_MEM, "rtc_data");
+ release_mem_region(res->start, resource_size(res));
+ }
+
+ if (priv->io_index) {
+ iounmap(priv->io_index);
+ res = platform_get_resource_byname(
+ pdev, IORESOURCE_MEM, "rtc_index");
+ release_mem_region(res->start, resource_size(res));
+ }
- if (rtc)
- rtc_device_unregister(rtc);
+ platform_set_drvdata(pdev, NULL);
- platform_set_drvdata(dev, NULL);
+ kfree(priv);
return 0;
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 4/6] arm: orion5x: move ts78xx to use rtc-m48t86 driver side memory interface
2013-04-01 23:22 ` [PATCH 4/6] arm: orion5x: move ts78xx to use rtc-m48t86 driver side memory interface Alexander Clouter
@ 2013-04-02 11:50 ` Jason Cooper
0 siblings, 0 replies; 14+ messages in thread
From: Jason Cooper @ 2013-04-02 11:50 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Apr 02, 2013 at 12:22:43AM +0100, Alexander Clouter wrote:
> Remove platform_data hooks into rtc-m48t86 and use named resource regions.
>
> Signed-off-by: Alexander Clouter <alex@digriz.org.uk>
> ---
> arch/arm/mach-orion5x/ts78xx-setup.c | 78 ++++++++--------------------------
> 1 file changed, 17 insertions(+), 61 deletions(-)
Acked-by: Jason Cooper <jason@lakedaemon.net>
thx,
Jason.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/6] rtc: rtc-m48t86: add hooks to support driver side memory mapping
2013-04-01 23:22 ` [PATCH 2/6] rtc: rtc-m48t86: add hooks to support driver side memory mapping Alexander Clouter
` (2 preceding siblings ...)
2013-04-02 11:04 ` [PATCHv2 " Alexander Clouter
@ 2013-04-04 7:25 ` Andrew Lunn
3 siblings, 0 replies; 14+ messages in thread
From: Andrew Lunn @ 2013-04-04 7:25 UTC (permalink / raw)
To: linux-arm-kernel
> -static int m48t86_rtc_probe(struct platform_device *dev)
> +static int m48t86_rtc_probe(struct platform_device *pdev)
> {
> unsigned char reg;
> - struct m48t86_ops *ops = dev->dev.platform_data;
> - struct rtc_device *rtc = rtc_device_register("m48t86",
> - &dev->dev, &m48t86_rtc_ops, THIS_MODULE);
> -
> - if (IS_ERR(rtc))
> - return PTR_ERR(rtc);
> -
> - platform_set_drvdata(dev, rtc);
> + int err;
> + struct resource *res_index, *res_data;
> + struct m48t86_rtc_private_data *priv;
> +
> + /* Allocate memory for the device structure (and zero it) */
> + priv = kzalloc(sizeof(struct m48t86_rtc_private_data), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> +
> + platform_set_drvdata(pdev, priv);
> +
> + if (!pdev->dev.platform_data) {
> + res_index = platform_get_resource_byname(
> + pdev, IORESOURCE_MEM, "rtc_index");
> + if (!res_index) {
> + err = -ENXIO;
> + goto out_free;
> + }
> +
> + res_data = platform_get_resource_byname(
> + pdev, IORESOURCE_MEM, "rtc_data");
> + if (!res_data) {
> + err = -ENXIO;
> + goto out_free;
> + }
> +
> + if (!request_mem_region(res_index->start,
> + resource_size(res_index),
> + dev_name(&pdev->dev))) {
> + err = -EBUSY;
> + goto out_free;
> + }
> +
> + if (!request_mem_region(res_data->start,
> + resource_size(res_data),
> + dev_name(&pdev->dev))) {
> + err = -EBUSY;
> + goto out_release_index;
> + }
> +
> + priv->io_index = ioremap(res_index->start,
> + resource_size(res_index));
> + if (!priv->io_index) {
> + err = -EIO;
> + goto out_release_data;
> + }
> +
> + priv->io_data = ioremap(res_data->start,
> + resource_size(res_data));
> + if (!priv->io_data) {
> + err = -EIO;
> + goto out_io_index;
> + }
> + } else
Hi Alexander
It would be good to use the devm_ functions here. It will make the
cleanup on error much simpler, solve your warnings problem, and simply
the remove function.
> + priv->ops = pdev->dev.platform_data;
> +
> + priv->rtc = rtc_device_register("m48t86",
> + &pdev->dev, &m48t86_rtc_ops, THIS_MODULE);
> + if (IS_ERR(priv->rtc)) {
> + err = PTR_ERR(priv->rtc);
> + if (!pdev->dev.platform_data)
> + goto out_io_data;
> + else
> + goto out_free;
> + }
>
> /* read battery status */
> - reg = ops->readbyte(M48T86_REG_D);
> - dev_info(&dev->dev, "battery %s\n",
> + reg = m48t86_rtc_readbyte(&pdev->dev, M48T86_REG_D);
> + dev_info(&pdev->dev, "battery %s\n",
> (reg & M48T86_REG_D_VRT) ? "ok" : "exhausted");
>
> return 0;
> +
> +out_io_data:
> + iounmap(priv->io_data);
> +out_io_index:
> + iounmap(priv->io_index);
> +out_release_data:
> + release_mem_region(res_data->start, resource_size(res_data));
> +out_release_index:
> + release_mem_region(res_index->start, resource_size(res_index));
> +out_free:
> + platform_set_drvdata(pdev, NULL);
> + kfree(priv);
> + return err;
> }
>
> -static int m48t86_rtc_remove(struct platform_device *dev)
> +static int m48t86_rtc_remove(struct platform_device *pdev)
> {
> - struct rtc_device *rtc = platform_get_drvdata(dev);
> + struct resource *res;
> + struct m48t86_rtc_private_data *priv = platform_get_drvdata(pdev);
> +
> + if (priv->rtc)
> + rtc_device_unregister(priv->rtc);
> +
> + if (priv->io_data) {
> + iounmap(priv->io_data);
> + res = platform_get_resource_byname(
> + pdev, IORESOURCE_MEM, "rtc_data");
> + release_mem_region(res->start, resource_size(res));
> + }
> +
> + if (priv->io_index) {
> + iounmap(priv->io_index);
> + res = platform_get_resource_byname(
> + pdev, IORESOURCE_MEM, "rtc_index");
> + release_mem_region(res->start, resource_size(res));
> + }
>
> - if (rtc)
> - rtc_device_unregister(rtc);
> + platform_set_drvdata(pdev, NULL);
>
> - platform_set_drvdata(dev, NULL);
> + kfree(priv);
>
> return 0;
> }
> --
> 1.7.10.4
>
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2013-04-04 7:25 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-01 23:22 [PATCHv2 0/6] add devicetree bindings for rtc-m48t86 Alexander Clouter
2013-04-01 23:22 ` [PATCH 1/6] rtc: rtc-m48t86: move m48t86.h to platform_data Alexander Clouter
2013-04-01 23:22 ` [PATCH 2/6] rtc: rtc-m48t86: add hooks to support driver side memory mapping Alexander Clouter
2013-04-01 23:36 ` Ryan Mallon
2013-04-01 23:42 ` Alexander Clouter
2013-04-02 5:37 ` Ryan Mallon
2013-04-02 5:34 ` Ryan Mallon
2013-04-02 11:04 ` [PATCHv2 " Alexander Clouter
2013-04-04 7:25 ` [PATCH " Andrew Lunn
2013-04-01 23:22 ` [PATCH 3/6] rtc: rtc-m48t86: add detect method for RTC Alexander Clouter
2013-04-01 23:22 ` [PATCH 4/6] arm: orion5x: move ts78xx to use rtc-m48t86 driver side memory interface Alexander Clouter
2013-04-02 11:50 ` Jason Cooper
2013-04-01 23:22 ` [PATCH 5/6] arm: ep93xx: move ts72xx " Alexander Clouter
2013-04-01 23:22 ` [PATCH 6/6] rtc: rtc-m48t86: add devicetree bindings Alexander Clouter
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).