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 *
  24 */
  25
  26#include <linux/kernel.h>
  27#include <linux/module.h>
  28#include <linux/delay.h>
  29#include <linux/i2c.h>
  30#include <linux/errno.h>
  31#include <linux/sched.h>
  32#include <linux/err.h>
  33#include <linux/interrupt.h>
  34#include <linux/io.h>
  35#include <linux/slab.h>
  36#include <linux/pci.h>
  37#include <linux/pm_runtime.h>
  38#include "i2c-designware-core.h"
  39
  40#define DRIVER_NAME "i2c-designware-pci"
  41
  42enum dw_pci_ctl_id_t {
  43        moorestown_0,
  44        moorestown_1,
  45        moorestown_2,
  46
  47        medfield_0,
  48        medfield_1,
  49        medfield_2,
  50        medfield_3,
  51        medfield_4,
  52        medfield_5,
  53
  54        baytrail,
  55        haswell,
  56};
  57
  58struct dw_scl_sda_cfg {
  59        u32 ss_hcnt;
  60        u32 fs_hcnt;
  61        u32 ss_lcnt;
  62        u32 fs_lcnt;
  63        u32 sda_hold;
  64};
  65
  66struct dw_pci_controller {
  67        u32 bus_num;
  68        u32 bus_cfg;
  69        u32 tx_fifo_depth;
  70        u32 rx_fifo_depth;
  71        u32 clk_khz;
  72        u32 functionality;
  73        struct dw_scl_sda_cfg *scl_sda_cfg;
  74};
  75
  76#define INTEL_MID_STD_CFG  (DW_IC_CON_MASTER |                  \
  77                                DW_IC_CON_SLAVE_DISABLE |       \
  78                                DW_IC_CON_RESTART_EN)
  79
  80#define DW_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C |                        \
  81                                        I2C_FUNC_SMBUS_BYTE |           \
  82                                        I2C_FUNC_SMBUS_BYTE_DATA |      \
  83                                        I2C_FUNC_SMBUS_WORD_DATA |      \
  84                                        I2C_FUNC_SMBUS_I2C_BLOCK)
  85
  86/* BayTrail HCNT/LCNT/SDA hold time */
  87static struct dw_scl_sda_cfg byt_config = {
  88        .ss_hcnt = 0x200,
  89        .fs_hcnt = 0x55,
  90        .ss_lcnt = 0x200,
  91        .fs_lcnt = 0x99,
  92        .sda_hold = 0x6,
  93};
  94
  95/* Haswell HCNT/LCNT/SDA hold time */
  96static struct dw_scl_sda_cfg hsw_config = {
  97        .ss_hcnt = 0x01b0,
  98        .fs_hcnt = 0x48,
  99        .ss_lcnt = 0x01fb,
 100        .fs_lcnt = 0xa0,
 101        .sda_hold = 0x9,
 102};
 103
 104static struct  dw_pci_controller  dw_pci_controllers[] = {
 105        [moorestown_0] = {
 106                .bus_num     = 0,
 107                .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 108                .tx_fifo_depth = 32,
 109                .rx_fifo_depth = 32,
 110                .clk_khz      = 25000,
 111        },
 112        [moorestown_1] = {
 113                .bus_num     = 1,
 114                .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 115                .tx_fifo_depth = 32,
 116                .rx_fifo_depth = 32,
 117                .clk_khz      = 25000,
 118        },
 119        [moorestown_2] = {
 120                .bus_num     = 2,
 121                .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 122                .tx_fifo_depth = 32,
 123                .rx_fifo_depth = 32,
 124                .clk_khz      = 25000,
 125        },
 126        [medfield_0] = {
 127                .bus_num     = 0,
 128                .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 129                .tx_fifo_depth = 32,
 130                .rx_fifo_depth = 32,
 131                .clk_khz      = 25000,
 132        },
 133        [medfield_1] = {
 134                .bus_num     = 1,
 135                .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 136                .tx_fifo_depth = 32,
 137                .rx_fifo_depth = 32,
 138                .clk_khz      = 25000,
 139        },
 140        [medfield_2] = {
 141                .bus_num     = 2,
 142                .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 143                .tx_fifo_depth = 32,
 144                .rx_fifo_depth = 32,
 145                .clk_khz      = 25000,
 146        },
 147        [medfield_3] = {
 148                .bus_num     = 3,
 149                .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_STD,
 150                .tx_fifo_depth = 32,
 151                .rx_fifo_depth = 32,
 152                .clk_khz      = 25000,
 153        },
 154        [medfield_4] = {
 155                .bus_num     = 4,
 156                .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 157                .tx_fifo_depth = 32,
 158                .rx_fifo_depth = 32,
 159                .clk_khz      = 25000,
 160        },
 161        [medfield_5] = {
 162                .bus_num     = 5,
 163                .bus_cfg   = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 164                .tx_fifo_depth = 32,
 165                .rx_fifo_depth = 32,
 166                .clk_khz      = 25000,
 167        },
 168        [baytrail] = {
 169                .bus_num = -1,
 170                .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 171                .tx_fifo_depth = 32,
 172                .rx_fifo_depth = 32,
 173                .clk_khz = 100000,
 174                .functionality = I2C_FUNC_10BIT_ADDR,
 175                .scl_sda_cfg = &byt_config,
 176        },
 177        [haswell] = {
 178                .bus_num = -1,
 179                .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST,
 180                .tx_fifo_depth = 32,
 181                .rx_fifo_depth = 32,
 182                .clk_khz = 100000,
 183                .functionality = I2C_FUNC_10BIT_ADDR,
 184                .scl_sda_cfg = &hsw_config,
 185        },
 186};
 187
 188static struct i2c_algorithm i2c_dw_algo = {
 189        .master_xfer    = i2c_dw_xfer,
 190        .functionality  = i2c_dw_func,
 191};
 192
 193#ifdef CONFIG_PM
 194static int i2c_dw_pci_suspend(struct device *dev)
 195{
 196        struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
 197
 198        i2c_dw_disable(pci_get_drvdata(pdev));
 199        return 0;
 200}
 201
 202static int i2c_dw_pci_resume(struct device *dev)
 203{
 204        struct pci_dev *pdev = container_of(dev, struct pci_dev, dev);
 205
 206        return i2c_dw_init(pci_get_drvdata(pdev));
 207}
 208#endif
 209
 210static UNIVERSAL_DEV_PM_OPS(i2c_dw_pm_ops, i2c_dw_pci_suspend,
 211                            i2c_dw_pci_resume, NULL);
 212
 213static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
 214{
 215        return dev->controller->clk_khz;
 216}
 217
 218static int i2c_dw_pci_probe(struct pci_dev *pdev,
 219                            const struct pci_device_id *id)
 220{
 221        struct dw_i2c_dev *dev;
 222        struct i2c_adapter *adap;
 223        int r;
 224        struct  dw_pci_controller *controller;
 225        struct dw_scl_sda_cfg *cfg;
 226
 227        if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) {
 228                dev_err(&pdev->dev, "%s: invalid driver data %ld\n", __func__,
 229                        id->driver_data);
 230                return -EINVAL;
 231        }
 232
 233        controller = &dw_pci_controllers[id->driver_data];
 234
 235        r = pcim_enable_device(pdev);
 236        if (r) {
 237                dev_err(&pdev->dev, "Failed to enable I2C PCI device (%d)\n",
 238                        r);
 239                return r;
 240        }
 241
 242        r = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev));
 243        if (r) {
 244                dev_err(&pdev->dev, "I/O memory remapping failed\n");
 245                return r;
 246        }
 247
 248        dev = devm_kzalloc(&pdev->dev, sizeof(struct dw_i2c_dev), GFP_KERNEL);
 249        if (!dev)
 250                return -ENOMEM;
 251
 252        init_completion(&dev->cmd_complete);
 253        mutex_init(&dev->lock);
 254        dev->clk = NULL;
 255        dev->controller = controller;
 256        dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
 257        dev->base = pcim_iomap_table(pdev)[0];
 258        dev->dev = &pdev->dev;
 259        dev->functionality = controller->functionality |
 260                                DW_DEFAULT_FUNCTIONALITY;
 261
 262        dev->master_cfg =  controller->bus_cfg;
 263        if (controller->scl_sda_cfg) {
 264                cfg = controller->scl_sda_cfg;
 265                dev->ss_hcnt = cfg->ss_hcnt;
 266                dev->fs_hcnt = cfg->fs_hcnt;
 267                dev->ss_lcnt = cfg->ss_lcnt;
 268                dev->fs_lcnt = cfg->fs_lcnt;
 269                dev->sda_hold_time = cfg->sda_hold;
 270        }
 271
 272        pci_set_drvdata(pdev, dev);
 273
 274        dev->tx_fifo_depth = controller->tx_fifo_depth;
 275        dev->rx_fifo_depth = controller->rx_fifo_depth;
 276        r = i2c_dw_init(dev);
 277        if (r)
 278                return r;
 279
 280        adap = &dev->adapter;
 281        i2c_set_adapdata(adap, dev);
 282        adap->owner = THIS_MODULE;
 283        adap->class = 0;
 284        adap->algo = &i2c_dw_algo;
 285        adap->dev.parent = &pdev->dev;
 286        adap->nr = controller->bus_num;
 287
 288        snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci");
 289
 290        r = devm_request_irq(&pdev->dev, pdev->irq, i2c_dw_isr, IRQF_SHARED,
 291                        adap->name, dev);
 292        if (r) {
 293                dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
 294                return r;
 295        }
 296
 297        i2c_dw_disable_int(dev);
 298        i2c_dw_clear_int(dev);
 299        r = i2c_add_numbered_adapter(adap);
 300        if (r) {
 301                dev_err(&pdev->dev, "failure adding adapter\n");
 302                return r;
 303        }
 304
 305        pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
 306        pm_runtime_use_autosuspend(&pdev->dev);
 307        pm_runtime_put_autosuspend(&pdev->dev);
 308        pm_runtime_allow(&pdev->dev);
 309
 310        return 0;
 311}
 312
 313static void i2c_dw_pci_remove(struct pci_dev *pdev)
 314{
 315        struct dw_i2c_dev *dev = pci_get_drvdata(pdev);
 316
 317        i2c_dw_disable(dev);
 318        pm_runtime_forbid(&pdev->dev);
 319        pm_runtime_get_noresume(&pdev->dev);
 320
 321        i2c_del_adapter(&dev->adapter);
 322}
 323
 324/* work with hotplug and coldplug */
 325MODULE_ALIAS("i2c_designware-pci");
 326
 327static const struct pci_device_id i2_designware_pci_ids[] = {
 328        /* Moorestown */
 329        { PCI_VDEVICE(INTEL, 0x0802), moorestown_0 },
 330        { PCI_VDEVICE(INTEL, 0x0803), moorestown_1 },
 331        { PCI_VDEVICE(INTEL, 0x0804), moorestown_2 },
 332        /* Medfield */
 333        { PCI_VDEVICE(INTEL, 0x0817), medfield_3,},
 334        { PCI_VDEVICE(INTEL, 0x0818), medfield_4 },
 335        { PCI_VDEVICE(INTEL, 0x0819), medfield_5 },
 336        { PCI_VDEVICE(INTEL, 0x082C), medfield_0 },
 337        { PCI_VDEVICE(INTEL, 0x082D), medfield_1 },
 338        { PCI_VDEVICE(INTEL, 0x082E), medfield_2 },
 339        /* Baytrail */
 340        { PCI_VDEVICE(INTEL, 0x0F41), baytrail },
 341        { PCI_VDEVICE(INTEL, 0x0F42), baytrail },
 342        { PCI_VDEVICE(INTEL, 0x0F43), baytrail },
 343        { PCI_VDEVICE(INTEL, 0x0F44), baytrail },
 344        { PCI_VDEVICE(INTEL, 0x0F45), baytrail },
 345        { PCI_VDEVICE(INTEL, 0x0F46), baytrail },
 346        { PCI_VDEVICE(INTEL, 0x0F47), baytrail },
 347        /* Haswell */
 348        { PCI_VDEVICE(INTEL, 0x9c61), haswell },
 349        { PCI_VDEVICE(INTEL, 0x9c62), haswell },
 350        /* Braswell / Cherrytrail */
 351        { PCI_VDEVICE(INTEL, 0x22C1), baytrail,},
 352        { PCI_VDEVICE(INTEL, 0x22C2), baytrail },
 353        { PCI_VDEVICE(INTEL, 0x22C3), baytrail },
 354        { PCI_VDEVICE(INTEL, 0x22C4), baytrail },
 355        { PCI_VDEVICE(INTEL, 0x22C5), baytrail },
 356        { PCI_VDEVICE(INTEL, 0x22C6), baytrail },
 357        { PCI_VDEVICE(INTEL, 0x22C7), baytrail },
 358        { 0,}
 359};
 360MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids);
 361
 362static struct pci_driver dw_i2c_driver = {
 363        .name           = DRIVER_NAME,
 364        .id_table       = i2_designware_pci_ids,
 365        .probe          = i2c_dw_pci_probe,
 366        .remove         = i2c_dw_pci_remove,
 367        .driver         = {
 368                .pm     = &i2c_dw_pm_ops,
 369        },
 370};
 371
 372module_pci_driver(dw_i2c_driver);
 373
 374MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
 375MODULE_DESCRIPTION("Synopsys DesignWare PCI I2C bus adapter");
 376MODULE_LICENSE("GPL");
 377
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.