aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-designware-platdrv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/i2c-designware-platdrv.c')
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index e59c63ae4d41..a7431150acf7 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -30,6 +30,7 @@
30#include <linux/delay.h> 30#include <linux/delay.h>
31#include <linux/i2c.h> 31#include <linux/i2c.h>
32#include <linux/clk.h> 32#include <linux/clk.h>
33#include <linux/clk-provider.h>
33#include <linux/errno.h> 34#include <linux/errno.h>
34#include <linux/sched.h> 35#include <linux/sched.h>
35#include <linux/err.h> 36#include <linux/err.h>
@@ -80,6 +81,7 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
80static int dw_i2c_acpi_configure(struct platform_device *pdev) 81static int dw_i2c_acpi_configure(struct platform_device *pdev)
81{ 82{
82 struct dw_i2c_dev *dev = platform_get_drvdata(pdev); 83 struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
84 const struct acpi_device_id *id;
83 85
84 dev->adapter.nr = -1; 86 dev->adapter.nr = -1;
85 dev->tx_fifo_depth = 32; 87 dev->tx_fifo_depth = 32;
@@ -93,9 +95,29 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)
93 dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, 95 dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
94 &dev->sda_hold_time); 96 &dev->sda_hold_time);
95 97
98 /*
99 * Provide a way for Designware I2C host controllers that are not
100 * based on Intel LPSS to specify their input clock frequency via
101 * id->driver_data.
102 */
103 id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
104 if (id && id->driver_data)
105 clk_register_fixed_rate(&pdev->dev, dev_name(&pdev->dev), NULL,
106 CLK_IS_ROOT, id->driver_data);
107
96 return 0; 108 return 0;
97} 109}
98 110
111static void dw_i2c_acpi_unconfigure(struct platform_device *pdev)
112{
113 struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
114 const struct acpi_device_id *id;
115
116 id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
117 if (id && id->driver_data)
118 clk_unregister(dev->clk);
119}
120
99static const struct acpi_device_id dw_i2c_acpi_match[] = { 121static const struct acpi_device_id dw_i2c_acpi_match[] = {
100 { "INT33C2", 0 }, 122 { "INT33C2", 0 },
101 { "INT33C3", 0 }, 123 { "INT33C3", 0 },
@@ -103,6 +125,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = {
103 { "INT3433", 0 }, 125 { "INT3433", 0 },
104 { "80860F41", 0 }, 126 { "80860F41", 0 },
105 { "808622C1", 0 }, 127 { "808622C1", 0 },
128 { "AMD0010", 133 * 1000 * 1000 },
106 { } 129 { }
107}; 130};
108MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match); 131MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
@@ -111,6 +134,7 @@ static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
111{ 134{
112 return -ENODEV; 135 return -ENODEV;
113} 136}
137static inline void dw_i2c_acpi_unconfigure(struct platform_device *pdev) { }
114#endif 138#endif
115 139
116static int dw_i2c_probe(struct platform_device *pdev) 140static int dw_i2c_probe(struct platform_device *pdev)
@@ -258,6 +282,9 @@ static int dw_i2c_remove(struct platform_device *pdev)
258 pm_runtime_put(&pdev->dev); 282 pm_runtime_put(&pdev->dev);
259 pm_runtime_disable(&pdev->dev); 283 pm_runtime_disable(&pdev->dev);
260 284
285 if (ACPI_COMPANION(&pdev->dev))
286 dw_i2c_acpi_unconfigure(pdev);
287
261 return 0; 288 return 0;
262} 289}
263 290