Linux Audio

Check our new training course

Linux BSP upgrade and security maintenance

Need help to get security updates for your Linux BSP?
Loading...
v6.8
  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);
v6.2
  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);