brintos

brintos / linux-shallow public Read only

0
0
Text · 12.8 KiB · 63a4c6a Raw
509 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt3 4#include <linux/i2c.h>5#include <linux/mutex.h>6#include <linux/module.h>7 8#include "dibx000_common.h"9 10static int debug;11module_param(debug, int, 0644);12MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");13 14#define dprintk(fmt, arg...) do {					\15	if (debug)							\16		printk(KERN_DEBUG pr_fmt("%s: " fmt),			\17		       __func__, ##arg);				\18} while (0)19 20static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)21{22	int ret;23 24	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {25		dprintk("could not acquire lock\n");26		return -EINVAL;27	}28 29	mst->i2c_write_buffer[0] = (reg >> 8) & 0xff;30	mst->i2c_write_buffer[1] = reg & 0xff;31	mst->i2c_write_buffer[2] = (val >> 8) & 0xff;32	mst->i2c_write_buffer[3] = val & 0xff;33 34	memset(mst->msg, 0, sizeof(struct i2c_msg));35	mst->msg[0].addr = mst->i2c_addr;36	mst->msg[0].flags = 0;37	mst->msg[0].buf = mst->i2c_write_buffer;38	mst->msg[0].len = 4;39 40	ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;41	mutex_unlock(&mst->i2c_buffer_lock);42 43	return ret;44}45 46static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)47{48	u16 ret;49 50	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {51		dprintk("could not acquire lock\n");52		return 0;53	}54 55	mst->i2c_write_buffer[0] = reg >> 8;56	mst->i2c_write_buffer[1] = reg & 0xff;57 58	memset(mst->msg, 0, 2 * sizeof(struct i2c_msg));59	mst->msg[0].addr = mst->i2c_addr;60	mst->msg[0].flags = 0;61	mst->msg[0].buf = mst->i2c_write_buffer;62	mst->msg[0].len = 2;63	mst->msg[1].addr = mst->i2c_addr;64	mst->msg[1].flags = I2C_M_RD;65	mst->msg[1].buf = mst->i2c_read_buffer;66	mst->msg[1].len = 2;67 68	if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)69		dprintk("i2c read error on %d\n", reg);70 71	ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];72	mutex_unlock(&mst->i2c_buffer_lock);73 74	return ret;75}76 77static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)78{79	int i = 100;80	u16 status;81 82	while (((status = dibx000_read_word(mst, mst->base_reg + 2)) & 0x0100) == 0 && --i > 0)83		;84 85	/* i2c timed out */86	if (i == 0)87		return -EREMOTEIO;88 89	/* no acknowledge */90	if ((status & 0x0080) == 0)91		return -EREMOTEIO;92 93	return 0;94}95 96static int dibx000_master_i2c_write(struct dibx000_i2c_master *mst, struct i2c_msg *msg, u8 stop)97{98	u16 data;99	u16 da;100	u16 i;101	u16 txlen = msg->len, len;102	const u8 *b = msg->buf;103 104	while (txlen) {105		dibx000_read_word(mst, mst->base_reg + 2);106 107		len = txlen > 8 ? 8 : txlen;108		for (i = 0; i < len; i += 2) {109			data = *b++ << 8;110			if (i+1 < len)111				data |= *b++;112			dibx000_write_word(mst, mst->base_reg, data);113		}114		da = (((u8) (msg->addr))  << 9) |115			(1           << 8) |116			(1           << 7) |117			(0           << 6) |118			(0           << 5) |119			((len & 0x7) << 2) |120			(0           << 1) |121			(0           << 0);122 123		if (txlen == msg->len)124			da |= 1 << 5; /* start */125 126		if (txlen-len == 0 && stop)127			da |= 1 << 6; /* stop */128 129		dibx000_write_word(mst, mst->base_reg+1, da);130 131		if (dibx000_is_i2c_done(mst) != 0)132			return -EREMOTEIO;133		txlen -= len;134	}135 136	return 0;137}138 139static int dibx000_master_i2c_read(struct dibx000_i2c_master *mst, struct i2c_msg *msg)140{141	u16 da;142	u8 *b = msg->buf;143	u16 rxlen = msg->len, len;144 145	while (rxlen) {146		len = rxlen > 8 ? 8 : rxlen;147		da = (((u8) (msg->addr)) << 9) |148			(1           << 8) |149			(1           << 7) |150			(0           << 6) |151			(0           << 5) |152			((len & 0x7) << 2) |153			(1           << 1) |154			(0           << 0);155 156		if (rxlen == msg->len)157			da |= 1 << 5; /* start */158 159		if (rxlen-len == 0)160			da |= 1 << 6; /* stop */161		dibx000_write_word(mst, mst->base_reg+1, da);162 163		if (dibx000_is_i2c_done(mst) != 0)164			return -EREMOTEIO;165 166		rxlen -= len;167 168		while (len) {169			da = dibx000_read_word(mst, mst->base_reg);170			*b++ = (da >> 8) & 0xff;171			len--;172			if (len >= 1) {173				*b++ =  da   & 0xff;174				len--;175			}176		}177	}178 179	return 0;180}181 182int dibx000_i2c_set_speed(struct i2c_adapter *i2c_adap, u16 speed)183{184	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);185 186	if (mst->device_rev < DIB7000MC && speed < 235)187		speed = 235;188	return dibx000_write_word(mst, mst->base_reg + 3, (u16)(60000 / speed));189 190}191EXPORT_SYMBOL(dibx000_i2c_set_speed);192 193static u32 dibx000_i2c_func(struct i2c_adapter *adapter)194{195	return I2C_FUNC_I2C;196}197 198static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst,199					enum dibx000_i2c_interface intf)200{201	if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) {202		dprintk("selecting interface: %d\n", intf);203		mst->selected_interface = intf;204		return dibx000_write_word(mst, mst->base_reg + 4, intf);205	}206	return 0;207}208 209static int dibx000_i2c_master_xfer_gpio12(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)210{211	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);212	int msg_index;213	int ret = 0;214 215	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_1_2);216	for (msg_index = 0; msg_index < num; msg_index++) {217		if (msg[msg_index].flags & I2C_M_RD) {218			ret = dibx000_master_i2c_read(mst, &msg[msg_index]);219			if (ret != 0)220				return 0;221		} else {222			ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1);223			if (ret != 0)224				return 0;225		}226	}227 228	return num;229}230 231static int dibx000_i2c_master_xfer_gpio34(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)232{233	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);234	int msg_index;235	int ret = 0;236 237	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_3_4);238	for (msg_index = 0; msg_index < num; msg_index++) {239		if (msg[msg_index].flags & I2C_M_RD) {240			ret = dibx000_master_i2c_read(mst, &msg[msg_index]);241			if (ret != 0)242				return 0;243		} else {244			ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1);245			if (ret != 0)246				return 0;247		}248	}249 250	return num;251}252 253static struct i2c_algorithm dibx000_i2c_master_gpio12_xfer_algo = {254	.master_xfer = dibx000_i2c_master_xfer_gpio12,255	.functionality = dibx000_i2c_func,256};257 258static struct i2c_algorithm dibx000_i2c_master_gpio34_xfer_algo = {259	.master_xfer = dibx000_i2c_master_xfer_gpio34,260	.functionality = dibx000_i2c_func,261};262 263static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4],264				 u8 addr, int onoff)265{266	u16 val;267 268 269	if (onoff)270		val = addr << 8;	// bit 7 = use master or not, if 0, the gate is open271	else272		val = 1 << 7;273 274	if (mst->device_rev > DIB7000)275		val <<= 1;276 277	tx[0] = (((mst->base_reg + 1) >> 8) & 0xff);278	tx[1] = ((mst->base_reg + 1) & 0xff);279	tx[2] = val >> 8;280	tx[3] = val & 0xff;281 282	return 0;283}284 285static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,286					struct i2c_msg msg[], int num)287{288	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);289	int ret;290 291	if (num > 32) {292		dprintk("%s: too much I2C message to be transmitted (%i). Maximum is 32",293			__func__, num);294		return -ENOMEM;295	}296 297	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);298 299	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {300		dprintk("could not acquire lock\n");301		return -EINVAL;302	}303 304	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));305 306	/* open the gate */307	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);308	mst->msg[0].addr = mst->i2c_addr;309	mst->msg[0].buf = &mst->i2c_write_buffer[0];310	mst->msg[0].len = 4;311 312	memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);313 314	/* close the gate */315	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);316	mst->msg[num + 1].addr = mst->i2c_addr;317	mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];318	mst->msg[num + 1].len = 4;319 320	ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?321			num : -EIO);322 323	mutex_unlock(&mst->i2c_buffer_lock);324	return ret;325}326 327static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {328	.master_xfer = dibx000_i2c_gated_gpio67_xfer,329	.functionality = dibx000_i2c_func,330};331 332static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,333					struct i2c_msg msg[], int num)334{335	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);336	int ret;337 338	if (num > 32) {339		dprintk("%s: too much I2C message to be transmitted (%i). Maximum is 32",340			__func__, num);341		return -ENOMEM;342	}343 344	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);345 346	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {347		dprintk("could not acquire lock\n");348		return -EINVAL;349	}350	memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));351 352	/* open the gate */353	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);354	mst->msg[0].addr = mst->i2c_addr;355	mst->msg[0].buf = &mst->i2c_write_buffer[0];356	mst->msg[0].len = 4;357 358	memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);359 360	/* close the gate */361	dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);362	mst->msg[num + 1].addr = mst->i2c_addr;363	mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];364	mst->msg[num + 1].len = 4;365 366	ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?367			num : -EIO);368	mutex_unlock(&mst->i2c_buffer_lock);369	return ret;370}371 372static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {373	.master_xfer = dibx000_i2c_gated_tuner_xfer,374	.functionality = dibx000_i2c_func,375};376 377struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst,378						enum dibx000_i2c_interface intf,379						int gating)380{381	struct i2c_adapter *i2c = NULL;382 383	switch (intf) {384	case DIBX000_I2C_INTERFACE_TUNER:385		if (gating)386			i2c = &mst->gated_tuner_i2c_adap;387		break;388	case DIBX000_I2C_INTERFACE_GPIO_1_2:389		if (!gating)390			i2c = &mst->master_i2c_adap_gpio12;391		break;392	case DIBX000_I2C_INTERFACE_GPIO_3_4:393		if (!gating)394			i2c = &mst->master_i2c_adap_gpio34;395		break;396	case DIBX000_I2C_INTERFACE_GPIO_6_7:397		if (gating)398			i2c = &mst->master_i2c_adap_gpio67;399		break;400	default:401		pr_err("incorrect I2C interface selected\n");402		break;403	}404 405	return i2c;406}407 408EXPORT_SYMBOL(dibx000_get_i2c_adapter);409 410void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst)411{412	/* initialize the i2c-master by closing the gate */413	u8 tx[4];414	struct i2c_msg m = {.addr = mst->i2c_addr,.buf = tx,.len = 4 };415 416	dibx000_i2c_gate_ctrl(mst, tx, 0, 0);417	i2c_transfer(mst->i2c_adap, &m, 1);418	mst->selected_interface = 0xff;	// the first time force a select of the I2C419	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);420}421 422EXPORT_SYMBOL(dibx000_reset_i2c_master);423 424static int i2c_adapter_init(struct i2c_adapter *i2c_adap,425				struct i2c_algorithm *algo, const char *name,426				struct dibx000_i2c_master *mst)427{428	strscpy(i2c_adap->name, name, sizeof(i2c_adap->name));429	i2c_adap->algo = algo;430	i2c_adap->algo_data = NULL;431	i2c_set_adapdata(i2c_adap, mst);432	if (i2c_add_adapter(i2c_adap) < 0)433		return -ENODEV;434	return 0;435}436 437int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev,438				struct i2c_adapter *i2c_adap, u8 i2c_addr)439{440	int ret;441 442	mutex_init(&mst->i2c_buffer_lock);443	if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {444		dprintk("could not acquire lock\n");445		return -EINVAL;446	}447	memset(mst->msg, 0, sizeof(struct i2c_msg));448	mst->msg[0].addr = i2c_addr >> 1;449	mst->msg[0].flags = 0;450	mst->msg[0].buf = mst->i2c_write_buffer;451	mst->msg[0].len = 4;452 453	mst->device_rev = device_rev;454	mst->i2c_adap = i2c_adap;455	mst->i2c_addr = i2c_addr >> 1;456 457	if (device_rev == DIB7000P || device_rev == DIB8000)458		mst->base_reg = 1024;459	else460		mst->base_reg = 768;461 462	mst->gated_tuner_i2c_adap.dev.parent = mst->i2c_adap->dev.parent;463	if (i2c_adapter_init464			(&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo,465			 "DiBX000 tuner I2C bus", mst) != 0)466		pr_err("could not initialize the tuner i2c_adapter\n");467 468	mst->master_i2c_adap_gpio12.dev.parent = mst->i2c_adap->dev.parent;469	if (i2c_adapter_init470			(&mst->master_i2c_adap_gpio12, &dibx000_i2c_master_gpio12_xfer_algo,471			 "DiBX000 master GPIO12 I2C bus", mst) != 0)472		pr_err("could not initialize the master i2c_adapter\n");473 474	mst->master_i2c_adap_gpio34.dev.parent = mst->i2c_adap->dev.parent;475	if (i2c_adapter_init476			(&mst->master_i2c_adap_gpio34, &dibx000_i2c_master_gpio34_xfer_algo,477			 "DiBX000 master GPIO34 I2C bus", mst) != 0)478		pr_err("could not initialize the master i2c_adapter\n");479 480	mst->master_i2c_adap_gpio67.dev.parent = mst->i2c_adap->dev.parent;481	if (i2c_adapter_init482			(&mst->master_i2c_adap_gpio67, &dibx000_i2c_gated_gpio67_algo,483			 "DiBX000 master GPIO67 I2C bus", mst) != 0)484		pr_err("could not initialize the master i2c_adapter\n");485 486	/* initialize the i2c-master by closing the gate */487	dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0);488 489	ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1);490	mutex_unlock(&mst->i2c_buffer_lock);491 492	return ret;493}494 495EXPORT_SYMBOL(dibx000_init_i2c_master);496 497void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)498{499	i2c_del_adapter(&mst->gated_tuner_i2c_adap);500	i2c_del_adapter(&mst->master_i2c_adap_gpio12);501	i2c_del_adapter(&mst->master_i2c_adap_gpio34);502	i2c_del_adapter(&mst->master_i2c_adap_gpio67);503}504EXPORT_SYMBOL(dibx000_exit_i2c_master);505 506MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");507MODULE_DESCRIPTION("Common function the DiBcom demodulator family");508MODULE_LICENSE("GPL");509