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

88pm860x-i2c.c (4218B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * I2C driver for Marvell 88PM860x
      4 *
      5 * Copyright (C) 2009 Marvell International Ltd.
      6 *
      7 * Author: Haojian Zhuang <haojian.zhuang@marvell.com>
      8 */
      9#include <linux/kernel.h>
     10#include <linux/module.h>
     11#include <linux/i2c.h>
     12#include <linux/regmap.h>
     13#include <linux/mfd/88pm860x.h>
     14
     15int pm860x_reg_read(struct i2c_client *i2c, int reg)
     16{
     17	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
     18	struct regmap *map = (i2c == chip->client) ? chip->regmap
     19				: chip->regmap_companion;
     20	unsigned int data;
     21	int ret;
     22
     23	ret = regmap_read(map, reg, &data);
     24	if (ret < 0)
     25		return ret;
     26	else
     27		return (int)data;
     28}
     29EXPORT_SYMBOL(pm860x_reg_read);
     30
     31int pm860x_reg_write(struct i2c_client *i2c, int reg,
     32		     unsigned char data)
     33{
     34	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
     35	struct regmap *map = (i2c == chip->client) ? chip->regmap
     36				: chip->regmap_companion;
     37	int ret;
     38
     39	ret = regmap_write(map, reg, data);
     40	return ret;
     41}
     42EXPORT_SYMBOL(pm860x_reg_write);
     43
     44int pm860x_bulk_read(struct i2c_client *i2c, int reg,
     45		     int count, unsigned char *buf)
     46{
     47	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
     48	struct regmap *map = (i2c == chip->client) ? chip->regmap
     49				: chip->regmap_companion;
     50	int ret;
     51
     52	ret = regmap_raw_read(map, reg, buf, count);
     53	return ret;
     54}
     55EXPORT_SYMBOL(pm860x_bulk_read);
     56
     57int pm860x_bulk_write(struct i2c_client *i2c, int reg,
     58		      int count, unsigned char *buf)
     59{
     60	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
     61	struct regmap *map = (i2c == chip->client) ? chip->regmap
     62				: chip->regmap_companion;
     63	int ret;
     64
     65	ret = regmap_raw_write(map, reg, buf, count);
     66	return ret;
     67}
     68EXPORT_SYMBOL(pm860x_bulk_write);
     69
     70int pm860x_set_bits(struct i2c_client *i2c, int reg,
     71		    unsigned char mask, unsigned char data)
     72{
     73	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
     74	struct regmap *map = (i2c == chip->client) ? chip->regmap
     75				: chip->regmap_companion;
     76	int ret;
     77
     78	ret = regmap_update_bits(map, reg, mask, data);
     79	return ret;
     80}
     81EXPORT_SYMBOL(pm860x_set_bits);
     82
     83static int read_device(struct i2c_client *i2c, int reg,
     84		       int bytes, void *dest)
     85{
     86	unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX + 3];
     87	unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX + 2];
     88	struct i2c_adapter *adap = i2c->adapter;
     89	struct i2c_msg msg[2] = {
     90					{
     91						.addr = i2c->addr,
     92						.flags = 0,
     93						.len = 1,
     94						.buf = msgbuf0
     95					},
     96					{	.addr = i2c->addr,
     97						.flags = I2C_M_RD,
     98						.len = 0,
     99						.buf = msgbuf1
    100					},
    101				};
    102	int num = 1, ret = 0;
    103
    104	if (dest == NULL)
    105		return -EINVAL;
    106	msgbuf0[0] = (unsigned char)reg;	/* command */
    107	msg[1].len = bytes;
    108
    109	/* if data needs to read back, num should be 2 */
    110	if (bytes > 0)
    111		num = 2;
    112	ret = adap->algo->master_xfer(adap, msg, num);
    113	memcpy(dest, msgbuf1, bytes);
    114	if (ret < 0)
    115		return ret;
    116	return 0;
    117}
    118
    119static int write_device(struct i2c_client *i2c, int reg,
    120			int bytes, void *src)
    121{
    122	unsigned char buf[2];
    123	struct i2c_adapter *adap = i2c->adapter;
    124	struct i2c_msg msg;
    125	int ret;
    126
    127	buf[0] = (unsigned char)reg;
    128	memcpy(&buf[1], src, bytes);
    129	msg.addr = i2c->addr;
    130	msg.flags = 0;
    131	msg.len = bytes + 1;
    132	msg.buf = buf;
    133
    134	ret = adap->algo->master_xfer(adap, &msg, 1);
    135	if (ret < 0)
    136		return ret;
    137	return 0;
    138}
    139
    140int pm860x_page_reg_write(struct i2c_client *i2c, int reg,
    141			  unsigned char data)
    142{
    143	unsigned char zero;
    144	int ret;
    145
    146	i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
    147	read_device(i2c, 0xFA, 0, &zero);
    148	read_device(i2c, 0xFB, 0, &zero);
    149	read_device(i2c, 0xFF, 0, &zero);
    150	ret = write_device(i2c, reg, 1, &data);
    151	read_device(i2c, 0xFE, 0, &zero);
    152	read_device(i2c, 0xFC, 0, &zero);
    153	i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
    154	return ret;
    155}
    156EXPORT_SYMBOL(pm860x_page_reg_write);
    157
    158int pm860x_page_bulk_read(struct i2c_client *i2c, int reg,
    159			  int count, unsigned char *buf)
    160{
    161	unsigned char zero = 0;
    162	int ret;
    163
    164	i2c_lock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
    165	read_device(i2c, 0xfa, 0, &zero);
    166	read_device(i2c, 0xfb, 0, &zero);
    167	read_device(i2c, 0xff, 0, &zero);
    168	ret = read_device(i2c, reg, count, buf);
    169	read_device(i2c, 0xFE, 0, &zero);
    170	read_device(i2c, 0xFC, 0, &zero);
    171	i2c_unlock_bus(i2c->adapter, I2C_LOCK_SEGMENT);
    172	return ret;
    173}
    174EXPORT_SYMBOL(pm860x_page_bulk_read);