1 /* 2 * Synopsys DesignWare I2C adapter driver (master only). 3 * 4 * Based on the TI DAVINCI I2C adapter driver. 5 * 6 * Copyright (C) 2006 Texas Instruments. 7 * Copyright (C) 2007 MontaVista Software Inc. 8 * Copyright (C) 2009 Provigent Ltd. 9 * Copyright (C) 2011 Intel corporation. 10 * 11 * ---------------------------------------------------------------------------- 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or 16 * (at your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 26 * ---------------------------------------------------------------------------- 27 * 28 */ 29 30 #include <linux/kernel.h> 31 #include <linux/module.h> 32 #include <linux/delay.h> 33 #include <linux/i2c.h> 34 #include <linux/errno.h> 35 #include <linux/sched.h> 36 #include <linux/err.h> 37 #include <linux/interrupt.h> 38 #include <linux/io.h> 39 #include <linux/slab.h> 40 #include <linux/pci.h> 41 #include <linux/pm_runtime.h> 42 #include "i2c-designware-core.h" 43 44 #define DRIVER_NAME "i2c-designware-pci" 45 46 enum dw_pci_ctl_id_t { 47 moorestown_0, 48 moorestown_1, 49 moorestown_2, 50 51 medfield_0, 52 medfield_1, 53 medfield_2, 54 medfield_3, 55 medfield_4, 56 medfield_5, 57 }; 58 59 struct dw_pci_controller { 60 u32 bus_num; 61 u32 bus_cfg; 62 u32 tx_fifo_depth; 63 u32 rx_fifo_depth; 64 u32 clk_khz; 65 }; 66 67 #define INTEL_MID_STD_CFG (DW_IC_CON_MASTER | \ 68 DW_IC_CON_SLAVE_DISABLE | \ 69 DW_IC_CON_RESTART_EN) 70 71 static struct dw_pci_controller dw_pci_controllers[] = { 72 [moorestown_0] = { 73 .bus_num = 0, 74 .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, 75 .tx_fifo_depth = 32, 76 .rx_fifo_depth = 32, 77 .clk_khz = 25000, 78 }, 79 [moorestown_1] = { 80 .bus_num = 1, 81 .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, 82 .tx_fifo_depth = 32, 83 .rx_fifo_depth = 32, 84 .clk_khz = 25000, 85 }, 86 [moorestown_2] = { 87 .bus_num = 2, 88 .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, 89 .tx_fifo_depth = 32, 90 .rx_fifo_depth = 32, 91 .clk_khz = 25000, 92 }, 93 [medfield_0] = { 94 .bus_num = 0, 95 .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, 96 .tx_fifo_depth = 32, 97 .rx_fifo_depth = 32, 98 .clk_khz = 25000, 99 }, 100 [medfield_1] = { 101 .bus_num = 1, 102 .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, 103 .tx_fifo_depth = 32, 104 .rx_fifo_depth = 32, 105 .clk_khz = 25000, 106 }, 107 [medfield_2] = { 108 .bus_num = 2, 109 .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, 110 .tx_fifo_depth = 32, 111 .rx_fifo_depth = 32, 112 .clk_khz = 25000, 113 }, 114 [medfield_3] = { 115 .bus_num = 3, 116 .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_STD, 117 .tx_fifo_depth = 32, 118 .rx_fifo_depth = 32, 119 .clk_khz = 25000, 120 }, 121 [medfield_4] = { 122 .bus_num = 4, 123 .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, 124 .tx_fifo_depth = 32, 125 .rx_fifo_depth = 32, 126 .clk_khz = 25000, 127 }, 128 [medfield_5] = { 129 .bus_num = 5, 130 .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, 131 .tx_fifo_depth = 32, 132 .rx_fifo_depth = 32, 133 .clk_khz = 25000, 134 }, 135 }; 136 static struct i2c_algorithm i2c_dw_algo = { 137 .master_xfer = i2c_dw_xfer, 138 .functionality = i2c_dw_func, 139 }; 140 141 static int i2c_dw_pci_suspend(struct device *dev) 142 { 143 struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); 144 struct dw_i2c_dev *i2c = pci_get_drvdata(pdev); 145 int err; 146 147 148 i2c_dw_disable(i2c); 149 150 err = pci_save_state(pdev); 151 if (err) { 152 dev_err(&pdev->dev, "pci_save_state failed\n"); 153 return err; 154 } 155 156 err = pci_set_power_state(pdev, PCI_D3hot); 157 if (err) { 158 dev_err(&pdev->dev, "pci_set_power_state failed\n"); 159 return err; 160 } 161 162 return 0; 163 } 164 165 static int i2c_dw_pci_resume(struct device *dev) 166 { 167 struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); 168 struct dw_i2c_dev *i2c = pci_get_drvdata(pdev); 169 int err; 170 u32 enabled; 171 172 enabled = i2c_dw_is_enabled(i2c); 173 if (enabled) 174 return 0; 175 176 err = pci_set_power_state(pdev, PCI_D0); 177 if (err) { 178 dev_err(&pdev->dev, "pci_set_power_state() failed\n"); 179 return err; 180 } 181 182 pci_restore_state(pdev); 183 184 i2c_dw_init(i2c); 185 i2c_dw_enable(i2c); 186 return 0; 187 } 188 189 static int i2c_dw_pci_runtime_idle(struct device *dev) 190 { 191 int err = pm_schedule_suspend(dev, 500); 192 dev_dbg(dev, "runtime_idle called\n"); 193 194 if (err != 0) 195 return 0; 196 return -EBUSY; 197 } 198 199 static const struct dev_pm_ops i2c_dw_pm_ops = { 200 .resume = i2c_dw_pci_resume, 201 .suspend = i2c_dw_pci_suspend, 202 SET_RUNTIME_PM_OPS(i2c_dw_pci_suspend, i2c_dw_pci_resume, 203 i2c_dw_pci_runtime_idle) 204 }; 205 206 static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev) 207 { 208 return dev->controller->clk_khz; 209 } 210 211 static int __devinit i2c_dw_pci_probe(struct pci_dev *pdev, 212 const struct pci_device_id *id) 213 { 214 struct dw_i2c_dev *dev; 215 struct i2c_adapter *adap; 216 unsigned long start, len; 217 void __iomem *base; 218 int r; 219 struct dw_pci_controller *controller; 220 221 if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) { 222 printk(KERN_ERR "dw_i2c_pci_probe: invalid driver data %ld\n", 223 id->driver_data); 224 return -EINVAL; 225 } 226 227 controller = &dw_pci_controllers[id->driver_data]; 228 229 r = pci_enable_device(pdev); 230 if (r) { 231 dev_err(&pdev->dev, "Failed to enable I2C PCI device (%d)\n", 232 r); 233 goto exit; 234 } 235 236 /* Determine the address of the I2C area */ 237 start = pci_resource_start(pdev, 0); 238 len = pci_resource_len(pdev, 0); 239 if (!start || len == 0) { 240 dev_err(&pdev->dev, "base address not set\n"); 241 r = -ENODEV; 242 goto exit; 243 } 244 245 r = pci_request_region(pdev, 0, DRIVER_NAME); 246 if (r) { 247 dev_err(&pdev->dev, "failed to request I2C region " 248 "0x%lx-0x%lx\n", start, 249 (unsigned long)pci_resource_end(pdev, 0)); 250 goto exit; 251 } 252 253 base = ioremap_nocache(start, len); 254 if (!base) { 255 dev_err(&pdev->dev, "I/O memory remapping failed\n"); 256 r = -ENOMEM; 257 goto err_release_region; 258 } 259 260 261 dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL); 262 if (!dev) { 263 r = -ENOMEM; 264 goto err_release_region; 265 } 266 267 init_completion(&dev->cmd_complete); 268 mutex_init(&dev->lock); 269 dev->clk = NULL; 270 dev->controller = controller; 271 dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz; 272 dev->base = base; 273 dev->dev = get_device(&pdev->dev); 274 dev->functionality = 275 I2C_FUNC_I2C | 276 I2C_FUNC_SMBUS_BYTE | 277 I2C_FUNC_SMBUS_BYTE_DATA | 278 I2C_FUNC_SMBUS_WORD_DATA | 279 I2C_FUNC_SMBUS_I2C_BLOCK; 280 dev->master_cfg = controller->bus_cfg; 281 282 pci_set_drvdata(pdev, dev); 283 284 dev->tx_fifo_depth = controller->tx_fifo_depth; 285 dev->rx_fifo_depth = controller->rx_fifo_depth; 286 r = i2c_dw_init(dev); 287 if (r) 288 goto err_iounmap; 289 290 adap = &dev->adapter; 291 i2c_set_adapdata(adap, dev); 292 adap->owner = THIS_MODULE; 293 adap->class = 0; 294 adap->algo = &i2c_dw_algo; 295 adap->dev.parent = &pdev->dev; 296 adap->nr = controller->bus_num; 297 snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci-%d", 298 adap->nr); 299 300 r = request_irq(pdev->irq, i2c_dw_isr, IRQF_SHARED, adap->name, dev); 301 if (r) { 302 dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq); 303 goto err_iounmap; 304 } 305 306 i2c_dw_disable_int(dev); 307 i2c_dw_clear_int(dev); 308 r = i2c_add_numbered_adapter(adap); 309 if (r) { 310 dev_err(&pdev->dev, "failure adding adapter\n"); 311 goto err_free_irq; 312 } 313 314 pm_runtime_put_noidle(&pdev->dev); 315 pm_runtime_allow(&pdev->dev); 316 317 return 0; 318 319 err_free_irq: 320 free_irq(pdev->irq, dev); 321 err_iounmap: 322 iounmap(dev->base); 323 pci_set_drvdata(pdev, NULL); 324 put_device(&pdev->dev); 325 kfree(dev); 326 err_release_region: 327 pci_release_region(pdev, 0); 328 exit: 329 return r; 330 } 331 332 static void __devexit i2c_dw_pci_remove(struct pci_dev *pdev) 333 { 334 struct dw_i2c_dev *dev = pci_get_drvdata(pdev); 335 336 i2c_dw_disable(dev); 337 pm_runtime_forbid(&pdev->dev); 338 pm_runtime_get_noresume(&pdev->dev); 339 340 pci_set_drvdata(pdev, NULL); 341 i2c_del_adapter(&dev->adapter); 342 put_device(&pdev->dev); 343 344 free_irq(dev->irq, dev); 345 kfree(dev); 346 pci_release_region(pdev, 0); 347 } 348 349 /* work with hotplug and coldplug */ 350 MODULE_ALIAS("i2c_designware-pci"); 351 352 static DEFINE_PCI_DEVICE_TABLE(i2_designware_pci_ids) = { 353 /* Moorestown */ 354 { PCI_VDEVICE(INTEL, 0x0802), moorestown_0 }, 355 { PCI_VDEVICE(INTEL, 0x0803), moorestown_1 }, 356 { PCI_VDEVICE(INTEL, 0x0804), moorestown_2 }, 357 /* Medfield */ 358 { PCI_VDEVICE(INTEL, 0x0817), medfield_3,}, 359 { PCI_VDEVICE(INTEL, 0x0818), medfield_4 }, 360 { PCI_VDEVICE(INTEL, 0x0819), medfield_5 }, 361 { PCI_VDEVICE(INTEL, 0x082C), medfield_0 }, 362 { PCI_VDEVICE(INTEL, 0x082D), medfield_1 }, 363 { PCI_VDEVICE(INTEL, 0x082E), medfield_2 }, 364 { 0,} 365 }; 366 MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids); 367 368 static struct pci_driver dw_i2c_driver = { 369 .name = DRIVER_NAME, 370 .id_table = i2_designware_pci_ids, 371 .probe = i2c_dw_pci_probe, 372 .remove = __devexit_p(i2c_dw_pci_remove), 373 .driver = { 374 .pm = &i2c_dw_pm_ops, 375 }, 376 }; 377 378 static int __init dw_i2c_init_driver(void) 379 { 380 return pci_register_driver(&dw_i2c_driver); 381 } 382 module_init(dw_i2c_init_driver); 383 384 static void __exit dw_i2c_exit_driver(void) 385 { 386 pci_unregister_driver(&dw_i2c_driver); 387 } 388 module_exit(dw_i2c_exit_driver); 389 390 MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); 391 MODULE_DESCRIPTION("Synopsys DesignWare PCI I2C bus adapter"); 392 MODULE_LICENSE("GPL"); 393