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