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

sp887x.c (15219B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3   Driver for the Spase sp887x demodulator
      4*/
      5
      6/*
      7 * This driver needs external firmware. Please use the command
      8 * "<kerneldir>/scripts/get_dvb_firmware sp887x" to
      9 * download/extract it, and then copy it to /usr/lib/hotplug/firmware
     10 * or /lib/firmware (depending on configuration of firmware hotplug).
     11 */
     12#define SP887X_DEFAULT_FIRMWARE "dvb-fe-sp887x.fw"
     13
     14#include <linux/init.h>
     15#include <linux/module.h>
     16#include <linux/device.h>
     17#include <linux/firmware.h>
     18#include <linux/string.h>
     19#include <linux/slab.h>
     20
     21#include <media/dvb_frontend.h>
     22#include "sp887x.h"
     23
     24
     25struct sp887x_state {
     26	struct i2c_adapter* i2c;
     27	const struct sp887x_config* config;
     28	struct dvb_frontend frontend;
     29
     30	/* demodulator private data */
     31	u8 initialised:1;
     32};
     33
     34static int debug;
     35#define dprintk(args...) \
     36	do { \
     37		if (debug) printk(KERN_DEBUG "sp887x: " args); \
     38	} while (0)
     39
     40static int i2c_writebytes (struct sp887x_state* state, u8 *buf, u8 len)
     41{
     42	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = len };
     43	int err;
     44
     45	if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
     46		printk ("%s: i2c write error (addr %02x, err == %i)\n",
     47			__func__, state->config->demod_address, err);
     48		return -EREMOTEIO;
     49	}
     50
     51	return 0;
     52}
     53
     54static int sp887x_writereg (struct sp887x_state* state, u16 reg, u16 data)
     55{
     56	u8 b0 [] = { reg >> 8 , reg & 0xff, data >> 8, data & 0xff };
     57	struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 4 };
     58	int ret;
     59
     60	if ((ret = i2c_transfer(state->i2c, &msg, 1)) != 1) {
     61		/*
     62		 *  in case of soft reset we ignore ACK errors...
     63		 */
     64		if (!(reg == 0xf1a && data == 0x000 &&
     65			(ret == -EREMOTEIO || ret == -EFAULT)))
     66		{
     67			printk("%s: writereg error (reg %03x, data %03x, ret == %i)\n",
     68			       __func__, reg & 0xffff, data & 0xffff, ret);
     69			return ret;
     70		}
     71	}
     72
     73	return 0;
     74}
     75
     76static int sp887x_readreg (struct sp887x_state* state, u16 reg)
     77{
     78	u8 b0 [] = { reg >> 8 , reg & 0xff };
     79	u8 b1 [2];
     80	int ret;
     81	struct i2c_msg msg[] = {{ .addr = state->config->demod_address, .flags = 0, .buf = b0, .len = 2 },
     82			 { .addr = state->config->demod_address, .flags = I2C_M_RD, .buf = b1, .len = 2 }};
     83
     84	if ((ret = i2c_transfer(state->i2c, msg, 2)) != 2) {
     85		printk("%s: readreg error (ret == %i)\n", __func__, ret);
     86		return -1;
     87	}
     88
     89	return (((b1[0] << 8) | b1[1]) & 0xfff);
     90}
     91
     92static void sp887x_microcontroller_stop (struct sp887x_state* state)
     93{
     94	dprintk("%s\n", __func__);
     95	sp887x_writereg(state, 0xf08, 0x000);
     96	sp887x_writereg(state, 0xf09, 0x000);
     97
     98	/* microcontroller STOP */
     99	sp887x_writereg(state, 0xf00, 0x000);
    100}
    101
    102static void sp887x_microcontroller_start (struct sp887x_state* state)
    103{
    104	dprintk("%s\n", __func__);
    105	sp887x_writereg(state, 0xf08, 0x000);
    106	sp887x_writereg(state, 0xf09, 0x000);
    107
    108	/* microcontroller START */
    109	sp887x_writereg(state, 0xf00, 0x001);
    110}
    111
    112static void sp887x_setup_agc (struct sp887x_state* state)
    113{
    114	/* setup AGC parameters */
    115	dprintk("%s\n", __func__);
    116	sp887x_writereg(state, 0x33c, 0x054);
    117	sp887x_writereg(state, 0x33b, 0x04c);
    118	sp887x_writereg(state, 0x328, 0x000);
    119	sp887x_writereg(state, 0x327, 0x005);
    120	sp887x_writereg(state, 0x326, 0x001);
    121	sp887x_writereg(state, 0x325, 0x001);
    122	sp887x_writereg(state, 0x324, 0x001);
    123	sp887x_writereg(state, 0x318, 0x050);
    124	sp887x_writereg(state, 0x317, 0x3fe);
    125	sp887x_writereg(state, 0x316, 0x001);
    126	sp887x_writereg(state, 0x313, 0x005);
    127	sp887x_writereg(state, 0x312, 0x002);
    128	sp887x_writereg(state, 0x306, 0x000);
    129	sp887x_writereg(state, 0x303, 0x000);
    130}
    131
    132#define BLOCKSIZE 30
    133#define FW_SIZE 0x4000
    134/*
    135 *  load firmware and setup MPEG interface...
    136 */
    137static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware *fw)
    138{
    139	struct sp887x_state* state = fe->demodulator_priv;
    140	u8 buf [BLOCKSIZE + 2];
    141	int i;
    142	int fw_size = fw->size;
    143	const unsigned char *mem = fw->data + 10;
    144
    145	dprintk("%s\n", __func__);
    146
    147	/* ignore the first 10 bytes, then we expect 0x4000 bytes of firmware */
    148	if (fw_size < FW_SIZE + 10)
    149		return -ENODEV;
    150
    151	/* soft reset */
    152	sp887x_writereg(state, 0xf1a, 0x000);
    153
    154	sp887x_microcontroller_stop (state);
    155
    156	printk ("%s: firmware upload... ", __func__);
    157
    158	/* setup write pointer to -1 (end of memory) */
    159	/* bit 0x8000 in address is set to enable 13bit mode */
    160	sp887x_writereg(state, 0x8f08, 0x1fff);
    161
    162	/* dummy write (wrap around to start of memory) */
    163	sp887x_writereg(state, 0x8f0a, 0x0000);
    164
    165	for (i = 0; i < FW_SIZE; i += BLOCKSIZE) {
    166		int c = BLOCKSIZE;
    167		int err;
    168
    169		if (c > FW_SIZE - i)
    170			c = FW_SIZE - i;
    171
    172		/* bit 0x8000 in address is set to enable 13bit mode */
    173		/* bit 0x4000 enables multibyte read/write transfers */
    174		/* write register is 0xf0a */
    175		buf[0] = 0xcf;
    176		buf[1] = 0x0a;
    177
    178		memcpy(&buf[2], mem + i, c);
    179
    180		if ((err = i2c_writebytes (state, buf, c+2)) < 0) {
    181			printk ("failed.\n");
    182			printk ("%s: i2c error (err == %i)\n", __func__, err);
    183			return err;
    184		}
    185	}
    186
    187	/* don't write RS bytes between packets */
    188	sp887x_writereg(state, 0xc13, 0x001);
    189
    190	/* suppress clock if (!data_valid) */
    191	sp887x_writereg(state, 0xc14, 0x000);
    192
    193	/* setup MPEG interface... */
    194	sp887x_writereg(state, 0xc1a, 0x872);
    195	sp887x_writereg(state, 0xc1b, 0x001);
    196	sp887x_writereg(state, 0xc1c, 0x000); /* parallel mode (serial mode == 1) */
    197	sp887x_writereg(state, 0xc1a, 0x871);
    198
    199	/* ADC mode, 2 for MT8872, 3 for SP8870/SP8871 */
    200	sp887x_writereg(state, 0x301, 0x002);
    201
    202	sp887x_setup_agc(state);
    203
    204	/* bit 0x010: enable data valid signal */
    205	sp887x_writereg(state, 0xd00, 0x010);
    206	sp887x_writereg(state, 0x0d1, 0x000);
    207	return 0;
    208};
    209
    210static int configure_reg0xc05(struct dtv_frontend_properties *p, u16 *reg0xc05)
    211{
    212	int known_parameters = 1;
    213
    214	*reg0xc05 = 0x000;
    215
    216	switch (p->modulation) {
    217	case QPSK:
    218		break;
    219	case QAM_16:
    220		*reg0xc05 |= (1 << 10);
    221		break;
    222	case QAM_64:
    223		*reg0xc05 |= (2 << 10);
    224		break;
    225	case QAM_AUTO:
    226		known_parameters = 0;
    227		break;
    228	default:
    229		return -EINVAL;
    230	}
    231
    232	switch (p->hierarchy) {
    233	case HIERARCHY_NONE:
    234		break;
    235	case HIERARCHY_1:
    236		*reg0xc05 |= (1 << 7);
    237		break;
    238	case HIERARCHY_2:
    239		*reg0xc05 |= (2 << 7);
    240		break;
    241	case HIERARCHY_4:
    242		*reg0xc05 |= (3 << 7);
    243		break;
    244	case HIERARCHY_AUTO:
    245		known_parameters = 0;
    246		break;
    247	default:
    248		return -EINVAL;
    249	}
    250
    251	switch (p->code_rate_HP) {
    252	case FEC_1_2:
    253		break;
    254	case FEC_2_3:
    255		*reg0xc05 |= (1 << 3);
    256		break;
    257	case FEC_3_4:
    258		*reg0xc05 |= (2 << 3);
    259		break;
    260	case FEC_5_6:
    261		*reg0xc05 |= (3 << 3);
    262		break;
    263	case FEC_7_8:
    264		*reg0xc05 |= (4 << 3);
    265		break;
    266	case FEC_AUTO:
    267		known_parameters = 0;
    268		break;
    269	default:
    270		return -EINVAL;
    271	}
    272
    273	if (known_parameters)
    274		*reg0xc05 |= (2 << 1);	/* use specified parameters */
    275	else
    276		*reg0xc05 |= (1 << 1);	/* enable autoprobing */
    277
    278	return 0;
    279}
    280
    281/*
    282 *  estimates division of two 24bit numbers,
    283 *  derived from the ves1820/stv0299 driver code
    284 */
    285static void divide (int n, int d, int *quotient_i, int *quotient_f)
    286{
    287	unsigned int q, r;
    288
    289	r = (n % d) << 8;
    290	q = (r / d);
    291
    292	if (quotient_i)
    293		*quotient_i = q;
    294
    295	if (quotient_f) {
    296		r = (r % d) << 8;
    297		q = (q << 8) | (r / d);
    298		r = (r % d) << 8;
    299		*quotient_f = (q << 8) | (r / d);
    300	}
    301}
    302
    303static void sp887x_correct_offsets (struct sp887x_state* state,
    304				    struct dtv_frontend_properties *p,
    305				    int actual_freq)
    306{
    307	static const u32 srate_correction [] = { 1879617, 4544878, 8098561 };
    308	int bw_index;
    309	int freq_offset = actual_freq - p->frequency;
    310	int sysclock = 61003; //[kHz]
    311	int ifreq = 36000000;
    312	int freq;
    313	int frequency_shift;
    314
    315	switch (p->bandwidth_hz) {
    316	default:
    317	case 8000000:
    318		bw_index = 0;
    319		break;
    320	case 7000000:
    321		bw_index = 1;
    322		break;
    323	case 6000000:
    324		bw_index = 2;
    325		break;
    326	}
    327
    328	if (p->inversion == INVERSION_ON)
    329		freq = ifreq - freq_offset;
    330	else
    331		freq = ifreq + freq_offset;
    332
    333	divide(freq / 333, sysclock, NULL, &frequency_shift);
    334
    335	if (p->inversion == INVERSION_ON)
    336		frequency_shift = -frequency_shift;
    337
    338	/* sample rate correction */
    339	sp887x_writereg(state, 0x319, srate_correction[bw_index] >> 12);
    340	sp887x_writereg(state, 0x31a, srate_correction[bw_index] & 0xfff);
    341
    342	/* carrier offset correction */
    343	sp887x_writereg(state, 0x309, frequency_shift >> 12);
    344	sp887x_writereg(state, 0x30a, frequency_shift & 0xfff);
    345}
    346
    347static int sp887x_setup_frontend_parameters(struct dvb_frontend *fe)
    348{
    349	struct dtv_frontend_properties *p = &fe->dtv_property_cache;
    350	struct sp887x_state* state = fe->demodulator_priv;
    351	unsigned actual_freq;
    352	int err;
    353	u16 val, reg0xc05;
    354
    355	if (p->bandwidth_hz != 8000000 &&
    356	    p->bandwidth_hz != 7000000 &&
    357	    p->bandwidth_hz != 6000000)
    358		return -EINVAL;
    359
    360	if ((err = configure_reg0xc05(p, &reg0xc05)))
    361		return err;
    362
    363	sp887x_microcontroller_stop(state);
    364
    365	/* setup the PLL */
    366	if (fe->ops.tuner_ops.set_params) {
    367		fe->ops.tuner_ops.set_params(fe);
    368		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
    369	}
    370	if (fe->ops.tuner_ops.get_frequency) {
    371		fe->ops.tuner_ops.get_frequency(fe, &actual_freq);
    372		if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0);
    373	} else {
    374		actual_freq = p->frequency;
    375	}
    376
    377	/* read status reg in order to clear <pending irqs */
    378	sp887x_readreg(state, 0x200);
    379
    380	sp887x_correct_offsets(state, p, actual_freq);
    381
    382	/* filter for 6/7/8 Mhz channel */
    383	if (p->bandwidth_hz == 6000000)
    384		val = 2;
    385	else if (p->bandwidth_hz == 7000000)
    386		val = 1;
    387	else
    388		val = 0;
    389
    390	sp887x_writereg(state, 0x311, val);
    391
    392	/* scan order: 2k first = 0, 8k first = 1 */
    393	if (p->transmission_mode == TRANSMISSION_MODE_2K)
    394		sp887x_writereg(state, 0x338, 0x000);
    395	else
    396		sp887x_writereg(state, 0x338, 0x001);
    397
    398	sp887x_writereg(state, 0xc05, reg0xc05);
    399
    400	if (p->bandwidth_hz == 6000000)
    401		val = 2 << 3;
    402	else if (p->bandwidth_hz == 7000000)
    403		val = 3 << 3;
    404	else
    405		val = 0 << 3;
    406
    407	/* enable OFDM and SAW bits as lock indicators in sync register 0xf17,
    408	 * optimize algorithm for given bandwidth...
    409	 */
    410	sp887x_writereg(state, 0xf14, 0x160 | val);
    411	sp887x_writereg(state, 0xf15, 0x000);
    412
    413	sp887x_microcontroller_start(state);
    414	return 0;
    415}
    416
    417static int sp887x_read_status(struct dvb_frontend *fe, enum fe_status *status)
    418{
    419	struct sp887x_state* state = fe->demodulator_priv;
    420	u16 snr12 = sp887x_readreg(state, 0xf16);
    421	u16 sync0x200 = sp887x_readreg(state, 0x200);
    422	u16 sync0xf17 = sp887x_readreg(state, 0xf17);
    423
    424	*status = 0;
    425
    426	if (snr12 > 0x00f)
    427		*status |= FE_HAS_SIGNAL;
    428
    429	//if (sync0x200 & 0x004)
    430	//	*status |= FE_HAS_SYNC | FE_HAS_CARRIER;
    431
    432	//if (sync0x200 & 0x008)
    433	//	*status |= FE_HAS_VITERBI;
    434
    435	if ((sync0xf17 & 0x00f) == 0x002) {
    436		*status |= FE_HAS_LOCK;
    437		*status |= FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_CARRIER;
    438	}
    439
    440	if (sync0x200 & 0x001) {	/* tuner adjustment requested...*/
    441		int steps = (sync0x200 >> 4) & 0x00f;
    442		if (steps & 0x008)
    443			steps = -steps;
    444		dprintk("sp887x: implement tuner adjustment (%+i steps)!!\n",
    445		       steps);
    446	}
    447
    448	return 0;
    449}
    450
    451static int sp887x_read_ber(struct dvb_frontend* fe, u32* ber)
    452{
    453	struct sp887x_state* state = fe->demodulator_priv;
    454
    455	*ber = (sp887x_readreg(state, 0xc08) & 0x3f) |
    456	       (sp887x_readreg(state, 0xc07) << 6);
    457	sp887x_writereg(state, 0xc08, 0x000);
    458	sp887x_writereg(state, 0xc07, 0x000);
    459	if (*ber >= 0x3fff0)
    460		*ber = ~0;
    461
    462	return 0;
    463}
    464
    465static int sp887x_read_signal_strength(struct dvb_frontend* fe, u16* strength)
    466{
    467	struct sp887x_state* state = fe->demodulator_priv;
    468
    469	u16 snr12 = sp887x_readreg(state, 0xf16);
    470	u32 signal = 3 * (snr12 << 4);
    471	*strength = (signal < 0xffff) ? signal : 0xffff;
    472
    473	return 0;
    474}
    475
    476static int sp887x_read_snr(struct dvb_frontend* fe, u16* snr)
    477{
    478	struct sp887x_state* state = fe->demodulator_priv;
    479
    480	u16 snr12 = sp887x_readreg(state, 0xf16);
    481	*snr = (snr12 << 4) | (snr12 >> 8);
    482
    483	return 0;
    484}
    485
    486static int sp887x_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks)
    487{
    488	struct sp887x_state* state = fe->demodulator_priv;
    489
    490	*ucblocks = sp887x_readreg(state, 0xc0c);
    491	if (*ucblocks == 0xfff)
    492		*ucblocks = ~0;
    493
    494	return 0;
    495}
    496
    497static int sp887x_i2c_gate_ctrl(struct dvb_frontend* fe, int enable)
    498{
    499	struct sp887x_state* state = fe->demodulator_priv;
    500
    501	if (enable) {
    502		return sp887x_writereg(state, 0x206, 0x001);
    503	} else {
    504		return sp887x_writereg(state, 0x206, 0x000);
    505	}
    506}
    507
    508static int sp887x_sleep(struct dvb_frontend* fe)
    509{
    510	struct sp887x_state* state = fe->demodulator_priv;
    511
    512	/* tristate TS output and disable interface pins */
    513	sp887x_writereg(state, 0xc18, 0x000);
    514
    515	return 0;
    516}
    517
    518static int sp887x_init(struct dvb_frontend* fe)
    519{
    520	struct sp887x_state* state = fe->demodulator_priv;
    521	const struct firmware *fw = NULL;
    522	int ret;
    523
    524	if (!state->initialised) {
    525		/* request the firmware, this will block until someone uploads it */
    526		printk("sp887x: waiting for firmware upload (%s)...\n", SP887X_DEFAULT_FIRMWARE);
    527		ret = state->config->request_firmware(fe, &fw, SP887X_DEFAULT_FIRMWARE);
    528		if (ret) {
    529			printk("sp887x: no firmware upload (timeout or file not found?)\n");
    530			return ret;
    531		}
    532
    533		ret = sp887x_initial_setup(fe, fw);
    534		release_firmware(fw);
    535		if (ret) {
    536			printk("sp887x: writing firmware to device failed\n");
    537			return ret;
    538		}
    539		printk("sp887x: firmware upload complete\n");
    540		state->initialised = 1;
    541	}
    542
    543	/* enable TS output and interface pins */
    544	sp887x_writereg(state, 0xc18, 0x00d);
    545
    546	return 0;
    547}
    548
    549static int sp887x_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings* fesettings)
    550{
    551	fesettings->min_delay_ms = 350;
    552	fesettings->step_size = 166666*2;
    553	fesettings->max_drift = (166666*2)+1;
    554	return 0;
    555}
    556
    557static void sp887x_release(struct dvb_frontend* fe)
    558{
    559	struct sp887x_state* state = fe->demodulator_priv;
    560	kfree(state);
    561}
    562
    563static const struct dvb_frontend_ops sp887x_ops;
    564
    565struct dvb_frontend* sp887x_attach(const struct sp887x_config* config,
    566				   struct i2c_adapter* i2c)
    567{
    568	struct sp887x_state* state = NULL;
    569
    570	/* allocate memory for the internal state */
    571	state = kzalloc(sizeof(struct sp887x_state), GFP_KERNEL);
    572	if (state == NULL) goto error;
    573
    574	/* setup the state */
    575	state->config = config;
    576	state->i2c = i2c;
    577	state->initialised = 0;
    578
    579	/* check if the demod is there */
    580	if (sp887x_readreg(state, 0x0200) < 0) goto error;
    581
    582	/* create dvb_frontend */
    583	memcpy(&state->frontend.ops, &sp887x_ops, sizeof(struct dvb_frontend_ops));
    584	state->frontend.demodulator_priv = state;
    585	return &state->frontend;
    586
    587error:
    588	kfree(state);
    589	return NULL;
    590}
    591
    592static const struct dvb_frontend_ops sp887x_ops = {
    593	.delsys = { SYS_DVBT },
    594	.info = {
    595		.name = "Spase SP887x DVB-T",
    596		.frequency_min_hz =  50500 * kHz,
    597		.frequency_max_hz = 858000 * kHz,
    598		.frequency_stepsize_hz = 166666,
    599		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
    600			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
    601			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
    602			FE_CAN_RECOVER
    603	},
    604
    605	.release = sp887x_release,
    606
    607	.init = sp887x_init,
    608	.sleep = sp887x_sleep,
    609	.i2c_gate_ctrl = sp887x_i2c_gate_ctrl,
    610
    611	.set_frontend = sp887x_setup_frontend_parameters,
    612	.get_tune_settings = sp887x_get_tune_settings,
    613
    614	.read_status = sp887x_read_status,
    615	.read_ber = sp887x_read_ber,
    616	.read_signal_strength = sp887x_read_signal_strength,
    617	.read_snr = sp887x_read_snr,
    618	.read_ucblocks = sp887x_read_ucblocks,
    619};
    620
    621module_param(debug, int, 0644);
    622MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
    623
    624MODULE_DESCRIPTION("Spase sp887x DVB-T demodulator driver");
    625MODULE_LICENSE("GPL");
    626
    627EXPORT_SYMBOL(sp887x_attach);