new file mode 100644
@@ -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>;
+ };
+ ...
+
@@ -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
},
};
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(-)