Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  i2c Support for Atmel's AT91 Two-Wire Interface (TWI)
0004  *
0005  *  Copyright (C) 2011 Weinmann Medical GmbH
0006  *  Author: Nikolaus Voss <n.voss@weinmann.de>
0007  *
0008  *  Evolved from original work by:
0009  *  Copyright (C) 2004 Rick Bronson
0010  *  Converted to 2.6 by Andrew Victor <andrew@sanpeople.com>
0011  *
0012  *  Borrowed heavily from original work by:
0013  *  Copyright (C) 2000 Philip Edelbrock <phil@stimpy.netroedge.com>
0014  */
0015 
0016 #include <linux/clk.h>
0017 #include <linux/err.h>
0018 #include <linux/i2c.h>
0019 #include <linux/io.h>
0020 #include <linux/module.h>
0021 #include <linux/of.h>
0022 #include <linux/of_device.h>
0023 #include <linux/platform_device.h>
0024 #include <linux/pm_runtime.h>
0025 #include <linux/pinctrl/consumer.h>
0026 
0027 #include "i2c-at91.h"
0028 
0029 unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg)
0030 {
0031     return readl_relaxed(dev->base + reg);
0032 }
0033 
0034 void at91_twi_write(struct at91_twi_dev *dev, unsigned reg, unsigned val)
0035 {
0036     writel_relaxed(val, dev->base + reg);
0037 }
0038 
0039 void at91_disable_twi_interrupts(struct at91_twi_dev *dev)
0040 {
0041     at91_twi_write(dev, AT91_TWI_IDR, AT91_TWI_INT_MASK);
0042 }
0043 
0044 void at91_twi_irq_save(struct at91_twi_dev *dev)
0045 {
0046     dev->imr = at91_twi_read(dev, AT91_TWI_IMR) & AT91_TWI_INT_MASK;
0047     at91_disable_twi_interrupts(dev);
0048 }
0049 
0050 void at91_twi_irq_restore(struct at91_twi_dev *dev)
0051 {
0052     at91_twi_write(dev, AT91_TWI_IER, dev->imr);
0053 }
0054 
0055 void at91_init_twi_bus(struct at91_twi_dev *dev)
0056 {
0057     at91_disable_twi_interrupts(dev);
0058     at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SWRST);
0059     if (dev->slave_detected)
0060         at91_init_twi_bus_slave(dev);
0061     else
0062         at91_init_twi_bus_master(dev);
0063 }
0064 
0065 static struct at91_twi_pdata at91rm9200_config = {
0066     .clk_max_div = 5,
0067     .clk_offset = 3,
0068     .has_unre_flag = true,
0069 };
0070 
0071 static struct at91_twi_pdata at91sam9261_config = {
0072     .clk_max_div = 5,
0073     .clk_offset = 4,
0074 };
0075 
0076 static struct at91_twi_pdata at91sam9260_config = {
0077     .clk_max_div = 7,
0078     .clk_offset = 4,
0079 };
0080 
0081 static struct at91_twi_pdata at91sam9g20_config = {
0082     .clk_max_div = 7,
0083     .clk_offset = 4,
0084 };
0085 
0086 static struct at91_twi_pdata at91sam9g10_config = {
0087     .clk_max_div = 7,
0088     .clk_offset = 4,
0089 };
0090 
0091 static const struct platform_device_id at91_twi_devtypes[] = {
0092     {
0093         .name = "i2c-at91rm9200",
0094         .driver_data = (unsigned long) &at91rm9200_config,
0095     }, {
0096         .name = "i2c-at91sam9261",
0097         .driver_data = (unsigned long) &at91sam9261_config,
0098     }, {
0099         .name = "i2c-at91sam9260",
0100         .driver_data = (unsigned long) &at91sam9260_config,
0101     }, {
0102         .name = "i2c-at91sam9g20",
0103         .driver_data = (unsigned long) &at91sam9g20_config,
0104     }, {
0105         .name = "i2c-at91sam9g10",
0106         .driver_data = (unsigned long) &at91sam9g10_config,
0107     }, {
0108         /* sentinel */
0109     }
0110 };
0111 
0112 #if defined(CONFIG_OF)
0113 static struct at91_twi_pdata at91sam9x5_config = {
0114     .clk_max_div = 7,
0115     .clk_offset = 4,
0116 };
0117 
0118 static struct at91_twi_pdata sama5d4_config = {
0119     .clk_max_div = 7,
0120     .clk_offset = 4,
0121     .has_hold_field = true,
0122     .has_dig_filtr = true,
0123 };
0124 
0125 static struct at91_twi_pdata sama5d2_config = {
0126     .clk_max_div = 7,
0127     .clk_offset = 3,
0128     .has_unre_flag = true,
0129     .has_alt_cmd = true,
0130     .has_hold_field = true,
0131     .has_dig_filtr = true,
0132     .has_adv_dig_filtr = true,
0133     .has_ana_filtr = true,
0134     .has_clear_cmd = false, /* due to errata, CLEAR cmd is not working */
0135 };
0136 
0137 static struct at91_twi_pdata sam9x60_config = {
0138     .clk_max_div = 7,
0139     .clk_offset = 3,
0140     .has_unre_flag = true,
0141     .has_alt_cmd = true,
0142     .has_hold_field = true,
0143     .has_dig_filtr = true,
0144     .has_adv_dig_filtr = true,
0145     .has_ana_filtr = true,
0146     .has_clear_cmd = true,
0147 };
0148 
0149 static const struct of_device_id atmel_twi_dt_ids[] = {
0150     {
0151         .compatible = "atmel,at91rm9200-i2c",
0152         .data = &at91rm9200_config,
0153     }, {
0154         .compatible = "atmel,at91sam9260-i2c",
0155         .data = &at91sam9260_config,
0156     }, {
0157         .compatible = "atmel,at91sam9261-i2c",
0158         .data = &at91sam9261_config,
0159     }, {
0160         .compatible = "atmel,at91sam9g20-i2c",
0161         .data = &at91sam9g20_config,
0162     }, {
0163         .compatible = "atmel,at91sam9g10-i2c",
0164         .data = &at91sam9g10_config,
0165     }, {
0166         .compatible = "atmel,at91sam9x5-i2c",
0167         .data = &at91sam9x5_config,
0168     }, {
0169         .compatible = "atmel,sama5d4-i2c",
0170         .data = &sama5d4_config,
0171     }, {
0172         .compatible = "atmel,sama5d2-i2c",
0173         .data = &sama5d2_config,
0174     }, {
0175         .compatible = "microchip,sam9x60-i2c",
0176         .data = &sam9x60_config,
0177     }, {
0178         /* sentinel */
0179     }
0180 };
0181 MODULE_DEVICE_TABLE(of, atmel_twi_dt_ids);
0182 #endif
0183 
0184 static struct at91_twi_pdata *at91_twi_get_driver_data(
0185                     struct platform_device *pdev)
0186 {
0187     if (pdev->dev.of_node) {
0188         const struct of_device_id *match;
0189         match = of_match_node(atmel_twi_dt_ids, pdev->dev.of_node);
0190         if (!match)
0191             return NULL;
0192         return (struct at91_twi_pdata *)match->data;
0193     }
0194     return (struct at91_twi_pdata *) platform_get_device_id(pdev)->driver_data;
0195 }
0196 
0197 static int at91_twi_probe(struct platform_device *pdev)
0198 {
0199     struct at91_twi_dev *dev;
0200     struct resource *mem;
0201     int rc;
0202     u32 phy_addr;
0203 
0204     dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
0205     if (!dev)
0206         return -ENOMEM;
0207 
0208     dev->dev = &pdev->dev;
0209 
0210     mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0211     if (!mem)
0212         return -ENODEV;
0213     phy_addr = mem->start;
0214 
0215     dev->pdata = at91_twi_get_driver_data(pdev);
0216     if (!dev->pdata)
0217         return -ENODEV;
0218 
0219     dev->base = devm_ioremap_resource(&pdev->dev, mem);
0220     if (IS_ERR(dev->base))
0221         return PTR_ERR(dev->base);
0222 
0223     dev->irq = platform_get_irq(pdev, 0);
0224     if (dev->irq < 0)
0225         return dev->irq;
0226 
0227     platform_set_drvdata(pdev, dev);
0228 
0229     dev->clk = devm_clk_get(dev->dev, NULL);
0230     if (IS_ERR(dev->clk)) {
0231         dev_err(dev->dev, "no clock defined\n");
0232         return -ENODEV;
0233     }
0234     clk_prepare_enable(dev->clk);
0235 
0236     snprintf(dev->adapter.name, sizeof(dev->adapter.name), "AT91");
0237     i2c_set_adapdata(&dev->adapter, dev);
0238     dev->adapter.owner = THIS_MODULE;
0239     dev->adapter.class = I2C_CLASS_DEPRECATED;
0240     dev->adapter.dev.parent = dev->dev;
0241     dev->adapter.nr = pdev->id;
0242     dev->adapter.timeout = AT91_I2C_TIMEOUT;
0243     dev->adapter.dev.of_node = pdev->dev.of_node;
0244 
0245     dev->slave_detected = i2c_detect_slave_mode(&pdev->dev);
0246 
0247     if (dev->slave_detected)
0248         rc = at91_twi_probe_slave(pdev, phy_addr, dev);
0249     else
0250         rc = at91_twi_probe_master(pdev, phy_addr, dev);
0251     if (rc)
0252         return rc;
0253 
0254     at91_init_twi_bus(dev);
0255 
0256     pm_runtime_set_autosuspend_delay(dev->dev, AUTOSUSPEND_TIMEOUT);
0257     pm_runtime_use_autosuspend(dev->dev);
0258     pm_runtime_set_active(dev->dev);
0259     pm_runtime_enable(dev->dev);
0260 
0261     rc = i2c_add_numbered_adapter(&dev->adapter);
0262     if (rc) {
0263         clk_disable_unprepare(dev->clk);
0264 
0265         pm_runtime_disable(dev->dev);
0266         pm_runtime_set_suspended(dev->dev);
0267 
0268         return rc;
0269     }
0270 
0271     dev_info(dev->dev, "AT91 i2c bus driver (hw version: %#x).\n",
0272          at91_twi_read(dev, AT91_TWI_VER));
0273     return 0;
0274 }
0275 
0276 static int at91_twi_remove(struct platform_device *pdev)
0277 {
0278     struct at91_twi_dev *dev = platform_get_drvdata(pdev);
0279 
0280     i2c_del_adapter(&dev->adapter);
0281     clk_disable_unprepare(dev->clk);
0282 
0283     pm_runtime_disable(dev->dev);
0284     pm_runtime_set_suspended(dev->dev);
0285 
0286     return 0;
0287 }
0288 
0289 static int __maybe_unused at91_twi_runtime_suspend(struct device *dev)
0290 {
0291     struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
0292 
0293     clk_disable_unprepare(twi_dev->clk);
0294 
0295     pinctrl_pm_select_sleep_state(dev);
0296 
0297     return 0;
0298 }
0299 
0300 static int __maybe_unused at91_twi_runtime_resume(struct device *dev)
0301 {
0302     struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
0303 
0304     pinctrl_pm_select_default_state(dev);
0305 
0306     return clk_prepare_enable(twi_dev->clk);
0307 }
0308 
0309 static int __maybe_unused at91_twi_suspend_noirq(struct device *dev)
0310 {
0311     if (!pm_runtime_status_suspended(dev))
0312         at91_twi_runtime_suspend(dev);
0313 
0314     return 0;
0315 }
0316 
0317 static int __maybe_unused at91_twi_resume_noirq(struct device *dev)
0318 {
0319     struct at91_twi_dev *twi_dev = dev_get_drvdata(dev);
0320     int ret;
0321 
0322     if (!pm_runtime_status_suspended(dev)) {
0323         ret = at91_twi_runtime_resume(dev);
0324         if (ret)
0325             return ret;
0326     }
0327 
0328     pm_runtime_mark_last_busy(dev);
0329     pm_request_autosuspend(dev);
0330 
0331     at91_init_twi_bus(twi_dev);
0332 
0333     return 0;
0334 }
0335 
0336 static const struct dev_pm_ops __maybe_unused at91_twi_pm = {
0337     .suspend_noirq  = at91_twi_suspend_noirq,
0338     .resume_noirq   = at91_twi_resume_noirq,
0339     .runtime_suspend    = at91_twi_runtime_suspend,
0340     .runtime_resume     = at91_twi_runtime_resume,
0341 };
0342 
0343 static struct platform_driver at91_twi_driver = {
0344     .probe      = at91_twi_probe,
0345     .remove     = at91_twi_remove,
0346     .id_table   = at91_twi_devtypes,
0347     .driver     = {
0348         .name   = "at91_i2c",
0349         .of_match_table = of_match_ptr(atmel_twi_dt_ids),
0350         .pm = pm_ptr(&at91_twi_pm),
0351     },
0352 };
0353 
0354 static int __init at91_twi_init(void)
0355 {
0356     return platform_driver_register(&at91_twi_driver);
0357 }
0358 
0359 static void __exit at91_twi_exit(void)
0360 {
0361     platform_driver_unregister(&at91_twi_driver);
0362 }
0363 
0364 subsys_initcall(at91_twi_init);
0365 module_exit(at91_twi_exit);
0366 
0367 MODULE_AUTHOR("Nikolaus Voss <n.voss@weinmann.de>");
0368 MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91");
0369 MODULE_LICENSE("GPL");
0370 MODULE_ALIAS("platform:at91_i2c");