nb7vpq904m.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include <linux/module.h>
  7. #include <linux/i2c.h>
  8. #include <linux/slab.h>
  9. #include <linux/usb/ch9.h>
  10. #include <linux/debugfs.h>
  11. #include <linux/uaccess.h>
  12. #include <linux/regmap.h>
  13. #include <linux/ctype.h>
  14. #include <linux/pinctrl/consumer.h>
  15. #include <linux/of_gpio.h>
  16. #include <linux/regulator/consumer.h>
  17. #include <linux/usb/redriver.h>
  18. /* priority: INT_MAX >= x >= 0 */
  19. #define NOTIFIER_PRIORITY 1
  20. /* Registers Address */
  21. #define GEN_DEV_SET_REG 0x00
  22. #define CHIP_VERSION_REG 0x17
  23. #define REDRIVER_REG_MAX 0x1f
  24. #define EQ_SET_REG_BASE 0x01
  25. #define FLAT_GAIN_REG_BASE 0x18
  26. #define OUT_COMP_AND_POL_REG_BASE 0x02
  27. #define LOSS_MATCH_REG_BASE 0x19
  28. #define AUX_SWITCH_REG 0x09
  29. #define AUX_NORMAL_VAL 0
  30. #define AUX_FLIP_VAL 1
  31. #define AUX_DISABLE_VAL 2
  32. /* Default Register Value */
  33. #define GEN_DEV_SET_REG_DEFAULT 0xFB
  34. /* Register bits */
  35. /* General Device Settings Register Bits */
  36. #define CHIP_EN BIT(0)
  37. #define CHNA_EN BIT(4)
  38. #define CHNB_EN BIT(5)
  39. #define CHNC_EN BIT(6)
  40. #define CHND_EN BIT(7)
  41. #define CHANNEL_NUM 4
  42. #define OP_MODE_SHIFT 1
  43. #define EQ_SETTING_MASK 0x07
  44. #define OUTPUT_COMPRESSION_MASK 0x0b
  45. #define LOSS_MATCH_MASK 0x03
  46. #define FLAT_GAIN_MASK 0x03
  47. #define EQ_SETTING_SHIFT 0x01
  48. #define OUTPUT_COMPRESSION_SHIFT 0x01
  49. #define LOSS_MATCH_SHIFT 0x00
  50. #define FLAT_GAIN_SHIFT 0x00
  51. #define CHNA_INDEX 0
  52. #define CHNB_INDEX 1
  53. #define CHNC_INDEX 2
  54. #define CHND_INDEX 3
  55. enum operation_mode {
  56. OP_MODE_NONE, /* 4 lanes disabled */
  57. OP_MODE_USB, /* 2 lanes for USB and 2 lanes disabled */
  58. OP_MODE_DP, /* 4 lanes DP */
  59. OP_MODE_USB_AND_DP, /* 2 lanes for USB and 2 lanes DP */
  60. OP_MODE_DEFAULT, /* 4 lanes USB */
  61. };
  62. #define CHAN_MODE_USB 0
  63. #define CHAN_MODE_DP 1
  64. #define CHAN_MODE_NUM 2
  65. #define CHAN_MODE_DISABLE 0xff /* when disable, not configure eq, gain ... */
  66. #define LANES_DP 4
  67. #define LANES_DP_AND_USB 2
  68. #define PULLUP_WORKER_DELAY_US 500000
  69. #define CHIP_MAX_PWR_UA 260000
  70. #define CHIP_MIN_PWR_UV 1710000
  71. #define CHIP_MAX_PWR_UV 1890000
  72. struct nb7vpq904m_redriver {
  73. struct usb_redriver r;
  74. struct device *dev;
  75. struct regmap *regmap;
  76. struct i2c_client *client;
  77. struct regulator *vdd;
  78. int typec_orientation;
  79. enum operation_mode op_mode;
  80. u8 chan_mode[CHANNEL_NUM];
  81. u8 eq[CHAN_MODE_NUM][CHANNEL_NUM];
  82. u8 output_comp[CHAN_MODE_NUM][CHANNEL_NUM];
  83. u8 loss_match[CHAN_MODE_NUM][CHANNEL_NUM];
  84. u8 flat_gain[CHAN_MODE_NUM][CHANNEL_NUM];
  85. u8 gen_dev_val;
  86. bool lane_channel_swap;
  87. bool vdd_enable;
  88. bool is_set_aux;
  89. struct workqueue_struct *pullup_wq;
  90. struct work_struct pullup_work;
  91. bool work_ongoing;
  92. struct work_struct host_work;
  93. struct dentry *debug_root;
  94. };
  95. static int nb7vpq904m_channel_update(struct nb7vpq904m_redriver *redriver);
  96. static void nb7vpq904m_debugfs_entries(struct nb7vpq904m_redriver *redriver);
  97. static const char * const opmode_string[] = {
  98. [OP_MODE_NONE] = "NONE",
  99. [OP_MODE_USB] = "USB",
  100. [OP_MODE_DP] = "DP",
  101. [OP_MODE_USB_AND_DP] = "USB and DP",
  102. [OP_MODE_DEFAULT] = "DEFAULT",
  103. };
  104. #define OPMODESTR(x) opmode_string[x]
  105. static int nb7vpq904m_reg_set(struct nb7vpq904m_redriver *redriver,
  106. u8 reg, u8 val)
  107. {
  108. int ret;
  109. ret = regmap_write(redriver->regmap, (unsigned int)reg,
  110. (unsigned int)val);
  111. if (ret < 0) {
  112. dev_err(redriver->dev, "writing reg 0x%02x failure\n", reg);
  113. return ret;
  114. }
  115. dev_dbg(redriver->dev, "writing reg 0x%02x=0x%02x\n", reg, val);
  116. return 0;
  117. }
  118. static void nb7vpq904m_vdd_enable(struct nb7vpq904m_redriver *redriver, bool on)
  119. {
  120. int l, v, s;
  121. if (!redriver->vdd) {
  122. dev_dbg(redriver->dev, "no vdd regulator operation\n");
  123. return;
  124. }
  125. if (on && !redriver->vdd_enable) {
  126. redriver->vdd_enable = true;
  127. l = regulator_set_load(redriver->vdd, CHIP_MAX_PWR_UA);
  128. v = regulator_set_voltage(redriver->vdd, CHIP_MIN_PWR_UV, CHIP_MAX_PWR_UV);
  129. s = regulator_enable(redriver->vdd);
  130. dev_dbg(redriver->dev, "vdd regulator enable return %d-%d-%d\n", l, v, s);
  131. } else if (!on && redriver->vdd_enable) {
  132. redriver->vdd_enable = false;
  133. s = regulator_disable(redriver->vdd);
  134. v = regulator_set_voltage(redriver->vdd, 0, CHIP_MAX_PWR_UV);
  135. l = regulator_set_load(redriver->vdd, 0);
  136. dev_dbg(redriver->dev, "vdd regulator disable return %d-%d-%d\n", l, v, s);
  137. }
  138. }
  139. static void nb7vpq904m_dev_aux_set(struct nb7vpq904m_redriver *redriver)
  140. {
  141. u8 aux_val = AUX_DISABLE_VAL;
  142. if (!redriver->is_set_aux)
  143. return;
  144. switch (redriver->op_mode) {
  145. case OP_MODE_DP:
  146. case OP_MODE_USB_AND_DP:
  147. if (redriver->typec_orientation == ORIENTATION_CC1)
  148. aux_val = AUX_NORMAL_VAL;
  149. else
  150. aux_val = AUX_FLIP_VAL;
  151. break;
  152. default:
  153. break;
  154. }
  155. nb7vpq904m_reg_set(redriver, AUX_SWITCH_REG, aux_val);
  156. }
  157. static int nb7vpq904m_gen_dev_set(struct nb7vpq904m_redriver *redriver)
  158. {
  159. u8 val = 0;
  160. switch (redriver->op_mode) {
  161. case OP_MODE_DEFAULT:
  162. /* Enable channel A, B, C and D */
  163. val |= (CHNA_EN | CHNB_EN);
  164. val |= (CHNC_EN | CHND_EN);
  165. val |= (0x5 << OP_MODE_SHIFT);
  166. val |= CHIP_EN;
  167. break;
  168. case OP_MODE_USB:
  169. /* Use source side I/O mapping */
  170. if (redriver->typec_orientation
  171. == ORIENTATION_CC1) {
  172. /* Enable channel C and D */
  173. val &= ~(CHNA_EN | CHNB_EN);
  174. val |= (CHNC_EN | CHND_EN);
  175. } else if (redriver->typec_orientation
  176. == ORIENTATION_CC2) {
  177. /* Enable channel A and B*/
  178. val |= (CHNA_EN | CHNB_EN);
  179. val &= ~(CHNC_EN | CHND_EN);
  180. }
  181. /* Set to default USB Mode */
  182. val |= (0x5 << OP_MODE_SHIFT);
  183. val |= CHIP_EN;
  184. break;
  185. case OP_MODE_DP:
  186. /* Enable channel A, B, C and D */
  187. val |= (CHNA_EN | CHNB_EN);
  188. val |= (CHNC_EN | CHND_EN);
  189. /* Set to DP 4 Lane Mode (OP Mode 2) */
  190. val |= (0x2 << OP_MODE_SHIFT);
  191. val |= CHIP_EN;
  192. break;
  193. case OP_MODE_USB_AND_DP:
  194. /* Enable channel A, B, C and D */
  195. val |= (CHNA_EN | CHNB_EN);
  196. val |= (CHNC_EN | CHND_EN);
  197. val |= CHIP_EN;
  198. if (redriver->typec_orientation
  199. == ORIENTATION_CC1)
  200. val |= (0x1 << OP_MODE_SHIFT);
  201. else if (redriver->typec_orientation
  202. == ORIENTATION_CC2)
  203. val |= (0x0 << OP_MODE_SHIFT);
  204. break;
  205. default:
  206. val &= ~CHIP_EN;
  207. break;
  208. }
  209. redriver->gen_dev_val = val;
  210. return nb7vpq904m_reg_set(redriver, GEN_DEV_SET_REG, val);
  211. }
  212. static int nb7vpq904m_param_config(struct nb7vpq904m_redriver *redriver,
  213. u8 reg_base, u8 channel, u8 chan_mode, u8 mask, u8 shift,
  214. u8 val, u8 (*stored_val)[CHANNEL_NUM])
  215. {
  216. int i, j, ret = -EINVAL;
  217. u8 reg_addr, reg_val;
  218. if (channel == CHANNEL_NUM) {
  219. for (i = 0; i < CHAN_MODE_NUM; i++)
  220. for (j = 0; j < CHANNEL_NUM; j++) {
  221. if (redriver->chan_mode[j] == i) {
  222. reg_addr = reg_base + (j << 1);
  223. reg_val = (val << shift);
  224. reg_val &= (mask << shift);
  225. ret = nb7vpq904m_reg_set(redriver,
  226. reg_addr, reg_val);
  227. if (ret < 0)
  228. return ret;
  229. }
  230. stored_val[i][j] = val;
  231. }
  232. } else {
  233. if (redriver->chan_mode[channel] == chan_mode) {
  234. reg_addr = reg_base + (channel << 1);
  235. reg_val = (val << shift);
  236. reg_val &= (mask << shift);
  237. ret = nb7vpq904m_reg_set(redriver,
  238. reg_addr, reg_val);
  239. if (ret < 0)
  240. return ret;
  241. }
  242. stored_val[chan_mode][channel] = val;
  243. }
  244. return 0;
  245. }
  246. static int nb7vpq904m_eq_config(
  247. struct nb7vpq904m_redriver *redriver, u8 channel, u8 chan_mode, u8 val)
  248. {
  249. return nb7vpq904m_param_config(redriver,
  250. EQ_SET_REG_BASE, channel, chan_mode,
  251. EQ_SETTING_MASK, EQ_SETTING_SHIFT,
  252. val, redriver->eq);
  253. }
  254. static int nb7vpq904m_flat_gain_config(
  255. struct nb7vpq904m_redriver *redriver, u8 channel, u8 chan_mode, u8 val)
  256. {
  257. return nb7vpq904m_param_config(redriver,
  258. FLAT_GAIN_REG_BASE, channel, chan_mode,
  259. FLAT_GAIN_MASK, FLAT_GAIN_SHIFT,
  260. val, redriver->flat_gain);
  261. }
  262. static int nb7vpq904m_output_comp_config(
  263. struct nb7vpq904m_redriver *redriver, u8 channel, u8 chan_mode, u8 val)
  264. {
  265. return nb7vpq904m_param_config(redriver,
  266. OUT_COMP_AND_POL_REG_BASE, channel, chan_mode,
  267. OUTPUT_COMPRESSION_MASK, OUTPUT_COMPRESSION_SHIFT,
  268. val, redriver->output_comp);
  269. }
  270. static int nb7vpq904m_loss_match_config(
  271. struct nb7vpq904m_redriver *redriver, u8 channel, u8 chan_mode, u8 val)
  272. {
  273. return nb7vpq904m_param_config(redriver,
  274. LOSS_MATCH_REG_BASE, channel, chan_mode,
  275. LOSS_MATCH_MASK, LOSS_MATCH_SHIFT, val,
  276. redriver->loss_match);
  277. }
  278. static int nb7vpq904m_channel_update(struct nb7vpq904m_redriver *redriver)
  279. {
  280. int ret;
  281. u8 i, chan_mode;
  282. switch (redriver->op_mode) {
  283. case OP_MODE_DEFAULT:
  284. redriver->chan_mode[CHNA_INDEX] = CHAN_MODE_USB;
  285. redriver->chan_mode[CHNB_INDEX] = CHAN_MODE_USB;
  286. redriver->chan_mode[CHNC_INDEX] = CHAN_MODE_USB;
  287. redriver->chan_mode[CHND_INDEX] = CHAN_MODE_USB;
  288. break;
  289. case OP_MODE_USB:
  290. if (redriver->typec_orientation == ORIENTATION_CC1) {
  291. redriver->chan_mode[CHNA_INDEX] = CHAN_MODE_DISABLE;
  292. redriver->chan_mode[CHNB_INDEX] = CHAN_MODE_DISABLE;
  293. redriver->chan_mode[CHNC_INDEX] = CHAN_MODE_USB;
  294. redriver->chan_mode[CHND_INDEX] = CHAN_MODE_USB;
  295. } else {
  296. redriver->chan_mode[CHNA_INDEX] = CHAN_MODE_USB;
  297. redriver->chan_mode[CHNB_INDEX] = CHAN_MODE_USB;
  298. redriver->chan_mode[CHNC_INDEX] = CHAN_MODE_DISABLE;
  299. redriver->chan_mode[CHND_INDEX] = CHAN_MODE_DISABLE;
  300. }
  301. break;
  302. case OP_MODE_USB_AND_DP:
  303. if (redriver->typec_orientation == ORIENTATION_CC1) {
  304. redriver->chan_mode[CHNA_INDEX] = CHAN_MODE_DP;
  305. redriver->chan_mode[CHNB_INDEX] = CHAN_MODE_DP;
  306. redriver->chan_mode[CHNC_INDEX] = CHAN_MODE_USB;
  307. redriver->chan_mode[CHND_INDEX] = CHAN_MODE_USB;
  308. } else {
  309. redriver->chan_mode[CHNA_INDEX] = CHAN_MODE_USB;
  310. redriver->chan_mode[CHNB_INDEX] = CHAN_MODE_USB;
  311. redriver->chan_mode[CHNC_INDEX] = CHAN_MODE_DP;
  312. redriver->chan_mode[CHND_INDEX] = CHAN_MODE_DP;
  313. }
  314. break;
  315. case OP_MODE_DP:
  316. redriver->chan_mode[CHNA_INDEX] = CHAN_MODE_DP;
  317. redriver->chan_mode[CHNB_INDEX] = CHAN_MODE_DP;
  318. redriver->chan_mode[CHNC_INDEX] = CHAN_MODE_DP;
  319. redriver->chan_mode[CHND_INDEX] = CHAN_MODE_DP;
  320. break;
  321. default:
  322. return 0;
  323. }
  324. for (i = 0; i < CHANNEL_NUM; i++) {
  325. if (redriver->chan_mode[i] == CHAN_MODE_DISABLE)
  326. continue;
  327. chan_mode = redriver->chan_mode[i];
  328. ret = nb7vpq904m_eq_config(redriver, i, chan_mode,
  329. redriver->eq[chan_mode][i]);
  330. if (ret)
  331. goto err;
  332. ret = nb7vpq904m_flat_gain_config(redriver, i, chan_mode,
  333. redriver->flat_gain[chan_mode][i]);
  334. if (ret)
  335. goto err;
  336. ret = nb7vpq904m_output_comp_config(redriver, i, chan_mode,
  337. redriver->output_comp[chan_mode][i]);
  338. if (ret)
  339. goto err;
  340. ret = nb7vpq904m_loss_match_config(redriver, i, chan_mode,
  341. redriver->loss_match[chan_mode][i]);
  342. if (ret)
  343. goto err;
  344. }
  345. return 0;
  346. err:
  347. dev_err(redriver->dev, "channel parameters update failure(%d).\n", ret);
  348. return ret;
  349. }
  350. static int nb7vpq904m_read_configuration(struct nb7vpq904m_redriver *redriver)
  351. {
  352. struct device_node *node = redriver->dev->of_node;
  353. int ret = 0;
  354. if (of_find_property(node, "eq", NULL)) {
  355. ret = of_property_read_u8_array(node, "eq",
  356. redriver->eq[0], sizeof(redriver->eq));
  357. if (ret)
  358. goto err;
  359. }
  360. if (of_find_property(node, "flat-gain", NULL)) {
  361. ret = of_property_read_u8_array(node,
  362. "flat-gain", redriver->flat_gain[0],
  363. sizeof(redriver->flat_gain));
  364. if (ret)
  365. goto err;
  366. }
  367. if (of_find_property(node, "output-comp", NULL)) {
  368. ret = of_property_read_u8_array(node,
  369. "output-comp", redriver->output_comp[0],
  370. sizeof(redriver->output_comp));
  371. if (ret)
  372. goto err;
  373. }
  374. if (of_find_property(node, "loss-match", NULL)) {
  375. ret = of_property_read_u8_array(node,
  376. "loss-match", redriver->loss_match[0],
  377. sizeof(redriver->loss_match));
  378. if (ret)
  379. goto err;
  380. }
  381. redriver->is_set_aux = of_property_read_bool(node, "set-aux");
  382. return 0;
  383. err:
  384. dev_err(redriver->dev,
  385. "%s: error read parameters.\n", __func__);
  386. return ret;
  387. }
  388. static inline void orientation_set(struct nb7vpq904m_redriver *redriver, int ort)
  389. {
  390. redriver->typec_orientation = ort;
  391. if (redriver->lane_channel_swap) {
  392. if (redriver->typec_orientation == ORIENTATION_CC1)
  393. redriver->typec_orientation = ORIENTATION_CC2;
  394. else
  395. redriver->typec_orientation = ORIENTATION_CC1;
  396. }
  397. }
  398. static int nb7vpq904m_notify_connect(struct usb_redriver *r, int ort)
  399. {
  400. struct nb7vpq904m_redriver *redriver =
  401. container_of(r, struct nb7vpq904m_redriver, r);
  402. dev_dbg(redriver->dev, "%s: mode %s, orientation %s, %d\n", __func__,
  403. OPMODESTR(redriver->op_mode),
  404. ort == ORIENTATION_CC1 ? "CC1" : "CC2",
  405. redriver->lane_channel_swap);
  406. nb7vpq904m_vdd_enable(redriver, true);
  407. if (redriver->op_mode == OP_MODE_NONE)
  408. redriver->op_mode = OP_MODE_USB;
  409. orientation_set(redriver, ort);
  410. nb7vpq904m_gen_dev_set(redriver);
  411. nb7vpq904m_channel_update(redriver);
  412. return 0;
  413. }
  414. static int nb7vpq904m_notify_disconnect(struct usb_redriver *r)
  415. {
  416. int ret = 0;
  417. struct nb7vpq904m_redriver *redriver =
  418. container_of(r, struct nb7vpq904m_redriver, r);
  419. dev_dbg(redriver->dev, "%s: mode %s\n", __func__,
  420. OPMODESTR(redriver->op_mode));
  421. if (redriver->op_mode == OP_MODE_NONE)
  422. return 0;
  423. redriver->op_mode = OP_MODE_NONE;
  424. ret = nb7vpq904m_reg_set(redriver, GEN_DEV_SET_REG, 0);
  425. if (!ret)
  426. nb7vpq904m_vdd_enable(redriver, false);
  427. return 0;
  428. }
  429. static int nb7vpq904m_release_usb_lanes(struct usb_redriver *r, int ort, int num)
  430. {
  431. struct nb7vpq904m_redriver *redriver =
  432. container_of(r, struct nb7vpq904m_redriver, r);
  433. dev_dbg(redriver->dev, "%s: mode %s, orientation %s-%d, lanes %d\n", __func__,
  434. OPMODESTR(redriver->op_mode), ort == ORIENTATION_CC1 ? "CC1" : "CC2",
  435. redriver->lane_channel_swap, num);
  436. if (num == LANES_DP)
  437. redriver->op_mode = OP_MODE_DP;
  438. else if (num == LANES_DP_AND_USB)
  439. redriver->op_mode = OP_MODE_USB_AND_DP;
  440. nb7vpq904m_vdd_enable(redriver, true);
  441. /* in case it need aux function from redriver and the first call is release lane */
  442. orientation_set(redriver, ort);
  443. nb7vpq904m_gen_dev_set(redriver);
  444. nb7vpq904m_dev_aux_set(redriver);
  445. nb7vpq904m_channel_update(redriver);
  446. return 0;
  447. }
  448. static void nb7vpq904m_gadget_pullup_work(struct work_struct *w)
  449. {
  450. struct nb7vpq904m_redriver *redriver =
  451. container_of(w, struct nb7vpq904m_redriver, pullup_work);
  452. u8 val = redriver->gen_dev_val;
  453. nb7vpq904m_reg_set(redriver, GEN_DEV_SET_REG, val & ~CHIP_EN);
  454. usleep_range(1000, 1500);
  455. nb7vpq904m_reg_set(redriver, GEN_DEV_SET_REG, val);
  456. redriver->work_ongoing = false;
  457. }
  458. static int nb7vpq904m_gadget_pullup_enter(struct usb_redriver *r, int is_on)
  459. {
  460. struct nb7vpq904m_redriver *redriver =
  461. container_of(r, struct nb7vpq904m_redriver, r);
  462. u64 time = 0;
  463. dev_dbg(redriver->dev, "%s: mode %s, %d, %d\n", __func__,
  464. OPMODESTR(redriver->op_mode), is_on, redriver->work_ongoing);
  465. if (redriver->op_mode != OP_MODE_USB)
  466. return -EINVAL;
  467. if (!is_on)
  468. return 0;
  469. while (redriver->work_ongoing) {
  470. /*
  471. * this function can work in atomic context, no sleep function here,
  472. * it need wait pull down complete before pull up again.
  473. */
  474. udelay(1);
  475. if (time++ > PULLUP_WORKER_DELAY_US) {
  476. dev_warn(redriver->dev, "pullup timeout\n");
  477. break;
  478. }
  479. }
  480. dev_dbg(redriver->dev, "pull-up disable work took %llu us\n", time);
  481. return 0;
  482. }
  483. static int nb7vpq904m_gadget_pullup_exit(struct usb_redriver *r, int is_on)
  484. {
  485. struct nb7vpq904m_redriver *redriver =
  486. container_of(r, struct nb7vpq904m_redriver, r);
  487. dev_dbg(redriver->dev, "%s: mode %s, %d, %d\n", __func__,
  488. OPMODESTR(redriver->op_mode), is_on, redriver->work_ongoing);
  489. if (redriver->op_mode != OP_MODE_USB)
  490. return -EINVAL;
  491. if (is_on)
  492. return 0;
  493. redriver->work_ongoing = true;
  494. queue_work(redriver->pullup_wq, &redriver->pullup_work);
  495. return 0;
  496. }
  497. static void nb7vpq904m_host_work(struct work_struct *w)
  498. {
  499. struct nb7vpq904m_redriver *redriver =
  500. container_of(w, struct nb7vpq904m_redriver, host_work);
  501. u8 val = redriver->gen_dev_val;
  502. nb7vpq904m_reg_set(redriver, GEN_DEV_SET_REG, val & ~CHIP_EN);
  503. /* sleep for a while to make sure xhci host detect device disconnect */
  504. usleep_range(2000, 2500);
  505. nb7vpq904m_reg_set(redriver, GEN_DEV_SET_REG, val);
  506. }
  507. static int nb7vpq904m_host_powercycle(struct usb_redriver *r)
  508. {
  509. struct nb7vpq904m_redriver *redriver =
  510. container_of(r, struct nb7vpq904m_redriver, r);
  511. if (redriver->op_mode != OP_MODE_USB)
  512. return -EINVAL;
  513. schedule_work(&redriver->host_work);
  514. return 0;
  515. }
  516. static const struct regmap_config redriver_regmap = {
  517. .name = "nb7vpq904m",
  518. .max_register = REDRIVER_REG_MAX,
  519. .reg_bits = 8,
  520. .val_bits = 8,
  521. };
  522. static int nb7vpq904m_probe(struct i2c_client *client,
  523. const struct i2c_device_id *dev_id)
  524. {
  525. struct nb7vpq904m_redriver *redriver;
  526. int ret;
  527. redriver = devm_kzalloc(&client->dev, sizeof(struct nb7vpq904m_redriver),
  528. GFP_KERNEL);
  529. if (!redriver)
  530. return -ENOMEM;
  531. redriver->pullup_wq = alloc_workqueue("%s:pullup",
  532. WQ_UNBOUND | WQ_HIGHPRI, 0,
  533. dev_name(&client->dev));
  534. if (!redriver->pullup_wq) {
  535. dev_err(&client->dev, "Failed to create pullup workqueue\n");
  536. return -ENOMEM;
  537. }
  538. redriver->regmap = devm_regmap_init_i2c(client, &redriver_regmap);
  539. if (IS_ERR(redriver->regmap)) {
  540. ret = PTR_ERR(redriver->regmap);
  541. dev_err(&client->dev,
  542. "Failed to allocate register map: %d\n", ret);
  543. return ret;
  544. }
  545. redriver->dev = &client->dev;
  546. i2c_set_clientdata(client, redriver);
  547. ret = nb7vpq904m_read_configuration(redriver);
  548. if (ret < 0) {
  549. dev_err(&client->dev,
  550. "Failed to read default configuration: %d\n", ret);
  551. return ret;
  552. }
  553. redriver->vdd = devm_regulator_get_optional(&client->dev, "vdd");
  554. if (IS_ERR(redriver->vdd)) {
  555. ret = PTR_ERR(redriver->vdd);
  556. redriver->vdd = NULL;
  557. if (ret != -ENODEV)
  558. dev_err(&client->dev, "Failed to get vdd regulator %d\n", ret);
  559. }
  560. INIT_WORK(&redriver->pullup_work, nb7vpq904m_gadget_pullup_work);
  561. INIT_WORK(&redriver->host_work, nb7vpq904m_host_work);
  562. redriver->lane_channel_swap =
  563. of_property_read_bool(redriver->dev->of_node, "lane-channel-swap");
  564. /* disable it at start, one i2c register write time is acceptable */
  565. redriver->op_mode = OP_MODE_NONE;
  566. nb7vpq904m_vdd_enable(redriver, true);
  567. nb7vpq904m_gen_dev_set(redriver);
  568. /* when private vdd present and change to none mode, it can simply disable vdd regulator,
  569. * but to keep things simple and avoid if/else operation, keep one same rule as,
  570. * allow original register write operation then control vdd regulator.
  571. * also it will keep consistent behavior if it still need vdd control when multiple
  572. * clients share the same vdd regulator.
  573. */
  574. nb7vpq904m_vdd_enable(redriver, false);
  575. nb7vpq904m_debugfs_entries(redriver);
  576. redriver->r.of_node = redriver->dev->of_node;
  577. redriver->r.release_usb_lanes = nb7vpq904m_release_usb_lanes;
  578. redriver->r.notify_connect = nb7vpq904m_notify_connect;
  579. redriver->r.notify_disconnect = nb7vpq904m_notify_disconnect;
  580. redriver->r.gadget_pullup_enter = nb7vpq904m_gadget_pullup_enter;
  581. redriver->r.gadget_pullup_exit = nb7vpq904m_gadget_pullup_exit;
  582. redriver->r.host_powercycle = nb7vpq904m_host_powercycle;
  583. usb_add_redriver(&redriver->r);
  584. return 0;
  585. }
  586. static void nb7vpq904m_remove(struct i2c_client *client)
  587. {
  588. struct nb7vpq904m_redriver *redriver = i2c_get_clientdata(client);
  589. if (usb_remove_redriver(&redriver->r))
  590. return;
  591. debugfs_remove_recursive(redriver->debug_root);
  592. redriver->work_ongoing = false;
  593. destroy_workqueue(redriver->pullup_wq);
  594. if (redriver->vdd)
  595. regulator_disable(redriver->vdd);
  596. }
  597. static ssize_t channel_config_write(struct file *file,
  598. const char __user *ubuf, size_t count, loff_t *ppos,
  599. int (*config_func)(struct nb7vpq904m_redriver *redriver,
  600. u8 channel, u8 chan_mode, u8 val))
  601. {
  602. struct seq_file *s = file->private_data;
  603. struct nb7vpq904m_redriver *redriver = s->private;
  604. char buf[40];
  605. char *token_chan, *token_val, *this_buf;
  606. u8 channel, chan_mode;
  607. int ret = 0;
  608. memset(buf, 0, sizeof(buf));
  609. this_buf = buf;
  610. if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
  611. return -EFAULT;
  612. if (isdigit(buf[0])) {
  613. ret = config_func(redriver, CHANNEL_NUM, -1, buf[0] - '0');
  614. if (ret < 0)
  615. goto err;
  616. } else if (isalpha(buf[0])) {
  617. while ((token_chan = strsep(&this_buf, " ")) != NULL) {
  618. switch (*token_chan) {
  619. case 'A':
  620. case 'B':
  621. case 'C':
  622. case 'D':
  623. channel = *token_chan - 'A';
  624. chan_mode = CHAN_MODE_USB;
  625. token_val = strsep(&this_buf, " ");
  626. if (!isdigit(*token_val))
  627. goto err;
  628. break;
  629. case 'a':
  630. case 'b':
  631. case 'c':
  632. case 'd':
  633. channel = *token_chan - 'a';
  634. chan_mode = CHAN_MODE_DP;
  635. token_val = strsep(&this_buf, " ");
  636. if (!isdigit(*token_val))
  637. goto err;
  638. break;
  639. default:
  640. goto err;
  641. }
  642. ret = config_func(redriver, channel, chan_mode,
  643. *token_val - '0');
  644. if (ret < 0)
  645. goto err;
  646. }
  647. } else
  648. goto err;
  649. return count;
  650. err:
  651. pr_err("Used to config redriver A/B/C/D channels' parameters\n"
  652. "A/B/C/D represent for re-driver parameters for USB\n"
  653. "a/b/c/d represent for re-driver parameters for DP\n"
  654. "1. Set all channels to same value(both USB and DP)\n"
  655. "echo n > [eq|output_comp|flat_gain|loss_match]\n"
  656. "- eq: Equalization, range 0-7\n"
  657. "- output_comp: Output Compression, range 0-3\n"
  658. "- loss_match: LOSS Profile Matching, range 0-3\n"
  659. "- flat_gain: Flat Gain, range 0-3\n"
  660. "Example: Set all channels to same EQ value\n"
  661. "echo 1 > eq\n"
  662. "2. Set two channels to different values leave others unchanged\n"
  663. "echo [A|B|C|D] n [A|B|C|D] n > [eq|output_comp|flat_gain|loss_match]\n"
  664. "Example2: USB mode: set channel B flat gain to 2, set channel C flat gain to 3\n"
  665. "echo B 2 C 3 > flat_gain\n"
  666. "Example3: DP mode: set channel A equalization to 6, set channel B equalization to 4\n"
  667. "echo a 6 b 4 > eq\n");
  668. return -EFAULT;
  669. }
  670. static int eq_status(struct seq_file *s, void *p)
  671. {
  672. struct nb7vpq904m_redriver *redriver = s->private;
  673. seq_puts(s, "\t\t\t A(USB)\t B(USB)\t C(USB)\t D(USB)\t"
  674. "A(DP)\t B(DP)\t C(DP)\t D(DP)\n");
  675. seq_printf(s, "Equalization:\t\t %d\t %d\t %d\t %d\t"
  676. "%d\t %d\t %d\t %d\n",
  677. redriver->eq[CHAN_MODE_USB][CHNA_INDEX],
  678. redriver->eq[CHAN_MODE_USB][CHNB_INDEX],
  679. redriver->eq[CHAN_MODE_USB][CHNC_INDEX],
  680. redriver->eq[CHAN_MODE_USB][CHND_INDEX],
  681. redriver->eq[CHAN_MODE_DP][CHNA_INDEX],
  682. redriver->eq[CHAN_MODE_DP][CHNB_INDEX],
  683. redriver->eq[CHAN_MODE_DP][CHNC_INDEX],
  684. redriver->eq[CHAN_MODE_DP][CHND_INDEX]);
  685. return 0;
  686. }
  687. static int eq_status_open(struct inode *inode,
  688. struct file *file)
  689. {
  690. return single_open(file, eq_status, inode->i_private);
  691. }
  692. static ssize_t eq_write(struct file *file,
  693. const char __user *ubuf, size_t count, loff_t *ppos)
  694. {
  695. return channel_config_write(file, ubuf, count, ppos,
  696. nb7vpq904m_eq_config);
  697. }
  698. static const struct file_operations eq_ops = {
  699. .open = eq_status_open,
  700. .read = seq_read,
  701. .write = eq_write,
  702. };
  703. static int flat_gain_status(struct seq_file *s, void *p)
  704. {
  705. struct nb7vpq904m_redriver *redriver = s->private;
  706. seq_puts(s, "\t\t\t A(USB)\t B(USB)\t C(USB)\t D(USB)\t"
  707. "A(DP)\t B(DP)\t C(DP)\t D(DP)\n");
  708. seq_printf(s, "TX/RX Flat Gain:\t %d\t %d\t %d\t %d\t"
  709. "%d\t %d\t %d\t %d\n",
  710. redriver->flat_gain[CHAN_MODE_USB][CHNA_INDEX],
  711. redriver->flat_gain[CHAN_MODE_USB][CHNB_INDEX],
  712. redriver->flat_gain[CHAN_MODE_USB][CHNC_INDEX],
  713. redriver->flat_gain[CHAN_MODE_USB][CHND_INDEX],
  714. redriver->flat_gain[CHAN_MODE_DP][CHNA_INDEX],
  715. redriver->flat_gain[CHAN_MODE_DP][CHNB_INDEX],
  716. redriver->flat_gain[CHAN_MODE_DP][CHNC_INDEX],
  717. redriver->flat_gain[CHAN_MODE_DP][CHND_INDEX]);
  718. return 0;
  719. }
  720. static int flat_gain_status_open(struct inode *inode,
  721. struct file *file)
  722. {
  723. return single_open(file, flat_gain_status, inode->i_private);
  724. }
  725. static ssize_t flat_gain_write(struct file *file,
  726. const char __user *ubuf, size_t count, loff_t *ppos)
  727. {
  728. return channel_config_write(file, ubuf, count, ppos,
  729. nb7vpq904m_flat_gain_config);
  730. }
  731. static const struct file_operations flat_gain_ops = {
  732. .open = flat_gain_status_open,
  733. .read = seq_read,
  734. .write = flat_gain_write,
  735. };
  736. static int output_comp_status(struct seq_file *s, void *p)
  737. {
  738. struct nb7vpq904m_redriver *redriver = s->private;
  739. seq_puts(s, "\t\t\t A(USB)\t B(USB)\t C(USB)\t D(USB)\t"
  740. "A(DP)\t B(DP)\t C(DP)\t D(DP)\n");
  741. seq_printf(s, "Output Compression:\t %d\t %d\t %d\t %d\t"
  742. "%d\t %d\t %d\t %d\n",
  743. redriver->output_comp[CHAN_MODE_USB][CHNA_INDEX],
  744. redriver->output_comp[CHAN_MODE_USB][CHNB_INDEX],
  745. redriver->output_comp[CHAN_MODE_USB][CHNC_INDEX],
  746. redriver->output_comp[CHAN_MODE_USB][CHND_INDEX],
  747. redriver->output_comp[CHAN_MODE_DP][CHNA_INDEX],
  748. redriver->output_comp[CHAN_MODE_DP][CHNB_INDEX],
  749. redriver->output_comp[CHAN_MODE_DP][CHNC_INDEX],
  750. redriver->output_comp[CHAN_MODE_DP][CHND_INDEX]);
  751. return 0;
  752. }
  753. static int output_comp_status_open(struct inode *inode,
  754. struct file *file)
  755. {
  756. return single_open(file, output_comp_status, inode->i_private);
  757. }
  758. static ssize_t output_comp_write(struct file *file,
  759. const char __user *ubuf, size_t count, loff_t *ppos)
  760. {
  761. return channel_config_write(file, ubuf, count, ppos,
  762. nb7vpq904m_output_comp_config);
  763. }
  764. static const struct file_operations output_comp_ops = {
  765. .open = output_comp_status_open,
  766. .read = seq_read,
  767. .write = output_comp_write,
  768. };
  769. static int loss_match_status(struct seq_file *s, void *p)
  770. {
  771. struct nb7vpq904m_redriver *redriver = s->private;
  772. seq_puts(s, "\t\t\t A(USB)\t B(USB)\t C(USB)\t D(USB)\t"
  773. "A(DP)\t B(DP)\t C(DP)\t D(DP)\n");
  774. seq_printf(s, "Loss Profile Match:\t %d\t %d\t %d\t %d\t"
  775. "%d\t %d\t %d\t %d\n",
  776. redriver->loss_match[CHAN_MODE_USB][CHNA_INDEX],
  777. redriver->loss_match[CHAN_MODE_USB][CHNB_INDEX],
  778. redriver->loss_match[CHAN_MODE_USB][CHNC_INDEX],
  779. redriver->loss_match[CHAN_MODE_USB][CHND_INDEX],
  780. redriver->loss_match[CHAN_MODE_DP][CHNA_INDEX],
  781. redriver->loss_match[CHAN_MODE_DP][CHNB_INDEX],
  782. redriver->loss_match[CHAN_MODE_DP][CHNC_INDEX],
  783. redriver->loss_match[CHAN_MODE_DP][CHND_INDEX]);
  784. return 0;
  785. }
  786. static int loss_match_status_open(struct inode *inode,
  787. struct file *file)
  788. {
  789. return single_open(file, loss_match_status, inode->i_private);
  790. }
  791. static ssize_t loss_match_write(struct file *file,
  792. const char __user *ubuf, size_t count, loff_t *ppos)
  793. {
  794. return channel_config_write(file, ubuf, count, ppos,
  795. nb7vpq904m_loss_match_config);
  796. }
  797. static const struct file_operations loss_match_ops = {
  798. .open = loss_match_status_open,
  799. .read = seq_read,
  800. .write = loss_match_write,
  801. };
  802. static void nb7vpq904m_debugfs_entries(
  803. struct nb7vpq904m_redriver *redriver)
  804. {
  805. redriver->debug_root = debugfs_create_dir("nb7vpq904m_redriver", NULL);
  806. if (!redriver->debug_root) {
  807. dev_warn(redriver->dev, "Couldn't create debug dir\n");
  808. return;
  809. }
  810. debugfs_create_file("eq", 0600,
  811. redriver->debug_root, redriver, &eq_ops);
  812. debugfs_create_file("flat_gain", 0600,
  813. redriver->debug_root, redriver, &flat_gain_ops);
  814. debugfs_create_file("output_comp", 0600,
  815. redriver->debug_root, redriver, &output_comp_ops);
  816. debugfs_create_file("loss_match", 0600,
  817. redriver->debug_root, redriver, &loss_match_ops);
  818. debugfs_create_bool("lane-channel-swap", 0644,
  819. redriver->debug_root, &redriver->lane_channel_swap);
  820. }
  821. static void nb7vpq904m_shutdown(struct i2c_client *client)
  822. {
  823. struct nb7vpq904m_redriver *redriver = i2c_get_clientdata(client);
  824. int ret;
  825. /* Set back to USB mode with four channel enabled */
  826. ret = nb7vpq904m_reg_set(redriver, GEN_DEV_SET_REG,
  827. GEN_DEV_SET_REG_DEFAULT);
  828. if (ret < 0)
  829. dev_err(&client->dev,
  830. "%s: fail to set USB mode with 4 channel enabled.\n",
  831. __func__);
  832. else
  833. dev_dbg(&client->dev,
  834. "%s: successfully set back to USB mode.\n",
  835. __func__);
  836. }
  837. static const struct of_device_id nb7vpq904m_match_table[] = {
  838. { .compatible = "onnn,redriver" },
  839. { }
  840. };
  841. static struct i2c_driver nb7vpq904m_driver = {
  842. .driver = {
  843. .name = "ssusb-redriver",
  844. .of_match_table = nb7vpq904m_match_table,
  845. },
  846. .probe = nb7vpq904m_probe,
  847. .remove = nb7vpq904m_remove,
  848. .shutdown = nb7vpq904m_shutdown,
  849. };
  850. module_i2c_driver(nb7vpq904m_driver);
  851. MODULE_DESCRIPTION("USB Super Speed Linear Re-Driver");
  852. MODULE_LICENSE("GPL");