Patchwork RTC: rtc-v3020.c: Added support for device-tree platform data

login
register
mail settings
Submitter David Jander
Date May 31, 2011, 11:24 a.m.
Message ID <1306841072-8115-1-git-send-email-david@protonic.nl>
Download mbox | patch
Permalink /patch/98011/
State New
Headers show

Comments

David Jander - May 31, 2011, 11:24 a.m.
Added support for fetching platform data from OF device-tree.

Signed-off-by: David Jander <david@protonic.nl>
---
 .../devicetree/bindings/rtc/rtc-v3020.txt          |   32 +++++++++
 drivers/rtc/rtc-v3020.c                            |   74 ++++++++++++++++++++
 2 files changed, 106 insertions(+), 0 deletions(-)
David Jander - May 31, 2011, 11:39 a.m.
Ooops. Please ignore this version of the patch, there is a typo, which
I forgot to add to the commit. My excuses!
Will resend this immediately.

>[...]
> @@ -379,17 +440,30 @@ static int rtc_remove(struct platform_device *dev)
>                 rtc_device_unregister(rtc);
>
>         chip->ops->unmap_io(chip);
> +       if (chip->dyn_pdata)
> +               kfree(pdev->dev.platform_data);

This should be dev instead of pdev.

Patch

diff --git a/Documentation/devicetree/bindings/rtc/rtc-v3020.txt b/Documentation/devicetree/bindings/rtc/rtc-v3020.txt
new file mode 100644
index 0000000..8c470e1
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/rtc-v3020.txt
@@ -0,0 +1,32 @@ 
+ EM Marin V3020 compatible RTC
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Required properties:
+  - compatible: "em,v3020", "v3020"
+  - reg: Memory address if mmio mode is used, otherwise not used.
+
+Optional properties:
+  - "use_gpio": integer. If defined and not "0", use gpio access mode.
+  - "leftshift": integer. Contains the leftshift parameter of 
+    struct v3020_platform_data.
+  - "gpio_cs", "gpio_wr", "gpio_rd" and "gpio_io": integers, representing
+    the GPIO pin numbers to use in struct v3020_platform_data if gpio access
+    mode is used.
+
+Example for MMIO on MPC5121 localbus:
+
+	localbus@80000020 {
+		compatible = "fsl,mpc5121-localbus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		reg = <0x80000020 0x40>;
+		ranges = <0x0 0x0 0xfe000000 0x02000000   /* Flash */
+			  0x1 0x0 0xf8000000 0x00000004>; /* V3020 */
+		...
+		v3020@1,0 {
+			compatible = "em,v3020", "v3020";
+			reg = <1 0 4>;
+			leftshift = <24>;
+		};
+		...
+
diff --git a/drivers/rtc/rtc-v3020.c b/drivers/rtc/rtc-v3020.c
index f71c3ce..08d04e0 100644
--- a/drivers/rtc/rtc-v3020.c
+++ b/drivers/rtc/rtc-v3020.c
@@ -11,6 +11,9 @@ 
  *
  * Changelog:
  *
+ *  31-May-2011: David Jander <david@protonic.nl>
+ *				- Added OF support
+ *
  *  10-May-2006: Raphael Assenat <raph@8d.com>
  *				- Converted to platform driver
  *				- Use the generic rtc class
@@ -29,6 +32,9 @@ 
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#ifdef CONFIG_OF
+#include <linux/of.h>
+#endif
 
 #include <linux/io.h>
 
@@ -65,6 +71,8 @@  struct v3020 {
 	struct v3020_chip_ops *ops;
 
 	struct rtc_device *rtc;
+
+	int dyn_pdata;
 };
 
 
@@ -301,6 +309,50 @@  static const struct rtc_class_ops v3020_rtc_ops = {
 	.set_time	= v3020_set_time,
 };
 
+#ifdef CONFIG_OF
+static int get_of_pdata(struct v3020_platform_data **pdata, struct platform_device *pdev)
+{
+	const unsigned int *val;
+
+	*pdata = kzalloc(sizeof **pdata, GFP_KERNEL);
+	if (!*pdata)
+		return -ENOMEM;
+
+	pdev->dev.platform_data = *pdata;
+
+	val = of_get_property(pdev->dev.of_node, "use_gpio", NULL);
+	if (val)
+		(*pdata)->use_gpio = *val;
+
+	val = of_get_property(pdev->dev.of_node, "leftshift", NULL);
+	if (val)
+		(*pdata)->leftshift = *val;
+
+	val = of_get_property(pdev->dev.of_node, "gpio_cs", NULL);
+	if (val)
+		(*pdata)->gpio_cs = *val;
+
+	val = of_get_property(pdev->dev.of_node, "gpio_wr", NULL);
+	if (val)
+		(*pdata)->gpio_wr = *val;
+
+	val = of_get_property(pdev->dev.of_node, "gpio_rd", NULL);
+	if (val)
+		(*pdata)->gpio_rd = *val;
+
+	val = of_get_property(pdev->dev.of_node, "gpio_io", NULL);
+	if (val)
+		(*pdata)->gpio_io = *val;
+
+	return 0;
+}
+#else
+static int get_of_pdata(struct v3020_platform_data *pdata, struct v3020 *chip)
+{
+	return -ENODEV;
+}
+#endif
+
 static int rtc_probe(struct platform_device *pdev)
 {
 	struct v3020_platform_data *pdata = pdev->dev.platform_data;
@@ -313,6 +365,13 @@  static int rtc_probe(struct platform_device *pdev)
 	if (!chip)
 		return -ENOMEM;
 
+	if (!pdata && pdev->dev.of_node) {
+		retval = get_of_pdata(&pdata, pdev);
+		if (retval)
+			goto err_chip;
+		chip->dyn_pdata = 1;
+	}
+
 	if (pdata->use_gpio)
 		chip->ops = &v3020_gpio_ops;
 	else
@@ -365,6 +424,8 @@  static int rtc_probe(struct platform_device *pdev)
 err_io:
 	chip->ops->unmap_io(chip);
 err_chip:
+	if (chip->dyn_pdata)
+		kfree(pdev->dev.platform_data);
 	kfree(chip);
 
 	return retval;
@@ -379,17 +440,30 @@  static int rtc_remove(struct platform_device *dev)
 		rtc_device_unregister(rtc);
 
 	chip->ops->unmap_io(chip);
+	if (chip->dyn_pdata)
+		kfree(pdev->dev.platform_data);
 	kfree(chip);
 
 	return 0;
 }
 
+#ifdef CONFIG_OF
+const struct of_device_id v3020_of_match[] = {
+	{
+		.compatible = "v3020",
+	},
+};
+#endif
+
 static struct platform_driver rtc_device_driver = {
 	.probe	= rtc_probe,
 	.remove = rtc_remove,
 	.driver = {
 		.name	= "v3020",
 		.owner	= THIS_MODULE,
+#ifdef CONFIG_OF
+		.of_match_table = v3020_of_match,
+#endif
 	},
 };