aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-designware-platdrv.c
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2013-01-17 05:31:07 -0500
committerWolfram Sang <w.sang@pengutronix.de>2013-01-27 23:26:42 -0500
commitb61b14154b19e1ef1da9c1e283f0cf93470e0c70 (patch)
treec82e1c647347d2f18becf6bec50ff151087469a5 /drivers/i2c/busses/i2c-designware-platdrv.c
parent7272194ed391f9db8bb320c50d715e7e6bba8ff3 (diff)
i2c-designware: add support for Intel Lynxpoint
Intel Lynxpoint has two I2C controllers. These controllers are enumerated from ACPI namespace with IDs INT33C2 and INT33C3. Add support for these to the I2C DesignWare platform driver. This is based on the work of Dirk Brandewie. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
Diffstat (limited to 'drivers/i2c/busses/i2c-designware-platdrv.c')
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c49
1 files changed, 46 insertions, 3 deletions
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index d8afc85420be..d2a33e93f8ab 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -40,6 +40,7 @@
40#include <linux/pm_runtime.h> 40#include <linux/pm_runtime.h>
41#include <linux/io.h> 41#include <linux/io.h>
42#include <linux/slab.h> 42#include <linux/slab.h>
43#include <linux/acpi.h>
43#include "i2c-designware-core.h" 44#include "i2c-designware-core.h"
44 45
45static struct i2c_algorithm i2c_dw_algo = { 46static struct i2c_algorithm i2c_dw_algo = {
@@ -51,6 +52,42 @@ static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
51 return clk_get_rate(dev->clk)/1000; 52 return clk_get_rate(dev->clk)/1000;
52} 53}
53 54
55#ifdef CONFIG_ACPI
56static int dw_i2c_acpi_configure(struct platform_device *pdev)
57{
58 struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
59 struct acpi_device *adev;
60 int busno, ret;
61
62 if (!ACPI_HANDLE(&pdev->dev))
63 return -ENODEV;
64
65 ret = acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev);
66 if (ret)
67 return -ENODEV;
68
69 dev->adapter.nr = -1;
70 if (adev->pnp.unique_id && !kstrtoint(adev->pnp.unique_id, 0, &busno))
71 dev->adapter.nr = busno;
72
73 dev->tx_fifo_depth = 32;
74 dev->rx_fifo_depth = 32;
75 return 0;
76}
77
78static const struct acpi_device_id dw_i2c_acpi_match[] = {
79 { "INT33C2", 0 },
80 { "INT33C3", 0 },
81 { }
82};
83MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
84#else
85static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
86{
87 return -ENODEV;
88}
89#endif
90
54static int dw_i2c_probe(struct platform_device *pdev) 91static int dw_i2c_probe(struct platform_device *pdev)
55{ 92{
56 struct dw_i2c_dev *dev; 93 struct dw_i2c_dev *dev;
@@ -115,18 +152,22 @@ static int dw_i2c_probe(struct platform_device *pdev)
115 r = -EBUSY; 152 r = -EBUSY;
116 goto err_unuse_clocks; 153 goto err_unuse_clocks;
117 } 154 }
118 { 155
156 /* Try first if we can configure the device from ACPI */
157 r = dw_i2c_acpi_configure(pdev);
158 if (r) {
119 u32 param1 = i2c_dw_read_comp_param(dev); 159 u32 param1 = i2c_dw_read_comp_param(dev);
120 160
121 dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1; 161 dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
122 dev->rx_fifo_depth = ((param1 >> 8) & 0xff) + 1; 162 dev->rx_fifo_depth = ((param1 >> 8) & 0xff) + 1;
163 dev->adapter.nr = pdev->id;
123 } 164 }
124 r = i2c_dw_init(dev); 165 r = i2c_dw_init(dev);
125 if (r) 166 if (r)
126 goto err_iounmap; 167 goto err_iounmap;
127 168
128 i2c_dw_disable_int(dev); 169 i2c_dw_disable_int(dev);
129 r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev); 170 r = request_irq(dev->irq, i2c_dw_isr, IRQF_SHARED, pdev->name, dev);
130 if (r) { 171 if (r) {
131 dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq); 172 dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
132 goto err_iounmap; 173 goto err_iounmap;
@@ -141,14 +182,15 @@ static int dw_i2c_probe(struct platform_device *pdev)
141 adap->algo = &i2c_dw_algo; 182 adap->algo = &i2c_dw_algo;
142 adap->dev.parent = &pdev->dev; 183 adap->dev.parent = &pdev->dev;
143 adap->dev.of_node = pdev->dev.of_node; 184 adap->dev.of_node = pdev->dev.of_node;
185 ACPI_HANDLE_SET(&adap->dev, ACPI_HANDLE(&pdev->dev));
144 186
145 adap->nr = pdev->id;
146 r = i2c_add_numbered_adapter(adap); 187 r = i2c_add_numbered_adapter(adap);
147 if (r) { 188 if (r) {
148 dev_err(&pdev->dev, "failure adding adapter\n"); 189 dev_err(&pdev->dev, "failure adding adapter\n");
149 goto err_free_irq; 190 goto err_free_irq;
150 } 191 }
151 of_i2c_register_devices(adap); 192 of_i2c_register_devices(adap);
193 acpi_i2c_register_devices(adap);
152 194
153 pm_runtime_set_active(&pdev->dev); 195 pm_runtime_set_active(&pdev->dev);
154 pm_runtime_enable(&pdev->dev); 196 pm_runtime_enable(&pdev->dev);
@@ -243,6 +285,7 @@ static struct platform_driver dw_i2c_driver = {
243 .name = "i2c_designware", 285 .name = "i2c_designware",
244 .owner = THIS_MODULE, 286 .owner = THIS_MODULE,
245 .of_match_table = of_match_ptr(dw_i2c_of_match), 287 .of_match_table = of_match_ptr(dw_i2c_of_match),
288 .acpi_match_table = ACPI_PTR(dw_i2c_acpi_match),
246 .pm = &dw_i2c_dev_pm_ops, 289 .pm = &dw_i2c_dev_pm_ops,
247 }, 290 },
248}; 291};