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

cx23885-f300.c (3550B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Driver for Silicon Labs C8051F300 microcontroller.
      4 *
      5 * It is used for LNB power control in TeVii S470,
      6 * TBS 6920 PCIe DVB-S2 cards.
      7 *
      8 * Microcontroller connected to cx23885 GPIO pins:
      9 * GPIO0 - data		- P0.3 F300
     10 * GPIO1 - reset	- P0.2 F300
     11 * GPIO2 - clk		- P0.1 F300
     12 * GPIO3 - busy		- P0.0 F300
     13 *
     14 * Copyright (C) 2009 Igor M. Liplianin <liplianin@me.by>
     15 */
     16
     17#include "cx23885.h"
     18#include "cx23885-f300.h"
     19
     20#define F300_DATA	GPIO_0
     21#define F300_RESET	GPIO_1
     22#define F300_CLK	GPIO_2
     23#define F300_BUSY	GPIO_3
     24
     25static void f300_set_line(struct cx23885_dev *dev, u32 line, u8 lvl)
     26{
     27	cx23885_gpio_enable(dev, line, 1);
     28	if (lvl == 1)
     29		cx23885_gpio_set(dev, line);
     30	else
     31		cx23885_gpio_clear(dev, line);
     32}
     33
     34static u8 f300_get_line(struct cx23885_dev *dev, u32 line)
     35{
     36	cx23885_gpio_enable(dev, line, 0);
     37
     38	return cx23885_gpio_get(dev, line);
     39}
     40
     41static void f300_send_byte(struct cx23885_dev *dev, u8 dta)
     42{
     43	u8 i;
     44
     45	for (i = 0; i < 8; i++) {
     46		f300_set_line(dev, F300_CLK, 0);
     47		udelay(30);
     48		f300_set_line(dev, F300_DATA, (dta & 0x80) >> 7);/* msb first */
     49		udelay(30);
     50		dta <<= 1;
     51		f300_set_line(dev, F300_CLK, 1);
     52		udelay(30);
     53	}
     54}
     55
     56static u8 f300_get_byte(struct cx23885_dev *dev)
     57{
     58	u8 i, dta = 0;
     59
     60	for (i = 0; i < 8; i++) {
     61		f300_set_line(dev, F300_CLK, 0);
     62		udelay(30);
     63		dta <<= 1;
     64		f300_set_line(dev, F300_CLK, 1);
     65		udelay(30);
     66		dta |= f300_get_line(dev, F300_DATA);/* msb first */
     67
     68	}
     69
     70	return dta;
     71}
     72
     73static u8 f300_xfer(struct dvb_frontend *fe, u8 *buf)
     74{
     75	struct cx23885_tsport *port = fe->dvb->priv;
     76	struct cx23885_dev *dev = port->dev;
     77	u8 i, temp, ret = 0;
     78
     79	temp = buf[0];
     80	for (i = 0; i < buf[0]; i++)
     81		temp += buf[i + 1];
     82	temp = (~temp + 1);/* get check sum */
     83	buf[1 + buf[0]] = temp;
     84
     85	f300_set_line(dev, F300_RESET, 1);
     86	f300_set_line(dev, F300_CLK, 1);
     87	udelay(30);
     88	f300_set_line(dev, F300_DATA, 1);
     89	msleep(1);
     90
     91	/* question: */
     92	f300_set_line(dev, F300_RESET, 0);/* begin to send data */
     93	msleep(1);
     94
     95	f300_send_byte(dev, 0xe0);/* the slave address is 0xe0, write */
     96	msleep(1);
     97
     98	temp = buf[0];
     99	temp += 2;
    100	for (i = 0; i < temp; i++)
    101		f300_send_byte(dev, buf[i]);
    102
    103	f300_set_line(dev, F300_RESET, 1);/* sent data over */
    104	f300_set_line(dev, F300_DATA, 1);
    105
    106	/* answer: */
    107	temp = 0;
    108	for (i = 0; ((i < 8) & (temp == 0)); i++) {
    109		msleep(1);
    110		if (f300_get_line(dev, F300_BUSY) == 0)
    111			temp = 1;
    112	}
    113
    114	if (i > 7) {
    115		pr_err("%s: timeout, the slave no response\n",
    116								__func__);
    117		ret = 1; /* timeout, the slave no response */
    118	} else { /* the slave not busy, prepare for getting data */
    119		f300_set_line(dev, F300_RESET, 0);/*ready...*/
    120		msleep(1);
    121		f300_send_byte(dev, 0xe1);/* 0xe1 is Read */
    122		msleep(1);
    123		temp = f300_get_byte(dev);/*get the data length */
    124		if (temp > 14)
    125			temp = 14;
    126
    127		for (i = 0; i < (temp + 1); i++)
    128			f300_get_byte(dev);/* get data to empty buffer */
    129
    130		f300_set_line(dev, F300_RESET, 1);/* received data over */
    131		f300_set_line(dev, F300_DATA, 1);
    132	}
    133
    134	return ret;
    135}
    136
    137int f300_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
    138{
    139	u8 buf[16];
    140
    141	buf[0] = 0x05;
    142	buf[1] = 0x38;/* write port */
    143	buf[2] = 0x01;/* A port, lnb power */
    144
    145	switch (voltage) {
    146	case SEC_VOLTAGE_13:
    147		buf[3] = 0x01;/* power on */
    148		buf[4] = 0x02;/* B port, H/V */
    149		buf[5] = 0x00;/*13V v*/
    150		break;
    151	case SEC_VOLTAGE_18:
    152		buf[3] = 0x01;
    153		buf[4] = 0x02;
    154		buf[5] = 0x01;/* 18V h*/
    155		break;
    156	case SEC_VOLTAGE_OFF:
    157		buf[3] = 0x00;/* power off */
    158		buf[4] = 0x00;
    159		buf[5] = 0x00;
    160		break;
    161	}
    162
    163	return f300_xfer(fe, buf);
    164}