rockchip,drive = <VALUE_DRV_DEFAULT>;
//rockchip,tristate = <VALUE_TRI_DEFAULT>;
};
+
+ i2c0_gpio: i2c0-gpio {
+ rockchip,pins = <FUNC_TO_GPIO(I2C0_SDA)>, <FUNC_TO_GPIO(I2C0_SCL)>;
+ rockchip,drive = <VALUE_DRV_DEFAULT>;
+ };
};
gpio1_i2c1 {
rockchip,drive = <VALUE_DRV_DEFAULT>;
//rockchip,tristate = <VALUE_TRI_DEFAULT>;
};
+
+ i2c1_gpio: i2c1-gpio {
+ rockchip,pins = <FUNC_TO_GPIO(I2C1_SDA)>, <FUNC_TO_GPIO(I2C1_SCL)>;
+ rockchip,drive = <VALUE_DRV_DEFAULT>;
+ };
};
gpio1_i2c2 {
rockchip,drive = <VALUE_DRV_DEFAULT>;
//rockchip,tristate = <VALUE_TRI_DEFAULT>;
};
+
+ i2c2_gpio: i2c2-gpio {
+ rockchip,pins = <FUNC_TO_GPIO(I2C2_SDA)>, <FUNC_TO_GPIO(I2C2_SCL)>;
+ rockchip,drive = <VALUE_DRV_DEFAULT>;
+ };
};
gpio1_i2c3 {
rockchip,drive = <VALUE_DRV_DEFAULT>;
//rockchip,tristate = <VALUE_TRI_DEFAULT>;
};
+
+ i2c3_gpio: i2c3-gpio {
+ rockchip,pins = <FUNC_TO_GPIO(I2C3_SDA)>, <FUNC_TO_GPIO(I2C3_SCL)>;
+ rockchip,drive = <VALUE_DRV_DEFAULT>;
+ };
};
gpio1_i2c4 {
rockchip,drive = <VALUE_DRV_DEFAULT>;
//rockchip,tristate = <VALUE_TRI_DEFAULT>;
};
+
+ i2c4_gpio: i2c4-gpio {
+ rockchip,pins = <FUNC_TO_GPIO(I2C4_SDA)>, <FUNC_TO_GPIO(I2C4_SCL)>;
+ rockchip,drive = <VALUE_DRV_DEFAULT>;
+ };
};
gpio1_spi0 {
interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&i2c0_sda &i2c0_scl>;
+ pinctrl-1 = <&i2c0_gpio>;
+ gpios = <&gpio1 GPIO_D0 GPIO_ACTIVE_LOW>, <&gpio1 GPIO_D1 GPIO_ACTIVE_LOW>;
+ clocks = <&clk_gates8 4>;
+ rockchip,check-idle = <1>;
status = "disabled";
};
interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&i2c1_sda &i2c1_scl>;
+ pinctrl-1 = <&i2c1_gpio>;
+ gpios = <&gpio1 GPIO_D2 GPIO_ACTIVE_LOW>, <&gpio1 GPIO_D3 GPIO_ACTIVE_LOW>;
+ clocks = <&clk_gates8 5>;
+ rockchip,check-idle = <1>;
status = "disabled";
};
interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&i2c2_sda &i2c2_scl>;
+ pinctrl-1 = <&i2c2_gpio>;
+ gpios = <&gpio1 GPIO_D4 GPIO_ACTIVE_LOW>, <&gpio1 GPIO_D5 GPIO_ACTIVE_LOW>;
+ clocks = <&clk_gates8 6>;
+ rockchip,check-idle = <1>;
status = "disabled";
};
interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&i2c3_sda &i2c3_scl>;
+ pinctrl-1 = <&i2c3_gpio>;
+ gpios = <&gpio3 GPIO_B6 GPIO_ACTIVE_LOW>, <&gpio3 GPIO_B7 GPIO_ACTIVE_LOW>;
+ clocks = <&clk_gates8 7>;
+ rockchip,check-idle = <1>;
status = "disabled";
};
interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&i2c4_sda &i2c4_scl>;
+ pinctrl-1 = <&i2c4_gpio>;
+ gpios = <&gpio1 GPIO_D6 GPIO_ACTIVE_LOW>, <&gpio1 GPIO_D7 GPIO_ACTIVE_LOW>;
+ clocks = <&clk_gates8 8>;
+ rockchip,check-idle = <1>;
status = "disabled";
};
-
+
clocks-init{
compatible = "rockchip,clocks-init";
rockchip,clocks-init-rate =<&clk_cpll 768000000>,<&clk_gpll 594000000>;
rockchip,clocks-init-parent =<&aclk_peri_mux &clk_gpll>,<&aclk_cpu &clk_gpll>;
};
-
};
-
-
-
/*
- * Copyright (C) 2012, 2013 ROCKCHIP, Inc.
+ * Copyright (C) 2012-2014 ROCKCHIP, Inc.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
#include <linux/module.h>
#include <linux/wakelock.h>
#include <linux/i2c.h>
+#include <linux/of_gpio.h>
#include <linux/of_i2c.h>
#include <linux/init.h>
#include <linux/time.h>
#define i2c_dbg(dev, format, arg...)
#endif
-//#define I2C_CHECK_IDLE
-
enum {
I2C_IDLE = 0,
I2C_SDA_LOW,
unsigned int mode;
unsigned int count;
- int sda_mode, scl_mode;
-
- struct wake_lock idlelock[5];
+ unsigned int check_idle;
+ int sda_gpio, scl_gpio;
+ struct pinctrl_state *gpio_state;
};
#define COMPLETE_READ (1<<STATE_START | 1<<STATE_READ | 1<<STATE_STOP)
dev_info(i2c->dev, "I2C_RXDATA%d: 0x%08x\n", i, i2c_readl(i2c->regs + I2C_RXDATA_BASE + i * 4));
}
-#ifdef I2C_CHECK_IDLE
static int rockchip_i2c_check_idle(struct rockchip_i2c *i2c)
{
- int ret = 0;
- int sda_io, scl_io;
+ int ret = I2C_IDLE;
int sda_lev, scl_lev;
- sda_io = iomux_mode_to_gpio(i2c->sda_mode);
- scl_io = iomux_mode_to_gpio(i2c->scl_mode);
-
- ret = gpio_request(sda_io, NULL);
- if (unlikely(ret < 0)) {
- dev_err(i2c->dev, "Failed to request gpio: SDA_GPIO\n");
- return ret;
- }
- ret = gpio_request(scl_io, NULL);
- if (unlikely(ret < 0)) {
- dev_err(i2c->dev, "Failed to request gpio: SCL_GPIO\n");
- gpio_free(sda_io);
+ if (!gpio_is_valid(i2c->sda_gpio))
return ret;
- }
- gpio_direction_input(sda_io);
- gpio_direction_input(scl_io);
- sda_lev = gpio_get_value(sda_io);
- scl_lev = gpio_get_value(scl_io);
+ if (pinctrl_select_state(i2c->dev->pins->p, i2c->gpio_state))
+ return ret;
- gpio_free(sda_io);
- gpio_free(scl_io);
+ sda_lev = gpio_get_value(i2c->sda_gpio);
+ scl_lev = gpio_get_value(i2c->scl_gpio);
- iomux_set(i2c->sda_mode);
- iomux_set(i2c->scl_mode);
+ pinctrl_select_state(i2c->dev->pins->p, i2c->dev->pins->default_state);
if (sda_lev == 1 && scl_lev == 1)
return I2C_IDLE;
else
return BOTH_LOW;
}
-#endif
static inline void rockchip_i2c_enable(struct rockchip_i2c *i2c, unsigned int lastnak)
{
unsigned long i2c_rate = clk_get_rate(i2c->clk);
int div, divl, divh;
- if (!i2c_rate)
- i2c_rate = 9375000;
-
if ((scl_rate == i2c->scl_rate) && (i2c_rate == i2c->i2c_rate))
return;
i2c->i2c_rate = i2c_rate;
}
i2c_writel(I2C_CLKDIV_VAL(divl, divh), i2c->regs + I2C_CLKDIV);
i2c_dbg(i2c->dev, "set clk(I2C_CLKDIV: 0x%08x)\n", i2c_readl(i2c->regs + I2C_CLKDIV));
- dev_info(i2c->dev, "set clk(I2C_CLKDIV: 0x%08x)\n", i2c_readl(i2c->regs + I2C_CLKDIV));
}
static void rockchip_i2c_init_hw(struct rockchip_i2c *i2c, unsigned long scl_rate)
{
i2c->scl_rate = 0;
- clk_enable(i2c->clk);
+ clk_prepare_enable(i2c->clk);
rockchip_i2c_set_clk(i2c, scl_rate);
- clk_disable(i2c->clk);
+ clk_disable_unprepare(i2c->clk);
}
/* returns TRUE if we this is the last byte in the current message */
static int rockchip_i2c_xfer(struct i2c_adapter *adap,
struct i2c_msg *msgs, int num)
{
-#ifdef I2C_CHECK_IDLE
- int state, retry = 10;
-#endif
int ret;
struct rockchip_i2c *i2c = i2c_get_adapdata(adap);
unsigned long scl_rate = i2c->scl_rate;
- clk_enable(i2c->clk);
-#ifdef I2C_CHECK_IDLE
- int state, retry = 10;
- while (retry-- && ((state = rockchip_i2c_check_idle(i2c)) != I2C_IDLE)) {
- if (in_atomic())
- mdelay(10);
- else
- msleep(10);
- }
- if (retry == 0) {
- dev_err(i2c->dev, "i2c is not in idle(state = %d)\n", state);
- return -EIO;
+ clk_prepare_enable(i2c->clk);
+ if (i2c->check_idle) {
+ int state, retry = 10;
+ while (retry--) {
+ state = rockchip_i2c_check_idle(i2c);
+ if (state == I2C_IDLE)
+ break;
+ if (in_atomic())
+ mdelay(10);
+ else
+ msleep(10);
+ }
+ if (retry == 0) {
+ dev_err(i2c->dev, "i2c is not in idle(state = %d)\n", state);
+ return -EIO;
+ }
}
-#endif
#ifdef CONFIG_I2C_ROCKCHIP_COMPAT
if (msgs[0].scl_rate <= 400000 && msgs[0].scl_rate >= 10000)
ret = rockchip_i2c_doxfer(i2c, msgs, num);
i2c_dbg(i2c->dev, "i2c transfer stop: addr: 0x%04x, state: %d, ret: %d\n", msgs[0].addr, ret, i2c->state);
- clk_disable(i2c->clk);
+ clk_disable_unprepare(i2c->clk);
return (ret < 0) ? ret : num;
}
.functionality = rockchip_i2c_func,
};
-static int i2c_max_adap;
-
/* rockchip_i2c_probe
*
* called by the bus driver when a suitable device is found
i2c_dbg(&pdev->dev, "registers %p (%p, %p)\n",
i2c->regs, i2c->ioarea, res);
+ i2c->check_idle = true;
+ of_property_read_u32(np, "rockchip,check-idle", &i2c->check_idle);
+ if (i2c->check_idle) {
+ i2c->sda_gpio = of_get_gpio(np, 0);
+ if (!gpio_is_valid(i2c->sda_gpio)) {
+ dev_err(&pdev->dev, "sda gpio is invalid\n");
+ return -EINVAL;
+ }
+ ret = devm_gpio_request(&pdev->dev, i2c->sda_gpio, dev_name(&i2c->adap.dev));
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request sda gpio\n");
+ return ret;
+ }
+ i2c->scl_gpio = of_get_gpio(np, 1);
+ if (!gpio_is_valid(i2c->scl_gpio)) {
+ dev_err(&pdev->dev, "scl gpio is invalid\n");
+ return -EINVAL;
+ }
+ ret = devm_gpio_request(&pdev->dev, i2c->scl_gpio, dev_name(&i2c->adap.dev));
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request scl gpio\n");
+ return ret;
+ }
+ i2c->gpio_state = pinctrl_lookup_state(i2c->dev->pins->p, "gpio");
+ if (IS_ERR(i2c->gpio_state)) {
+ dev_err(&pdev->dev, "no gpio pinctrl state\n");
+ return PTR_ERR(i2c->gpio_state);
+ }
+ gpio_direction_input(i2c->sda_gpio);
+ gpio_direction_input(i2c->scl_gpio);
+ pinctrl_select_state(i2c->dev->pins->p, i2c->dev->pins->default_state);
+ }
+
/* setup info block for the i2c core */
ret = i2c_add_adapter(&i2c->adap);
if (ret < 0) {
return ret;
}
+ platform_set_drvdata(pdev, i2c);
+
+ /* find the clock and enable it */
+ i2c->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(i2c->clk)) {
+ dev_err(&pdev->dev, "cannot get clock\n");
+ return PTR_ERR(i2c->clk);
+ }
+
+ i2c_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
+
/* find the IRQ for this unit (note, this relies on the init call to
* ensure no current IRQs pending
*/
return ret;
}
- /* find the clock and enable it */
- i2c->clk = clk_get(&pdev->dev, "i2c");
- if (IS_ERR(i2c->clk)) {
- dev_err(&pdev->dev, "cannot get clock\n");
- i2c->clk = NULL;
-// return PTR_ERR(i2c->clk);
- }
-
- i2c_dbg(&pdev->dev, "clock source %p\n", i2c->clk);
-
- platform_set_drvdata(pdev, i2c);
-
+ clk_prepare_enable(i2c->clk); // FIXME: enable i2c clock temporarily
rockchip_i2c_init_hw(i2c, 100 * 1000);
- i2c_max_adap++;
dev_info(&pdev->dev, "%s: Rockchip I2C adapter\n", dev_name(&i2c->adap.dev));
of_i2c_register_devices(&i2c->adap);
struct rockchip_i2c *i2c = platform_get_drvdata(pdev);
i2c_del_adapter(&i2c->adap);
- clk_put(i2c->clk);
return 0;
}
struct rockchip_i2c *i2c = platform_get_drvdata(pdev);
i2c->suspended = 1;
+ pinctrl_pm_select_sleep_state(dev);
return 0;
}
struct platform_device *pdev = to_platform_device(dev);
struct rockchip_i2c *i2c = platform_get_drvdata(pdev);
- i2c->suspended = 0;
+ pinctrl_pm_select_default_state(dev);
rockchip_i2c_init_hw(i2c, i2c->scl_rate);
+ i2c->suspended = 0;
return 0;
}