cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

i2c-versatile.c (3196B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 *  i2c-versatile.c
      4 *
      5 *  Copyright (C) 2006 ARM Ltd.
      6 *  written by Russell King, Deep Blue Solutions Ltd.
      7 */
      8#include <linux/kernel.h>
      9#include <linux/module.h>
     10#include <linux/i2c.h>
     11#include <linux/i2c-algo-bit.h>
     12#include <linux/init.h>
     13#include <linux/platform_device.h>
     14#include <linux/slab.h>
     15#include <linux/io.h>
     16
     17#define I2C_CONTROL	0x00
     18#define I2C_CONTROLS	0x00
     19#define I2C_CONTROLC	0x04
     20#define SCL		(1 << 0)
     21#define SDA		(1 << 1)
     22
     23struct i2c_versatile {
     24	struct i2c_adapter	 adap;
     25	struct i2c_algo_bit_data algo;
     26	void __iomem		 *base;
     27};
     28
     29static void i2c_versatile_setsda(void *data, int state)
     30{
     31	struct i2c_versatile *i2c = data;
     32
     33	writel(SDA, i2c->base + (state ? I2C_CONTROLS : I2C_CONTROLC));
     34}
     35
     36static void i2c_versatile_setscl(void *data, int state)
     37{
     38	struct i2c_versatile *i2c = data;
     39
     40	writel(SCL, i2c->base + (state ? I2C_CONTROLS : I2C_CONTROLC));
     41}
     42
     43static int i2c_versatile_getsda(void *data)
     44{
     45	struct i2c_versatile *i2c = data;
     46	return !!(readl(i2c->base + I2C_CONTROL) & SDA);
     47}
     48
     49static int i2c_versatile_getscl(void *data)
     50{
     51	struct i2c_versatile *i2c = data;
     52	return !!(readl(i2c->base + I2C_CONTROL) & SCL);
     53}
     54
     55static const struct i2c_algo_bit_data i2c_versatile_algo = {
     56	.setsda	= i2c_versatile_setsda,
     57	.setscl = i2c_versatile_setscl,
     58	.getsda	= i2c_versatile_getsda,
     59	.getscl = i2c_versatile_getscl,
     60	.udelay	= 30,
     61	.timeout = HZ,
     62};
     63
     64static int i2c_versatile_probe(struct platform_device *dev)
     65{
     66	struct i2c_versatile *i2c;
     67	struct resource *r;
     68	int ret;
     69
     70	i2c = devm_kzalloc(&dev->dev, sizeof(struct i2c_versatile), GFP_KERNEL);
     71	if (!i2c)
     72		return -ENOMEM;
     73
     74	r = platform_get_resource(dev, IORESOURCE_MEM, 0);
     75	i2c->base = devm_ioremap_resource(&dev->dev, r);
     76	if (IS_ERR(i2c->base))
     77		return PTR_ERR(i2c->base);
     78
     79	writel(SCL | SDA, i2c->base + I2C_CONTROLS);
     80
     81	i2c->adap.owner = THIS_MODULE;
     82	strlcpy(i2c->adap.name, "Versatile I2C adapter", sizeof(i2c->adap.name));
     83	i2c->adap.algo_data = &i2c->algo;
     84	i2c->adap.dev.parent = &dev->dev;
     85	i2c->adap.dev.of_node = dev->dev.of_node;
     86	i2c->algo = i2c_versatile_algo;
     87	i2c->algo.data = i2c;
     88
     89	i2c->adap.nr = dev->id;
     90	ret = i2c_bit_add_numbered_bus(&i2c->adap);
     91	if (ret < 0)
     92		return ret;
     93
     94	platform_set_drvdata(dev, i2c);
     95
     96	return 0;
     97}
     98
     99static int i2c_versatile_remove(struct platform_device *dev)
    100{
    101	struct i2c_versatile *i2c = platform_get_drvdata(dev);
    102
    103	i2c_del_adapter(&i2c->adap);
    104	return 0;
    105}
    106
    107static const struct of_device_id i2c_versatile_match[] = {
    108	{ .compatible = "arm,versatile-i2c", },
    109	{},
    110};
    111MODULE_DEVICE_TABLE(of, i2c_versatile_match);
    112
    113static struct platform_driver i2c_versatile_driver = {
    114	.probe		= i2c_versatile_probe,
    115	.remove		= i2c_versatile_remove,
    116	.driver		= {
    117		.name	= "versatile-i2c",
    118		.of_match_table = i2c_versatile_match,
    119	},
    120};
    121
    122static int __init i2c_versatile_init(void)
    123{
    124	return platform_driver_register(&i2c_versatile_driver);
    125}
    126
    127static void __exit i2c_versatile_exit(void)
    128{
    129	platform_driver_unregister(&i2c_versatile_driver);
    130}
    131
    132subsys_initcall(i2c_versatile_init);
    133module_exit(i2c_versatile_exit);
    134
    135MODULE_DESCRIPTION("ARM Versatile I2C bus driver");
    136MODULE_LICENSE("GPL");
    137MODULE_ALIAS("platform:versatile-i2c");