|
@@ -60,6 +60,12 @@
|
|
#define DAVINCI_I2C_IVR_REG 0x28
|
|
#define DAVINCI_I2C_IVR_REG 0x28
|
|
#define DAVINCI_I2C_EMDR_REG 0x2c
|
|
#define DAVINCI_I2C_EMDR_REG 0x2c
|
|
#define DAVINCI_I2C_PSC_REG 0x30
|
|
#define DAVINCI_I2C_PSC_REG 0x30
|
|
|
|
+#define DAVINCI_I2C_FUNC_REG 0x48
|
|
|
|
+#define DAVINCI_I2C_DIR_REG 0x4c
|
|
|
|
+#define DAVINCI_I2C_DIN_REG 0x50
|
|
|
|
+#define DAVINCI_I2C_DOUT_REG 0x54
|
|
|
|
+#define DAVINCI_I2C_DSET_REG 0x58
|
|
|
|
+#define DAVINCI_I2C_DCLR_REG 0x5c
|
|
|
|
|
|
#define DAVINCI_I2C_IVR_AAS 0x07
|
|
#define DAVINCI_I2C_IVR_AAS 0x07
|
|
#define DAVINCI_I2C_IVR_SCD 0x06
|
|
#define DAVINCI_I2C_IVR_SCD 0x06
|
|
@@ -93,6 +99,29 @@
|
|
#define DAVINCI_I2C_IMR_NACK BIT(1)
|
|
#define DAVINCI_I2C_IMR_NACK BIT(1)
|
|
#define DAVINCI_I2C_IMR_AL BIT(0)
|
|
#define DAVINCI_I2C_IMR_AL BIT(0)
|
|
|
|
|
|
|
|
+/* set SDA and SCL as GPIO */
|
|
|
|
+#define DAVINCI_I2C_FUNC_PFUNC0 BIT(0)
|
|
|
|
+
|
|
|
|
+/* set SCL as output when used as GPIO*/
|
|
|
|
+#define DAVINCI_I2C_DIR_PDIR0 BIT(0)
|
|
|
|
+/* set SDA as output when used as GPIO*/
|
|
|
|
+#define DAVINCI_I2C_DIR_PDIR1 BIT(1)
|
|
|
|
+
|
|
|
|
+/* read SCL GPIO level */
|
|
|
|
+#define DAVINCI_I2C_DIN_PDIN0 BIT(0)
|
|
|
|
+/* read SDA GPIO level */
|
|
|
|
+#define DAVINCI_I2C_DIN_PDIN1 BIT(1)
|
|
|
|
+
|
|
|
|
+/*set the SCL GPIO high */
|
|
|
|
+#define DAVINCI_I2C_DSET_PDSET0 BIT(0)
|
|
|
|
+/*set the SDA GPIO high */
|
|
|
|
+#define DAVINCI_I2C_DSET_PDSET1 BIT(1)
|
|
|
|
+
|
|
|
|
+/* set the SCL GPIO low */
|
|
|
|
+#define DAVINCI_I2C_DCLR_PDCLR0 BIT(0)
|
|
|
|
+/* set the SDA GPIO low */
|
|
|
|
+#define DAVINCI_I2C_DCLR_PDCLR1 BIT(1)
|
|
|
|
+
|
|
struct davinci_i2c_dev {
|
|
struct davinci_i2c_dev {
|
|
struct device *dev;
|
|
struct device *dev;
|
|
void __iomem *base;
|
|
void __iomem *base;
|
|
@@ -253,6 +282,71 @@ static struct i2c_bus_recovery_info davinci_i2c_gpio_recovery_info = {
|
|
.unprepare_recovery = davinci_i2c_unprepare_recovery,
|
|
.unprepare_recovery = davinci_i2c_unprepare_recovery,
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+static void davinci_i2c_set_scl(struct i2c_adapter *adap, int val)
|
|
|
|
+{
|
|
|
|
+ struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
|
|
|
|
+
|
|
|
|
+ if (val)
|
|
|
|
+ davinci_i2c_write_reg(dev, DAVINCI_I2C_DSET_REG,
|
|
|
|
+ DAVINCI_I2C_DSET_PDSET0);
|
|
|
|
+ else
|
|
|
|
+ davinci_i2c_write_reg(dev, DAVINCI_I2C_DCLR_REG,
|
|
|
|
+ DAVINCI_I2C_DCLR_PDCLR0);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int davinci_i2c_get_scl(struct i2c_adapter *adap)
|
|
|
|
+{
|
|
|
|
+ struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
|
|
|
|
+ int val;
|
|
|
|
+
|
|
|
|
+ /* read the state of SCL */
|
|
|
|
+ val = davinci_i2c_read_reg(dev, DAVINCI_I2C_DIN_REG);
|
|
|
|
+ return val & DAVINCI_I2C_DIN_PDIN0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int davinci_i2c_get_sda(struct i2c_adapter *adap)
|
|
|
|
+{
|
|
|
|
+ struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
|
|
|
|
+ int val;
|
|
|
|
+
|
|
|
|
+ /* read the state of SDA */
|
|
|
|
+ val = davinci_i2c_read_reg(dev, DAVINCI_I2C_DIN_REG);
|
|
|
|
+ return val & DAVINCI_I2C_DIN_PDIN1;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void davinci_i2c_scl_prepare_recovery(struct i2c_adapter *adap)
|
|
|
|
+{
|
|
|
|
+ struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
|
|
|
|
+
|
|
|
|
+ davinci_i2c_prepare_recovery(adap);
|
|
|
|
+
|
|
|
|
+ /* SCL output, SDA input */
|
|
|
|
+ davinci_i2c_write_reg(dev, DAVINCI_I2C_DIR_REG, DAVINCI_I2C_DIR_PDIR0);
|
|
|
|
+
|
|
|
|
+ /* change to GPIO mode */
|
|
|
|
+ davinci_i2c_write_reg(dev, DAVINCI_I2C_FUNC_REG,
|
|
|
|
+ DAVINCI_I2C_FUNC_PFUNC0);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void davinci_i2c_scl_unprepare_recovery(struct i2c_adapter *adap)
|
|
|
|
+{
|
|
|
|
+ struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
|
|
|
|
+
|
|
|
|
+ /* change back to I2C mode */
|
|
|
|
+ davinci_i2c_write_reg(dev, DAVINCI_I2C_FUNC_REG, 0);
|
|
|
|
+
|
|
|
|
+ davinci_i2c_unprepare_recovery(adap);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct i2c_bus_recovery_info davinci_i2c_scl_recovery_info = {
|
|
|
|
+ .recover_bus = i2c_generic_scl_recovery,
|
|
|
|
+ .set_scl = davinci_i2c_set_scl,
|
|
|
|
+ .get_scl = davinci_i2c_get_scl,
|
|
|
|
+ .get_sda = davinci_i2c_get_sda,
|
|
|
|
+ .prepare_recovery = davinci_i2c_scl_prepare_recovery,
|
|
|
|
+ .unprepare_recovery = davinci_i2c_scl_unprepare_recovery,
|
|
|
|
+};
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Waiting for bus not busy
|
|
* Waiting for bus not busy
|
|
*/
|
|
*/
|
|
@@ -660,6 +754,10 @@ static int davinci_i2c_probe(struct platform_device *pdev)
|
|
if (!of_property_read_u32(pdev->dev.of_node, "clock-frequency",
|
|
if (!of_property_read_u32(pdev->dev.of_node, "clock-frequency",
|
|
&prop))
|
|
&prop))
|
|
dev->pdata->bus_freq = prop / 1000;
|
|
dev->pdata->bus_freq = prop / 1000;
|
|
|
|
+
|
|
|
|
+ dev->pdata->has_pfunc =
|
|
|
|
+ of_property_read_bool(pdev->dev.of_node,
|
|
|
|
+ "ti,has-pfunc");
|
|
} else if (!dev->pdata) {
|
|
} else if (!dev->pdata) {
|
|
dev->pdata = &davinci_i2c_platform_data_default;
|
|
dev->pdata = &davinci_i2c_platform_data_default;
|
|
}
|
|
}
|
|
@@ -701,7 +799,9 @@ static int davinci_i2c_probe(struct platform_device *pdev)
|
|
adap->timeout = DAVINCI_I2C_TIMEOUT;
|
|
adap->timeout = DAVINCI_I2C_TIMEOUT;
|
|
adap->dev.of_node = pdev->dev.of_node;
|
|
adap->dev.of_node = pdev->dev.of_node;
|
|
|
|
|
|
- if (dev->pdata->scl_pin) {
|
|
|
|
|
|
+ if (dev->pdata->has_pfunc)
|
|
|
|
+ adap->bus_recovery_info = &davinci_i2c_scl_recovery_info;
|
|
|
|
+ else if (dev->pdata->scl_pin) {
|
|
adap->bus_recovery_info = &davinci_i2c_gpio_recovery_info;
|
|
adap->bus_recovery_info = &davinci_i2c_gpio_recovery_info;
|
|
adap->bus_recovery_info->scl_gpio = dev->pdata->scl_pin;
|
|
adap->bus_recovery_info->scl_gpio = dev->pdata->scl_pin;
|
|
adap->bus_recovery_info->sda_gpio = dev->pdata->sda_pin;
|
|
adap->bus_recovery_info->sda_gpio = dev->pdata->sda_pin;
|