1 /* 2 * Driver for Silicon Labs C8051F300 microcontroller. 3 * 4 * It is used for LNB power control in TeVii S470, 5 * TBS 6920 PCIe DVB-S2 cards. 6 * 7 * Microcontroller connected to cx23885 GPIO pins: 8 * GPIO0 - data - P0.3 F300 9 * GPIO1 - reset - P0.2 F300 10 * GPIO2 - clk - P0.1 F300 11 * GPIO3 - busy - P0.0 F300 12 * 13 * Copyright (C) 2009 Igor M. Liplianin <liplianin@me.by> 14 * 15 * This program is free software; you can redistribute it and/or modify 16 * it under the terms of the GNU General Public License as published by 17 * the Free Software Foundation; either version 2 of the License, or 18 * (at your option) any later version. 19 * 20 * This program is distributed in the hope that it will be useful, 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * 24 * GNU General Public License for more details. 25 * 26 * You should have received a copy of the GNU General Public License 27 * along with this program; if not, write to the Free Software 28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 29 */ 30 31 #include "cx23885.h" 32 33 #define F300_DATA GPIO_0 34 #define F300_RESET GPIO_1 35 #define F300_CLK GPIO_2 36 #define F300_BUSY GPIO_3 37 38 static void f300_set_line(struct cx23885_dev *dev, u32 line, u8 lvl) 39 { 40 cx23885_gpio_enable(dev, line, 1); 41 if (lvl == 1) 42 cx23885_gpio_set(dev, line); 43 else 44 cx23885_gpio_clear(dev, line); 45 } 46 47 static u8 f300_get_line(struct cx23885_dev *dev, u32 line) 48 { 49 cx23885_gpio_enable(dev, line, 0); 50 51 return cx23885_gpio_get(dev, line); 52 } 53 54 static void f300_send_byte(struct cx23885_dev *dev, u8 dta) 55 { 56 u8 i; 57 58 for (i = 0; i < 8; i++) { 59 f300_set_line(dev, F300_CLK, 0); 60 udelay(30); 61 f300_set_line(dev, F300_DATA, (dta & 0x80) >> 7);/* msb first */ 62 udelay(30); 63 dta <<= 1; 64 f300_set_line(dev, F300_CLK, 1); 65 udelay(30); 66 } 67 } 68 69 static u8 f300_get_byte(struct cx23885_dev *dev) 70 { 71 u8 i, dta = 0; 72 73 for (i = 0; i < 8; i++) { 74 f300_set_line(dev, F300_CLK, 0); 75 udelay(30); 76 dta <<= 1; 77 f300_set_line(dev, F300_CLK, 1); 78 udelay(30); 79 dta |= f300_get_line(dev, F300_DATA);/* msb first */ 80 81 } 82 83 return dta; 84 } 85 86 static u8 f300_xfer(struct dvb_frontend *fe, u8 *buf) 87 { 88 struct cx23885_tsport *port = fe->dvb->priv; 89 struct cx23885_dev *dev = port->dev; 90 u8 i, temp, ret = 0; 91 92 temp = buf[0]; 93 for (i = 0; i < buf[0]; i++) 94 temp += buf[i + 1]; 95 temp = (~temp + 1);/* get check sum */ 96 buf[1 + buf[0]] = temp; 97 98 f300_set_line(dev, F300_RESET, 1); 99 f300_set_line(dev, F300_CLK, 1); 100 udelay(30); 101 f300_set_line(dev, F300_DATA, 1); 102 msleep(1); 103 104 /* question: */ 105 f300_set_line(dev, F300_RESET, 0);/* begin to send data */ 106 msleep(1); 107 108 f300_send_byte(dev, 0xe0);/* the slave address is 0xe0, write */ 109 msleep(1); 110 111 temp = buf[0]; 112 temp += 2; 113 for (i = 0; i < temp; i++) 114 f300_send_byte(dev, buf[i]); 115 116 f300_set_line(dev, F300_RESET, 1);/* sent data over */ 117 f300_set_line(dev, F300_DATA, 1); 118 119 /* answer: */ 120 temp = 0; 121 for (i = 0; ((i < 8) & (temp == 0)); i++) { 122 msleep(1); 123 if (f300_get_line(dev, F300_BUSY) == 0) 124 temp = 1; 125 } 126 127 if (i > 7) { 128 printk(KERN_ERR "%s: timeout, the slave no response\n", 129 __func__); 130 ret = 1; /* timeout, the slave no response */ 131 } else { /* the slave not busy, prepare for getting data */ 132 f300_set_line(dev, F300_RESET, 0);/*ready...*/ 133 msleep(1); 134 f300_send_byte(dev, 0xe1);/* 0xe1 is Read */ 135 msleep(1); 136 temp = f300_get_byte(dev);/*get the data length */ 137 if (temp > 14) 138 temp = 14; 139 140 for (i = 0; i < (temp + 1); i++) 141 f300_get_byte(dev);/* get data to empty buffer */ 142 143 f300_set_line(dev, F300_RESET, 1);/* received data over */ 144 f300_set_line(dev, F300_DATA, 1); 145 } 146 147 return ret; 148 } 149 150 int f300_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) 151 { 152 u8 buf[16]; 153 154 buf[0] = 0x05; 155 buf[1] = 0x38;/* write port */ 156 buf[2] = 0x01;/* A port, lnb power */ 157 158 switch (voltage) { 159 case SEC_VOLTAGE_13: 160 buf[3] = 0x01;/* power on */ 161 buf[4] = 0x02;/* B port, H/V */ 162 buf[5] = 0x00;/*13V v*/ 163 break; 164 case SEC_VOLTAGE_18: 165 buf[3] = 0x01; 166 buf[4] = 0x02; 167 buf[5] = 0x01;/* 18V h*/ 168 break; 169 case SEC_VOLTAGE_OFF: 170 buf[3] = 0x00;/* power off */ 171 buf[4] = 0x00; 172 buf[5] = 0x00; 173 break; 174 } 175 176 return f300_xfer(fe, buf); 177 } 178