linux/drivers/i2c/busses/i2c-designware-platdrv.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 *
  10 * ----------------------------------------------------------------------------
  11 *
  12 * This program is free software; you can redistribute it and/or modify
  13 * it under the terms of the GNU General Public License as published by
  14 * the Free Software Foundation; either version 2 of the License, or
  15 * (at your option) any later version.
  16 *
  17 * This program is distributed in the hope that it will be useful,
  18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20 * GNU General Public License for more details.
  21 * ----------------------------------------------------------------------------
  22 *
  23 */
  24#include <linux/kernel.h>
  25#include <linux/module.h>
  26#include <linux/delay.h>
  27#include <linux/i2c.h>
  28#include <linux/clk.h>
  29#include <linux/clk-provider.h>
  30#include <linux/errno.h>
  31#include <linux/sched.h>
  32#include <linux/err.h>
  33#include <linux/interrupt.h>
  34#include <linux/of.h>
  35#include <linux/platform_device.h>
  36#include <linux/pm.h>
  37#include <linux/pm_runtime.h>
  38#include <linux/io.h>
  39#include <linux/slab.h>
  40#include <linux/acpi.h>
  41#include <linux/platform_data/i2c-designware.h>
  42#include "i2c-designware-core.h"
  43
  44static struct i2c_algorithm i2c_dw_algo = {
  45        .master_xfer    = i2c_dw_xfer,
  46        .functionality  = i2c_dw_func,
  47};
  48static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
  49{
  50        return clk_get_rate(dev->clk)/1000;
  51}
  52
  53#ifdef CONFIG_ACPI
  54static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
  55                               u16 *hcnt, u16 *lcnt, u32 *sda_hold)
  56{
  57        struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
  58        acpi_handle handle = ACPI_HANDLE(&pdev->dev);
  59        union acpi_object *obj;
  60
  61        if (ACPI_FAILURE(acpi_evaluate_object(handle, method, NULL, &buf)))
  62                return;
  63
  64        obj = (union acpi_object *)buf.pointer;
  65        if (obj->type == ACPI_TYPE_PACKAGE && obj->package.count == 3) {
  66                const union acpi_object *objs = obj->package.elements;
  67
  68                *hcnt = (u16)objs[0].integer.value;
  69                *lcnt = (u16)objs[1].integer.value;
  70                if (sda_hold)
  71                        *sda_hold = (u32)objs[2].integer.value;
  72        }
  73
  74        kfree(buf.pointer);
  75}
  76
  77static int dw_i2c_acpi_configure(struct platform_device *pdev)
  78{
  79        struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
  80        const struct acpi_device_id *id;
  81
  82        dev->adapter.nr = -1;
  83        dev->tx_fifo_depth = 32;
  84        dev->rx_fifo_depth = 32;
  85
  86        /*
  87         * Try to get SDA hold time and *CNT values from an ACPI method if
  88         * it exists for both supported speed modes.
  89         */
  90        dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, NULL);
  91        dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
  92                           &dev->sda_hold_time);
  93
  94        /*
  95         * Provide a way for Designware I2C host controllers that are not
  96         * based on Intel LPSS to specify their input clock frequency via
  97         * id->driver_data.
  98         */
  99        id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
 100        if (id && id->driver_data)
 101                clk_register_fixed_rate(&pdev->dev, dev_name(&pdev->dev), NULL,
 102                                        CLK_IS_ROOT, id->driver_data);
 103
 104        return 0;
 105}
 106
 107static void dw_i2c_acpi_unconfigure(struct platform_device *pdev)
 108{
 109        struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
 110        const struct acpi_device_id *id;
 111
 112        id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
 113        if (id && id->driver_data)
 114                clk_unregister(dev->clk);
 115}
 116
 117static const struct acpi_device_id dw_i2c_acpi_match[] = {
 118        { "INT33C2", 0 },
 119        { "INT33C3", 0 },
 120        { "INT3432", 0 },
 121        { "INT3433", 0 },
 122        { "80860F41", 0 },
 123        { "808622C1", 0 },
 124        { "AMD0010", 133 * 1000 * 1000 },
 125        { }
 126};
 127MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
 128#else
 129static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
 130{
 131        return -ENODEV;
 132}
 133static inline void dw_i2c_acpi_unconfigure(struct platform_device *pdev) { }
 134#endif
 135
 136static int dw_i2c_probe(struct platform_device *pdev)
 137{
 138        struct dw_i2c_dev *dev;
 139        struct i2c_adapter *adap;
 140        struct resource *mem;
 141        struct dw_i2c_platform_data *pdata;
 142        int irq, r;
 143        u32 clk_freq, ht = 0;
 144
 145        irq = platform_get_irq(pdev, 0);
 146        if (irq < 0) {
 147                dev_err(&pdev->dev, "no irq resource?\n");
 148                return irq; /* -ENXIO */
 149        }
 150
 151        dev = devm_kzalloc(&pdev->dev, sizeof(struct dw_i2c_dev), GFP_KERNEL);
 152        if (!dev)
 153                return -ENOMEM;
 154
 155        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 156        dev->base = devm_ioremap_resource(&pdev->dev, mem);
 157        if (IS_ERR(dev->base))
 158                return PTR_ERR(dev->base);
 159
 160        init_completion(&dev->cmd_complete);
 161        mutex_init(&dev->lock);
 162        dev->dev = &pdev->dev;
 163        dev->irq = irq;
 164        platform_set_drvdata(pdev, dev);
 165
 166        /* fast mode by default because of legacy reasons */
 167        clk_freq = 400000;
 168
 169        if (ACPI_COMPANION(&pdev->dev)) {
 170                dw_i2c_acpi_configure(pdev);
 171        } else if (pdev->dev.of_node) {
 172                of_property_read_u32(pdev->dev.of_node,
 173                                        "i2c-sda-hold-time-ns", &ht);
 174
 175                of_property_read_u32(pdev->dev.of_node,
 176                                     "i2c-sda-falling-time-ns",
 177                                     &dev->sda_falling_time);
 178                of_property_read_u32(pdev->dev.of_node,
 179                                     "i2c-scl-falling-time-ns",
 180                                     &dev->scl_falling_time);
 181
 182                of_property_read_u32(pdev->dev.of_node, "clock-frequency",
 183                                     &clk_freq);
 184
 185                /* Only standard mode at 100kHz and fast mode at 400kHz
 186                 * are supported.
 187                 */
 188                if (clk_freq != 100000 && clk_freq != 400000) {
 189                        dev_err(&pdev->dev, "Only 100kHz and 400kHz supported");
 190                        return -EINVAL;
 191                }
 192        } else {
 193                pdata = dev_get_platdata(&pdev->dev);
 194                if (pdata)
 195                        clk_freq = pdata->i2c_scl_freq;
 196        }
 197
 198        dev->functionality =
 199                I2C_FUNC_I2C |
 200                I2C_FUNC_10BIT_ADDR |
 201                I2C_FUNC_SMBUS_BYTE |
 202                I2C_FUNC_SMBUS_BYTE_DATA |
 203                I2C_FUNC_SMBUS_WORD_DATA |
 204                I2C_FUNC_SMBUS_I2C_BLOCK;
 205        if (clk_freq == 100000)
 206                dev->master_cfg =  DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
 207                        DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_STD;
 208        else
 209                dev->master_cfg =  DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
 210                        DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST;
 211
 212        dev->clk = devm_clk_get(&pdev->dev, NULL);
 213        dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz;
 214        if (IS_ERR(dev->clk))
 215                return PTR_ERR(dev->clk);
 216        clk_prepare_enable(dev->clk);
 217
 218        if (!dev->sda_hold_time && ht) {
 219                u32 ic_clk = dev->get_clk_rate_khz(dev);
 220
 221                dev->sda_hold_time = div_u64((u64)ic_clk * ht + 500000,
 222                                             1000000);
 223        }
 224
 225        if (!dev->tx_fifo_depth) {
 226                u32 param1 = i2c_dw_read_comp_param(dev);
 227
 228                dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1;
 229                dev->rx_fifo_depth = ((param1 >> 8)  & 0xff) + 1;
 230                dev->adapter.nr = pdev->id;
 231        }
 232        r = i2c_dw_init(dev);
 233        if (r)
 234                return r;
 235
 236        i2c_dw_disable_int(dev);
 237        r = devm_request_irq(&pdev->dev, dev->irq, i2c_dw_isr, IRQF_SHARED,
 238                        pdev->name, dev);
 239        if (r) {
 240                dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
 241                return r;
 242        }
 243
 244        adap = &dev->adapter;
 245        i2c_set_adapdata(adap, dev);
 246        adap->owner = THIS_MODULE;
 247        adap->class = I2C_CLASS_DEPRECATED;
 248        strlcpy(adap->name, "Synopsys DesignWare I2C adapter",
 249                        sizeof(adap->name));
 250        adap->algo = &i2c_dw_algo;
 251        adap->dev.parent = &pdev->dev;
 252        adap->dev.of_node = pdev->dev.of_node;
 253
 254        r = i2c_add_numbered_adapter(adap);
 255        if (r) {
 256                dev_err(&pdev->dev, "failure adding adapter\n");
 257                return r;
 258        }
 259
 260        pm_runtime_set_autosuspend_delay(&pdev->dev, 1000);
 261        pm_runtime_use_autosuspend(&pdev->dev);
 262        pm_runtime_set_active(&pdev->dev);
 263        pm_runtime_enable(&pdev->dev);
 264
 265        return 0;
 266}
 267
 268static int dw_i2c_remove(struct platform_device *pdev)
 269{
 270        struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
 271
 272        pm_runtime_get_sync(&pdev->dev);
 273
 274        i2c_del_adapter(&dev->adapter);
 275
 276        i2c_dw_disable(dev);
 277
 278        pm_runtime_put(&pdev->dev);
 279        pm_runtime_disable(&pdev->dev);
 280
 281        if (ACPI_COMPANION(&pdev->dev))
 282                dw_i2c_acpi_unconfigure(pdev);
 283
 284        return 0;
 285}
 286
 287#ifdef CONFIG_OF
 288static const struct of_device_id dw_i2c_of_match[] = {
 289        { .compatible = "snps,designware-i2c", },
 290        {},
 291};
 292MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
 293#endif
 294
 295#ifdef CONFIG_PM
 296static int dw_i2c_suspend(struct device *dev)
 297{
 298        struct platform_device *pdev = to_platform_device(dev);
 299        struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
 300
 301        i2c_dw_disable(i_dev);
 302        clk_disable_unprepare(i_dev->clk);
 303
 304        return 0;
 305}
 306
 307static int dw_i2c_resume(struct device *dev)
 308{
 309        struct platform_device *pdev = to_platform_device(dev);
 310        struct dw_i2c_dev *i_dev = platform_get_drvdata(pdev);
 311
 312        clk_prepare_enable(i_dev->clk);
 313        i2c_dw_init(i_dev);
 314
 315        return 0;
 316}
 317#endif
 318
 319static UNIVERSAL_DEV_PM_OPS(dw_i2c_dev_pm_ops, dw_i2c_suspend,
 320                            dw_i2c_resume, NULL);
 321
 322/* work with hotplug and coldplug */
 323MODULE_ALIAS("platform:i2c_designware");
 324
 325static struct platform_driver dw_i2c_driver = {
 326        .probe = dw_i2c_probe,
 327        .remove = dw_i2c_remove,
 328        .driver         = {
 329                .name   = "i2c_designware",
 330                .owner  = THIS_MODULE,
 331                .of_match_table = of_match_ptr(dw_i2c_of_match),
 332                .acpi_match_table = ACPI_PTR(dw_i2c_acpi_match),
 333                .pm     = &dw_i2c_dev_pm_ops,
 334        },
 335};
 336
 337static int __init dw_i2c_init_driver(void)
 338{
 339        return platform_driver_register(&dw_i2c_driver);
 340}
 341subsys_initcall(dw_i2c_init_driver);
 342
 343static void __exit dw_i2c_exit_driver(void)
 344{
 345        platform_driver_unregister(&dw_i2c_driver);
 346}
 347module_exit(dw_i2c_exit_driver);
 348
 349MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
 350MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
 351MODULE_LICENSE("GPL");
 352