brintos

brintos / linux-shallow public Read only

0
0
Text · 2.7 KiB · 2697b67 Raw
141 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2021-2023 Digiteq Automotive4 *     author: Martin Tuma <martin.tuma@digiteqautomotive.com>5 *6 * The i2c module unifies the I2C access to the serializes/deserializes. The I2C7 * chips on the GMSL module use 16b addressing, the FPDL3 chips use standard8 * 8b addressing.9 */10 11#include "mgb4_i2c.h"12 13static int read_r16(struct i2c_client *client, u16 reg, u8 *val, int len)14{15	int ret;16	u8 buf[2];17	struct i2c_msg msg[2] = {18		{19			.addr = client->addr,20			.flags = 0,21			.len = 2,22			.buf = buf,23		}, {24			.addr = client->addr,25			.flags = I2C_M_RD,26			.len = len,27			.buf = val,28		}29	};30 31	buf[0] = (reg >> 8) & 0xff;32	buf[1] = (reg >> 0) & 0xff;33 34	ret = i2c_transfer(client->adapter, msg, 2);35	if (ret < 0)36		return ret;37	else if (ret != 2)38		return -EREMOTEIO;39	else40		return 0;41}42 43static int write_r16(struct i2c_client *client, u16 reg, const u8 *val, int len)44{45	int ret;46	u8 buf[4];47	struct i2c_msg msg[1] = {48		{49			.addr = client->addr,50			.flags = 0,51			.len = 2 + len,52			.buf = buf,53		}54	};55 56	if (2 + len > sizeof(buf))57		return -EINVAL;58 59	buf[0] = (reg >> 8) & 0xff;60	buf[1] = (reg >> 0) & 0xff;61	memcpy(&buf[2], val, len);62 63	ret = i2c_transfer(client->adapter, msg, 1);64	if (ret < 0)65		return ret;66	else if (ret != 1)67		return -EREMOTEIO;68	else69		return 0;70}71 72int mgb4_i2c_init(struct mgb4_i2c_client *client, struct i2c_adapter *adap,73		  struct i2c_board_info const *info, int addr_size)74{75	client->client = i2c_new_client_device(adap, info);76	if (IS_ERR(client->client))77		return PTR_ERR(client->client);78 79	client->addr_size = addr_size;80 81	return 0;82}83 84void mgb4_i2c_free(struct mgb4_i2c_client *client)85{86	i2c_unregister_device(client->client);87}88 89s32 mgb4_i2c_read_byte(struct mgb4_i2c_client *client, u16 reg)90{91	int ret;92	u8 b;93 94	if (client->addr_size == 8)95		return i2c_smbus_read_byte_data(client->client, reg);96 97	ret = read_r16(client->client, reg, &b, 1);98	if (ret < 0)99		return ret;100 101	return (s32)b;102}103 104s32 mgb4_i2c_write_byte(struct mgb4_i2c_client *client, u16 reg, u8 val)105{106	if (client->addr_size == 8)107		return i2c_smbus_write_byte_data(client->client, reg, val);108	else109		return write_r16(client->client, reg, &val, 1);110}111 112s32 mgb4_i2c_mask_byte(struct mgb4_i2c_client *client, u16 reg, u8 mask, u8 val)113{114	s32 ret;115 116	if (mask != 0xFF) {117		ret = mgb4_i2c_read_byte(client, reg);118		if (ret < 0)119			return ret;120		val |= (u8)ret & ~mask;121	}122 123	return mgb4_i2c_write_byte(client, reg, val);124}125 126int mgb4_i2c_configure(struct mgb4_i2c_client *client,127		       const struct mgb4_i2c_kv *values, size_t count)128{129	size_t i;130	s32 res;131 132	for (i = 0; i < count; i++) {133		res = mgb4_i2c_mask_byte(client, values[i].reg, values[i].mask,134					 values[i].val);135		if (res < 0)136			return res;137	}138 139	return 0;140}141