linux/drivers/media/pci/netup_unidvb/netup_unidvb_ci.c
<<
>>
Prefs
   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
 240