mt_spi_slave.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  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 <platform/mt_spi.h>
  32. #include <platform/mt_spi_slave.h>
  33. #include <platform/mt_gpio.h>
  34. #include <malloc.h>
  35. #include <bits.h>
  36. #include <libfdt.h>
  37. /*
  38. * SPI command description.
  39. */
  40. #define CMD_PWOFF 0x02 /* Power Off */
  41. #define CMD_PWON 0x04 /* Power On */
  42. #define CMD_RS 0x06 /* Read Status */
  43. #define CMD_WS 0x08 /* Write Status */
  44. #define CMD_CR 0x0a /* Config Read */
  45. #define CMD_CW 0x0c /* Config Write */
  46. #define CMD_RD 0x81 /* Read Data */
  47. #define CMD_WD 0x0e /* Write Data */
  48. #define CMD_CT 0x10 /* Config Type */
  49. /*
  50. * SPI slave status register (to master).
  51. */
  52. #define SLV_ON BIT(0)
  53. #define SR_CFG_SUCCESS BIT(1)
  54. #define SR_TXRX_FIFO_RDY BIT(2)
  55. #define SR_RD_ERR BIT(3)
  56. #define SR_WR_ERR BIT(4)
  57. #define SR_RDWR_FINISH BIT(5)
  58. #define SR_TIMEOUT_ERR BIT(6)
  59. #define SR_CMD_ERR BIT(7)
  60. #define CONFIG_READY ((SR_CFG_SUCCESS | SR_TXRX_FIFO_RDY))
  61. /*
  62. * hardware limit for once transfter.
  63. */
  64. #define MTK_SPI_BUFSIZ 32
  65. #define MAX_SPI_XFER_SIZE_ONCE (64 * 1024 - 1)
  66. #define MAX_SPI_TRY_CNT (10)
  67. #define SPI_READ true
  68. #define SPI_WRITE false
  69. #define SPI_READ_STA_ERR_RET (1)
  70. /*
  71. * spi slave config
  72. */
  73. #define IOCFG_BASE_ADDR 0x00005000
  74. #define DRV_CFG0 (IOCFG_BASE_ADDR + 0x0)
  75. #define SPIS_SLVO_MASK (0x7 << 21)
  76. #define SPISLV_BASE_ADDR 0x00002000
  77. #define SPISLV_CTRL (SPISLV_BASE_ADDR + 0x0)
  78. #define EARLY_TRANS_MASK (0x1 << 16)
  79. static int spi_bus_num;
  80. /* specific SPI data */
  81. struct mtk_spi_slave_data {
  82. u32 tx_speed_hz;
  83. u32 rx_speed_hz;
  84. u32 addr;
  85. u32 len;
  86. void *buffer;
  87. u8 slave_drive_strength;
  88. u8 high_speed_tick_delay;
  89. u8 low_speed_tick_delay;
  90. u8 high_speed_early_trans;
  91. u8 low_speed_early_trans;
  92. bool is_read:1;
  93. };
  94. static u8 cmd_trans_type_4byte_single[2] = {CMD_CT, 0x04};
  95. static u8 tx_cmd_read_sta[2] = {CMD_RS, 0x00};
  96. static u8 rx_cmd_read_sta[2] = {0x00, 0x00};
  97. static struct spi_transfer CT_TRANSFER = {0};
  98. static struct spi_transfer RS_TRANSFER = {0};
  99. static struct mtk_spi_slave_data slv_data = {
  100. .tx_speed_hz = SPI_TX_LOW_SPEED_HZ,
  101. .rx_speed_hz = SPI_RX_LOW_SPEED_HZ,
  102. .addr = 0,
  103. .len = 0,
  104. .buffer = NULL,
  105. .is_read = 0,
  106. .slave_drive_strength = 0,
  107. .high_speed_tick_delay = 0,
  108. .low_speed_tick_delay = 0,
  109. .high_speed_early_trans = 0,
  110. .low_speed_early_trans = 0,
  111. };
  112. struct mtk_spi_bus_config spislv_chip_info = {
  113. .spi_mode = 0,
  114. .tick_delay = 0,
  115. };
  116. static int spislv_sync_sub(void)
  117. {
  118. int ret = 0, i = 0;
  119. struct spi_transfer x[2] = {0};
  120. void *local_buf = NULL;
  121. u8 mtk_spi_buffer[MTK_SPI_BUFSIZ];
  122. u8 cmd_write_sta[2] = {CMD_WS, 0xff};
  123. u8 status = 0;
  124. u32 retry = 0;
  125. u8 cmd_config[] = {
  126. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  127. /* CR or CW */
  128. if (slv_data.is_read)
  129. cmd_config[0] = CMD_CR;
  130. else
  131. cmd_config[0] = CMD_CW;
  132. for (i = 0; i < 4; i++) {
  133. cmd_config[1 + i] = (slv_data.addr & (0xff << (i * 8)))
  134. >> (i * 8);
  135. cmd_config[5 + i] = ((slv_data.len - 1) & (0xff << (i * 8)))
  136. >> (i * 8);
  137. }
  138. x[0].tx_buf = cmd_config;
  139. x[0].len = ARRAY_SIZE(cmd_config);
  140. x[0].speed_hz = slv_data.tx_speed_hz;
  141. x[0].cs_change = 1;
  142. x[0].tick_delay = spislv_chip_info.tick_delay;
  143. ret = spi_sync(spi_bus_num, x);
  144. if (ret)
  145. goto tail;
  146. /* RS */
  147. rx_cmd_read_sta[1] = 0;
  148. RS_TRANSFER.tick_delay = spislv_chip_info.tick_delay;
  149. ret = spi_sync(spi_bus_num, &RS_TRANSFER);
  150. if (ret)
  151. goto tail;
  152. status = rx_cmd_read_sta[1];
  153. if ((status & CONFIG_READY) != CONFIG_READY) {
  154. dprintf(CRITICAL, "SPI config %s status error: 0x%x, err addr: 0x%x\n",
  155. slv_data.is_read ? "read" : "write", status, slv_data.addr);
  156. ret = SPI_READ_STA_ERR_RET;
  157. goto tail;
  158. }
  159. /* RD or WD */
  160. if (slv_data.len > MTK_SPI_BUFSIZ - 1) {
  161. local_buf = malloc(slv_data.len + 1);
  162. if (!local_buf) {
  163. dprintf(CRITICAL, "[spislv]local buf malloc fail\n");
  164. goto tail;
  165. }
  166. } else {
  167. local_buf = mtk_spi_buffer;
  168. memset(local_buf, 0, MTK_SPI_BUFSIZ);
  169. }
  170. if (slv_data.is_read) {
  171. *((u8 *)local_buf) = CMD_RD;
  172. x[1].tx_buf = local_buf;
  173. x[1].rx_buf = local_buf;
  174. x[1].speed_hz = slv_data.rx_speed_hz;
  175. } else {
  176. *((u8 *)local_buf) = CMD_WD;
  177. memcpy((u8 *)local_buf + 1, slv_data.buffer, slv_data.len);
  178. x[1].tx_buf = local_buf;
  179. x[1].speed_hz = slv_data.tx_speed_hz;
  180. }
  181. x[1].len = slv_data.len + 1;
  182. x[1].cs_change = 1;
  183. x[1].tick_delay = spislv_chip_info.tick_delay;
  184. ret = spi_sync(spi_bus_num, x+1);
  185. if (ret)
  186. goto tail;
  187. /* RS */
  188. rx_cmd_read_sta[1] = 0;
  189. RS_TRANSFER.tick_delay = spislv_chip_info.tick_delay;
  190. ret = spi_sync(spi_bus_num, &RS_TRANSFER);
  191. if (ret)
  192. goto tail;
  193. status = rx_cmd_read_sta[1];
  194. /* ignore status for set early transfer bit */
  195. if (slv_data.addr == SPISLV_CTRL)
  196. status = 0x26;
  197. if (((status & SR_RD_ERR) == SR_RD_ERR) ||
  198. ((status & SR_WR_ERR) == SR_WR_ERR) ||
  199. ((status & SR_TIMEOUT_ERR) == SR_TIMEOUT_ERR)) {
  200. dprintf(CRITICAL, "SPI %s error: 0x%x, err addr: 0x%x\n",
  201. slv_data.is_read ? "read" : "write", status, slv_data.addr);
  202. /* WS */
  203. x[2].tx_buf = cmd_write_sta;
  204. x[2].len = ARRAY_SIZE(cmd_write_sta);
  205. x[2].speed_hz = slv_data.tx_speed_hz;
  206. x[2].cs_change = 1;
  207. x[2].tick_delay = spislv_chip_info.tick_delay;
  208. ret = spi_sync(spi_bus_num, x+2);
  209. if (ret)
  210. goto tail;
  211. ret = SPI_READ_STA_ERR_RET;
  212. } else {
  213. while (((status & SR_RDWR_FINISH) != SR_RDWR_FINISH)) {
  214. dprintf(CRITICAL, "SPI %s not finish: 0x%x, err addr: 0x%x, polling: %d\n",
  215. slv_data.is_read ? "read" : "write", status, slv_data.addr, retry);
  216. if (retry++ >= MAX_SPI_TRY_CNT) {
  217. ret = SPI_READ_STA_ERR_RET;
  218. goto tail;
  219. }
  220. mdelay(1);
  221. /* RS */
  222. rx_cmd_read_sta[1] = 0;
  223. RS_TRANSFER.tick_delay = spislv_chip_info.tick_delay;
  224. ret = spi_sync(spi_bus_num, &RS_TRANSFER);
  225. if (ret)
  226. goto tail;
  227. status = rx_cmd_read_sta[1];
  228. }
  229. }
  230. tail:
  231. /* Only for successful read */
  232. if (slv_data.is_read && !ret)
  233. memcpy(slv_data.buffer, ((u8 *)x[1].rx_buf + 1), slv_data.len);
  234. if (local_buf != mtk_spi_buffer)
  235. free(local_buf);
  236. return ret;
  237. }
  238. static int spislv_sync(void)
  239. {
  240. int ret = 0;
  241. int once_addr = MAX_SPI_XFER_SIZE_ONCE / 4;
  242. u32 len = 0;
  243. u32 try = 0;
  244. if (slv_data.len < MAX_SPI_XFER_SIZE_ONCE)
  245. goto transfer_drect;
  246. len = slv_data.len;
  247. while (len > MAX_SPI_XFER_SIZE_ONCE) {
  248. slv_data.len = MAX_SPI_XFER_SIZE_ONCE;
  249. ret = spislv_sync_sub();
  250. while (ret) {
  251. dprintf(CRITICAL, "spi slave error, addr: 0x%x, ret(%d), retry: %d\n",
  252. slv_data.addr, ret, try);
  253. if (try++ == MAX_SPI_TRY_CNT)
  254. goto tail;
  255. ret = spislv_sync_sub();
  256. }
  257. slv_data.addr = slv_data.addr + once_addr;
  258. slv_data.buffer = (u8 *)slv_data.buffer + MAX_SPI_XFER_SIZE_ONCE;
  259. len = len - MAX_SPI_XFER_SIZE_ONCE;
  260. }
  261. slv_data.len = len;
  262. transfer_drect:
  263. ret = spislv_sync_sub();
  264. while (ret) {
  265. dprintf(CRITICAL, "spi slave error, addr: 0x%x, ret(%d), retry: %d\n",
  266. slv_data.addr, ret, try);
  267. if (try++ == MAX_SPI_TRY_CNT)
  268. goto tail;
  269. ret = spislv_sync_sub();
  270. }
  271. tail:
  272. /* slv_data's transfer info will not be original if split. */
  273. return ret;
  274. }
  275. int spislv_init(void)
  276. {
  277. int ret = 0;
  278. spislv_chip_info.tick_delay = slv_data.low_speed_tick_delay;
  279. CT_TRANSFER.tick_delay = spislv_chip_info.tick_delay;
  280. ret = spi_sync(spi_bus_num, &CT_TRANSFER);
  281. ret = spislv_write_register_mask(SPISLV_CTRL,
  282. (slv_data.low_speed_early_trans << 16),
  283. EARLY_TRANS_MASK);
  284. if (slv_data.slave_drive_strength)
  285. ret = spislv_write_register_mask(DRV_CFG0, (0x7 << 21),
  286. SPIS_SLVO_MASK);
  287. return ret;
  288. }
  289. int spislv_switch_speed_hz(u32 tx_speed_hz, u32 rx_speed_hz)
  290. {
  291. int ret = 0;
  292. slv_data.tx_speed_hz =
  293. (tx_speed_hz > SPI_TX_MAX_SPEED_HZ ? SPI_TX_MAX_SPEED_HZ : tx_speed_hz);
  294. slv_data.rx_speed_hz =
  295. (rx_speed_hz > SPI_RX_MAX_SPEED_HZ ? SPI_RX_MAX_SPEED_HZ : rx_speed_hz);
  296. RS_TRANSFER.speed_hz = slv_data.rx_speed_hz;
  297. if (slv_data.rx_speed_hz == SPI_RX_MAX_SPEED_HZ) {
  298. spislv_chip_info.tick_delay = slv_data.high_speed_tick_delay;
  299. ret = spislv_write_register_mask(SPISLV_CTRL,
  300. (slv_data.high_speed_early_trans << 16),
  301. EARLY_TRANS_MASK);
  302. } else {
  303. spislv_chip_info.tick_delay = slv_data.low_speed_tick_delay;
  304. ret = spislv_write_register_mask(SPISLV_CTRL,
  305. (slv_data.low_speed_early_trans << 16),
  306. EARLY_TRANS_MASK);
  307. }
  308. return ret;
  309. }
  310. int spislv_write(u32 addr, void *val, int len)
  311. {
  312. slv_data.buffer = val;
  313. slv_data.addr = addr;
  314. slv_data.len = len;
  315. slv_data.is_read = 0;
  316. return spislv_sync();
  317. }
  318. int spislv_read(u32 addr, void *val, int len)
  319. {
  320. slv_data.buffer = val;
  321. slv_data.addr = addr;
  322. slv_data.len = len;
  323. slv_data.is_read = 1;
  324. return spislv_sync();
  325. }
  326. int spislv_read_register(u32 addr, u32 *val)
  327. {
  328. return spislv_read(addr, (u8 *)val, 4);
  329. }
  330. int spislv_write_register(u32 addr, u32 val)
  331. {
  332. return spislv_write(addr, (u8 *)&val, 4);
  333. }
  334. int spislv_set_register32(u32 addr, u32 val)
  335. {
  336. u32 ret = 0;
  337. u32 read_val;
  338. ret = spislv_read_register(addr, &read_val);
  339. if (ret)
  340. return ret;
  341. ret = spislv_write_register(addr, read_val | val);
  342. return ret;
  343. }
  344. int spislv_clr_register32(u32 addr, u32 val)
  345. {
  346. u32 ret = 0;
  347. u32 read_val;
  348. ret = spislv_read_register(addr, &read_val);
  349. if (ret)
  350. return ret;
  351. ret = spislv_write_register(addr, read_val & (~val));
  352. return ret;
  353. }
  354. int spislv_write_register_mask(u32 addr, u32 val, u32 msk)
  355. {
  356. u32 ret = 0;
  357. u32 read_val;
  358. ret = spislv_read_register(addr, &read_val);
  359. if (ret)
  360. return ret;
  361. ret = spislv_write_register(addr, ((read_val & (~(msk))) |
  362. ((val) & (msk))));
  363. return ret;
  364. }
  365. static void spislv_fdt_getprop_u32_array(int nodeoffset,
  366. const char *name, unsigned int *out_value)
  367. {
  368. u32 i;
  369. u32 *data = NULL;
  370. int len = 0;
  371. void *lk_drv_fdt = get_lk_overlayed_dtb();
  372. if (lk_drv_fdt == NULL)
  373. panic("lk driver fdt is NULL!\n");
  374. data = (unsigned int *)fdt_getprop(lk_drv_fdt, nodeoffset, name, &len);
  375. if (len > 0) {
  376. len = len / sizeof(unsigned int);
  377. for (i = 0; i < len; i++)
  378. *(out_value+i) = fdt32_to_cpu(*(data+i));
  379. } else
  380. *out_value = 0;
  381. }
  382. static u32 init_spislv_from_dt(const char *compatible)
  383. {
  384. u32 node = 0;
  385. u32 *data = NULL;
  386. int len = 0;
  387. struct mtk_spi_bus *bus = NULL;
  388. void *lk_drv_fdt = get_lk_overlayed_dtb();
  389. if (lk_drv_fdt == NULL)
  390. panic("lk driver fdt is NULL!\n");
  391. node = fdt_node_offset_by_compatible(lk_drv_fdt, -1, compatible);
  392. if (node < 0) {
  393. dprintf(CRITICAL, "[spislv]fdt node err: %d\n", node);
  394. return node;
  395. }
  396. data = (unsigned char *)fdt_getprop(lk_drv_fdt, node,
  397. "slave-drive-strength", &len);
  398. slv_data.slave_drive_strength = *data;
  399. data = (unsigned char *)fdt_getprop(lk_drv_fdt, node,
  400. "high-speed-tick-delay", &len);
  401. slv_data.high_speed_tick_delay = *data;
  402. data = (unsigned char *)fdt_getprop(lk_drv_fdt, node,
  403. "low-speed-tick-delay", &len);
  404. slv_data.low_speed_tick_delay = *data;
  405. data = (unsigned char *)fdt_getprop(lk_drv_fdt, node,
  406. "high-speed-early-trans", &len);
  407. slv_data.high_speed_early_trans = *data;
  408. data = (unsigned char *)fdt_getprop(lk_drv_fdt, node,
  409. "low-speed-early-trans", &len);
  410. slv_data.low_speed_early_trans = *data;
  411. dprintf(CRITICAL, "[spislv]slave-drive-strength: %d\n",
  412. slv_data.slave_drive_strength);
  413. dprintf(CRITICAL, "[spislv]high-speed-tick-delay: %d\n",
  414. slv_data.high_speed_tick_delay);
  415. dprintf(CRITICAL, "[spislv]low-speed-tick-delay: %d\n",
  416. slv_data.low_speed_tick_delay);
  417. dprintf(CRITICAL, "[spislv]high-speed-early-trans: %d\n",
  418. slv_data.high_speed_early_trans);
  419. dprintf(CRITICAL, "[spislv]low-speed-early-trans: %d\n",
  420. slv_data.low_speed_early_trans);
  421. return 0;
  422. }
  423. static void init_gpio_from_dt(const char *path)
  424. {
  425. u32 sub_node;
  426. u32 pin_mux[4];
  427. u32 driving;
  428. void *lk_drv_fdt = get_lk_overlayed_dtb();
  429. int node = fdt_path_offset(lk_drv_fdt, path);
  430. if (node > 0) {
  431. sub_node = fdt_first_subnode(lk_drv_fdt, node);
  432. if (sub_node > 0) {
  433. spislv_fdt_getprop_u32_array(sub_node,
  434. "pinmux", pin_mux);
  435. spislv_fdt_getprop_u32_array(sub_node,
  436. "drive-strength", &driving);
  437. }
  438. }
  439. dprintf(CRITICAL, "[spislv]pin_mux[0]: %d\n", pin_mux[0] >> 8);
  440. dprintf(CRITICAL, "[spislv]pin_mux[1]: %d\n", pin_mux[1] >> 8);
  441. dprintf(CRITICAL, "[spislv]pin_mux[2]: %d\n", pin_mux[2] >> 8);
  442. dprintf(CRITICAL, "[spislv]pin_mux[3]: %d\n", pin_mux[3] >> 8);
  443. dprintf(CRITICAL, "[spislv]drive-strength: %d\n", driving);
  444. mt_set_gpio_driving(pin_mux[0] >> 8, driving);
  445. mt_set_gpio_driving(pin_mux[1] >> 8, driving);
  446. mt_set_gpio_driving(pin_mux[2] >> 8, driving);
  447. mt_set_gpio_driving(pin_mux[3] >> 8, driving);
  448. }
  449. void spi_slave_probe(void)
  450. {
  451. int bus_num;
  452. const char *spislv_compatible = "mediatek,spi_slave";
  453. CT_TRANSFER.tx_buf = cmd_trans_type_4byte_single;
  454. CT_TRANSFER.len = ARRAY_SIZE(cmd_trans_type_4byte_single);;
  455. CT_TRANSFER.cs_change = 1;
  456. CT_TRANSFER.speed_hz = slv_data.tx_speed_hz;
  457. RS_TRANSFER.tx_buf = tx_cmd_read_sta;
  458. RS_TRANSFER.rx_buf = rx_cmd_read_sta;
  459. RS_TRANSFER.len = ARRAY_SIZE(tx_cmd_read_sta);
  460. RS_TRANSFER.cs_change = 1;
  461. RS_TRANSFER.speed_hz = slv_data.rx_speed_hz;
  462. init_gpio_from_dt("/pinctrl/spislv_mode_default");
  463. init_spislv_from_dt(spislv_compatible);
  464. bus_num = init_spi_bus_from_dt(spislv_compatible, &spislv_chip_info);
  465. if (bus_num >= 0)
  466. spi_bus_num = bus_num;
  467. else
  468. dprintf(CRITICAL, "[spislv]init spi bus fail!\n");
  469. }