i2c: sh_mobile: fix clock calculation for newer SoCs
authorWolfram Sang <wsa+renesas@sang-engineering.com>
Fri, 2 May 2014 19:15:16 +0000 (21:15 +0200)
committerWolfram Sang <wsa@the-dreams.de>
Thu, 22 May 2014 08:09:25 +0000 (10:09 +0200)
Newer SoCs have so fast input clocks that the ICCL/H registers only
count every second clock to have a meaningful 9-bit range. The driver
was already prepared for that happening, but didn't use it so far.
Add the proper DT configuration for SoCs that need it.

Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
drivers/i2c/busses/i2c-sh_mobile.c

index b1d399e3e5fc7de9921d580596ee6e0356b76538..c29be2bba6ea17f73ad1688600ef7bffcd650d79 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 #include <linux/i2c/i2c-sh_mobile.h>
 
 /* Transmit operation:                                                      */
@@ -139,6 +140,10 @@ struct sh_mobile_i2c_data {
        bool send_stop;
 };
 
+struct sh_mobile_dt_config {
+       int clks_per_count;
+};
+
 #define IIC_FLAG_HAS_ICIC67    (1 << 0)
 
 #define STANDARD_MODE          100000
@@ -617,6 +622,22 @@ static struct i2c_algorithm sh_mobile_i2c_algorithm = {
        .master_xfer    = sh_mobile_i2c_xfer,
 };
 
+static const struct sh_mobile_dt_config default_dt_config = {
+       .clks_per_count = 1,
+};
+
+static const struct sh_mobile_dt_config rcar_gen2_dt_config = {
+       .clks_per_count = 2,
+};
+
+static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
+       { .compatible = "renesas,rmobile-iic", .data = &default_dt_config },
+       { .compatible = "renesas,iic-r8a7790", .data = &rcar_gen2_dt_config },
+       { .compatible = "renesas,iic-r8a7791", .data = &rcar_gen2_dt_config },
+       {},
+};
+MODULE_DEVICE_TABLE(of, sh_mobile_i2c_dt_ids);
+
 static int sh_mobile_i2c_hook_irqs(struct platform_device *dev)
 {
        struct resource *res;
@@ -674,11 +695,24 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
        ret = of_property_read_u32(dev->dev.of_node, "clock-frequency", &bus_speed);
        pd->bus_speed = ret ? STANDARD_MODE : bus_speed;
 
-       if (pdata && pdata->bus_speed)
-               pd->bus_speed = pdata->bus_speed;
        pd->clks_per_count = 1;
-       if (pdata && pdata->clks_per_count)
-               pd->clks_per_count = pdata->clks_per_count;
+
+       if (dev->dev.of_node) {
+               const struct of_device_id *match;
+
+               match = of_match_device(sh_mobile_i2c_dt_ids, &dev->dev);
+               if (match) {
+                       const struct sh_mobile_dt_config *config;
+
+                       config = match->data;
+                       pd->clks_per_count = config->clks_per_count;
+               }
+       } else {
+               if (pdata && pdata->bus_speed)
+                       pd->bus_speed = pdata->bus_speed;
+               if (pdata && pdata->clks_per_count)
+                       pd->clks_per_count = pdata->clks_per_count;
+       }
 
        /* The IIC blocks on SH-Mobile ARM processors
         * come with two new bits in ICIC.
@@ -758,12 +792,6 @@ static const struct dev_pm_ops sh_mobile_i2c_dev_pm_ops = {
        .runtime_resume = sh_mobile_i2c_runtime_nop,
 };
 
-static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
-       { .compatible = "renesas,rmobile-iic", },
-       {},
-};
-MODULE_DEVICE_TABLE(of, sh_mobile_i2c_dt_ids);
-
 static struct platform_driver sh_mobile_i2c_driver = {
        .driver         = {
                .name           = "i2c-sh_mobile",