Merge git://git.denx.de/u-boot-socfpga
[platform/kernel/u-boot.git] / drivers / i2c / tegra_i2c.c
index 87290c3..3255e8e 100644 (file)
@@ -9,14 +9,15 @@
 #include <common.h>
 #include <dm.h>
 #include <errno.h>
-#include <fdtdec.h>
 #include <i2c.h>
 #include <asm/io.h>
+#include <clk.h>
+#include <reset.h>
+#ifndef CONFIG_TEGRA186
 #include <asm/arch/clock.h>
 #include <asm/arch/funcmux.h>
+#endif
 #include <asm/arch/gpio.h>
-#include <asm/arch/pinmux.h>
-#include <asm/arch-tegra/clk_rst.h>
 #include <asm/arch-tegra/tegra_i2c.h>
 
 DECLARE_GLOBAL_DATA_PTR;
@@ -30,7 +31,8 @@ enum i2c_type {
 /* Information about i2c controller */
 struct i2c_bus {
        int                     id;
-       enum periph_id          periph_id;
+       struct reset_ctl        reset_ctl;
+       struct clk              clk;
        int                     speed;
        int                     pinmux_config;
        struct i2c_control      *control;
@@ -62,12 +64,35 @@ static void set_packet_mode(struct i2c_bus *i2c_bus)
 static void i2c_reset_controller(struct i2c_bus *i2c_bus)
 {
        /* Reset I2C controller. */
-       reset_periph(i2c_bus->periph_id, 1);
+       reset_assert(&i2c_bus->reset_ctl);
+       udelay(1);
+       reset_deassert(&i2c_bus->reset_ctl);
+       udelay(1);
 
        /* re-program config register to packet mode */
        set_packet_mode(i2c_bus);
 }
 
+static int i2c_init_clock(struct i2c_bus *i2c_bus, unsigned rate)
+{
+       int ret;
+
+       ret = reset_assert(&i2c_bus->reset_ctl);
+       if (ret)
+               return ret;
+       ret = clk_enable(&i2c_bus->clk);
+       if (ret)
+               return ret;
+       ret = clk_set_rate(&i2c_bus->clk, rate);
+       if (IS_ERR_VALUE(ret))
+               return ret;
+       ret = reset_deassert(&i2c_bus->reset_ctl);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 static void i2c_init_controller(struct i2c_bus *i2c_bus)
 {
        if (!i2c_bus->speed)
@@ -78,8 +103,7 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
         * here, in section 23.3.1, but in fact we seem to need a factor of
         * 16 to get the right frequency.
         */
-       clock_start_periph_pll(i2c_bus->periph_id, CLOCK_ID_PERIPH,
-               i2c_bus->speed * 2 * 8);
+       i2c_init_clock(i2c_bus, i2c_bus->speed * 2 * 8);
 
        if (i2c_bus->type == TYPE_114) {
                /*
@@ -94,12 +118,12 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
                 * is running, we hang, and we need it for the new calc.
                 */
                int clk_div_stdfst_mode = readl(&i2c_bus->regs->clk_div) >> 16;
+               unsigned rate = CLK_MULT_STD_FAST_MODE *
+                               (clk_div_stdfst_mode + 1) * i2c_bus->speed * 2;
                debug("%s: CLK_DIV_STD_FAST_MODE setting = %d\n", __func__,
                        clk_div_stdfst_mode);
 
-               clock_start_periph_pll(i2c_bus->periph_id, CLOCK_ID_PERIPH,
-                       CLK_MULT_STD_FAST_MODE * (clk_div_stdfst_mode + 1) *
-                       i2c_bus->speed * 2);
+               i2c_init_clock(i2c_bus, rate);
        }
 
        /* Reset I2C controller. */
@@ -112,7 +136,9 @@ static void i2c_init_controller(struct i2c_bus *i2c_bus)
                setbits_le32(&dvc->ctrl3, DVC_CTRL_REG3_I2C_HW_SW_PROG_MASK);
        }
 
-       funcmux_select(i2c_bus->periph_id, i2c_bus->pinmux_config);
+#ifndef CONFIG_TEGRA186
+       funcmux_select(i2c_bus->clk.id, i2c_bus->pinmux_config);
+#endif
 }
 
 static void send_packet_headers(
@@ -235,7 +261,7 @@ static int send_recv_packets(struct i2c_bus *i2c_bus,
                        if ((words == 1) && last_bytes) {
                                local = 0;
                                memcpy(&local, dptr, last_bytes);
-                       } else if ((unsigned)dptr & 3) {
+                       } else if ((unsigned long)dptr & 3) {
                                memcpy(&local, dptr, sizeof(u32));
                        } else {
                                local = *wptr;
@@ -258,7 +284,7 @@ static int send_recv_packets(struct i2c_bus *i2c_bus,
                        local = readl(&control->rx_fifo);
                        if ((words == 1) && last_bytes)
                                memcpy(dptr, (char *)&local, last_bytes);
-                       else if ((unsigned)dptr & 3)
+                       else if ((unsigned long)dptr & 3)
                                memcpy(dptr, &local, sizeof(u32));
                        else
                                *wptr = local;
@@ -333,20 +359,34 @@ static int tegra_i2c_set_bus_speed(struct udevice *dev, unsigned int speed)
 static int tegra_i2c_probe(struct udevice *dev)
 {
        struct i2c_bus *i2c_bus = dev_get_priv(dev);
-       const void *blob = gd->fdt_blob;
-       int node = dev->of_offset;
+       int ret;
        bool is_dvc;
 
        i2c_bus->id = dev->seq;
-       i2c_bus->type = dev_get_of_data(dev);
-       i2c_bus->regs = (struct i2c_ctlr *)fdtdec_get_addr(blob, node, "reg");
+       i2c_bus->type = dev_get_driver_data(dev);
+       i2c_bus->regs = (struct i2c_ctlr *)dev_read_addr(dev);
+       if ((ulong)i2c_bus->regs == FDT_ADDR_T_NONE) {
+               debug("%s: Cannot get regs address\n", __func__);
+               return -EINVAL;
+       }
+
+       ret = reset_get_by_name(dev, "i2c", &i2c_bus->reset_ctl);
+       if (ret) {
+               error("reset_get_by_name() failed: %d\n", ret);
+               return ret;
+       }
+       ret = clk_get_by_name(dev, "div-clk", &i2c_bus->clk);
+       if (ret) {
+               error("clk_get_by_name() failed: %d\n", ret);
+               return ret;
+       }
 
+#ifndef CONFIG_TEGRA186
        /*
         * We don't have a binding for pinmux yet. Leave it out for now. So
         * far no one needs anything other than the default.
         */
        i2c_bus->pinmux_config = FUNCMUX_DEFAULT;
-       i2c_bus->periph_id = clock_decode_periph_id(blob, node);
 
        /*
         * We can't specify the pinmux config in the fdt, so I2C2 will not
@@ -354,13 +394,12 @@ static int tegra_i2c_probe(struct udevice *dev)
         * You could add in this little hack if you need to use it.
         * The correct solution is a pinmux binding in the fdt.
         *
-        *      if (i2c_bus->periph_id == PERIPH_ID_I2C2)
+        *      if (i2c_bus->clk.id == PERIPH_ID_I2C2)
         *              i2c_bus->pinmux_config = FUNCMUX_I2C2_PTA;
         */
-       if (i2c_bus->periph_id == -1)
-               return -EINVAL;
+#endif
 
-       is_dvc = dev_get_of_data(dev) == TYPE_DVC;
+       is_dvc = dev_get_driver_data(dev) == TYPE_DVC;
        if (is_dvc) {
                i2c_bus->control =
                        &((struct dvc_ctlr *)i2c_bus->regs)->control;
@@ -368,9 +407,8 @@ static int tegra_i2c_probe(struct udevice *dev)
                i2c_bus->control = &i2c_bus->regs->control;
        }
        i2c_init_controller(i2c_bus);
-       debug("%s: controller bus %d at %p, periph_id %d, speed %d: ",
-             is_dvc ? "dvc" : "i2c", dev->seq, i2c_bus->regs,
-             i2c_bus->periph_id, i2c_bus->speed);
+       debug("%s: controller bus %d at %p, speed %d: ",
+             is_dvc ? "dvc" : "i2c", dev->seq, i2c_bus->regs, i2c_bus->speed);
 
        return 0;
 }
@@ -469,7 +507,7 @@ int tegra_i2c_get_dvc_bus(struct udevice **busp)
        for (uclass_first_device(UCLASS_I2C, &bus);
             bus;
             uclass_next_device(&bus)) {
-               if (dev_get_of_data(bus) == TYPE_DVC) {
+               if (dev_get_driver_data(bus) == TYPE_DVC) {
                        *busp = bus;
                        return 0;
                }
@@ -484,21 +522,6 @@ static const struct dm_i2c_ops tegra_i2c_ops = {
        .set_bus_speed  = tegra_i2c_set_bus_speed,
 };
 
-static int tegra_i2c_child_pre_probe(struct udevice *dev)
-{
-       struct dm_i2c_chip *i2c_chip = dev_get_parentdata(dev);
-
-       if (dev->of_offset == -1)
-               return 0;
-       return i2c_chip_ofdata_to_platdata(gd->fdt_blob, dev->of_offset,
-                                          i2c_chip);
-}
-
-static int tegra_i2c_ofdata_to_platdata(struct udevice *dev)
-{
-       return 0;
-}
-
 static const struct udevice_id tegra_i2c_ids[] = {
        { .compatible = "nvidia,tegra114-i2c", .data = TYPE_114 },
        { .compatible = "nvidia,tegra20-i2c", .data = TYPE_STD },
@@ -510,10 +533,7 @@ U_BOOT_DRIVER(i2c_tegra) = {
        .name   = "i2c_tegra",
        .id     = UCLASS_I2C,
        .of_match = tegra_i2c_ids,
-       .ofdata_to_platdata = tegra_i2c_ofdata_to_platdata,
        .probe  = tegra_i2c_probe,
-       .per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
-       .child_pre_probe = tegra_i2c_child_pre_probe,
        .priv_auto_alloc_size = sizeof(struct i2c_bus),
        .ops    = &tegra_i2c_ops,
 };