|
@@ -30,6 +30,7 @@
|
|
#include <linux/delay.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/i2c.h>
|
|
#include <linux/i2c.h>
|
|
#include <linux/clk.h>
|
|
#include <linux/clk.h>
|
|
|
|
+#include <linux/clk-provider.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/err.h>
|
|
#include <linux/err.h>
|
|
@@ -80,6 +81,7 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
|
|
static int dw_i2c_acpi_configure(struct platform_device *pdev)
|
|
static int dw_i2c_acpi_configure(struct platform_device *pdev)
|
|
{
|
|
{
|
|
struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
|
|
struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
|
|
|
|
+ const struct acpi_device_id *id;
|
|
|
|
|
|
dev->adapter.nr = -1;
|
|
dev->adapter.nr = -1;
|
|
dev->tx_fifo_depth = 32;
|
|
dev->tx_fifo_depth = 32;
|
|
@@ -93,9 +95,29 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)
|
|
dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
|
|
dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
|
|
&dev->sda_hold_time);
|
|
&dev->sda_hold_time);
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Provide a way for Designware I2C host controllers that are not
|
|
|
|
+ * based on Intel LPSS to specify their input clock frequency via
|
|
|
|
+ * id->driver_data.
|
|
|
|
+ */
|
|
|
|
+ id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
|
|
|
|
+ if (id && id->driver_data)
|
|
|
|
+ clk_register_fixed_rate(&pdev->dev, dev_name(&pdev->dev), NULL,
|
|
|
|
+ CLK_IS_ROOT, id->driver_data);
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void dw_i2c_acpi_unconfigure(struct platform_device *pdev)
|
|
|
|
+{
|
|
|
|
+ struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
|
|
|
|
+ const struct acpi_device_id *id;
|
|
|
|
+
|
|
|
|
+ id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
|
|
|
|
+ if (id && id->driver_data)
|
|
|
|
+ clk_unregister(dev->clk);
|
|
|
|
+}
|
|
|
|
+
|
|
static const struct acpi_device_id dw_i2c_acpi_match[] = {
|
|
static const struct acpi_device_id dw_i2c_acpi_match[] = {
|
|
{ "INT33C2", 0 },
|
|
{ "INT33C2", 0 },
|
|
{ "INT33C3", 0 },
|
|
{ "INT33C3", 0 },
|
|
@@ -103,6 +125,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = {
|
|
{ "INT3433", 0 },
|
|
{ "INT3433", 0 },
|
|
{ "80860F41", 0 },
|
|
{ "80860F41", 0 },
|
|
{ "808622C1", 0 },
|
|
{ "808622C1", 0 },
|
|
|
|
+ { "AMD0010", 133 * 1000 * 1000 },
|
|
{ }
|
|
{ }
|
|
};
|
|
};
|
|
MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
|
|
MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
|
|
@@ -111,6 +134,7 @@ static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
|
|
{
|
|
{
|
|
return -ENODEV;
|
|
return -ENODEV;
|
|
}
|
|
}
|
|
|
|
+static inline void dw_i2c_acpi_unconfigure(struct platform_device *pdev) { }
|
|
#endif
|
|
#endif
|
|
|
|
|
|
static int dw_i2c_probe(struct platform_device *pdev)
|
|
static int dw_i2c_probe(struct platform_device *pdev)
|
|
@@ -258,6 +282,9 @@ static int dw_i2c_remove(struct platform_device *pdev)
|
|
pm_runtime_put(&pdev->dev);
|
|
pm_runtime_put(&pdev->dev);
|
|
pm_runtime_disable(&pdev->dev);
|
|
pm_runtime_disable(&pdev->dev);
|
|
|
|
|
|
|
|
+ if (ACPI_COMPANION(&pdev->dev))
|
|
|
|
+ dw_i2c_acpi_unconfigure(pdev);
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|