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.c46
1 files changed, 40 insertions, 6 deletions
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 4c5fadabe49d..4c1b60539a25 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -35,7 +35,6 @@
35#include <linux/err.h> 35#include <linux/err.h>
36#include <linux/interrupt.h> 36#include <linux/interrupt.h>
37#include <linux/of.h> 37#include <linux/of.h>
38#include <linux/of_i2c.h>
39#include <linux/platform_device.h> 38#include <linux/platform_device.h>
40#include <linux/pm.h> 39#include <linux/pm.h>
41#include <linux/pm_runtime.h> 40#include <linux/pm_runtime.h>
@@ -54,9 +53,33 @@ static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
54} 53}
55 54
56#ifdef CONFIG_ACPI 55#ifdef CONFIG_ACPI
56static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
57 u16 *hcnt, u16 *lcnt, u32 *sda_hold)
58{
59 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
60 acpi_handle handle = ACPI_HANDLE(&pdev->dev);
61 union acpi_object *obj;
62
63 if (ACPI_FAILURE(acpi_evaluate_object(handle, method, NULL, &buf)))
64 return;
65
66 obj = (union acpi_object *)buf.pointer;
67 if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 3) {
68 const union acpi_object *objs = obj->package.elements;
69
70 *hcnt = (u16)objs[0].integer.value;
71 *lcnt = (u16)objs[1].integer.value;
72 if (sda_hold)
73 *sda_hold = (u32)objs[2].integer.value;
74 }
75
76 kfree(buf.pointer);
77}
78
57static int dw_i2c_acpi_configure(struct platform_device *pdev) 79static int dw_i2c_acpi_configure(struct platform_device *pdev)
58{ 80{
59 struct dw_i2c_dev *dev = platform_get_drvdata(pdev); 81 struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
82 bool fs_mode = dev->master_cfg & DW_IC_CON_SPEED_FAST;
60 83
61 if (!ACPI_HANDLE(&pdev->dev)) 84 if (!ACPI_HANDLE(&pdev->dev))
62 return -ENODEV; 85 return -ENODEV;
@@ -64,6 +87,16 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)
64 dev->adapter.nr = -1; 87 dev->adapter.nr = -1;
65 dev->tx_fifo_depth = 32; 88 dev->tx_fifo_depth = 32;
66 dev->rx_fifo_depth = 32; 89 dev->rx_fifo_depth = 32;
90
91 /*
92 * Try to get SDA hold time and *CNT values from an ACPI method if
93 * it exists for both supported speed modes.
94 */
95 dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt,
96 fs_mode ? NULL : &dev->sda_hold_time);
97 dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
98 fs_mode ? &dev->sda_hold_time : NULL);
99
67 return 0; 100 return 0;
68} 101}
69 102
@@ -172,8 +205,6 @@ static int dw_i2c_probe(struct platform_device *pdev)
172 dev_err(&pdev->dev, "failure adding adapter\n"); 205 dev_err(&pdev->dev, "failure adding adapter\n");
173 return r; 206 return r;
174 } 207 }
175 of_i2c_register_devices(adap);
176 acpi_i2c_register_devices(adap);
177 208
178 pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); 209 pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
179 pm_runtime_use_autosuspend(&pdev->dev); 210 pm_runtime_use_autosuspend(&pdev->dev);
@@ -207,7 +238,7 @@ static const struct of_device_id dw_i2c_of_match[] = {
207MODULE_DEVICE_TABLE(of, dw_i2c_of_match); 238MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
208#endif 239#endif
209 240
210#ifdef CONFIG_PM 241#ifdef CONFIG_PM_SLEEP
211static int dw_i2c_suspend(struct device *dev) 242static int dw_i2c_suspend(struct device *dev)
212{ 243{
213 struct platform_device *pdev = to_platform_device(dev); 244 struct platform_device *pdev = to_platform_device(dev);
@@ -228,9 +259,12 @@ static int dw_i2c_resume(struct device *dev)
228 259
229 return 0; 260 return 0;
230} 261}
231#endif
232 262
233static SIMPLE_DEV_PM_OPS(dw_i2c_dev_pm_ops, dw_i2c_suspend, dw_i2c_resume); 263static SIMPLE_DEV_PM_OPS(dw_i2c_dev_pm_ops, dw_i2c_suspend, dw_i2c_resume);
264#define DW_I2C_DEV_PM_OPS (&dw_i2c_dev_pm_ops)
265#else
266#define DW_I2C_DEV_PM_OPS NULL
267#endif
234 268
235/* work with hotplug and coldplug */ 269/* work with hotplug and coldplug */
236MODULE_ALIAS("platform:i2c_designware"); 270MODULE_ALIAS("platform:i2c_designware");
@@ -242,7 +276,7 @@ static struct platform_driver dw_i2c_driver = {
242 .owner = THIS_MODULE, 276 .owner = THIS_MODULE,
243 .of_match_table = of_match_ptr(dw_i2c_of_match), 277 .of_match_table = of_match_ptr(dw_i2c_of_match),
244 .acpi_match_table = ACPI_PTR(dw_i2c_acpi_match), 278 .acpi_match_table = ACPI_PTR(dw_i2c_acpi_match),
245 .pm = &dw_i2c_dev_pm_ops, 279 .pm = DW_I2C_DEV_PM_OPS,
246 }, 280 },
247}; 281};
248 282