linux/drivers/i2c/busses/i2c-at91-core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  i2c Support for Atmel's AT91 Two-Wire Interface (TWI)
   4 *
   5 *  Copyright (C) 2011 Weinmann Medical GmbH
   6 *  Author: Nikolaus Voss <n.voss@weinmann.de>
   7 *
   8 *  Evolved from original work by:
   9 *  Copyright (C) 2004 Rick Bronson
  10 *  Converted to 2.6 by Andrew Victor <andrew@sanpeople.com>
  11 *
  12 *  Borrowed heavily from original work by:
  13 *  Copyright (C) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
  14 */
  15
  16#include <linux/clk.h>
  17#include <linux/err.h>
  18#include <linux/i2c.h>
  19#include <linux/io.h>
  20#include <linux/module.h>
  21#include <linux/of.h>
  22#include <linux/of_device.h>
  23#include <linux/platform_device.h>
  24#include <linux/pm_runtime.h>
  25#include <linux/pinctrl/consumer.h>
  26
  27#include "i2c-at91.h"
  28
  29unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg)
  30{
  31        return readl_relaxed(dev->base + reg);
  32}
  33
  34void at91_twi_write(struct at91_twi_dev *dev, unsigned reg, unsigned val)
  35{
  36        writel_relaxed(val, dev->base + reg);
  37}
  38
  39void at91_disable_twi_interrupts(struct at91_twi_dev *dev)
  40{
  41        at91_twi_write(dev, AT91_TWI_IDR, AT91_TWI_INT_MASK);
  42}
  43
  44void at91_twi_irq_save(struct at91_twi_dev *dev)
  45{
  46        dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & AT91_TWI_INT_MASK;
  47        at91_disable_twi_interrupts(dev);
  48}
  49
  50void at91_twi_irq_restore(struct at91_twi_dev *dev)
  51{
  52        at91_twi_write(dev, AT91_TWI_IER, dev->imr);
  53}
  54
  55void at91_init_twi_bus(struct at91_twi_dev *dev)
  56{
  57        at91_disable_twi_interrupts(dev);
  58        at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SWRST);
  59        if (dev->slave_detected)
  60                at91_init_twi_bus_slave(dev);
  61        else
  62                at91_init_twi_bus_master(dev);
  63}
  64
  65static struct at91_twi_pdata at91rm9200_config = {
  66        .clk_max_div = 5,
  67        .clk_offset = 3,
  68        .has_unre_flag = true,
  69        .has_alt_cmd = false,
  70        .has_hold_field = false,
  71};
  72
  73static struct at91_twi_pdata at91sam9261_config = {
  74        .clk_max_div = 5,
  75        .clk_offset = 4,
  76        .has_unre_flag = false,
  77        .has_alt_cmd = false,
  78        .has_hold_field = false,
  79};
  80
  81static struct at91_twi_pdata at91sam9260_config = {
  82        .clk_max_div = 7,
  83        .clk_offset = 4,
  84        .has_unre_flag = false,
  85        .has_alt_cmd = false,
  86        .has_hold_field = false,
  87};
  88
  89static struct at91_twi_pdata at91sam9g20_config = {
  90        .clk_max_div = 7,
  91        .clk_offset = 4,
  92        .has_unre_flag = false,
  93        .has_alt_cmd = false,
  94        .has_hold_field = false,
  95};
  96
  97static struct at91_twi_pdata at91sam9g10_config = {
  98        .clk_max_div = 7,
  99        .clk_offset = 4,
 100        .has_unre_flag = false,
 101        .has_alt_cmd = false,
 102        .has_hold_field = false,
 103};
 104
 105static const struct platform_device_id at91_twi_devtypes[] = {
 106        {
 107                .name = "i2c-at91rm9200",
 108                .driver_data = (unsigned long) &at91rm9200_config,
 109        }, {
 110                .name = "i2c-at91sam9261",
 111                .driver_data = (unsigned long) &at91sam9261_config,
 112        }, {
 113                .name = "i2c-at91sam9260",
 114                .driver_data = (unsigned long) &at91sam9260_config,
 115        }, {
 116                .name = "i2c-at91sam9g20",
 117                .driver_data = (unsigned long) &at91sam9g20_config,
 118        }, {
 119                .name = "i2c-at91sam9g10",
 120                .driver_data = (unsigned long) &at91sam9g10_config,
 121        }, {
 122                /* sentinel */
 123        }
 124};
 125
 126#if defined(CONFIG_OF)
 127static struct at91_twi_pdata at91sam9x5_config = {
 128        .clk_max_div = 7,
 129        .clk_offset = 4,
 130        .has_unre_flag = false,
 131        .has_alt_cmd = false,
 132        .has_hold_field = false,
 133};
 134
 135static struct at91_twi_pdata sama5d4_config = {
 136        .clk_max_div = 7,
 137        .clk_offset = 4,
 138        .has_unre_flag = false,
 139        .has_alt_cmd = false,
 140        .has_hold_field = true,
 141};
 142
 143static struct at91_twi_pdata sama5d2_config = {
 144        .clk_max_div = 7,
 145        .clk_offset = 3,
 146        .has_unre_flag = true,
 147        .has_alt_cmd = true,
 148        .has_hold_field = true,
 149};
 150
 151static const struct of_device_id atmel_twi_dt_ids[] = {
 152        {
 153                .compatible = "atmel,at91rm9200-i2c",
 154                .data = &at91rm9200_config,
 155        }, {
 156                .compatible = "atmel,at91sam9260-i2c",
 157                .data = &at91sam9260_config,
 158        }, {
 159                .compatible = "atmel,at91sam9261-i2c",
 160                .data = &at91sam9261_config,
 161        }, {
 162                .compatible = "atmel,at91sam9g20-i2c",
 163                .data = &at91sam9g20_config,
 164        }, {
 165                .compatible = "atmel,at91sam9g10-i2c",
 166                .data = &at91sam9g10_config,
 167        }, {
 168                .compatible = "atmel,at91sam9x5-i2c",
 169                .data = &at91sam9x5_config,
 170        }, {
 171                .compatible = "atmel,sama5d4-i2c",
 172                .data = &sama5d4_config,
 173        }, {
 174                .compatible = "atmel,sama5d2-i2c",
 175                .data = &sama5d2_config,
 176        }, {
 177                /* sentinel */
 178        }
 179};
 180MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids);
 181#endif
 182
 183static struct at91_twi_pdata *at91_twi_get_driver_data(
 184                                        struct platform_device *pdev)
 185{
 186        if (pdev->dev.of_node) {
 187                const struct of_device_id *match;
 188                match = of_match_node(atmel_twi_dt_ids, pdev->dev.of_node);
 189                if (!match)
 190                        return NULL;
 191                return (struct at91_twi_pdata *)match->data;
 192        }
 193        return (struct at91_twi_pdata *) platform_get_device_id(pdev)->driver_data;
 194}
 195
 196static int at91_twi_probe(struct platform_device *pdev)
 197{
 198        struct at91_twi_dev *dev;
 199        struct resource *mem;
 200        int rc;
 201        u32 phy_addr;
 202
 203        dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
 204        if (!dev)
 205                return -ENOMEM;
 206
 207        dev->dev = &pdev->dev;
 208
 209        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 210        if (!mem)
 211                return -ENODEV;
 212        phy_addr = mem->start;
 213
 214        dev->pdata = at91_twi_get_driver_data(pdev);
 215        if (!dev->pdata)
 216                return -ENODEV;
 217
 218        dev->base = devm_ioremap_resource(&pdev->dev, mem);
 219        if (IS_ERR(dev->base))
 220                return PTR_ERR(dev->base);
 221
 222        dev->irq = platform_get_irq(pdev, 0);
 223        if (dev->irq < 0)
 224                return dev->irq;
 225
 226        platform_set_drvdata(pdev, dev);
 227
 228        dev->clk = devm_clk_get(dev->dev, NULL);
 229        if (IS_ERR(dev->clk)) {
 230                dev_err(dev->dev, "no clock defined\n");
 231                return -ENODEV;
 232        }
 233        clk_prepare_enable(dev->clk);
 234
 235        snprintf(dev->adapter.name, sizeof(dev->adapter.name), "AT91");
 236        i2c_set_adapdata(&dev->adapter, dev);
 237        dev->adapter.owner = THIS_MODULE;
 238        dev->adapter.class = I2C_CLASS_DEPRECATED;
 239        dev->adapter.dev.parent = dev->dev;
 240        dev->adapter.nr = pdev->id;
 241        dev->adapter.timeout = AT91_I2C_TIMEOUT;
 242        dev->adapter.dev.of_node = pdev->dev.of_node;
 243
 244        dev->slave_detected = i2c_detect_slave_mode(&pdev->dev);
 245
 246        if (dev->slave_detected)
 247                rc = at91_twi_probe_slave(pdev, phy_addr, dev);
 248        else
 249                rc = at91_twi_probe_master(pdev, phy_addr, dev);
 250        if (rc)
 251                return rc;
 252
 253        at91_init_twi_bus(dev);
 254
 255        pm_runtime_set_autosuspend_delay(dev->dev, AUTOSUSPEND_TIMEOUT);
 256        pm_runtime_use_autosuspend(dev->dev);
 257        pm_runtime_set_active(dev->dev);
 258        pm_runtime_enable(dev->dev);
 259
 260        rc = i2c_add_numbered_adapter(&dev->adapter);
 261        if (rc) {
 262                clk_disable_unprepare(dev->clk);
 263
 264                pm_runtime_disable(dev->dev);
 265                pm_runtime_set_suspended(dev->dev);
 266
 267                return rc;
 268        }
 269
 270        dev_info(dev->dev, "AT91 i2c bus driver (hw version: %#x).\n",
 271                 at91_twi_read(dev, AT91_TWI_VER));
 272        return 0;
 273}
 274
 275static int at91_twi_remove(struct platform_device *pdev)
 276{
 277        struct at91_twi_dev *dev = platform_get_drvdata(pdev);
 278
 279        i2c_del_adapter(&dev->adapter);
 280        clk_disable_unprepare(dev->clk);
 281
 282        pm_runtime_disable(dev->dev);
 283        pm_runtime_set_suspended(dev->dev);
 284
 285        return 0;
 286}
 287
 288#ifdef CONFIG_PM
 289
 290static int at91_twi_runtime_suspend(struct device *dev)
 291{
 292        struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
 293
 294        clk_disable_unprepare(twi_dev->clk);
 295
 296        pinctrl_pm_select_sleep_state(dev);
 297
 298        return 0;
 299}
 300
 301static int at91_twi_runtime_resume(struct device *dev)
 302{
 303        struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
 304
 305        pinctrl_pm_select_default_state(dev);
 306
 307        return clk_prepare_enable(twi_dev->clk);
 308}
 309
 310static int at91_twi_suspend_noirq(struct device *dev)
 311{
 312        if (!pm_runtime_status_suspended(dev))
 313                at91_twi_runtime_suspend(dev);
 314
 315        return 0;
 316}
 317
 318static int at91_twi_resume_noirq(struct device *dev)
 319{
 320        struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
 321        int ret;
 322
 323        if (!pm_runtime_status_suspended(dev)) {
 324                ret = at91_twi_runtime_resume(dev);
 325                if (ret)
 326                        return ret;
 327        }
 328
 329        pm_runtime_mark_last_busy(dev);
 330        pm_request_autosuspend(dev);
 331
 332        at91_init_twi_bus(twi_dev);
 333
 334        return 0;
 335}
 336
 337static const struct dev_pm_ops at91_twi_pm = {
 338        .suspend_noirq  = at91_twi_suspend_noirq,
 339        .resume_noirq   = at91_twi_resume_noirq,
 340        .runtime_suspend        = at91_twi_runtime_suspend,
 341        .runtime_resume         = at91_twi_runtime_resume,
 342};
 343
 344#define at91_twi_pm_ops (&at91_twi_pm)
 345#else
 346#define at91_twi_pm_ops NULL
 347#endif
 348
 349static struct platform_driver at91_twi_driver = {
 350        .probe          = at91_twi_probe,
 351        .remove         = at91_twi_remove,
 352        .id_table       = at91_twi_devtypes,
 353        .driver         = {
 354                .name   = "at91_i2c",
 355                .of_match_table = of_match_ptr(atmel_twi_dt_ids),
 356                .pm     = at91_twi_pm_ops,
 357        },
 358};
 359
 360static int __init at91_twi_init(void)
 361{
 362        return platform_driver_register(&at91_twi_driver);
 363}
 364
 365static void __exit at91_twi_exit(void)
 366{
 367        platform_driver_unregister(&at91_twi_driver);
 368}
 369
 370subsys_initcall(at91_twi_init);
 371module_exit(at91_twi_exit);
 372
 373MODULE_AUTHOR("Nikolaus Voss <n.voss@weinmann.de>");
 374MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91");
 375MODULE_LICENSE("GPL");
 376MODULE_ALIAS("platform:at91_i2c");
 377