linux/drivers/i2c/busses/i2c-designware-pcidrv.c
<<
>>
Prefs
   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
  46enum 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
  59struct 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
  71static 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};
 136static struct i2c_algorithm i2c_dw_algo = {
 137        .master_xfer    = i2c_dw_xfer,
 138        .functionality  = i2c_dw_func,
 139};
 140
 141static 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
 165static 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
 188static 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
 198static 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
 205static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
 206{
 207        return dev->controller->clk_khz;
 208}
 209
 210static 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
 298static 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 */
 310MODULE_ALIAS("i2c_designware-pci");
 311
 312static 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};
 326MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids);
 327
 328static 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
 338module_pci_driver(dw_i2c_driver);
 339
 340MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
 341MODULE_DESCRIPTION("Synopsys DesignWare PCI I2C bus adapter");
 342MODULE_LICENSE("GPL");
 343