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