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 return 0; 186 } 187 188 static int i2c_dw_pci_runtime_idle(struct device *dev) 189 { 190 int err = pm_schedule_suspend(dev, 500); 191 dev_dbg(dev, "runtime_idle called\n"); 192 193 if (err != 0) 194 return 0; 195 return -EBUSY; 196 } 197 198 static const struct dev_pm_ops i2c_dw_pm_ops = { 199 .resume = i2c_dw_pci_resume, 200 .suspend = i2c_dw_pci_suspend, 201 SET_RUNTIME_PM_OPS(i2c_dw_pci_suspend, i2c_dw_pci_resume, 202 i2c_dw_pci_runtime_idle) 203 }; 204 205 static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev) 206 { 207 return dev->controller->clk_khz; 208 } 209 210 static int __devinit i2c_dw_pci_probe(struct pci_dev *pdev, 211 const struct pci_device_id *id) 212 { 213 struct dw_i2c_dev *dev; 214 struct i2c_adapter *adap; 215 unsigned long start, len; 216 void __iomem *base; 217 int r; 218 struct dw_pci_controller *controller; 219 220 if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) { 221 printk(KERN_ERR "dw_i2c_pci_probe: invalid driver data %ld\n", 222 id->driver_data); 223 return -EINVAL; 224 } 225 226 controller = &dw_pci_controllers[id->driver_data]; 227 228 r = pci_enable_device(pdev); 229 if (r) { 230 dev_err(&pdev->dev, "Failed to enable I2C PCI device (%d)\n", 231 r); 232 goto exit; 233 } 234 235 /* Determine the address of the I2C area */ 236 start = pci_resource_start(pdev, 0); 237 len = pci_resource_len(pdev, 0); 238 if (!start || len == 0) { 239 dev_err(&pdev->dev, "base address not set\n"); 240 r = -ENODEV; 241 goto exit; 242 } 243 244 r = pci_request_region(pdev, 0, DRIVER_NAME); 245 if (r) { 246 dev_err(&pdev->dev, "failed to request I2C region " 247 "0x%lx-0x%lx\n", start, 248 (unsigned long)pci_resource_end(pdev, 0)); 249 goto exit; 250 } 251 252 base = ioremap_nocache(start, len); 253 if (!base) { 254 dev_err(&pdev->dev, "I/O memory remapping failed\n"); 255 r = -ENOMEM; 256 goto err_release_region; 257 } 258 259 260 dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL); 261 if (!dev) { 262 r = -ENOMEM; 263 goto err_release_region; 264 } 265 266 init_completion(&dev->cmd_complete); 267 mutex_init(&dev->lock); 268 dev->clk = NULL; 269 dev->controller = controller; 270 dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz; 271 dev->base = base; 272 dev->dev = get_device(&pdev->dev); 273 dev->functionality = 274 I2C_FUNC_I2C | 275 I2C_FUNC_SMBUS_BYTE | 276 I2C_FUNC_SMBUS_BYTE_DATA | 277 I2C_FUNC_SMBUS_WORD_DATA | 278 I2C_FUNC_SMBUS_I2C_BLOCK; 279 dev->master_cfg = controller->bus_cfg; 280 281 pci_set_drvdata(pdev, dev); 282 283 dev->tx_fifo_depth = controller->tx_fifo_depth; 284 dev->rx_fifo_depth = controller->rx_fifo_depth; 285 r = i2c_dw_init(dev); 286 if (r) 287 goto err_iounmap; 288 289 adap = &dev->adapter; 290 i2c_set_adapdata(adap, dev); 291 adap->owner = THIS_MODULE; 292 adap->class = 0; 293 adap->algo = &i2c_dw_algo; 294 adap->dev.parent = &pdev->dev; 295 adap->nr = controller->bus_num; 296 snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci-%d", 297 adap->nr); 298 299 r = request_irq(pdev->irq, i2c_dw_isr, IRQF_SHARED, adap->name, dev); 300 if (r) { 301 dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq); 302 goto err_iounmap; 303 } 304 305 i2c_dw_disable_int(dev); 306 i2c_dw_clear_int(dev); 307 r = i2c_add_numbered_adapter(adap); 308 if (r) { 309 dev_err(&pdev->dev, "failure adding adapter\n"); 310 goto err_free_irq; 311 } 312 313 pm_runtime_put_noidle(&pdev->dev); 314 pm_runtime_allow(&pdev->dev); 315 316 return 0; 317 318 err_free_irq: 319 free_irq(pdev->irq, dev); 320 err_iounmap: 321 iounmap(dev->base); 322 pci_set_drvdata(pdev, NULL); 323 put_device(&pdev->dev); 324 kfree(dev); 325 err_release_region: 326 pci_release_region(pdev, 0); 327 exit: 328 return r; 329 } 330 331 static void __devexit i2c_dw_pci_remove(struct pci_dev *pdev) 332 { 333 struct dw_i2c_dev *dev = pci_get_drvdata(pdev); 334 335 i2c_dw_disable(dev); 336 pm_runtime_forbid(&pdev->dev); 337 pm_runtime_get_noresume(&pdev->dev); 338 339 pci_set_drvdata(pdev, NULL); 340 i2c_del_adapter(&dev->adapter); 341 put_device(&pdev->dev); 342 343 free_irq(dev->irq, dev); 344 kfree(dev); 345 pci_release_region(pdev, 0); 346 } 347 348 /* work with hotplug and coldplug */ 349 MODULE_ALIAS("i2c_designware-pci"); 350 351 static DEFINE_PCI_DEVICE_TABLE(i2_designware_pci_ids) = { 352 /* Moorestown */ 353 { PCI_VDEVICE(INTEL, 0x0802), moorestown_0 }, 354 { PCI_VDEVICE(INTEL, 0x0803), moorestown_1 }, 355 { PCI_VDEVICE(INTEL, 0x0804), moorestown_2 }, 356 /* Medfield */ 357 { PCI_VDEVICE(INTEL, 0x0817), medfield_3,}, 358 { PCI_VDEVICE(INTEL, 0x0818), medfield_4 }, 359 { PCI_VDEVICE(INTEL, 0x0819), medfield_5 }, 360 { PCI_VDEVICE(INTEL, 0x082C), medfield_0 }, 361 { PCI_VDEVICE(INTEL, 0x082D), medfield_1 }, 362 { PCI_VDEVICE(INTEL, 0x082E), medfield_2 }, 363 { 0,} 364 }; 365 MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids); 366 367 static struct pci_driver dw_i2c_driver = { 368 .name = DRIVER_NAME, 369 .id_table = i2_designware_pci_ids, 370 .probe = i2c_dw_pci_probe, 371 .remove = __devexit_p(i2c_dw_pci_remove), 372 .driver = { 373 .pm = &i2c_dw_pm_ops, 374 }, 375 }; 376 377 static int __init dw_i2c_init_driver(void) 378 { 379 return pci_register_driver(&dw_i2c_driver); 380 } 381 module_init(dw_i2c_init_driver); 382 383 static void __exit dw_i2c_exit_driver(void) 384 { 385 pci_unregister_driver(&dw_i2c_driver); 386 } 387 module_exit(dw_i2c_exit_driver); 388 389 MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); 390 MODULE_DESCRIPTION("Synopsys DesignWare PCI I2C bus adapter"); 391 MODULE_LICENSE("GPL"); 392