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-simtec.c (3207B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2005 Simtec Electronics
      4 *	Ben Dooks <ben@simtec.co.uk>
      5 *
      6 * Simtec Generic I2C Controller
      7*/
      8
      9#include <linux/kernel.h>
     10#include <linux/module.h>
     11#include <linux/delay.h>
     12#include <linux/platform_device.h>
     13#include <linux/slab.h>
     14#include <linux/io.h>
     15
     16#include <linux/i2c.h>
     17#include <linux/i2c-algo-bit.h>
     18
     19struct simtec_i2c_data {
     20	struct resource		*ioarea;
     21	void __iomem		*reg;
     22	struct i2c_adapter	 adap;
     23	struct i2c_algo_bit_data bit;
     24};
     25
     26#define CMD_SET_SDA	(1<<2)
     27#define CMD_SET_SCL	(1<<3)
     28
     29#define STATE_SDA	(1<<0)
     30#define STATE_SCL	(1<<1)
     31
     32/* i2c bit-bus functions */
     33
     34static void simtec_i2c_setsda(void *pw, int state)
     35{
     36	struct simtec_i2c_data *pd = pw;
     37	writeb(CMD_SET_SDA | (state ? STATE_SDA : 0), pd->reg);
     38}
     39
     40static void simtec_i2c_setscl(void *pw, int state)
     41{
     42	struct simtec_i2c_data *pd = pw;
     43	writeb(CMD_SET_SCL | (state ? STATE_SCL : 0), pd->reg);
     44}
     45
     46static int simtec_i2c_getsda(void *pw)
     47{
     48	struct simtec_i2c_data *pd = pw;
     49	return readb(pd->reg) & STATE_SDA ? 1 : 0;
     50}
     51
     52static int simtec_i2c_getscl(void *pw)
     53{
     54	struct simtec_i2c_data *pd = pw;
     55	return readb(pd->reg) & STATE_SCL ? 1 : 0;
     56}
     57
     58/* device registration */
     59
     60static int simtec_i2c_probe(struct platform_device *dev)
     61{
     62	struct simtec_i2c_data *pd;
     63	struct resource *res;
     64	int size;
     65	int ret;
     66
     67	pd = kzalloc(sizeof(struct simtec_i2c_data), GFP_KERNEL);
     68	if (pd == NULL)
     69		return -ENOMEM;
     70
     71	platform_set_drvdata(dev, pd);
     72
     73	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
     74	if (res == NULL) {
     75		dev_err(&dev->dev, "cannot find IO resource\n");
     76		ret = -ENOENT;
     77		goto err;
     78	}
     79
     80	size = resource_size(res);
     81
     82	pd->ioarea = request_mem_region(res->start, size, dev->name);
     83	if (pd->ioarea == NULL) {
     84		dev_err(&dev->dev, "cannot request IO\n");
     85		ret = -ENXIO;
     86		goto err;
     87	}
     88
     89	pd->reg = ioremap(res->start, size);
     90	if (pd->reg == NULL) {
     91		dev_err(&dev->dev, "cannot map IO\n");
     92		ret = -ENXIO;
     93		goto err_res;
     94	}
     95
     96	/* setup the private data */
     97
     98	pd->adap.owner = THIS_MODULE;
     99	pd->adap.algo_data = &pd->bit;
    100	pd->adap.dev.parent = &dev->dev;
    101
    102	strlcpy(pd->adap.name, "Simtec I2C", sizeof(pd->adap.name));
    103
    104	pd->bit.data = pd;
    105	pd->bit.setsda = simtec_i2c_setsda;
    106	pd->bit.setscl = simtec_i2c_setscl;
    107	pd->bit.getsda = simtec_i2c_getsda;
    108	pd->bit.getscl = simtec_i2c_getscl;
    109	pd->bit.timeout = HZ;
    110	pd->bit.udelay = 20;
    111
    112	ret = i2c_bit_add_bus(&pd->adap);
    113	if (ret)
    114		goto err_all;
    115
    116	return 0;
    117
    118 err_all:
    119	iounmap(pd->reg);
    120
    121 err_res:
    122	release_mem_region(pd->ioarea->start, size);
    123
    124 err:
    125	kfree(pd);
    126	return ret;
    127}
    128
    129static int simtec_i2c_remove(struct platform_device *dev)
    130{
    131	struct simtec_i2c_data *pd = platform_get_drvdata(dev);
    132
    133	i2c_del_adapter(&pd->adap);
    134
    135	iounmap(pd->reg);
    136	release_mem_region(pd->ioarea->start, resource_size(pd->ioarea));
    137	kfree(pd);
    138
    139	return 0;
    140}
    141
    142/* device driver */
    143
    144static struct platform_driver simtec_i2c_driver = {
    145	.driver		= {
    146		.name		= "simtec-i2c",
    147	},
    148	.probe		= simtec_i2c_probe,
    149	.remove		= simtec_i2c_remove,
    150};
    151
    152module_platform_driver(simtec_i2c_driver);
    153
    154MODULE_DESCRIPTION("Simtec Generic I2C Bus driver");
    155MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
    156MODULE_LICENSE("GPL");
    157MODULE_ALIAS("platform:simtec-i2c");