|
@@ -157,11 +157,48 @@ static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
|
|
|
#endif
|
|
|
|
|
|
#ifdef CONFIG_OF
|
|
|
+#define MSCC_ICPU_CFG_TWI_DELAY 0x0
|
|
|
+#define MSCC_ICPU_CFG_TWI_DELAY_ENABLE BIT(0)
|
|
|
+#define MSCC_ICPU_CFG_TWI_SPIKE_FILTER 0x4
|
|
|
+
|
|
|
+static int mscc_twi_set_sda_hold_time(struct dw_i2c_dev *dev)
|
|
|
+{
|
|
|
+ writel((dev->sda_hold_time << 1) | MSCC_ICPU_CFG_TWI_DELAY_ENABLE,
|
|
|
+ dev->ext + MSCC_ICPU_CFG_TWI_DELAY);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int dw_i2c_of_configure(struct platform_device *pdev)
|
|
|
+{
|
|
|
+ struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
|
|
|
+ struct resource *mem;
|
|
|
+
|
|
|
+ switch (dev->flags & MODEL_MASK) {
|
|
|
+ case MODEL_MSCC_OCELOT:
|
|
|
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
|
|
+ dev->ext = devm_ioremap_resource(&pdev->dev, mem);
|
|
|
+ if (!IS_ERR(dev->ext))
|
|
|
+ dev->set_sda_hold_time = mscc_twi_set_sda_hold_time;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static const struct of_device_id dw_i2c_of_match[] = {
|
|
|
{ .compatible = "snps,designware-i2c", },
|
|
|
+ { .compatible = "mscc,ocelot-i2c", .data = (void *)MODEL_MSCC_OCELOT },
|
|
|
{},
|
|
|
};
|
|
|
MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
|
|
|
+#else
|
|
|
+static inline int dw_i2c_of_configure(struct platform_device *pdev)
|
|
|
+{
|
|
|
+ return -ENODEV;
|
|
|
+}
|
|
|
#endif
|
|
|
|
|
|
static void i2c_dw_configure_master(struct dw_i2c_dev *dev)
|
|
@@ -296,6 +333,9 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
|
|
|
|
|
|
dev->flags |= (uintptr_t)device_get_match_data(&pdev->dev);
|
|
|
|
|
|
+ if (pdev->dev.of_node)
|
|
|
+ dw_i2c_of_configure(pdev);
|
|
|
+
|
|
|
if (has_acpi_companion(&pdev->dev))
|
|
|
dw_i2c_acpi_configure(pdev);
|
|
|
|