• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  
netup_ci_interrupt(struct netup_unidvb_dev * ndev)46  irqreturn_t netup_ci_interrupt(struct netup_unidvb_dev *ndev)
47  {
48  	writew(0x101, ndev->bmmio0 + CAM_CTRLSTAT_CLR);
49  	return IRQ_HANDLED;
50  }
51  
netup_unidvb_ci_slot_ts_ctl(struct dvb_ca_en50221 * en50221,int slot)52  static 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  
netup_unidvb_ci_slot_shutdown(struct dvb_ca_en50221 * en50221,int slot)70  static 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  
netup_unidvb_ci_slot_reset(struct dvb_ca_en50221 * en50221,int slot)80  static 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));
92  reset:
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  
netup_unidvb_poll_ci_slot_status(struct dvb_ca_en50221 * en50221,int slot,int open)114  static 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  
netup_unidvb_ci_read_attribute_mem(struct dvb_ca_en50221 * en50221,int slot,int addr)136  static 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  
netup_unidvb_ci_write_attribute_mem(struct dvb_ca_en50221 * en50221,int slot,int addr,u8 data)148  static 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  
netup_unidvb_ci_read_cam_ctl(struct dvb_ca_en50221 * en50221,int slot,u8 addr)160  static 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  
netup_unidvb_ci_write_cam_ctl(struct dvb_ca_en50221 * en50221,int slot,u8 addr,u8 data)172  static 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  
netup_unidvb_ci_register(struct netup_unidvb_dev * dev,int num,struct pci_dev * pci_dev)184  int 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  
netup_unidvb_ci_unregister(struct netup_unidvb_dev * dev,int num)226  void 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