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

netup_unidvb_ci.c (7102B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * netup_unidvb_ci.c
      4 *
      5 * DVB CAM support for NetUP Universal Dual DVB-CI
      6 *
      7 * Copyright (C) 2014 NetUP Inc.
      8 * Copyright (C) 2014 Sergey Kozlov <serjk@netup.ru>
      9 * Copyright (C) 2014 Abylay Ospan <aospan@netup.ru>
     10 */
     11
     12#include <linux/init.h>
     13#include <linux/module.h>
     14#include <linux/moduleparam.h>
     15#include <linux/kmod.h>
     16#include <linux/kernel.h>
     17#include <linux/slab.h>
     18#include <linux/interrupt.h>
     19#include <linux/delay.h>
     20#include "netup_unidvb.h"
     21
     22/* CI slot 0 base address */
     23#define CAM0_CONFIG		0x0
     24#define CAM0_IO			0x8000
     25#define CAM0_MEM		0x10000
     26#define CAM0_SZ			32
     27/* CI slot 1 base address */
     28#define CAM1_CONFIG		0x20000
     29#define CAM1_IO			0x28000
     30#define CAM1_MEM		0x30000
     31#define CAM1_SZ			32
     32/* ctrlstat registers */
     33#define CAM_CTRLSTAT_READ_SET	0x4980
     34#define CAM_CTRLSTAT_CLR	0x4982
     35/* register bits */
     36#define BIT_CAM_STCHG		(1<<0)
     37#define BIT_CAM_PRESENT		(1<<1)
     38#define BIT_CAM_RESET		(1<<2)
     39#define BIT_CAM_BYPASS		(1<<3)
     40#define BIT_CAM_READY		(1<<4)
     41#define BIT_CAM_ERROR		(1<<5)
     42#define BIT_CAM_OVERCURR	(1<<6)
     43/* BIT_CAM_BYPASS bit shift for SLOT 1 */
     44#define CAM1_SHIFT 8
     45
     46irqreturn_t netup_ci_interrupt(struct netup_unidvb_dev *ndev)
     47{
     48	writew(0x101, ndev->bmmio0 + CAM_CTRLSTAT_CLR);
     49	return IRQ_HANDLED;
     50}
     51
     52static int netup_unidvb_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221,
     53				       int slot)
     54{
     55	struct netup_ci_state *state = en50221->data;
     56	struct netup_unidvb_dev *dev = state->dev;
     57	u16 shift = (state->nr == 1) ? CAM1_SHIFT : 0;
     58
     59	dev_dbg(&dev->pci_dev->dev, "%s(): CAM_CTRLSTAT=0x%x\n",
     60		__func__, readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET));
     61	if (slot != 0)
     62		return -EINVAL;
     63	/* pass data to CAM module */
     64	writew(BIT_CAM_BYPASS << shift, dev->bmmio0 + CAM_CTRLSTAT_CLR);
     65	dev_dbg(&dev->pci_dev->dev, "%s(): CAM_CTRLSTAT=0x%x done\n",
     66		__func__, readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET));
     67	return 0;
     68}
     69
     70static int netup_unidvb_ci_slot_shutdown(struct dvb_ca_en50221 *en50221,
     71					 int slot)
     72{
     73	struct netup_ci_state *state = en50221->data;
     74	struct netup_unidvb_dev *dev = state->dev;
     75
     76	dev_dbg(&dev->pci_dev->dev, "%s()\n", __func__);
     77	return 0;
     78}
     79
     80static int netup_unidvb_ci_slot_reset(struct dvb_ca_en50221 *en50221,
     81				      int slot)
     82{
     83	struct netup_ci_state *state = en50221->data;
     84	struct netup_unidvb_dev *dev = state->dev;
     85	unsigned long timeout = 0;
     86	u16 shift = (state->nr == 1) ? CAM1_SHIFT : 0;
     87	u16 ci_stat = 0;
     88	int reset_counter = 3;
     89
     90	dev_dbg(&dev->pci_dev->dev, "%s(): CAM_CTRLSTAT_READ_SET=0x%x\n",
     91		__func__, readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET));
     92reset:
     93	timeout = jiffies + msecs_to_jiffies(5000);
     94	/* start reset */
     95	writew(BIT_CAM_RESET << shift, dev->bmmio0 + CAM_CTRLSTAT_READ_SET);
     96	dev_dbg(&dev->pci_dev->dev, "%s(): waiting for reset\n", __func__);
     97	/* wait until reset done */
     98	while (time_before(jiffies, timeout)) {
     99		ci_stat = readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET);
    100		if (ci_stat & (BIT_CAM_READY << shift))
    101			break;
    102		udelay(1000);
    103	}
    104	if (!(ci_stat & (BIT_CAM_READY << shift)) && reset_counter > 0) {
    105		dev_dbg(&dev->pci_dev->dev,
    106			"%s(): CAMP reset timeout! Will try again..\n",
    107			 __func__);
    108		reset_counter--;
    109		goto reset;
    110	}
    111	return 0;
    112}
    113
    114static int netup_unidvb_poll_ci_slot_status(struct dvb_ca_en50221 *en50221,
    115					    int slot, int open)
    116{
    117	struct netup_ci_state *state = en50221->data;
    118	struct netup_unidvb_dev *dev = state->dev;
    119	u16 shift = (state->nr == 1) ? CAM1_SHIFT : 0;
    120	u16 ci_stat = 0;
    121
    122	dev_dbg(&dev->pci_dev->dev, "%s(): CAM_CTRLSTAT_READ_SET=0x%x\n",
    123		__func__, readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET));
    124	ci_stat = readw(dev->bmmio0 + CAM_CTRLSTAT_READ_SET);
    125	if (ci_stat & (BIT_CAM_READY << shift)) {
    126		state->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
    127			DVB_CA_EN50221_POLL_CAM_READY;
    128	} else if (ci_stat & (BIT_CAM_PRESENT << shift)) {
    129		state->status = DVB_CA_EN50221_POLL_CAM_PRESENT;
    130	} else {
    131		state->status = 0;
    132	}
    133	return state->status;
    134}
    135
    136static int netup_unidvb_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
    137					      int slot, int addr)
    138{
    139	struct netup_ci_state *state = en50221->data;
    140	struct netup_unidvb_dev *dev = state->dev;
    141	u8 val = *((u8 __force *)state->membase8_config + addr);
    142
    143	dev_dbg(&dev->pci_dev->dev,
    144		"%s(): addr=0x%x val=0x%x\n", __func__, addr, val);
    145	return val;
    146}
    147
    148static int netup_unidvb_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
    149					       int slot, int addr, u8 data)
    150{
    151	struct netup_ci_state *state = en50221->data;
    152	struct netup_unidvb_dev *dev = state->dev;
    153
    154	dev_dbg(&dev->pci_dev->dev,
    155		"%s(): addr=0x%x data=0x%x\n", __func__, addr, data);
    156	*((u8 __force *)state->membase8_config + addr) = data;
    157	return 0;
    158}
    159
    160static int netup_unidvb_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221,
    161					int slot, u8 addr)
    162{
    163	struct netup_ci_state *state = en50221->data;
    164	struct netup_unidvb_dev *dev = state->dev;
    165	u8 val = *((u8 __force *)state->membase8_io + addr);
    166
    167	dev_dbg(&dev->pci_dev->dev,
    168		"%s(): addr=0x%x val=0x%x\n", __func__, addr, val);
    169	return val;
    170}
    171
    172static int netup_unidvb_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221,
    173					 int slot, u8 addr, u8 data)
    174{
    175	struct netup_ci_state *state = en50221->data;
    176	struct netup_unidvb_dev *dev = state->dev;
    177
    178	dev_dbg(&dev->pci_dev->dev,
    179		"%s(): addr=0x%x data=0x%x\n", __func__, addr, data);
    180	*((u8 __force *)state->membase8_io + addr) = data;
    181	return 0;
    182}
    183
    184int netup_unidvb_ci_register(struct netup_unidvb_dev *dev,
    185			     int num, struct pci_dev *pci_dev)
    186{
    187	int result;
    188	struct netup_ci_state *state;
    189
    190	if (num < 0 || num > 1) {
    191		dev_err(&pci_dev->dev, "%s(): invalid CI adapter %d\n",
    192			__func__, num);
    193		return -EINVAL;
    194	}
    195	state = &dev->ci[num];
    196	state->nr = num;
    197	state->membase8_config = dev->bmmio1 +
    198		((num == 0) ? CAM0_CONFIG : CAM1_CONFIG);
    199	state->membase8_io = dev->bmmio1 +
    200		((num == 0) ? CAM0_IO : CAM1_IO);
    201	state->dev = dev;
    202	state->ca.owner = THIS_MODULE;
    203	state->ca.read_attribute_mem = netup_unidvb_ci_read_attribute_mem;
    204	state->ca.write_attribute_mem = netup_unidvb_ci_write_attribute_mem;
    205	state->ca.read_cam_control = netup_unidvb_ci_read_cam_ctl;
    206	state->ca.write_cam_control = netup_unidvb_ci_write_cam_ctl;
    207	state->ca.slot_reset = netup_unidvb_ci_slot_reset;
    208	state->ca.slot_shutdown = netup_unidvb_ci_slot_shutdown;
    209	state->ca.slot_ts_enable = netup_unidvb_ci_slot_ts_ctl;
    210	state->ca.poll_slot_status = netup_unidvb_poll_ci_slot_status;
    211	state->ca.data = state;
    212	result = dvb_ca_en50221_init(&dev->frontends[num].adapter,
    213		&state->ca, 0, 1);
    214	if (result < 0) {
    215		dev_err(&pci_dev->dev,
    216			"%s(): dvb_ca_en50221_init result %d\n",
    217			__func__, result);
    218		return result;
    219	}
    220	writew(NETUP_UNIDVB_IRQ_CI, dev->bmmio0 + REG_IMASK_SET);
    221	dev_info(&pci_dev->dev,
    222		"%s(): CI adapter %d init done\n", __func__, num);
    223	return 0;
    224}
    225
    226void netup_unidvb_ci_unregister(struct netup_unidvb_dev *dev, int num)
    227{
    228	struct netup_ci_state *state;
    229
    230	dev_dbg(&dev->pci_dev->dev, "%s()\n", __func__);
    231	if (num < 0 || num > 1) {
    232		dev_err(&dev->pci_dev->dev, "%s(): invalid CI adapter %d\n",
    233				__func__, num);
    234		return;
    235	}
    236	state = &dev->ci[num];
    237	dvb_ca_en50221_release(&state->ca);
    238}
    239