spi_slave.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein
  5. * is confidential and proprietary to MediaTek Inc. and/or its licensors.
  6. * Without the prior written permission of MediaTek inc. and/or its licensors,
  7. * any reproduction, modification, use or disclosure of MediaTek Software,
  8. * and information contained herein, in whole or in part, shall be strictly prohibited.
  9. */
  10. /* MediaTek Inc. (C) 2021. All rights reserved.
  11. *
  12. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  13. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  14. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER ON
  15. * AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
  18. * NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
  19. * SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
  20. * SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES TO LOOK ONLY TO SUCH
  21. * THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. RECEIVER EXPRESSLY ACKNOWLEDGES
  22. * THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES
  23. * CONTAINED IN MEDIATEK SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK
  24. * SOFTWARE RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  25. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND
  26. * CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
  27. * AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
  28. * OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY RECEIVER TO
  29. * MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  30. */
  31. #include "spi.h"
  32. #include "spi_slave.h"
  33. #include <platform/mt_gpio.h>
  34. #include <malloc.h>
  35. #include <bits.h>
  36. #include <libfdt.h>
  37. #include <lk_builtin_dtb.h>
  38. #include <kernel/mutex.h>
  39. /*
  40. * SPI command description.
  41. */
  42. #define CMD_PWOFF 0x02 /* Power Off */
  43. #define CMD_PWON 0x04 /* Power On */
  44. #define CMD_RS 0x06 /* Read Status */
  45. #define CMD_WS 0x08 /* Write Status */
  46. #define CMD_CR 0x0a /* Config Read */
  47. #define CMD_CW 0x0c /* Config Write */
  48. #define CMD_RD 0x81 /* Read Data */
  49. #define CMD_WD 0x0e /* Write Data */
  50. #define CMD_CT 0x10 /* Config Type */
  51. /*
  52. * SPI slave status register (to master).
  53. */
  54. #define SLV_ON BIT(0)
  55. #define SR_CFG_SUCCESS BIT(1)
  56. #define SR_TXRX_FIFO_RDY BIT(2)
  57. #define SR_RD_ERR BIT(3)
  58. #define SR_WR_ERR BIT(4)
  59. #define SR_RDWR_FINISH BIT(5)
  60. #define SR_TIMEOUT_ERR BIT(6)
  61. #define SR_CMD_ERR BIT(7)
  62. #define CONFIG_READY ((SR_CFG_SUCCESS | SR_TXRX_FIFO_RDY))
  63. /*
  64. * hardware limit for once transfter.
  65. */
  66. #define MTK_SPI_BUFSIZ 32
  67. #define MAX_SPI_XFER_SIZE_ONCE (64 * 1024 - 1)
  68. #define MAX_SPI_TRY_CNT (5)
  69. #define SPI_READ true
  70. #define SPI_WRITE false
  71. #define SPI_READ_STA_ERR_RET (1)
  72. /*
  73. * spi slave config
  74. */
  75. #define IOCFG_BASE_ADDR 0x00005000
  76. #define DRV_CFG0 (IOCFG_BASE_ADDR + 0x0)
  77. #define SPIS_SLVO_MASK (0x7 << 21)
  78. #define SPISLV_BASE_ADDR 0x00002000
  79. #define SPISLV_CTRL (SPISLV_BASE_ADDR + 0x0)
  80. #define EARLY_TRANS_MASK (0x1 << 16)
  81. static int spi_bus_num;
  82. /* specific SPI data */
  83. struct mtk_spi_slave_data {
  84. u32 tx_speed_hz;
  85. u32 rx_speed_hz;
  86. u8 slave_drive_strength;
  87. u8 high_speed_tick_delay;
  88. u8 low_speed_tick_delay;
  89. u8 high_speed_early_trans;
  90. u8 low_speed_early_trans;
  91. /* mutex for SPI Slave IO */
  92. struct mutex spislv_mutex;
  93. };
  94. static struct mtk_spi_slave_data slv_data = {
  95. .tx_speed_hz = SPI_TX_LOW_SPEED_HZ,
  96. .rx_speed_hz = SPI_RX_LOW_SPEED_HZ,
  97. .slave_drive_strength = 0,
  98. .high_speed_tick_delay = 0,
  99. .low_speed_tick_delay = 0,
  100. .high_speed_early_trans = 0,
  101. .low_speed_early_trans = 0,
  102. };
  103. struct mtk_spi_bus_config spislv_chip_info = {
  104. .spi_mode = 0,
  105. .tick_delay = 0,
  106. };
  107. static u8 cmd_trans_type_4byte_single[2] = {CMD_CT, 0x04};
  108. static u8 tx_cmd_read_sta[2] = {CMD_RS, 0x00};
  109. static u8 rx_cmd_read_sta[2] = {0x00, 0x00};
  110. static struct spi_transfer CT_TRANSFER = {0};
  111. static struct spi_transfer RS_TRANSFER = {0};
  112. static int spislv_sync_sub(u32 addr, void *val, u32 len, bool is_read)
  113. {
  114. int ret = 0, i = 0;
  115. struct spi_transfer x[3];/* CW/CR, WD/RD, WS */
  116. void *local_buf = NULL;
  117. u8 mtk_spi_buffer[MTK_SPI_BUFSIZ];
  118. u8 cmd_write_sta[2] = {CMD_WS, 0xff};
  119. u8 status = 0;
  120. u32 retry = 0;
  121. u8 cmd_config[9] = {0};
  122. memset(x, 0, sizeof(x));
  123. /* CR or CW */
  124. if (is_read)
  125. cmd_config[0] = CMD_CR;
  126. else
  127. cmd_config[0] = CMD_CW;
  128. for (i = 0; i < 4; i++) {
  129. cmd_config[1 + i] = (addr & (0xff << (i * 8))) >> (i * 8);
  130. cmd_config[5 + i] = ((len - 1) & (0xff << (i * 8))) >> (i * 8);
  131. }
  132. x[0].tx_buf = cmd_config;
  133. x[0].len = ARRAY_SIZE(cmd_config);
  134. x[0].speed_hz = slv_data.tx_speed_hz;
  135. x[0].cs_change = 1;
  136. x[0].tick_delay = spislv_chip_info.tick_delay;
  137. ret = spi_sync(spi_bus_num, x);
  138. if (ret)
  139. goto tail;
  140. /* RS */
  141. rx_cmd_read_sta[1] = 0;
  142. RS_TRANSFER.tick_delay = spislv_chip_info.tick_delay;
  143. ret = spi_sync(spi_bus_num, &RS_TRANSFER);
  144. if (ret)
  145. goto tail;
  146. status = rx_cmd_read_sta[1];
  147. /* ignore status for set early transfer bit */
  148. if (addr == SPISLV_CTRL && !is_read)
  149. status = 0x6;
  150. if ((status & CONFIG_READY) != CONFIG_READY) {
  151. dprintf(CRITICAL, "SPI config %s but status error: 0x%x, latched by %dHZ, err addr: 0x%x\n",
  152. is_read ? "read" : "write", status, slv_data.rx_speed_hz, addr);
  153. ret = SPI_READ_STA_ERR_RET;
  154. goto tail;
  155. }
  156. /* RD or WD */
  157. if (len > MTK_SPI_BUFSIZ - 1) {
  158. local_buf = malloc(len + 1);
  159. if (!local_buf) {
  160. dprintf(CRITICAL, "[spislv]local buf malloc fail\n");
  161. goto tail;
  162. }
  163. } else {
  164. local_buf = mtk_spi_buffer;
  165. memset(local_buf, 0, MTK_SPI_BUFSIZ);
  166. }
  167. if (is_read) {
  168. *((u8 *)local_buf) = CMD_RD;
  169. x[1].tx_buf = local_buf;
  170. x[1].rx_buf = local_buf;
  171. x[1].speed_hz = slv_data.rx_speed_hz;
  172. } else {
  173. *((u8 *)local_buf) = CMD_WD;
  174. memcpy((u8 *)local_buf + 1, val, len);
  175. x[1].tx_buf = local_buf;
  176. x[1].speed_hz = slv_data.tx_speed_hz;
  177. }
  178. x[1].len = len + 1;
  179. x[1].cs_change = 1;
  180. x[1].tick_delay = spislv_chip_info.tick_delay;
  181. ret = spi_sync(spi_bus_num, x+1);
  182. if (ret)
  183. goto tail;
  184. /* RS */
  185. rx_cmd_read_sta[1] = 0;
  186. RS_TRANSFER.tick_delay = spislv_chip_info.tick_delay;
  187. ret = spi_sync(spi_bus_num, &RS_TRANSFER);
  188. if (ret)
  189. goto tail;
  190. status = rx_cmd_read_sta[1];
  191. /* ignore status for set early transfer bit */
  192. if (addr == SPISLV_CTRL && !is_read)
  193. status = 0x26;
  194. if (((status & SR_RD_ERR) == SR_RD_ERR) ||
  195. ((status & SR_WR_ERR) == SR_WR_ERR) ||
  196. ((status & SR_TIMEOUT_ERR) == SR_TIMEOUT_ERR)) {
  197. dprintf(CRITICAL, "SPI %s error, status: 0x%x, latched by %dHZ, err addr: 0x%x\n",
  198. is_read ? "read" : "write", status, slv_data.rx_speed_hz, addr);
  199. /* WS */
  200. x[2].tx_buf = cmd_write_sta;
  201. x[2].len = ARRAY_SIZE(cmd_write_sta);
  202. x[2].speed_hz = slv_data.tx_speed_hz;
  203. x[2].cs_change = 1;
  204. x[2].tick_delay = spislv_chip_info.tick_delay;
  205. ret = spi_sync(spi_bus_num, x+2);
  206. if (ret)
  207. goto tail;
  208. ret = SPI_READ_STA_ERR_RET;
  209. } else {
  210. while (((status & SR_RDWR_FINISH) != SR_RDWR_FINISH)) {
  211. dprintf(CRITICAL, "SPI %s not finish, status: 0x%x, latched by %dHZ, err addr: 0x%x, polling: %d\n",
  212. is_read ? "read" : "write",
  213. status, slv_data.rx_speed_hz, addr, retry);
  214. if (retry++ >= MAX_SPI_TRY_CNT) {
  215. ret = SPI_READ_STA_ERR_RET;
  216. goto tail;
  217. }
  218. mdelay(1);
  219. /* RS */
  220. rx_cmd_read_sta[1] = 0;
  221. RS_TRANSFER.tick_delay = spislv_chip_info.tick_delay;
  222. ret = spi_sync(spi_bus_num, &RS_TRANSFER);
  223. if (ret)
  224. goto tail;
  225. status = rx_cmd_read_sta[1];
  226. }
  227. }
  228. tail:
  229. /* Only for successful read */
  230. if (is_read && !ret)
  231. memcpy(val, ((u8 *)x[1].rx_buf + 1), len);
  232. if (local_buf != mtk_spi_buffer)
  233. free(local_buf);
  234. return ret;
  235. }
  236. static int spislv_sync(u32 addr, void *val, u32 len, bool is_read)
  237. {
  238. int ret = 0;
  239. u32 addr_local = addr;
  240. void *val_local = val;
  241. u32 len_local = len;
  242. u32 try = 0;
  243. mutex_acquire(&slv_data.spislv_mutex);
  244. if (len_local < MAX_SPI_XFER_SIZE_ONCE)
  245. goto transfer_drect;
  246. while (len_local > MAX_SPI_XFER_SIZE_ONCE) {
  247. ret = spislv_sync_sub(addr_local, val_local, MAX_SPI_XFER_SIZE_ONCE, is_read);
  248. while (ret) {
  249. dprintf(CRITICAL, "spi slave error, addr: 0x%x, ret(%d), retry: %d\n",
  250. addr_local, ret, try);
  251. if (try++ == MAX_SPI_TRY_CNT)
  252. goto tail;
  253. ret = spislv_sync_sub(addr_local, val_local,
  254. MAX_SPI_XFER_SIZE_ONCE, is_read);
  255. }
  256. addr_local = addr_local + MAX_SPI_XFER_SIZE_ONCE;
  257. val_local = (u8 *)val_local + MAX_SPI_XFER_SIZE_ONCE;
  258. len_local = len_local - MAX_SPI_XFER_SIZE_ONCE;
  259. }
  260. transfer_drect:
  261. try = 0;
  262. ret = spislv_sync_sub(addr_local, val_local, len_local, is_read);
  263. while (ret) {
  264. dprintf(CRITICAL, "spi slave error, addr: 0x%x, ret(%d), retry: %d\n",
  265. addr_local, ret, try);
  266. if (try++ == MAX_SPI_TRY_CNT)
  267. goto tail;
  268. ret = spislv_sync_sub(addr_local, val_local, len_local, is_read);
  269. }
  270. tail:
  271. mutex_release(&slv_data.spislv_mutex);
  272. return ret;
  273. }
  274. static u8 tick_window_early_0[8];
  275. static u8 tick_window_early_0_len;
  276. static u8 tick_window_early_1[8];
  277. static u8 tick_window_early_1_len;
  278. static u8 spislv_select_tick_delay(u8 *tick_delay_window, u8 win_len)
  279. {
  280. u8 index = 0, win_start = 0, tick_delay = 0;
  281. for (index = 0; index < 8; index ++) {
  282. if (tick_delay_window[index] == 1) {
  283. win_start = index;
  284. break;
  285. }
  286. }
  287. if (win_len % 2)
  288. tick_delay = win_start + (win_len-1)/2;
  289. else
  290. tick_delay = win_start + win_len/2;
  291. if (tick_delay_window[tick_delay] == 1)
  292. return tick_delay;
  293. else
  294. return win_start;
  295. }
  296. static u32 spislv_test(u32 tx_speed_hz, u32 rx_speed_hz, u32 tick_delay)
  297. {
  298. int i, ret = 0;
  299. u32 addr = 0x00002000;
  300. u32 len = 4;
  301. u8 cmd_config[] = {
  302. CMD_CR, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,};
  303. u8 tx_cmd_read_sta[2] = {CMD_RS, 0x00};
  304. u8 rx_cmd_read_sta[2] = {0};
  305. u8 read_status;
  306. struct spi_transfer x[2];
  307. memset(x, 0, sizeof(x));
  308. for (i = 0; i < 4; i++) {
  309. cmd_config[1 + i] = (addr & (0xff << (i * 8))) >> (i * 8);
  310. cmd_config[5 + i] = ((len - 1) & (0xff << (i * 8))) >> (i * 8);
  311. }
  312. x[0].tx_buf = cmd_config;
  313. x[0].len = ARRAY_SIZE(cmd_config);
  314. x[0].speed_hz = tx_speed_hz;
  315. x[0].cs_change = 1;
  316. x[0].tick_delay = tick_delay;
  317. ret = spi_sync(spi_bus_num, x);
  318. if (ret)
  319. goto tail;
  320. x[1].tx_buf = tx_cmd_read_sta;
  321. x[1].rx_buf = rx_cmd_read_sta;
  322. x[1].len = ARRAY_SIZE(tx_cmd_read_sta);
  323. x[1].speed_hz = rx_speed_hz;
  324. x[1].cs_change = 1;
  325. x[1].tick_delay = tick_delay;
  326. ret = spi_sync(spi_bus_num, x+1);
  327. if (ret)
  328. goto tail;
  329. read_status = rx_cmd_read_sta[1];
  330. if ((read_status & CONFIG_READY) != CONFIG_READY)
  331. return 0;
  332. else
  333. return 1;
  334. tail:
  335. if (ret)
  336. dprintf(CRITICAL, "error: spi sync err: %d\n", ret);
  337. return 0;
  338. }
  339. static void spislv_autok(u32 tx_speed_hz, u32 rx_speed_hz)
  340. {
  341. u32 index;
  342. u8 early_trans, tick_delay;
  343. tick_window_early_0_len = 0;
  344. tick_window_early_1_len = 0;
  345. dprintf(CRITICAL, "[spislv] write: %dHz, read: %dHz, autok window:\n",
  346. tx_speed_hz, rx_speed_hz);
  347. /* set early_trans: 0 */
  348. spislv_write_register(SPISLV_CTRL,
  349. (0x40 & (~(EARLY_TRANS_MASK))) | ((0 << 16) & (EARLY_TRANS_MASK)));
  350. /* scan window */
  351. for (index = 0; index < 8; index ++) {
  352. if (spislv_test(tx_speed_hz, rx_speed_hz, index)) {
  353. tick_window_early_0[index] = 1;
  354. tick_window_early_0_len ++;
  355. } else
  356. tick_window_early_0[index] = 0;
  357. }
  358. for (index = 0; index < 8; index ++) {
  359. dprintf(CRITICAL, "[spislv] autok: early_trans: 0, tick_delay: %d, window: %s\n",
  360. index, tick_window_early_0[index] == 1 ? "O" : "X");
  361. }
  362. /* set early_trans: 1 */
  363. spislv_write_register(SPISLV_CTRL,
  364. (0x40 & (~(EARLY_TRANS_MASK))) | ((1 << 16) & (EARLY_TRANS_MASK)));
  365. /* scan window */
  366. for (index = 0; index < 8; index ++) {
  367. if (spislv_test(SPI_TX_LOW_SPEED_HZ, SPI_RX_LOW_SPEED_HZ, index)) {
  368. tick_window_early_1[index] = 1;
  369. tick_window_early_1_len++;
  370. } else
  371. tick_window_early_1[index] = 0;
  372. }
  373. for (index = 0; index < 8; index ++) {
  374. dprintf(CRITICAL, "[spislv] autok: early_trans: 1, tick_delay: %d, window: %s\n",
  375. index, tick_window_early_1[index] == 1 ? "O" : "X");
  376. }
  377. if (tick_window_early_0_len > tick_window_early_1_len) {
  378. early_trans = 0;
  379. tick_delay = spislv_select_tick_delay
  380. (tick_window_early_0, tick_window_early_0_len);
  381. } else {
  382. early_trans = 1;
  383. tick_delay = spislv_select_tick_delay
  384. (tick_window_early_1, tick_window_early_1_len);
  385. }
  386. if (rx_speed_hz >= SPI_RX_MAX_SPEED_HZ) {
  387. slv_data.high_speed_early_trans = early_trans;
  388. slv_data.high_speed_tick_delay = tick_delay;
  389. dprintf(CRITICAL, "[spislv] autok result: high_speed_early_trans: %d, high_speed_tick_delay: %d\n",
  390. slv_data.high_speed_early_trans, slv_data.high_speed_tick_delay);
  391. } else {
  392. slv_data.low_speed_early_trans = early_trans;
  393. slv_data.low_speed_tick_delay = tick_delay;
  394. dprintf(CRITICAL, "[spislv] autok low_speed_early_trans: %d, low_speed_tick_delay: %d\n",
  395. slv_data.low_speed_early_trans, slv_data.low_speed_tick_delay);
  396. }
  397. }
  398. static void spislv_fdt_getprop_u32_array(void *lk_drv_fdt, int nodeoffset,
  399. const char *name, unsigned int *out_value)
  400. {
  401. int i;
  402. u32 *data = NULL;
  403. int len = 0;
  404. data = (unsigned int *)fdt_getprop(lk_drv_fdt, nodeoffset, name, &len);
  405. if (len > 0 && data) {
  406. len = len / sizeof(unsigned int);
  407. for (i = 0; i < len; i++)
  408. *(out_value+i) = fdt32_to_cpu(*(data+i));
  409. } else
  410. *out_value = 0;
  411. }
  412. int spislv_write_param_to_dt(void *fdt)
  413. {
  414. int node = 0;
  415. int ret = 0;
  416. void *kernel_fdt = fdt;
  417. if (kernel_fdt == NULL)
  418. panic("kernel_fdt fdt is NULL!\n");
  419. node = fdt_node_offset_by_compatible(kernel_fdt, -1, "mediatek,spi_slave");
  420. if (node <= 0) {
  421. dprintf(CRITICAL, "[spislv] spi slave dts node is not set, just skip.\n");
  422. return 0;
  423. }
  424. ret = fdt_setprop(kernel_fdt, node, "high-speed-tick-delay", &slv_data.high_speed_tick_delay, 1);
  425. if (ret) {
  426. dprintf(CRITICAL, "[spislv] spislv_write_param_to_dt err\n");
  427. return ret;
  428. }
  429. ret = fdt_setprop(kernel_fdt, node, "high-speed-early-trans", &slv_data.high_speed_early_trans, 1);
  430. if (ret) {
  431. dprintf(CRITICAL, "[spislv] spislv_write_param_to_dt err\n");
  432. return ret;
  433. }
  434. ret = fdt_setprop(kernel_fdt, node, "low-speed-tick-delay", &slv_data.low_speed_tick_delay, 1);
  435. if (ret) {
  436. dprintf(CRITICAL, "[spislv] spislv_write_param_to_dt err\n");
  437. return ret;
  438. }
  439. ret = fdt_setprop(kernel_fdt, node, "low-speed-early-trans", &slv_data.low_speed_early_trans, 1);
  440. if (ret) {
  441. dprintf(CRITICAL, "[spislv] spislv_write_param_to_dt err\n");
  442. return ret;
  443. }
  444. return ret;
  445. }
  446. int spislv_write(u32 addr, void *val, u32 len)
  447. {
  448. return spislv_sync(addr, val, len, 0);
  449. }
  450. int spislv_read(u32 addr, void *val, u32 len)
  451. {
  452. return spislv_sync(addr, val, len, 1);
  453. }
  454. int spislv_read_register(u32 addr, u32 *val)
  455. {
  456. return spislv_read(addr, (u8 *)val, 4);
  457. }
  458. int spislv_write_register(u32 addr, u32 val)
  459. {
  460. return spislv_write(addr, (u8 *)&val, 4);
  461. }
  462. int spislv_write_register_mask(u32 addr, u32 val, u32 msk)
  463. {
  464. u32 ret = 0;
  465. u32 read_val;
  466. ret = spislv_read_register(addr, &read_val);
  467. if (ret)
  468. return ret;
  469. ret = spislv_write_register(addr, ((read_val & (~(msk))) | ((val) & (msk))));
  470. return ret;
  471. }
  472. int spislv_switch_speed_hz(u32 tx_speed_hz, u32 rx_speed_hz)
  473. {
  474. int ret = 0;
  475. if (rx_speed_hz >= SPI_RX_MAX_SPEED_HZ) {
  476. spislv_autok(tx_speed_hz, rx_speed_hz);
  477. ret = spislv_write_register(SPISLV_CTRL, (0x40 & (~(EARLY_TRANS_MASK)))
  478. | ((slv_data.high_speed_early_trans << 16) & (EARLY_TRANS_MASK)));
  479. spislv_chip_info.tick_delay = slv_data.high_speed_tick_delay;
  480. } else {
  481. /* needn't autok low speed because did when init */
  482. ret = spislv_write_register(SPISLV_CTRL, (0x40 & (~(EARLY_TRANS_MASK)))
  483. | ((slv_data.low_speed_early_trans << 16) & (EARLY_TRANS_MASK)));
  484. spislv_chip_info.tick_delay = slv_data.low_speed_tick_delay;
  485. }
  486. slv_data.tx_speed_hz =
  487. (tx_speed_hz > SPI_TX_MAX_SPEED_HZ ? SPI_TX_MAX_SPEED_HZ : tx_speed_hz);
  488. slv_data.rx_speed_hz =
  489. (rx_speed_hz > SPI_RX_MAX_SPEED_HZ ? SPI_RX_MAX_SPEED_HZ : rx_speed_hz);
  490. RS_TRANSFER.speed_hz = slv_data.rx_speed_hz;
  491. return ret;
  492. }
  493. int spislv_init(void)
  494. {
  495. int ret = 0;
  496. slv_data.tx_speed_hz = SPI_TX_LOW_SPEED_HZ;
  497. slv_data.rx_speed_hz = SPI_RX_LOW_SPEED_HZ;
  498. RS_TRANSFER.speed_hz = slv_data.rx_speed_hz;
  499. ret = spi_sync(spi_bus_num, &CT_TRANSFER);
  500. if (ret)
  501. return ret;
  502. /* autok before spi read in low speed */
  503. spislv_autok(SPI_TX_LOW_SPEED_HZ, SPI_RX_LOW_SPEED_HZ);
  504. spislv_chip_info.tick_delay = slv_data.low_speed_tick_delay;
  505. ret = spislv_write_register(SPISLV_CTRL,
  506. (0x40 & (~(EARLY_TRANS_MASK))) | ((slv_data.low_speed_early_trans << 16) & (EARLY_TRANS_MASK)));
  507. if (ret)
  508. return ret;
  509. ret = spislv_write_register_mask(DRV_CFG0,
  510. (slv_data.slave_drive_strength << 21), SPIS_SLVO_MASK);
  511. return ret;
  512. }
  513. /* different platforms maybe have different gpio apis, so try all. */
  514. extern S32 mt_set_gpio_drv(u32 pin, u32 drv)__attribute__((weak));
  515. extern S32 mt_set_gpio_driving(u32 pin, u32 drv)__attribute__((weak));
  516. void spi_slave_probe(void)
  517. {
  518. int node = 0, sub_node = 0, len = 0;
  519. u8 *data = NULL;
  520. u32 pin_mux[4] = {0};
  521. u32 driving;
  522. const char *spislv_compatible = "mediatek,spi_slave";
  523. void *lk_drv_fdt = NULL;
  524. lk_drv_fdt = (void *)get_lk_overlayed_dtb();
  525. if (lk_drv_fdt == NULL)
  526. panic("lk driver fdt is NULL!\n");
  527. node = fdt_node_offset_by_compatible(lk_drv_fdt, -1, spislv_compatible);
  528. if (node <= 0) {
  529. dprintf(CRITICAL, "[spislv] spi slave dts node is not set, just skip.\n");
  530. return;
  531. }
  532. spi_bus_num = init_spi_bus_from_dt(spislv_compatible, &spislv_chip_info);
  533. if (spi_bus_num < 0){
  534. return;
  535. }
  536. // needn't parse tick delay or early trans from dts because autok later
  537. data = (u8 *)fdt_getprop(lk_drv_fdt, node, "slave-drive-strength", &len);
  538. if (data) {
  539. slv_data.slave_drive_strength = *data;
  540. dprintf(CRITICAL, "[spislv]slave-drive-strength: %d\n",
  541. slv_data.slave_drive_strength);
  542. } else
  543. dprintf(CRITICAL, "[spislv]slave-drive-strength is not set\n");
  544. /* parse spi master gpio driving from dts */
  545. node = fdt_path_offset(lk_drv_fdt, "/pinctrl/spislv_mode_default");
  546. if (node <= 0)
  547. return;
  548. sub_node = fdt_first_subnode(lk_drv_fdt, node);
  549. if (sub_node <= 0)
  550. return;
  551. spislv_fdt_getprop_u32_array(lk_drv_fdt, sub_node, "pinmux", pin_mux);
  552. spislv_fdt_getprop_u32_array(lk_drv_fdt, sub_node, "drive-strength", &driving);
  553. mt_set_gpio_drv(pin_mux[0] >> 8, driving);
  554. mt_set_gpio_drv(pin_mux[1] >> 8, driving);
  555. mt_set_gpio_drv(pin_mux[2] >> 8, driving);
  556. mt_set_gpio_drv(pin_mux[3] >> 8, driving);
  557. mt_set_gpio_driving(pin_mux[0] >> 8, driving);
  558. mt_set_gpio_driving(pin_mux[1] >> 8, driving);
  559. mt_set_gpio_driving(pin_mux[2] >> 8, driving);
  560. mt_set_gpio_driving(pin_mux[3] >> 8, driving);
  561. dprintf(CRITICAL, "[spislv]pin_mux[0]: %d\n", pin_mux[0] >> 8);
  562. dprintf(CRITICAL, "[spislv]pin_mux[1]: %d\n", pin_mux[1] >> 8);
  563. dprintf(CRITICAL, "[spislv]pin_mux[2]: %d\n", pin_mux[2] >> 8);
  564. dprintf(CRITICAL, "[spislv]pin_mux[3]: %d\n", pin_mux[3] >> 8);
  565. dprintf(CRITICAL, "[spislv]drive-strength: %d\n", driving);
  566. CT_TRANSFER.tx_buf = cmd_trans_type_4byte_single;
  567. CT_TRANSFER.len = ARRAY_SIZE(cmd_trans_type_4byte_single);;
  568. CT_TRANSFER.cs_change = 1;
  569. CT_TRANSFER.speed_hz = slv_data.tx_speed_hz;
  570. CT_TRANSFER.tick_delay = spislv_chip_info.tick_delay;
  571. RS_TRANSFER.tx_buf = tx_cmd_read_sta;
  572. RS_TRANSFER.rx_buf = rx_cmd_read_sta;
  573. RS_TRANSFER.len = ARRAY_SIZE(tx_cmd_read_sta);
  574. RS_TRANSFER.cs_change = 1;
  575. RS_TRANSFER.speed_hz = slv_data.rx_speed_hz;
  576. mutex_init(&slv_data.spislv_mutex);
  577. }