brintos

brintos / linux-shallow public Read only

0
0
Text · 12.4 KiB · 06e41f9 Raw
534 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * cimax2.c4 *5 * CIMax2(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card6 *7 * Copyright (C) 2009 NetUP Inc.8 * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>9 * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>10 */11 12#include "cx23885.h"13#include "cimax2.h"14#include <media/dvb_ca_en50221.h>15 16/* Max transfer size done by I2C transfer functions */17#define MAX_XFER_SIZE  6418 19/**** Bit definitions for MC417_RWD and MC417_OEN registers  ***20  bits 31-1621+-----------+22| Reserved  |23+-----------+24  bit 15  bit 14  bit 13 bit 12  bit 11  bit 10  bit 9   bit 825+-------+-------+-------+-------+-------+-------+-------+-------+26|  WR#  |  RD#  |       |  ACK# |  ADHI |  ADLO |  CS1# |  CS0# |27+-------+-------+-------+-------+-------+-------+-------+-------+28 bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 029+-------+-------+-------+-------+-------+-------+-------+-------+30|  DATA7|  DATA6|  DATA5|  DATA4|  DATA3|  DATA2|  DATA1|  DATA0|31+-------+-------+-------+-------+-------+-------+-------+-------+32***/33/* MC417 */34#define NETUP_DATA		0x000000ff35#define NETUP_WR		0x0000800036#define NETUP_RD		0x0000400037#define NETUP_ACK		0x0000100038#define NETUP_ADHI		0x0000080039#define NETUP_ADLO		0x0000040040#define NETUP_CS1		0x0000020041#define NETUP_CS0		0x0000010042#define NETUP_EN_ALL		0x0000100043#define NETUP_CTRL_OFF		(NETUP_CS1 | NETUP_CS0 | NETUP_WR | NETUP_RD)44#define NETUP_CI_CTL		0x0445#define NETUP_CI_RD		146 47#define NETUP_IRQ_DETAM		0x148#define NETUP_IRQ_IRQAM		0x449 50static unsigned int ci_dbg;51module_param(ci_dbg, int, 0644);52MODULE_PARM_DESC(ci_dbg, "Enable CI debugging");53 54static unsigned int ci_irq_enable;55module_param(ci_irq_enable, int, 0644);56MODULE_PARM_DESC(ci_irq_enable, "Enable IRQ from CAM");57 58#define ci_dbg_print(fmt, args...) \59	do { \60		if (ci_dbg) \61			printk(KERN_DEBUG pr_fmt("%s: " fmt), \62			       __func__, ##args); \63	} while (0)64 65#define ci_irq_flags() (ci_irq_enable ? NETUP_IRQ_IRQAM : 0)66 67/* stores all private variables for communication with CI */68struct netup_ci_state {69	struct dvb_ca_en50221 ca;70	struct mutex ca_mutex;71	struct i2c_adapter *i2c_adap;72	u8 ci_i2c_addr;73	int status;74	struct work_struct work;75	void *priv;76	u8 current_irq_mode;77	int current_ci_flag;78	unsigned long next_status_checked_time;79};80 81 82static int netup_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,83						u8 *buf, int len)84{85	int ret;86	struct i2c_msg msg[] = {87		{88			.addr	= addr,89			.flags	= 0,90			.buf	= &reg,91			.len	= 192		}, {93			.addr	= addr,94			.flags	= I2C_M_RD,95			.buf	= buf,96			.len	= len97		}98	};99 100	ret = i2c_transfer(i2c_adap, msg, 2);101 102	if (ret != 2) {103		ci_dbg_print("%s: i2c read error, Reg = 0x%02x, Status = %d\n",104						__func__, reg, ret);105 106		return -1;107	}108 109	ci_dbg_print("%s: i2c read Addr=0x%04x, Reg = 0x%02x, data = %02x\n",110						__func__, addr, reg, buf[0]);111 112	return 0;113}114 115static int netup_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg,116						u8 *buf, int len)117{118	int ret;119	u8 buffer[MAX_XFER_SIZE];120 121	struct i2c_msg msg = {122		.addr	= addr,123		.flags	= 0,124		.buf	= &buffer[0],125		.len	= len + 1126	};127 128	if (1 + len > sizeof(buffer)) {129		pr_warn("%s: i2c wr reg=%04x: len=%d is too big!\n",130		       KBUILD_MODNAME, reg, len);131		return -EINVAL;132	}133 134	buffer[0] = reg;135	memcpy(&buffer[1], buf, len);136 137	ret = i2c_transfer(i2c_adap, &msg, 1);138 139	if (ret != 1) {140		ci_dbg_print("%s: i2c write error, Reg=[0x%02x], Status=%d\n",141						__func__, reg, ret);142		return -1;143	}144 145	return 0;146}147 148static int netup_ci_get_mem(struct cx23885_dev *dev)149{150	int mem;151	unsigned long timeout = jiffies + msecs_to_jiffies(1);152 153	for (;;) {154		mem = cx_read(MC417_RWD);155		if ((mem & NETUP_ACK) == 0)156			break;157		if (time_after(jiffies, timeout))158			break;159		udelay(1);160	}161 162	cx_set(MC417_RWD, NETUP_CTRL_OFF);163 164	return mem & 0xff;165}166 167static int netup_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,168				u8 flag, u8 read, int addr, u8 data)169{170	struct netup_ci_state *state = en50221->data;171	struct cx23885_tsport *port = state->priv;172	struct cx23885_dev *dev = port->dev;173 174	u8 store;175	int mem;176	int ret;177 178	if (0 != slot)179		return -EINVAL;180 181	if (state->current_ci_flag != flag) {182		ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,183				0, &store, 1);184		if (ret != 0)185			return ret;186 187		store &= ~0x0c;188		store |= flag;189 190		ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,191				0, &store, 1);192		if (ret != 0)193			return ret;194	}195	state->current_ci_flag = flag;196 197	mutex_lock(&dev->gpio_lock);198 199	/* write addr */200	cx_write(MC417_OEN, NETUP_EN_ALL);201	cx_write(MC417_RWD, NETUP_CTRL_OFF |202				NETUP_ADLO | (0xff & addr));203	cx_clear(MC417_RWD, NETUP_ADLO);204	cx_write(MC417_RWD, NETUP_CTRL_OFF |205				NETUP_ADHI | (0xff & (addr >> 8)));206	cx_clear(MC417_RWD, NETUP_ADHI);207 208	if (read) { /* data in */209		cx_write(MC417_OEN, NETUP_EN_ALL | NETUP_DATA);210	} else /* data out */211		cx_write(MC417_RWD, NETUP_CTRL_OFF | data);212 213	/* choose chip */214	cx_clear(MC417_RWD,215			(state->ci_i2c_addr == 0x40) ? NETUP_CS0 : NETUP_CS1);216	/* read/write */217	cx_clear(MC417_RWD, (read) ? NETUP_RD : NETUP_WR);218	mem = netup_ci_get_mem(dev);219 220	mutex_unlock(&dev->gpio_lock);221 222	if (!read)223		if (mem < 0)224			return -EREMOTEIO;225 226	ci_dbg_print("%s: %s: chipaddr=[0x%x] addr=[0x%02x], %s=%x\n", __func__,227			(read) ? "read" : "write", state->ci_i2c_addr, addr,228			(flag == NETUP_CI_CTL) ? "ctl" : "mem",229			(read) ? mem : data);230 231	if (read)232		return mem;233 234	return 0;235}236 237int netup_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,238						int slot, int addr)239{240	return netup_ci_op_cam(en50221, slot, 0, NETUP_CI_RD, addr, 0);241}242 243int netup_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,244						int slot, int addr, u8 data)245{246	return netup_ci_op_cam(en50221, slot, 0, 0, addr, data);247}248 249int netup_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,250				 u8 addr)251{252	return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL,253							NETUP_CI_RD, addr, 0);254}255 256int netup_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,257							u8 addr, u8 data)258{259	return netup_ci_op_cam(en50221, slot, NETUP_CI_CTL, 0, addr, data);260}261 262int netup_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)263{264	struct netup_ci_state *state = en50221->data;265	u8 buf =  0x80;266	int ret;267 268	if (0 != slot)269		return -EINVAL;270 271	udelay(500);272	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,273							0, &buf, 1);274 275	if (ret != 0)276		return ret;277 278	udelay(500);279 280	buf = 0x00;281	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,282							0, &buf, 1);283 284	msleep(1000);285	dvb_ca_en50221_camready_irq(&state->ca, 0);286 287	return 0;288 289}290 291int netup_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)292{293	/* not implemented */294	return 0;295}296 297static int netup_ci_set_irq(struct dvb_ca_en50221 *en50221, u8 irq_mode)298{299	struct netup_ci_state *state = en50221->data;300	int ret;301 302	if (irq_mode == state->current_irq_mode)303		return 0;304 305	ci_dbg_print("%s: chipaddr=[0x%x] setting ci IRQ to [0x%x] \n",306			__func__, state->ci_i2c_addr, irq_mode);307	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,308							0x1b, &irq_mode, 1);309 310	if (ret != 0)311		return ret;312 313	state->current_irq_mode = irq_mode;314 315	return 0;316}317 318int netup_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)319{320	struct netup_ci_state *state = en50221->data;321	u8 buf;322 323	if (0 != slot)324		return -EINVAL;325 326	netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,327			0, &buf, 1);328	buf |= 0x60;329 330	return netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,331							0, &buf, 1);332}333 334/* work handler */335static void netup_read_ci_status(struct work_struct *work)336{337	struct netup_ci_state *state =338			container_of(work, struct netup_ci_state, work);339	u8 buf[33];340	int ret;341 342	/* CAM module IRQ processing. fast operation */343	dvb_ca_en50221_frda_irq(&state->ca, 0);344 345	/* CAM module INSERT/REMOVE processing. slow operation because of i2c346	 * transfers */347	if (time_after(jiffies, state->next_status_checked_time)348			|| !state->status) {349		ret = netup_read_i2c(state->i2c_adap, state->ci_i2c_addr,350				0, &buf[0], 33);351 352		state->next_status_checked_time = jiffies353			+ msecs_to_jiffies(1000);354 355		if (ret != 0)356			return;357 358		ci_dbg_print("%s: Slot Status Addr=[0x%04x], Reg=[0x%02x], data=%02x, TS config = %02x\n",359			     __func__,	state->ci_i2c_addr, 0, buf[0], buf[0]);360 361 362		if (buf[0] & 1)363			state->status = DVB_CA_EN50221_POLL_CAM_PRESENT |364				DVB_CA_EN50221_POLL_CAM_READY;365		else366			state->status = 0;367	}368}369 370/* CI irq handler */371int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status)372{373	struct cx23885_tsport *port = NULL;374	struct netup_ci_state *state = NULL;375 376	ci_dbg_print("%s:\n", __func__);377 378	if (0 == (pci_status & (PCI_MSK_GPIO0 | PCI_MSK_GPIO1)))379		return 0;380 381	if (pci_status & PCI_MSK_GPIO0) {382		port = &dev->ts1;383		state = port->port_priv;384		schedule_work(&state->work);385		ci_dbg_print("%s: Wakeup CI0\n", __func__);386	}387 388	if (pci_status & PCI_MSK_GPIO1) {389		port = &dev->ts2;390		state = port->port_priv;391		schedule_work(&state->work);392		ci_dbg_print("%s: Wakeup CI1\n", __func__);393	}394 395	return 1;396}397 398int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221,399				     int slot, int open)400{401	struct netup_ci_state *state = en50221->data;402 403	if (0 != slot)404		return -EINVAL;405 406	netup_ci_set_irq(en50221, open ? (NETUP_IRQ_DETAM | ci_irq_flags())407			: NETUP_IRQ_DETAM);408 409	return state->status;410}411 412int netup_ci_init(struct cx23885_tsport *port)413{414	struct netup_ci_state *state;415	u8 cimax_init[34] = {416		0x00, /* module A control*/417		0x00, /* auto select mask high A */418		0x00, /* auto select mask low A */419		0x00, /* auto select pattern high A */420		0x00, /* auto select pattern low A */421		0x44, /* memory access time A */422		0x00, /* invert input A */423		0x00, /* RFU */424		0x00, /* RFU */425		0x00, /* module B control*/426		0x00, /* auto select mask high B */427		0x00, /* auto select mask low B */428		0x00, /* auto select pattern high B */429		0x00, /* auto select pattern low B */430		0x44, /* memory access time B */431		0x00, /* invert input B */432		0x00, /* RFU */433		0x00, /* RFU */434		0x00, /* auto select mask high Ext */435		0x00, /* auto select mask low Ext */436		0x00, /* auto select pattern high Ext */437		0x00, /* auto select pattern low Ext */438		0x00, /* RFU */439		0x02, /* destination - module A */440		0x01, /* power on (use it like store place) */441		0x00, /* RFU */442		0x00, /* int status read only */443		ci_irq_flags() | NETUP_IRQ_DETAM, /* DETAM, IRQAM unmasked */444		0x05, /* EXTINT=active-high, INT=push-pull */445		0x00, /* USCG1 */446		0x04, /* ack active low */447		0x00, /* LOCK = 0 */448		0x33, /* serial mode, rising in, rising out, MSB first*/449		0x31, /* synchronization */450	};451	int ret;452 453	ci_dbg_print("%s\n", __func__);454	state = kzalloc(sizeof(struct netup_ci_state), GFP_KERNEL);455	if (!state) {456		ci_dbg_print("%s: Unable create CI structure!\n", __func__);457		ret = -ENOMEM;458		goto err;459	}460 461	port->port_priv = state;462 463	switch (port->nr) {464	case 1:465		state->ci_i2c_addr = 0x40;466		break;467	case 2:468		state->ci_i2c_addr = 0x41;469		break;470	}471 472	state->i2c_adap = &port->dev->i2c_bus[0].i2c_adap;473	state->ca.owner = THIS_MODULE;474	state->ca.read_attribute_mem = netup_ci_read_attribute_mem;475	state->ca.write_attribute_mem = netup_ci_write_attribute_mem;476	state->ca.read_cam_control = netup_ci_read_cam_ctl;477	state->ca.write_cam_control = netup_ci_write_cam_ctl;478	state->ca.slot_reset = netup_ci_slot_reset;479	state->ca.slot_shutdown = netup_ci_slot_shutdown;480	state->ca.slot_ts_enable = netup_ci_slot_ts_ctl;481	state->ca.poll_slot_status = netup_poll_ci_slot_status;482	state->ca.data = state;483	state->priv = port;484	state->current_irq_mode = ci_irq_flags() | NETUP_IRQ_DETAM;485 486	ret = netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,487						0, &cimax_init[0], 34);488	/* lock registers */489	ret |= netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,490						0x1f, &cimax_init[0x18], 1);491	/* power on slots */492	ret |= netup_write_i2c(state->i2c_adap, state->ci_i2c_addr,493						0x18, &cimax_init[0x18], 1);494 495	if (0 != ret)496		goto err;497 498	ret = dvb_ca_en50221_init(&port->frontends.adapter,499				   &state->ca,500				   /* flags */ 0,501				   /* n_slots */ 1);502	if (0 != ret)503		goto err;504 505	INIT_WORK(&state->work, netup_read_ci_status);506	schedule_work(&state->work);507 508	ci_dbg_print("%s: CI initialized!\n", __func__);509 510	return 0;511err:512	ci_dbg_print("%s: Cannot initialize CI: Error %d.\n", __func__, ret);513	kfree(state);514	return ret;515}516 517void netup_ci_exit(struct cx23885_tsport *port)518{519	struct netup_ci_state *state;520 521	if (NULL == port)522		return;523 524	state = (struct netup_ci_state *)port->port_priv;525	if (NULL == state)526		return;527 528	if (NULL == state->ca.data)529		return;530 531	dvb_ca_en50221_release(&state->ca);532	kfree(state);533}534