pmif.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499
  1. /* Copyright Statement:
  2. *
  3. * This software/firmware and related documentation ("MediaTek Software") are
  4. * protected under relevant copyright laws. The information contained herein is
  5. * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
  6. * the prior written permission of MediaTek inc. and/or its licensors, any
  7. * reproduction, modification, use or disclosure of MediaTek Software, and
  8. * information contained herein, in whole or in part, shall be strictly
  9. * prohibited.
  10. *
  11. * MediaTek Inc. (C) 2019. All rights reserved.
  12. *
  13. * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
  14. * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
  15. * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
  16. * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
  17. * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
  19. * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
  20. * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
  21. * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
  22. * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
  23. * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
  24. * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
  25. * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
  26. * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
  27. * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
  28. * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
  29. * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
  30. * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
  31. * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
  32. *
  33. * The following software/firmware and/or related documentation ("MediaTek
  34. * Software") have been modified by MediaTek Inc. All revisions are subject to
  35. * any receiver's applicable license agreements with MediaTek Inc.
  36. */
  37. /*
  38. * MTK PMIF Driver
  39. *
  40. * Copyright 2019 MediaTek Co.,Ltd.
  41. *
  42. * DESCRIPTION:
  43. * This file provides API for other drivers to access PMIC registers
  44. *
  45. */
  46. #include <pmif.h>
  47. #include <spmi.h>
  48. #include <pmif_sw.h>
  49. #include <spmi_sw.h>
  50. #define GET_SWINF_0_FSM(x) ((x>>1) & 0x00000007)
  51. #define GET_PMIF_INIT_DONE(x) ((x>>15) & 0x00000001)
  52. #define TIMEOUT_WAIT_IDLE (1000000) /* ap latency concern 1ms */
  53. static int pmif_spmi_read_cmd(struct pmif *arb, unsigned char opc,
  54. unsigned char sid, unsigned short addr, unsigned char *buf,
  55. unsigned short len);
  56. static int pmif_spmi_write_cmd(struct pmif *arb, unsigned char opc,
  57. unsigned char sid, unsigned short addr, const unsigned char *buf,
  58. unsigned short len);
  59. #if PMIF_NO_PMIC
  60. static int pmif_spmi_read_cmd(struct pmif *arb, unsigned char opc,
  61. unsigned char sid, unsigned short addr, unsigned char *buf,
  62. unsigned short len)
  63. {
  64. PMIF_INFO("do Nothing.\n");
  65. return 0;
  66. }
  67. static int pmif_spmi_write_cmd(struct pmif *arb, unsigned char opc,
  68. unsigned char sid, unsigned short addr, const unsigned char *buf,
  69. unsigned short len)
  70. {
  71. PMIF_INFO("do Nothing.\n");
  72. return 0;
  73. }
  74. /* init interface */
  75. int pmif_spmi_init(int mstid)
  76. {
  77. PMIF_INFO("do Nothing.\n");
  78. return 0;
  79. }
  80. #else /* #if PMIF_NO_PMIC */
  81. /* pmif internal API declaration */
  82. #if PMIF_TIMEOUT
  83. static unsigned long long pmif_get_current_time(void);
  84. static int pmif_timeout_ns(unsigned long long start_time_ns,
  85. unsigned long long timeout_time_ns);
  86. static unsigned long long pmif_time2ns(unsigned long long time_us);
  87. #endif
  88. enum pmif_regs {
  89. PMIF_INIT_DONE,
  90. PMIF_INF_EN,
  91. PMIF_INF_CMD_PER_0,
  92. PMIF_INF_CMD_PER_1,
  93. PMIF_INF_CMD_PER_2,
  94. PMIF_INF_CMD_PER_3,
  95. PMIF_INF_MAX_BYTECNT_PER_0,
  96. PMIF_INF_MAX_BYTECNT_PER_1,
  97. PMIF_INF_MAX_BYTECNT_PER_2,
  98. PMIF_INF_MAX_BYTECNT_PER_3,
  99. PMIF_ARB_EN,
  100. PMIF_LAT_CNTER_EN,
  101. PMIF_LAT_LIMIT_LOADING,
  102. PMIF_LAT_LIMIT_0,
  103. PMIF_LAT_LIMIT_1,
  104. PMIF_LAT_LIMIT_2,
  105. PMIF_LAT_LIMIT_3,
  106. PMIF_LAT_LIMIT_4,
  107. PMIF_LAT_LIMIT_5,
  108. PMIF_LAT_LIMIT_6,
  109. PMIF_LAT_LIMIT_7,
  110. PMIF_LAT_LIMIT_8,
  111. PMIF_LAT_LIMIT_9,
  112. PMIF_CMDISSUE_EN,
  113. PMIF_TIMER_CTRL,
  114. PMIF_SPI_MODE_CTRL,
  115. PMIF_IRQ_EVENT_EN_0,
  116. PMIF_IRQ_FLAG_0,
  117. PMIF_IRQ_CLR_0,
  118. PMIF_SWINF_0_ACC,
  119. PMIF_SWINF_0_WDATA_31_0,
  120. PMIF_SWINF_0_WDATA_63_32,
  121. PMIF_SWINF_0_RDATA_31_0,
  122. PMIF_SWINF_0_RDATA_63_32,
  123. PMIF_SWINF_0_VLD_CLR,
  124. PMIF_SWINF_0_STA,
  125. PMIF_SWINF_1_ACC,
  126. PMIF_SWINF_1_WDATA_31_0,
  127. PMIF_SWINF_1_WDATA_63_32,
  128. PMIF_SWINF_1_RDATA_31_0,
  129. PMIF_SWINF_1_RDATA_63_32,
  130. PMIF_SWINF_1_VLD_CLR,
  131. PMIF_SWINF_1_STA,
  132. PMIF_SWINF_2_ACC,
  133. PMIF_SWINF_2_WDATA_31_0,
  134. PMIF_SWINF_2_WDATA_63_32,
  135. PMIF_SWINF_2_RDATA_31_0,
  136. PMIF_SWINF_2_RDATA_63_32,
  137. PMIF_SWINF_2_VLD_CLR,
  138. PMIF_SWINF_2_STA,
  139. PMIF_SWINF_3_ACC,
  140. PMIF_SWINF_3_WDATA_31_0,
  141. PMIF_SWINF_3_WDATA_63_32,
  142. PMIF_SWINF_3_RDATA_31_0,
  143. PMIF_SWINF_3_RDATA_63_32,
  144. PMIF_SWINF_3_VLD_CLR,
  145. PMIF_SWINF_3_STA,
  146. };
  147. static int mt6xxx_regs[] = {
  148. [PMIF_INIT_DONE] = 0x0000,
  149. [PMIF_INF_EN] = 0x0024,
  150. [PMIF_INF_CMD_PER_0] = 0x002c,
  151. [PMIF_INF_CMD_PER_1] = 0x0030,
  152. [PMIF_INF_CMD_PER_2] = 0x0034,
  153. [PMIF_INF_CMD_PER_3] = 0x0038,
  154. [PMIF_INF_MAX_BYTECNT_PER_0] = 0x003c,
  155. [PMIF_INF_MAX_BYTECNT_PER_1] = 0x0040,
  156. [PMIF_INF_MAX_BYTECNT_PER_2] = 0x0044,
  157. [PMIF_INF_MAX_BYTECNT_PER_3] = 0x0048,
  158. [PMIF_ARB_EN] = 0x0150,
  159. [PMIF_LAT_CNTER_EN] = 0x01DC,
  160. [PMIF_LAT_LIMIT_LOADING] = 0x01E0,
  161. [PMIF_LAT_LIMIT_0] = 0x01E4,
  162. [PMIF_LAT_LIMIT_1] = 0x01E8,
  163. [PMIF_LAT_LIMIT_2] = 0x01EC,
  164. [PMIF_LAT_LIMIT_3] = 0x01F0,
  165. [PMIF_LAT_LIMIT_4] = 0x01F4,
  166. [PMIF_LAT_LIMIT_5] = 0x01F8,
  167. [PMIF_LAT_LIMIT_6] = 0x01FC,
  168. [PMIF_LAT_LIMIT_7] = 0x0200,
  169. [PMIF_LAT_LIMIT_8] = 0x0204,
  170. [PMIF_LAT_LIMIT_9] = 0x0208,
  171. [PMIF_CMDISSUE_EN] = 0x03B4,
  172. [PMIF_TIMER_CTRL] = 0x03E0,
  173. [PMIF_SPI_MODE_CTRL] = 0x0400,
  174. [PMIF_IRQ_EVENT_EN_0] = 0x0418,
  175. [PMIF_IRQ_FLAG_0] = 0x0420,
  176. [PMIF_IRQ_CLR_0] = 0x0424,
  177. [PMIF_SWINF_0_ACC] = 0x0C00,
  178. [PMIF_SWINF_0_WDATA_31_0] = 0x0C04,
  179. [PMIF_SWINF_0_WDATA_63_32] = 0x0C08,
  180. [PMIF_SWINF_0_RDATA_31_0] = 0x0C14,
  181. [PMIF_SWINF_0_RDATA_63_32] = 0x0C18,
  182. [PMIF_SWINF_0_VLD_CLR] = 0x0C24,
  183. [PMIF_SWINF_0_STA] = 0x0C28,
  184. [PMIF_SWINF_1_ACC] = 0x0C40,
  185. [PMIF_SWINF_1_WDATA_31_0] = 0x0C44,
  186. [PMIF_SWINF_1_WDATA_63_32] = 0x0C48,
  187. [PMIF_SWINF_1_RDATA_31_0] = 0x0C54,
  188. [PMIF_SWINF_1_RDATA_63_32] = 0x0C58,
  189. [PMIF_SWINF_1_VLD_CLR] = 0x0C64,
  190. [PMIF_SWINF_1_STA] = 0x0C68,
  191. [PMIF_SWINF_2_ACC] = 0x0C80,
  192. [PMIF_SWINF_2_WDATA_31_0] = 0x0C84,
  193. [PMIF_SWINF_2_WDATA_63_32] = 0x0C88,
  194. [PMIF_SWINF_2_RDATA_31_0] = 0x0C94,
  195. [PMIF_SWINF_2_RDATA_63_32] = 0x0C98,
  196. [PMIF_SWINF_2_VLD_CLR] = 0x0CA4,
  197. [PMIF_SWINF_2_STA] = 0x0CA8,
  198. [PMIF_SWINF_3_ACC] = 0x0CC0,
  199. [PMIF_SWINF_3_WDATA_31_0] = 0x0CC4,
  200. [PMIF_SWINF_3_WDATA_63_32] = 0x0CC8,
  201. [PMIF_SWINF_3_RDATA_31_0] = 0x0CD4,
  202. [PMIF_SWINF_3_RDATA_63_32] = 0x0CD8,
  203. [PMIF_SWINF_3_VLD_CLR] = 0x0CE4,
  204. [PMIF_SWINF_3_STA] = 0x0CE8,
  205. };
  206. static struct pmif pmif_spmi_arb[] = {
  207. {
  208. .base = (unsigned int *)PMIF_SPMI_BASE,
  209. .regs = mt6xxx_regs,
  210. .swinf_ch_start = PMIF_SWINF_0_CHAN_NO,
  211. .swinf_no = PMIF_AP_SWINF_NO,
  212. .write = 0x0,
  213. .mstid = SPMI_MASTER_0,
  214. .pmifid = PMIF_PMIFID,
  215. .read_cmd = pmif_spmi_read_cmd,
  216. .write_cmd = pmif_spmi_write_cmd,
  217. .is_pmif_init_done = is_pmif_spmi_init_done,
  218. },
  219. };
  220. /* static struct pmif pmif_spi_arb[0]; */
  221. /* pmif timeout */
  222. #if PMIF_TIMEOUT
  223. static unsigned long long pmif_get_current_time(void)
  224. {
  225. return gpt4_get_current_tick();
  226. }
  227. static int pmif_timeout_ns(unsigned long long start_time_ns,
  228. unsigned long long timeout_time_ns)
  229. {
  230. return gpt4_timeout_tick(start_time_ns, timeout_time_ns);
  231. }
  232. static unsigned long long pmif_time2ns(unsigned long long time_us)
  233. {
  234. return gpt4_time2tick_us(time_us);
  235. }
  236. #else
  237. static unsigned long long pmif_get_current_time(void)
  238. {
  239. return 0;
  240. }
  241. static int pmif_timeout_ns(unsigned long long start_time_ns,
  242. unsigned long long elapse_time)
  243. {
  244. return 0;
  245. }
  246. static unsigned long long pmif_time2ns(unsigned long long time_us)
  247. {
  248. return 0;
  249. }
  250. #endif
  251. static inline unsigned int pmif_check_idle(int mstid) {
  252. struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
  253. unsigned int reg_rdata, offset = 0;
  254. #if PMIF_TIMEOUT
  255. unsigned long long start_time_ns = 0, end_time_ns = 0, timeout_ns = 0;
  256. unsigned long time_cnt = 100000;
  257. start_time_ns = pmif_get_current_time();
  258. timeout_ns = pmif_time2ns(TIMEOUT_WAIT_IDLE);
  259. #endif
  260. do {
  261. #if PMIF_TIMEOUT
  262. if (pmif_timeout_ns(start_time_ns, timeout_ns)) {
  263. end_time_ns = pmif_get_current_time();
  264. PMIF_ERR("%s timeout %d %d\n", __func__, start_time_ns,
  265. end_time_ns - start_time_ns);
  266. return -ETIMEDOUT;
  267. }
  268. if ((time_cnt--) == 0) {
  269. PMIF_ERR("%s timeout %d %d\n", __func__, start_time_ns,
  270. end_time_ns - start_time_ns);
  271. return -ETIMEDOUT;
  272. }
  273. #endif
  274. offset = arb->regs[PMIF_SWINF_0_STA] + (0x40 * arb->swinf_no);
  275. reg_rdata = DRV_Reg32(arb->base + offset);
  276. } while(GET_SWINF_0_FSM(reg_rdata) != SWINF_FSM_IDLE);
  277. return 0;
  278. }
  279. static inline unsigned int pmif_check_vldclr(int mstid) {
  280. struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
  281. unsigned int reg_rdata, offset = 0;
  282. #if PMIF_TIMEOUT
  283. unsigned long long start_time_ns = 0, end_time_ns = 0, timeout_ns = 0;
  284. unsigned long time_cnt = 100000;
  285. start_time_ns = pmif_get_current_time();
  286. timeout_ns = pmif_time2ns(TIMEOUT_WAIT_IDLE);
  287. #endif
  288. do {
  289. #if PMIF_TIMEOUT
  290. if (pmif_timeout_ns(start_time_ns, timeout_ns)) {
  291. end_time_ns = pmif_get_current_time();
  292. PMIF_ERR("%s timeout %d %d\n", __func__, start_time_ns,
  293. end_time_ns - start_time_ns);
  294. return -ETIMEDOUT;
  295. }
  296. if ((time_cnt--) == 0) {
  297. PMIF_ERR("%s timeout %d %d\n", __func__, start_time_ns,
  298. end_time_ns - start_time_ns);
  299. return -ETIMEDOUT;
  300. }
  301. #endif
  302. offset = arb->regs[PMIF_SWINF_0_STA] + (0x40 * arb->swinf_no);
  303. reg_rdata = DRV_Reg32(arb->base + offset);
  304. } while(GET_SWINF_0_FSM(reg_rdata) != SWINF_FSM_WFVLDCLR);
  305. return 0;
  306. }
  307. static int pmif_spmi_read_cmd(struct pmif *arb, unsigned char opc,
  308. unsigned char sid, unsigned short addr, unsigned char *buf,
  309. unsigned short len)
  310. {
  311. int write = 0x0;
  312. unsigned int ret = 0, offset = 0, data = 0;
  313. unsigned char bc = len - 1;
  314. if ((sid & ~(0xf)) != 0x0)
  315. return -EINVAL;
  316. if (len > PMIF_BYTECNT_MAX)
  317. return -EINVAL;
  318. if ((bc & ~(0x1)) != 0x0)
  319. return -EINVAL;
  320. /* Check the opcode */
  321. if (opc >= 0x60 && opc <= 0x7F)
  322. opc = PMIF_CMD_REG;
  323. else if (opc >= 0x20 && opc <= 0x2F)
  324. opc = PMIF_CMD_EXT_REG;
  325. else if (opc >= 0x38 && opc <= 0x3F)
  326. opc = PMIF_CMD_EXT_REG_LONG;
  327. else
  328. return -EINVAL;
  329. ENTER_CRITICAL();
  330. /* Wait for Software Interface FSM state to be IDLE. */
  331. ret = pmif_check_idle(arb->mstid);
  332. if(ret)
  333. return ret;
  334. /* Send the command. */
  335. offset = arb->regs[PMIF_SWINF_0_ACC] + (0x40 * arb->swinf_no);
  336. DRV_WriteReg32(arb->base + offset,
  337. ((unsigned)opc << 30) | (write << 29) | (sid << 24) | (bc << 16) | addr);
  338. /* Wait for Software Interface FSM state to be WFVLDCLR,
  339. *
  340. * read the data and clear the valid flag.
  341. */
  342. if(write == 0)
  343. {
  344. ret = pmif_check_vldclr(arb->mstid);
  345. if(ret)
  346. return ret;
  347. offset =
  348. arb->regs[PMIF_SWINF_0_RDATA_31_0] + (0x40 * arb->swinf_no);
  349. data = DRV_Reg32(arb->base + offset);
  350. memcpy(buf, &data, (bc & 3) + 1);
  351. offset =
  352. arb->regs[PMIF_SWINF_0_VLD_CLR] + (0x40 * arb->swinf_no);
  353. DRV_WriteReg32(arb->base + offset, 0x1);
  354. }
  355. EXIT_CRITICAL();
  356. return 0x0;
  357. }
  358. static int pmif_spmi_write_cmd(struct pmif *arb, unsigned char opc,
  359. unsigned char sid, unsigned short addr, const unsigned char *buf,
  360. unsigned short len)
  361. {
  362. int write = 0x1;
  363. unsigned int ret = 0, offset = 0, data = 0;
  364. unsigned char bc = len - 1;
  365. if ((sid & ~(0xf)) != 0x0)
  366. return -EINVAL;
  367. if (len > PMIF_BYTECNT_MAX)
  368. return -EINVAL;
  369. if ((bc & ~(0x1)) != 0x0)
  370. return -EINVAL;
  371. /* Check the opcode */
  372. if (opc >= 0x40 && opc <= 0x5F)
  373. opc = PMIF_CMD_REG;
  374. else if (opc <= 0x0F)
  375. opc = PMIF_CMD_EXT_REG;
  376. else if (opc >= 0x30 && opc <= 0x37)
  377. opc = PMIF_CMD_EXT_REG_LONG;
  378. else if (opc >= 0x80)
  379. opc = PMIF_CMD_REG_0;
  380. else
  381. return -EINVAL;
  382. ENTER_CRITICAL();
  383. /* Wait for Software Interface FSM state to be IDLE. */
  384. ret = pmif_check_idle(arb->mstid);
  385. if(ret)
  386. return ret;
  387. /* Set the write data. */
  388. if (write == 1)
  389. {
  390. offset =
  391. arb->regs[PMIF_SWINF_0_WDATA_31_0] + (0x40 * arb->swinf_no);
  392. memcpy(&data, buf, (bc & 3) + 1);
  393. DRV_WriteReg32(arb->base + offset, data);
  394. }
  395. /* Send the command. */
  396. offset = arb->regs[PMIF_SWINF_0_ACC] + (0x40 * arb->swinf_no);
  397. DRV_WriteReg32(arb->base + offset,
  398. ((unsigned)opc << 30) | (write << 29) | (sid << 24) |
  399. (bc << 16) | addr);
  400. EXIT_CRITICAL();
  401. return 0x0;
  402. }
  403. struct pmif *get_pmif_controller(int inf, int mstid)
  404. {
  405. if (inf == PMIF_SPMI) {
  406. return &pmif_spmi_arb[mstid];
  407. } else if (inf == PMIF_SPI) {
  408. /* TBD
  409. *pmif_spi_arb[mstid].base = (unsigned int *)PMIF_SPI_BASE;
  410. *pmif_spi_arb[mstid].swinf_no = 0x0;
  411. *pmif_spi_arb[mstid].write = 0x0;
  412. *pmif_spi_arb[mstid].pmifid = 0x0;
  413. *pmif_spi_arb[mstid].read_cmd = pmif_spi_read_cmd;
  414. *pmif_spi_arb[mstid].write_cmd = pmif_spi_write_cmd;
  415. *pmif_spi_arb[mstid].read_cmd_nochk = pmif_spi_read_cmd_nochk;
  416. *pmif_spi_arb[mstid].write_cmd_nochk =
  417. * pmif_spi_write_cmd_nochk;
  418. *return &pmif_spi_arb[mstid];
  419. */
  420. }
  421. return 0;
  422. }
  423. int is_pmif_spmi_init_done(int mstid)
  424. {
  425. int ret = 0;
  426. struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
  427. ret = DRV_Reg32(arb->base + arb->regs[PMIF_INIT_DONE]);
  428. PMIF_INFO("%s ret = %d\n", __func__, ret);
  429. if ((ret & 0x1) == 1)
  430. return 0;
  431. return -ENODEV;
  432. }
  433. int pmif_spmi_init(int mstid)
  434. {
  435. struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
  436. int ret = 0;
  437. INIT_CRITICAL();
  438. ret = arb->is_pmif_init_done(mstid);
  439. if(ret) {
  440. PMIF_ERR("init done check fail\n");
  441. return -ENODEV;
  442. }
  443. ret = spmi_init(arb);
  444. if(ret) {
  445. PMIF_ERR("init fail\n");
  446. return -ENODEV;
  447. }
  448. return 0;
  449. }
  450. #endif /* endif PMIF_NO_PMIC */