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 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 int r; 216 struct dw_pci_controller *controller; 217 218 if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) { 219 dev_err(&pdev->dev, "%s: invalid driver data %ld\n", __func__, 220 id->driver_data); 221 return -EINVAL; 222 } 223 224 controller = &dw_pci_controllers[id->driver_data]; 225 226 r = pcim_enable_device(pdev); 227 if (r) { 228 dev_err(&pdev->dev, "Failed to enable I2C PCI device (%d)\n", 229 r); 230 return r; 231 } 232 233 r = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev)); 234 if (r) { 235 dev_err(&pdev->dev, "I/O memory remapping failed\n"); 236 return r; 237 } 238 239 dev = devm_kzalloc(&pdev->dev, sizeof(struct dw_i2c_dev), GFP_KERNEL); 240 if (!dev) 241 return -ENOMEM; 242 243 init_completion(&dev->cmd_complete); 244 mutex_init(&dev->lock); 245 dev->clk = NULL; 246 dev->controller = controller; 247 dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz; 248 dev->base = pcim_iomap_table(pdev)[0]; 249 dev->dev = &pdev->dev; 250 dev->functionality = 251 I2C_FUNC_I2C | 252 I2C_FUNC_SMBUS_BYTE | 253 I2C_FUNC_SMBUS_BYTE_DATA | 254 I2C_FUNC_SMBUS_WORD_DATA | 255 I2C_FUNC_SMBUS_I2C_BLOCK; 256 dev->master_cfg = controller->bus_cfg; 257 258 pci_set_drvdata(pdev, dev); 259 260 dev->tx_fifo_depth = controller->tx_fifo_depth; 261 dev->rx_fifo_depth = controller->rx_fifo_depth; 262 r = i2c_dw_init(dev); 263 if (r) 264 return r; 265 266 adap = &dev->adapter; 267 i2c_set_adapdata(adap, dev); 268 adap->owner = THIS_MODULE; 269 adap->class = 0; 270 adap->algo = &i2c_dw_algo; 271 adap->dev.parent = &pdev->dev; 272 adap->nr = controller->bus_num; 273 snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci-%d", 274 adap->nr); 275 276 r = devm_request_irq(&pdev->dev, pdev->irq, i2c_dw_isr, IRQF_SHARED, 277 adap->name, dev); 278 if (r) { 279 dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq); 280 return r; 281 } 282 283 i2c_dw_disable_int(dev); 284 i2c_dw_clear_int(dev); 285 r = i2c_add_numbered_adapter(adap); 286 if (r) { 287 dev_err(&pdev->dev, "failure adding adapter\n"); 288 return r; 289 } 290 291 pm_runtime_set_autosuspend_delay(&pdev->dev, 1000); 292 pm_runtime_use_autosuspend(&pdev->dev); 293 pm_runtime_allow(&pdev->dev); 294 295 return 0; 296 } 297 298 static void i2c_dw_pci_remove(struct pci_dev *pdev) 299 { 300 struct dw_i2c_dev *dev = pci_get_drvdata(pdev); 301 302 i2c_dw_disable(dev); 303 pm_runtime_forbid(&pdev->dev); 304 pm_runtime_get_noresume(&pdev->dev); 305 306 i2c_del_adapter(&dev->adapter); 307 } 308 309 /* work with hotplug and coldplug */ 310 MODULE_ALIAS("i2c_designware-pci"); 311 312 static DEFINE_PCI_DEVICE_TABLE(i2_designware_pci_ids) = { 313 /* Moorestown */ 314 { PCI_VDEVICE(INTEL, 0x0802), moorestown_0 }, 315 { PCI_VDEVICE(INTEL, 0x0803), moorestown_1 }, 316 { PCI_VDEVICE(INTEL, 0x0804), moorestown_2 }, 317 /* Medfield */ 318 { PCI_VDEVICE(INTEL, 0x0817), medfield_3,}, 319 { PCI_VDEVICE(INTEL, 0x0818), medfield_4 }, 320 { PCI_VDEVICE(INTEL, 0x0819), medfield_5 }, 321 { PCI_VDEVICE(INTEL, 0x082C), medfield_0 }, 322 { PCI_VDEVICE(INTEL, 0x082D), medfield_1 }, 323 { PCI_VDEVICE(INTEL, 0x082E), medfield_2 }, 324 { 0,} 325 }; 326 MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids); 327 328 static struct pci_driver dw_i2c_driver = { 329 .name = DRIVER_NAME, 330 .id_table = i2_designware_pci_ids, 331 .probe = i2c_dw_pci_probe, 332 .remove = i2c_dw_pci_remove, 333 .driver = { 334 .pm = &i2c_dw_pm_ops, 335 }, 336 }; 337 338 module_pci_driver(dw_i2c_driver); 339 340 MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); 341 MODULE_DESCRIPTION("Synopsys DesignWare PCI I2C bus adapter"); 342 MODULE_LICENSE("GPL"); 343