cx23885-f300.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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 <[email protected]>
  15. */
  16. #include "cx23885.h"
  17. #include "cx23885-f300.h"
  18. #define F300_DATA GPIO_0
  19. #define F300_RESET GPIO_1
  20. #define F300_CLK GPIO_2
  21. #define F300_BUSY GPIO_3
  22. static void f300_set_line(struct cx23885_dev *dev, u32 line, u8 lvl)
  23. {
  24. cx23885_gpio_enable(dev, line, 1);
  25. if (lvl == 1)
  26. cx23885_gpio_set(dev, line);
  27. else
  28. cx23885_gpio_clear(dev, line);
  29. }
  30. static u8 f300_get_line(struct cx23885_dev *dev, u32 line)
  31. {
  32. cx23885_gpio_enable(dev, line, 0);
  33. return cx23885_gpio_get(dev, line);
  34. }
  35. static void f300_send_byte(struct cx23885_dev *dev, u8 dta)
  36. {
  37. u8 i;
  38. for (i = 0; i < 8; i++) {
  39. f300_set_line(dev, F300_CLK, 0);
  40. udelay(30);
  41. f300_set_line(dev, F300_DATA, (dta & 0x80) >> 7);/* msb first */
  42. udelay(30);
  43. dta <<= 1;
  44. f300_set_line(dev, F300_CLK, 1);
  45. udelay(30);
  46. }
  47. }
  48. static u8 f300_get_byte(struct cx23885_dev *dev)
  49. {
  50. u8 i, dta = 0;
  51. for (i = 0; i < 8; i++) {
  52. f300_set_line(dev, F300_CLK, 0);
  53. udelay(30);
  54. dta <<= 1;
  55. f300_set_line(dev, F300_CLK, 1);
  56. udelay(30);
  57. dta |= f300_get_line(dev, F300_DATA);/* msb first */
  58. }
  59. return dta;
  60. }
  61. static u8 f300_xfer(struct dvb_frontend *fe, u8 *buf)
  62. {
  63. struct cx23885_tsport *port = fe->dvb->priv;
  64. struct cx23885_dev *dev = port->dev;
  65. u8 i, temp, ret = 0;
  66. temp = buf[0];
  67. for (i = 0; i < buf[0]; i++)
  68. temp += buf[i + 1];
  69. temp = (~temp + 1);/* get check sum */
  70. buf[1 + buf[0]] = temp;
  71. f300_set_line(dev, F300_RESET, 1);
  72. f300_set_line(dev, F300_CLK, 1);
  73. udelay(30);
  74. f300_set_line(dev, F300_DATA, 1);
  75. msleep(1);
  76. /* question: */
  77. f300_set_line(dev, F300_RESET, 0);/* begin to send data */
  78. msleep(1);
  79. f300_send_byte(dev, 0xe0);/* the slave address is 0xe0, write */
  80. msleep(1);
  81. temp = buf[0];
  82. temp += 2;
  83. for (i = 0; i < temp; i++)
  84. f300_send_byte(dev, buf[i]);
  85. f300_set_line(dev, F300_RESET, 1);/* sent data over */
  86. f300_set_line(dev, F300_DATA, 1);
  87. /* answer: */
  88. temp = 0;
  89. for (i = 0; ((i < 8) & (temp == 0)); i++) {
  90. msleep(1);
  91. if (f300_get_line(dev, F300_BUSY) == 0)
  92. temp = 1;
  93. }
  94. if (i > 7) {
  95. pr_err("%s: timeout, the slave no response\n",
  96. __func__);
  97. ret = 1; /* timeout, the slave no response */
  98. } else { /* the slave not busy, prepare for getting data */
  99. f300_set_line(dev, F300_RESET, 0);/*ready...*/
  100. msleep(1);
  101. f300_send_byte(dev, 0xe1);/* 0xe1 is Read */
  102. msleep(1);
  103. temp = f300_get_byte(dev);/*get the data length */
  104. if (temp > 14)
  105. temp = 14;
  106. for (i = 0; i < (temp + 1); i++)
  107. f300_get_byte(dev);/* get data to empty buffer */
  108. f300_set_line(dev, F300_RESET, 1);/* received data over */
  109. f300_set_line(dev, F300_DATA, 1);
  110. }
  111. return ret;
  112. }
  113. int f300_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
  114. {
  115. u8 buf[16];
  116. buf[0] = 0x05;
  117. buf[1] = 0x38;/* write port */
  118. buf[2] = 0x01;/* A port, lnb power */
  119. switch (voltage) {
  120. case SEC_VOLTAGE_13:
  121. buf[3] = 0x01;/* power on */
  122. buf[4] = 0x02;/* B port, H/V */
  123. buf[5] = 0x00;/*13V v*/
  124. break;
  125. case SEC_VOLTAGE_18:
  126. buf[3] = 0x01;
  127. buf[4] = 0x02;
  128. buf[5] = 0x01;/* 18V h*/
  129. break;
  130. case SEC_VOLTAGE_OFF:
  131. buf[3] = 0x00;/* power off */
  132. buf[4] = 0x00;
  133. buf[5] = 0x00;
  134. break;
  135. }
  136. return f300_xfer(fe, buf);
  137. }