sp2.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * CIMaX SP2/SP2HF (Atmel T90FJR) CI driver
  4. *
  5. * Copyright (C) 2014 Olli Salonen <olli.salonen@iki.fi>
  6. *
  7. * Heavily based on CIMax2(R) SP2 driver in conjunction with NetUp Dual
  8. * DVB-S2 CI card (cimax2) with following copyrights:
  9. *
  10. * Copyright (C) 2009 NetUP Inc.
  11. * Copyright (C) 2009 Igor M. Liplianin <liplianin@netup.ru>
  12. * Copyright (C) 2009 Abylay Ospan <aospan@netup.ru>
  13. */
  14. #include "sp2_priv.h"
  15. static int sp2_read_i2c(struct sp2 *s, u8 reg, u8 *buf, int len)
  16. {
  17. int ret;
  18. struct i2c_client *client = s->client;
  19. struct i2c_adapter *adap = client->adapter;
  20. struct i2c_msg msg[] = {
  21. {
  22. .addr = client->addr,
  23. .flags = 0,
  24. .buf = &reg,
  25. .len = 1
  26. }, {
  27. .addr = client->addr,
  28. .flags = I2C_M_RD,
  29. .buf = buf,
  30. .len = len
  31. }
  32. };
  33. ret = i2c_transfer(adap, msg, 2);
  34. if (ret != 2) {
  35. dev_err(&client->dev, "i2c read error, reg = 0x%02x, status = %d\n",
  36. reg, ret);
  37. if (ret < 0)
  38. return ret;
  39. else
  40. return -EIO;
  41. }
  42. dev_dbg(&s->client->dev, "addr=0x%04x, reg = 0x%02x, data = %02x\n",
  43. client->addr, reg, buf[0]);
  44. return 0;
  45. }
  46. static int sp2_write_i2c(struct sp2 *s, u8 reg, u8 *buf, int len)
  47. {
  48. int ret;
  49. u8 buffer[35];
  50. struct i2c_client *client = s->client;
  51. struct i2c_adapter *adap = client->adapter;
  52. struct i2c_msg msg = {
  53. .addr = client->addr,
  54. .flags = 0,
  55. .buf = &buffer[0],
  56. .len = len + 1
  57. };
  58. if ((len + 1) > sizeof(buffer)) {
  59. dev_err(&client->dev, "i2c wr reg=%02x: len=%d is too big!\n",
  60. reg, len);
  61. return -EINVAL;
  62. }
  63. buffer[0] = reg;
  64. memcpy(&buffer[1], buf, len);
  65. ret = i2c_transfer(adap, &msg, 1);
  66. if (ret != 1) {
  67. dev_err(&client->dev, "i2c write error, reg = 0x%02x, status = %d\n",
  68. reg, ret);
  69. if (ret < 0)
  70. return ret;
  71. else
  72. return -EIO;
  73. }
  74. dev_dbg(&s->client->dev, "addr=0x%04x, reg = 0x%02x, data = %*ph\n",
  75. client->addr, reg, len, buf);
  76. return 0;
  77. }
  78. static int sp2_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot, u8 acs,
  79. u8 read, int addr, u8 data)
  80. {
  81. struct sp2 *s = en50221->data;
  82. u8 store;
  83. int mem, ret;
  84. int (*ci_op_cam)(void*, u8, int, u8, int*) = s->ci_control;
  85. if (slot != 0)
  86. return -EINVAL;
  87. /*
  88. * change module access type between IO space and attribute memory
  89. * when needed
  90. */
  91. if (s->module_access_type != acs) {
  92. ret = sp2_read_i2c(s, 0x00, &store, 1);
  93. if (ret)
  94. return ret;
  95. store &= ~(SP2_MOD_CTL_ACS1 | SP2_MOD_CTL_ACS0);
  96. store |= acs;
  97. ret = sp2_write_i2c(s, 0x00, &store, 1);
  98. if (ret)
  99. return ret;
  100. }
  101. s->module_access_type = acs;
  102. /* implementation of ci_op_cam is device specific */
  103. if (ci_op_cam) {
  104. ret = ci_op_cam(s->priv, read, addr, data, &mem);
  105. } else {
  106. dev_err(&s->client->dev, "callback not defined");
  107. return -EINVAL;
  108. }
  109. if (ret)
  110. return ret;
  111. dev_dbg(&s->client->dev, "%s: slot=%d, addr=0x%04x, %s, data=%x",
  112. (read) ? "read" : "write", slot, addr,
  113. (acs == SP2_CI_ATTR_ACS) ? "attr" : "io",
  114. (read) ? mem : data);
  115. if (read)
  116. return mem;
  117. else
  118. return 0;
  119. }
  120. int sp2_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
  121. int slot, int addr)
  122. {
  123. return sp2_ci_op_cam(en50221, slot, SP2_CI_ATTR_ACS,
  124. SP2_CI_RD, addr, 0);
  125. }
  126. int sp2_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
  127. int slot, int addr, u8 data)
  128. {
  129. return sp2_ci_op_cam(en50221, slot, SP2_CI_ATTR_ACS,
  130. SP2_CI_WR, addr, data);
  131. }
  132. int sp2_ci_read_cam_control(struct dvb_ca_en50221 *en50221,
  133. int slot, u8 addr)
  134. {
  135. return sp2_ci_op_cam(en50221, slot, SP2_CI_IO_ACS,
  136. SP2_CI_RD, addr, 0);
  137. }
  138. int sp2_ci_write_cam_control(struct dvb_ca_en50221 *en50221,
  139. int slot, u8 addr, u8 data)
  140. {
  141. return sp2_ci_op_cam(en50221, slot, SP2_CI_IO_ACS,
  142. SP2_CI_WR, addr, data);
  143. }
  144. int sp2_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
  145. {
  146. struct sp2 *s = en50221->data;
  147. u8 buf;
  148. int ret;
  149. dev_dbg(&s->client->dev, "slot: %d\n", slot);
  150. if (slot != 0)
  151. return -EINVAL;
  152. /* RST on */
  153. buf = SP2_MOD_CTL_RST;
  154. ret = sp2_write_i2c(s, 0x00, &buf, 1);
  155. if (ret)
  156. return ret;
  157. usleep_range(500, 600);
  158. /* RST off */
  159. buf = 0x00;
  160. ret = sp2_write_i2c(s, 0x00, &buf, 1);
  161. if (ret)
  162. return ret;
  163. msleep(1000);
  164. return 0;
  165. }
  166. int sp2_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
  167. {
  168. struct sp2 *s = en50221->data;
  169. dev_dbg(&s->client->dev, "slot:%d\n", slot);
  170. /* not implemented */
  171. return 0;
  172. }
  173. int sp2_ci_slot_ts_enable(struct dvb_ca_en50221 *en50221, int slot)
  174. {
  175. struct sp2 *s = en50221->data;
  176. u8 buf;
  177. dev_dbg(&s->client->dev, "slot:%d\n", slot);
  178. if (slot != 0)
  179. return -EINVAL;
  180. sp2_read_i2c(s, 0x00, &buf, 1);
  181. /* disable bypass and enable TS */
  182. buf |= (SP2_MOD_CTL_TSOEN | SP2_MOD_CTL_TSIEN);
  183. return sp2_write_i2c(s, 0, &buf, 1);
  184. }
  185. int sp2_ci_poll_slot_status(struct dvb_ca_en50221 *en50221,
  186. int slot, int open)
  187. {
  188. struct sp2 *s = en50221->data;
  189. u8 buf[2];
  190. int ret;
  191. dev_dbg(&s->client->dev, "slot:%d open:%d\n", slot, open);
  192. /*
  193. * CAM module INSERT/REMOVE processing. Slow operation because of i2c
  194. * transfers. Throttle read to one per sec.
  195. */
  196. if (time_after(jiffies, s->next_status_checked_time)) {
  197. ret = sp2_read_i2c(s, 0x00, buf, 1);
  198. s->next_status_checked_time = jiffies + msecs_to_jiffies(1000);
  199. if (ret)
  200. return 0;
  201. if (buf[0] & SP2_MOD_CTL_DET)
  202. s->status = DVB_CA_EN50221_POLL_CAM_PRESENT |
  203. DVB_CA_EN50221_POLL_CAM_READY;
  204. else
  205. s->status = 0;
  206. }
  207. return s->status;
  208. }
  209. static int sp2_init(struct sp2 *s)
  210. {
  211. int ret = 0;
  212. u8 buf;
  213. u8 cimax_init[34] = {
  214. 0x00, /* module A control*/
  215. 0x00, /* auto select mask high A */
  216. 0x00, /* auto select mask low A */
  217. 0x00, /* auto select pattern high A */
  218. 0x00, /* auto select pattern low A */
  219. 0x44, /* memory access time A, 600 ns */
  220. 0x00, /* invert input A */
  221. 0x00, /* RFU */
  222. 0x00, /* RFU */
  223. 0x00, /* module B control*/
  224. 0x00, /* auto select mask high B */
  225. 0x00, /* auto select mask low B */
  226. 0x00, /* auto select pattern high B */
  227. 0x00, /* auto select pattern low B */
  228. 0x44, /* memory access time B, 600 ns */
  229. 0x00, /* invert input B */
  230. 0x00, /* RFU */
  231. 0x00, /* RFU */
  232. 0x00, /* auto select mask high Ext */
  233. 0x00, /* auto select mask low Ext */
  234. 0x00, /* auto select pattern high Ext */
  235. 0x00, /* auto select pattern low Ext */
  236. 0x00, /* RFU */
  237. 0x02, /* destination - module A */
  238. 0x01, /* power control reg, VCC power on */
  239. 0x00, /* RFU */
  240. 0x00, /* int status read only */
  241. 0x00, /* Interrupt Mask Register */
  242. 0x05, /* EXTINT=active-high, INT=push-pull */
  243. 0x00, /* USCG1 */
  244. 0x04, /* ack active low */
  245. 0x00, /* LOCK = 0 */
  246. 0x22, /* unknown */
  247. 0x00, /* synchronization? */
  248. };
  249. dev_dbg(&s->client->dev, "\n");
  250. s->ca.owner = THIS_MODULE;
  251. s->ca.read_attribute_mem = sp2_ci_read_attribute_mem;
  252. s->ca.write_attribute_mem = sp2_ci_write_attribute_mem;
  253. s->ca.read_cam_control = sp2_ci_read_cam_control;
  254. s->ca.write_cam_control = sp2_ci_write_cam_control;
  255. s->ca.slot_reset = sp2_ci_slot_reset;
  256. s->ca.slot_shutdown = sp2_ci_slot_shutdown;
  257. s->ca.slot_ts_enable = sp2_ci_slot_ts_enable;
  258. s->ca.poll_slot_status = sp2_ci_poll_slot_status;
  259. s->ca.data = s;
  260. s->module_access_type = 0;
  261. /* initialize all regs */
  262. ret = sp2_write_i2c(s, 0x00, &cimax_init[0], 34);
  263. if (ret)
  264. goto err;
  265. /* lock registers */
  266. buf = 1;
  267. ret = sp2_write_i2c(s, 0x1f, &buf, 1);
  268. if (ret)
  269. goto err;
  270. /* power on slots */
  271. ret = sp2_write_i2c(s, 0x18, &buf, 1);
  272. if (ret)
  273. goto err;
  274. ret = dvb_ca_en50221_init(s->dvb_adap, &s->ca, 0, 1);
  275. if (ret)
  276. goto err;
  277. return 0;
  278. err:
  279. dev_dbg(&s->client->dev, "init failed=%d\n", ret);
  280. return ret;
  281. }
  282. static int sp2_exit(struct i2c_client *client)
  283. {
  284. struct sp2 *s;
  285. dev_dbg(&client->dev, "\n");
  286. if (!client)
  287. return 0;
  288. s = i2c_get_clientdata(client);
  289. if (!s)
  290. return 0;
  291. if (!s->ca.data)
  292. return 0;
  293. dvb_ca_en50221_release(&s->ca);
  294. return 0;
  295. }
  296. static int sp2_probe(struct i2c_client *client,
  297. const struct i2c_device_id *id)
  298. {
  299. struct sp2_config *cfg = client->dev.platform_data;
  300. struct sp2 *s;
  301. int ret;
  302. dev_dbg(&client->dev, "\n");
  303. s = kzalloc(sizeof(*s), GFP_KERNEL);
  304. if (!s) {
  305. ret = -ENOMEM;
  306. goto err;
  307. }
  308. s->client = client;
  309. s->dvb_adap = cfg->dvb_adap;
  310. s->priv = cfg->priv;
  311. s->ci_control = cfg->ci_control;
  312. i2c_set_clientdata(client, s);
  313. ret = sp2_init(s);
  314. if (ret)
  315. goto err;
  316. dev_info(&s->client->dev, "CIMaX SP2 successfully attached\n");
  317. return 0;
  318. err:
  319. dev_dbg(&client->dev, "init failed=%d\n", ret);
  320. kfree(s);
  321. return ret;
  322. }
  323. static int sp2_remove(struct i2c_client *client)
  324. {
  325. struct sp2 *s = i2c_get_clientdata(client);
  326. dev_dbg(&client->dev, "\n");
  327. sp2_exit(client);
  328. kfree(s);
  329. return 0;
  330. }
  331. static const struct i2c_device_id sp2_id[] = {
  332. {"sp2", 0},
  333. {}
  334. };
  335. MODULE_DEVICE_TABLE(i2c, sp2_id);
  336. static struct i2c_driver sp2_driver = {
  337. .driver = {
  338. .name = "sp2",
  339. },
  340. .probe = sp2_probe,
  341. .remove = sp2_remove,
  342. .id_table = sp2_id,
  343. };
  344. module_i2c_driver(sp2_driver);
  345. MODULE_DESCRIPTION("CIMaX SP2/HF CI driver");
  346. MODULE_AUTHOR("Olli Salonen <olli.salonen@iki.fi>");
  347. MODULE_LICENSE("GPL");