ipclite.c 53 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2021-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  4. */
  5. #define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__
  6. #include <linux/module.h>
  7. #include <linux/irq.h>
  8. #include <linux/interrupt.h>
  9. #include <linux/irqdomain.h>
  10. #include <linux/platform_device.h>
  11. #include <linux/of.h>
  12. #include <linux/of_address.h>
  13. #include <linux/of_irq.h>
  14. #include <asm/memory.h>
  15. #include <linux/sizes.h>
  16. #include <linux/hwspinlock.h>
  17. #include <linux/sysfs.h>
  18. #include "ipclite_client.h"
  19. #include "ipclite.h"
  20. static struct ipclite_info *ipclite;
  21. static struct ipclite_client synx_client;
  22. static struct ipclite_client test_client;
  23. static struct ipclite_debug_info *ipclite_dbg_info;
  24. static struct ipclite_debug_struct *ipclite_dbg_struct;
  25. static struct ipclite_debug_inmem_buf *ipclite_dbg_inmem;
  26. static struct mutex ssr_mutex;
  27. static struct kobject *sysfs_kobj;
  28. static uint32_t ipclite_debug_level = IPCLITE_ERR | IPCLITE_WARN | IPCLITE_INFO;
  29. static uint32_t ipclite_debug_control = IPCLITE_DMESG_LOG, ipclite_debug_dump;
  30. static uint32_t enabled_hosts, partitions, major_ver, minor_ver;
  31. static uint64_t feature_mask;
  32. static inline bool is_host_enabled(uint32_t host)
  33. {
  34. return (1U & (enabled_hosts >> host));
  35. }
  36. static inline bool is_loopback_except_apps(uint32_t h0, uint32_t h1)
  37. {
  38. return (h0 == h1 && h0 != IPCMEM_APPS);
  39. }
  40. static void ipclite_inmem_log(const char *psztStr, ...)
  41. {
  42. uint32_t local_index = 0;
  43. va_list pArgs;
  44. va_start(pArgs, psztStr);
  45. /* Incrementing the index atomically and storing the index in local variable */
  46. local_index = ipclite_global_atomic_inc((ipclite_atomic_int32_t *)
  47. &ipclite_dbg_info->debug_log_index);
  48. local_index %= IPCLITE_LOG_BUF_SIZE;
  49. /* Writes data on the index location */
  50. vsnprintf(ipclite_dbg_inmem->IPCLITELog[local_index], IPCLITE_LOG_MSG_SIZE, psztStr, pArgs);
  51. va_end(pArgs);
  52. }
  53. static void ipclite_dump_debug_struct(void)
  54. {
  55. int i = 0, host = 0;
  56. struct ipclite_debug_struct *temp_dbg_struct;
  57. /* Check if debug structures are initialized */
  58. if (!ipclite_dbg_info || !ipclite_dbg_struct) {
  59. pr_err("Debug Structures not initialized\n");
  60. return;
  61. }
  62. /* Check if debug structures are enabled before printing */
  63. if (!(IS_DEBUG_CONFIG(IPCLITE_DBG_STRUCT))) {
  64. pr_err("Debug Structures not enabled\n");
  65. return;
  66. }
  67. /* Dumping the debug structures */
  68. pr_info("------------------- Dumping IPCLite Debug Structure -------------------\n");
  69. for (host = 0; host < IPCMEM_NUM_HOSTS; host++) {
  70. if (!is_host_enabled(host))
  71. continue;
  72. temp_dbg_struct = (struct ipclite_debug_struct *)
  73. (((char *)ipclite_dbg_struct) +
  74. (sizeof(*temp_dbg_struct) * host));
  75. pr_info("---------- Host ID: %d dbg_mem:%p ----------\n",
  76. host, temp_dbg_struct);
  77. pr_info("Total Signals Sent : %d Total Signals Received : %d\n",
  78. temp_dbg_struct->dbg_info_overall.total_numsig_sent,
  79. temp_dbg_struct->dbg_info_overall.total_numsig_recv);
  80. pr_info("Last Signal Sent to Host ID : %d Last Signal Received from Host ID : %d\n",
  81. temp_dbg_struct->dbg_info_overall.last_sent_host_id,
  82. temp_dbg_struct->dbg_info_overall.last_recv_host_id);
  83. pr_info("Last Signal ID Sent : %d Last Signal ID Received : %d\n",
  84. temp_dbg_struct->dbg_info_overall.last_sigid_sent,
  85. temp_dbg_struct->dbg_info_overall.last_sigid_recv);
  86. for (i = 0; i < IPCMEM_NUM_HOSTS; i++) {
  87. if (!is_host_enabled(i))
  88. continue;
  89. pr_info("----------> Host ID : %d Host ID : %d\n", host, i);
  90. pr_info("No. of Messages Sent : %d No. of Messages Received : %d\n",
  91. temp_dbg_struct->dbg_info_host[i].numsig_sent,
  92. temp_dbg_struct->dbg_info_host[i].numsig_recv);
  93. pr_info("No. of Interrupts Received : %d\n",
  94. temp_dbg_struct->dbg_info_host[i].num_intr);
  95. pr_info("TX Write Index : %d TX Read Index : %d\n",
  96. temp_dbg_struct->dbg_info_host[i].tx_wr_index,
  97. temp_dbg_struct->dbg_info_host[i].tx_rd_index);
  98. pr_info("TX Write Index[0] : %d TX Read Index[0] : %d\n",
  99. temp_dbg_struct->dbg_info_host[i].prev_tx_wr_index[0],
  100. temp_dbg_struct->dbg_info_host[i].prev_tx_rd_index[0]);
  101. pr_info("TX Write Index[1] : %d TX Read Index[1] : %d\n",
  102. temp_dbg_struct->dbg_info_host[i].prev_tx_wr_index[1],
  103. temp_dbg_struct->dbg_info_host[i].prev_tx_rd_index[1]);
  104. pr_info("RX Write Index : %d RX Read Index : %d\n",
  105. temp_dbg_struct->dbg_info_host[i].rx_wr_index,
  106. temp_dbg_struct->dbg_info_host[i].rx_rd_index);
  107. pr_info("RX Write Index[0] : %d RX Read Index[0] : %d\n",
  108. temp_dbg_struct->dbg_info_host[i].prev_rx_wr_index[0],
  109. temp_dbg_struct->dbg_info_host[i].prev_rx_rd_index[0]);
  110. pr_info("RX Write Index[1] : %d RX Read Index[1] : %d\n",
  111. temp_dbg_struct->dbg_info_host[i].prev_rx_wr_index[1],
  112. temp_dbg_struct->dbg_info_host[i].prev_rx_rd_index[1]);
  113. }
  114. }
  115. return;
  116. }
  117. static void ipclite_dump_inmem_logs(void)
  118. {
  119. int i = 0;
  120. uint32_t local_index = 0;
  121. /* Check if debug and inmem structures are initialized */
  122. if (!ipclite_dbg_info || !ipclite_dbg_inmem) {
  123. pr_err("Debug structures not initialized\n");
  124. return;
  125. }
  126. /* Check if debug structures are enabled before printing */
  127. if (!(IS_DEBUG_CONFIG(IPCLITE_INMEM_LOG))) {
  128. pr_err("In-Memory Logs not enabled\n");
  129. return;
  130. }
  131. /* Dumping the debug in-memory logs */
  132. pr_info("------------------- Dumping In-Memory Logs -------------------\n");
  133. /* Storing the index atomically in local variable */
  134. local_index = ipclite_global_atomic_load_u32((ipclite_atomic_uint32_t *)
  135. &ipclite_dbg_info->debug_log_index);
  136. /* Printing from current index till the end of buffer */
  137. for (i = local_index % IPCLITE_LOG_BUF_SIZE; i < IPCLITE_LOG_BUF_SIZE; i++) {
  138. if (ipclite_dbg_inmem->IPCLITELog[i][0])
  139. pr_info("%s\n", ipclite_dbg_inmem->IPCLITELog[i]);
  140. }
  141. /* Printing from 0th index to current-1 index */
  142. for (i = 0; i < local_index % IPCLITE_LOG_BUF_SIZE; i++) {
  143. if (ipclite_dbg_inmem->IPCLITELog[i][0])
  144. pr_info("%s\n", ipclite_dbg_inmem->IPCLITELog[i]);
  145. }
  146. return;
  147. }
  148. int ipclite_hw_mutex_acquire(void)
  149. {
  150. int ret;
  151. if (unlikely(!ipclite)) {
  152. pr_err("IPCLite not initialized\n");
  153. return -ENOMEM;
  154. }
  155. ret = hwspin_lock_timeout_irqsave(ipclite->hwlock,
  156. HWSPINLOCK_TIMEOUT, &ipclite->hw_mutex_flags);
  157. if (ret) {
  158. pr_err("Hw mutex lock acquire failed\n");
  159. return ret;
  160. }
  161. ipclite->ipcmem.toc_data.host_info->hwlock_owner = IPCMEM_APPS;
  162. return ret;
  163. }
  164. EXPORT_SYMBOL(ipclite_hw_mutex_acquire);
  165. int ipclite_hw_mutex_release(void)
  166. {
  167. if (unlikely(!ipclite)) {
  168. pr_err("IPCLite not initialized\n");
  169. return -ENOMEM;
  170. }
  171. if (ipclite->ipcmem.toc_data.host_info->hwlock_owner != IPCMEM_APPS)
  172. return -EINVAL;
  173. ipclite->ipcmem.toc_data.host_info->hwlock_owner = IPCMEM_INVALID_HOST;
  174. hwspin_unlock_irqrestore(ipclite->hwlock, &ipclite->hw_mutex_flags);
  175. return 0;
  176. }
  177. EXPORT_SYMBOL(ipclite_hw_mutex_release);
  178. /* Atomic Functions Start */
  179. void ipclite_atomic_init_u32(ipclite_atomic_uint32_t *addr, uint32_t data)
  180. {
  181. BUG_ON(addr == NULL);
  182. atomic_set(addr, data);
  183. }
  184. EXPORT_SYMBOL(ipclite_atomic_init_u32);
  185. void ipclite_atomic_init_i32(ipclite_atomic_int32_t *addr, int32_t data)
  186. {
  187. BUG_ON(addr == NULL);
  188. atomic_set(addr, data);
  189. }
  190. EXPORT_SYMBOL(ipclite_atomic_init_i32);
  191. void ipclite_global_atomic_store_u32(ipclite_atomic_uint32_t *addr, uint32_t data)
  192. {
  193. BUG_ON(addr == NULL);
  194. ATOMIC_HW_MUTEX_ACQUIRE;
  195. atomic_set(addr, data);
  196. ATOMIC_HW_MUTEX_RELEASE;
  197. }
  198. EXPORT_SYMBOL(ipclite_global_atomic_store_u32);
  199. void ipclite_global_atomic_store_i32(ipclite_atomic_int32_t *addr, int32_t data)
  200. {
  201. BUG_ON(addr == NULL);
  202. ATOMIC_HW_MUTEX_ACQUIRE;
  203. atomic_set(addr, data);
  204. ATOMIC_HW_MUTEX_RELEASE;
  205. }
  206. EXPORT_SYMBOL(ipclite_global_atomic_store_i32);
  207. uint32_t ipclite_global_atomic_load_u32(ipclite_atomic_uint32_t *addr)
  208. {
  209. uint32_t ret = 0;
  210. BUG_ON(addr == NULL);
  211. ATOMIC_HW_MUTEX_ACQUIRE;
  212. ret = atomic_read(addr);
  213. ATOMIC_HW_MUTEX_RELEASE;
  214. return ret;
  215. }
  216. EXPORT_SYMBOL(ipclite_global_atomic_load_u32);
  217. int32_t ipclite_global_atomic_load_i32(ipclite_atomic_int32_t *addr)
  218. {
  219. int32_t ret = 0;
  220. BUG_ON(addr == NULL);
  221. ATOMIC_HW_MUTEX_ACQUIRE;
  222. ret = atomic_read(addr);
  223. ATOMIC_HW_MUTEX_RELEASE;
  224. return ret;
  225. }
  226. EXPORT_SYMBOL(ipclite_global_atomic_load_i32);
  227. uint32_t ipclite_global_test_and_set_bit(uint32_t nr, ipclite_atomic_uint32_t *addr)
  228. {
  229. uint32_t ret = 0, mask = (1 << nr);
  230. BUG_ON(addr == NULL);
  231. ATOMIC_HW_MUTEX_ACQUIRE;
  232. ret = atomic_fetch_or(mask, addr);
  233. ATOMIC_HW_MUTEX_RELEASE;
  234. return ret;
  235. }
  236. EXPORT_SYMBOL(ipclite_global_test_and_set_bit);
  237. uint32_t ipclite_global_test_and_clear_bit(uint32_t nr, ipclite_atomic_uint32_t *addr)
  238. {
  239. uint32_t ret = 0, mask = (1 << nr);
  240. BUG_ON(addr == NULL);
  241. ATOMIC_HW_MUTEX_ACQUIRE;
  242. ret = atomic_fetch_and(~mask, addr);
  243. ATOMIC_HW_MUTEX_RELEASE;
  244. return ret;
  245. }
  246. EXPORT_SYMBOL(ipclite_global_test_and_clear_bit);
  247. int32_t ipclite_global_atomic_inc(ipclite_atomic_int32_t *addr)
  248. {
  249. int32_t ret = 0;
  250. BUG_ON(addr == NULL);
  251. ATOMIC_HW_MUTEX_ACQUIRE;
  252. ret = atomic_fetch_add(1, addr);
  253. ATOMIC_HW_MUTEX_RELEASE;
  254. return ret;
  255. }
  256. EXPORT_SYMBOL(ipclite_global_atomic_inc);
  257. int32_t ipclite_global_atomic_dec(ipclite_atomic_int32_t *addr)
  258. {
  259. int32_t ret = 0;
  260. BUG_ON(addr == NULL);
  261. ATOMIC_HW_MUTEX_ACQUIRE;
  262. ret = atomic_fetch_sub(1, addr);
  263. ATOMIC_HW_MUTEX_RELEASE;
  264. return ret;
  265. }
  266. EXPORT_SYMBOL(ipclite_global_atomic_dec);
  267. /* Atomic Functions End */
  268. static size_t ipcmem_rx_avail(struct ipclite_fifo *rx_fifo)
  269. {
  270. size_t len = 0;
  271. u32 head = 0, tail = 0;
  272. head = le32_to_cpu(*rx_fifo->head);
  273. tail = le32_to_cpu(*rx_fifo->tail);
  274. IPCLITE_OS_LOG(IPCLITE_DBG, "head=%d, tail=%d\n", head, tail);
  275. if (head < tail)
  276. len = rx_fifo->length - tail + head;
  277. else
  278. len = head - tail;
  279. if (WARN_ON_ONCE(len > rx_fifo->length))
  280. len = 0;
  281. IPCLITE_OS_LOG(IPCLITE_DBG, "len=%d\n", len);
  282. return len;
  283. }
  284. static void ipcmem_rx_peak(struct ipclite_fifo *rx_fifo,
  285. void *data, size_t count)
  286. {
  287. size_t len = 0;
  288. u32 tail = 0;
  289. tail = le32_to_cpu(*rx_fifo->tail);
  290. if (WARN_ON_ONCE(tail > rx_fifo->length))
  291. return;
  292. if (tail >= rx_fifo->length)
  293. tail -= rx_fifo->length;
  294. len = min_t(size_t, count, rx_fifo->length - tail);
  295. if (len)
  296. memcpy_fromio(data, rx_fifo->fifo + tail, len);
  297. if (len != count)
  298. memcpy_fromio(data + len, rx_fifo->fifo, (count - len));
  299. }
  300. static void ipcmem_rx_advance(struct ipclite_fifo *rx_fifo,
  301. size_t count, uint32_t core_id)
  302. {
  303. u32 tail = 0;
  304. tail = le32_to_cpu(*rx_fifo->tail);
  305. tail += count;
  306. if (tail >= rx_fifo->length)
  307. tail %= rx_fifo->length;
  308. *rx_fifo->tail = cpu_to_le32(tail);
  309. /* Storing the debug data in debug structures */
  310. if (IS_DEBUG_CONFIG(IPCLITE_DBG_STRUCT)) {
  311. ipclite_dbg_struct->dbg_info_host[core_id].prev_rx_wr_index[1] =
  312. ipclite_dbg_struct->dbg_info_host[core_id].prev_rx_wr_index[0];
  313. ipclite_dbg_struct->dbg_info_host[core_id].prev_rx_wr_index[0] =
  314. ipclite_dbg_struct->dbg_info_host[core_id].rx_wr_index;
  315. ipclite_dbg_struct->dbg_info_host[core_id].rx_wr_index = *rx_fifo->head;
  316. ipclite_dbg_struct->dbg_info_host[core_id].prev_rx_rd_index[1] =
  317. ipclite_dbg_struct->dbg_info_host[core_id].prev_rx_rd_index[0];
  318. ipclite_dbg_struct->dbg_info_host[core_id].prev_rx_rd_index[0] =
  319. ipclite_dbg_struct->dbg_info_host[core_id].rx_rd_index;
  320. ipclite_dbg_struct->dbg_info_host[core_id].rx_rd_index = *rx_fifo->tail;
  321. ipclite_dbg_struct->dbg_info_overall.total_numsig_recv++;
  322. ipclite_dbg_struct->dbg_info_host[core_id].numsig_recv++;
  323. }
  324. }
  325. static size_t ipcmem_tx_avail(struct ipclite_fifo *tx_fifo)
  326. {
  327. u32 head = 0, tail = 0, avail = 0;
  328. head = le32_to_cpu(*tx_fifo->head);
  329. tail = le32_to_cpu(*tx_fifo->tail);
  330. if (tail <= head)
  331. avail = tx_fifo->length - head + tail;
  332. else
  333. avail = tail - head;
  334. if (avail < FIFO_FULL_RESERVE)
  335. avail = 0;
  336. else
  337. avail -= FIFO_FULL_RESERVE;
  338. if (WARN_ON_ONCE(avail > tx_fifo->length))
  339. avail = 0;
  340. return avail;
  341. }
  342. static unsigned int ipcmem_tx_write_one(struct ipclite_fifo *tx_fifo,
  343. unsigned int head,
  344. const void *data, size_t count)
  345. {
  346. size_t len = 0;
  347. if (WARN_ON_ONCE(head > tx_fifo->length))
  348. return head;
  349. len = min_t(size_t, count, tx_fifo->length - head);
  350. if (len)
  351. memcpy(tx_fifo->fifo + head, data, len);
  352. if (len != count)
  353. memcpy(tx_fifo->fifo, data + len, count - len);
  354. head += count;
  355. if (head >= tx_fifo->length)
  356. head -= tx_fifo->length;
  357. return head;
  358. }
  359. static void ipcmem_tx_write(struct ipclite_fifo *tx_fifo,
  360. const void *data, size_t dlen, uint32_t core_id, uint32_t signal_id)
  361. {
  362. unsigned int head = 0;
  363. head = le32_to_cpu(*tx_fifo->head);
  364. head = ipcmem_tx_write_one(tx_fifo, head, data, dlen);
  365. head = ALIGN(head, 8);
  366. if (head >= tx_fifo->length)
  367. head -= tx_fifo->length;
  368. /* Ensure ordering of fifo and head update */
  369. wmb();
  370. *tx_fifo->head = cpu_to_le32(head);
  371. IPCLITE_OS_LOG(IPCLITE_DBG, "head : %d core_id : %d signal_id : %d\n",
  372. *tx_fifo->head, core_id, signal_id);
  373. /* Storing the debug data in debug structures */
  374. if (IS_DEBUG_CONFIG(IPCLITE_DBG_STRUCT)) {
  375. ipclite_dbg_struct->dbg_info_host[core_id].prev_tx_wr_index[1] =
  376. ipclite_dbg_struct->dbg_info_host[core_id].prev_tx_wr_index[0];
  377. ipclite_dbg_struct->dbg_info_host[core_id].prev_tx_wr_index[0] =
  378. ipclite_dbg_struct->dbg_info_host[core_id].tx_wr_index;
  379. ipclite_dbg_struct->dbg_info_host[core_id].tx_wr_index = *tx_fifo->head;
  380. ipclite_dbg_struct->dbg_info_host[core_id].prev_tx_rd_index[1] =
  381. ipclite_dbg_struct->dbg_info_host[core_id].prev_tx_rd_index[0];
  382. ipclite_dbg_struct->dbg_info_host[core_id].prev_tx_rd_index[0] =
  383. ipclite_dbg_struct->dbg_info_host[core_id].tx_rd_index;
  384. ipclite_dbg_struct->dbg_info_host[core_id].tx_rd_index = *tx_fifo->tail;
  385. ipclite_dbg_struct->dbg_info_overall.total_numsig_sent++;
  386. ipclite_dbg_struct->dbg_info_host[core_id].numsig_sent++;
  387. ipclite_dbg_struct->dbg_info_overall.last_sent_host_id = core_id;
  388. ipclite_dbg_struct->dbg_info_overall.last_sigid_sent = signal_id;
  389. }
  390. }
  391. static size_t ipclite_rx_avail(struct ipclite_channel *channel)
  392. {
  393. return channel->rx_fifo->avail(channel->rx_fifo);
  394. }
  395. static void ipclite_rx_peak(struct ipclite_channel *channel,
  396. void *data, size_t count)
  397. {
  398. channel->rx_fifo->peak(channel->rx_fifo, data, count);
  399. }
  400. static void ipclite_rx_advance(struct ipclite_channel *channel,
  401. size_t count)
  402. {
  403. channel->rx_fifo->advance(channel->rx_fifo, count, channel->remote_pid);
  404. }
  405. static size_t ipclite_tx_avail(struct ipclite_channel *channel)
  406. {
  407. return channel->tx_fifo->avail(channel->tx_fifo);
  408. }
  409. static void ipclite_tx_write(struct ipclite_channel *channel,
  410. const void *data, size_t dlen)
  411. {
  412. channel->tx_fifo->write(channel->tx_fifo, data, dlen, channel->remote_pid,
  413. channel->irq_info->signal_id);
  414. }
  415. static int ipclite_rx_data(struct ipclite_channel *channel, size_t avail)
  416. {
  417. int ret = 0;
  418. uint64_t data = 0;
  419. if (avail < sizeof(data)) {
  420. IPCLITE_OS_LOG(IPCLITE_ERR, "Not enough data in fifo, Core : %d Signal : %d\n",
  421. channel->remote_pid, channel->irq_info->signal_id);
  422. return -EAGAIN;
  423. }
  424. ipclite_rx_peak(channel, &data, sizeof(data));
  425. if (synx_client.reg_complete == 1) {
  426. if (synx_client.callback)
  427. synx_client.callback(channel->remote_pid, data,
  428. synx_client.priv_data);
  429. }
  430. ipclite_rx_advance(channel, ALIGN(sizeof(data), 8));
  431. return ret;
  432. }
  433. static int ipclite_rx_test_data(struct ipclite_channel *channel, size_t avail)
  434. {
  435. int ret = 0;
  436. uint64_t data = 0;
  437. if (avail < sizeof(data)) {
  438. IPCLITE_OS_LOG(IPCLITE_ERR, "Not enough data in fifo, Core : %d Signal : %d\n",
  439. channel->remote_pid, channel->irq_info->signal_id);
  440. return -EAGAIN;
  441. }
  442. ipclite_rx_peak(channel, &data, sizeof(data));
  443. if (test_client.reg_complete == 1) {
  444. if (test_client.callback)
  445. test_client.callback(channel->remote_pid, data,
  446. test_client.priv_data);
  447. }
  448. ipclite_rx_advance(channel, ALIGN(sizeof(data), 8));
  449. return ret;
  450. }
  451. static irqreturn_t ipclite_intr(int irq, void *data)
  452. {
  453. int ret = 0;
  454. unsigned int avail = 0;
  455. uint64_t msg = 0;
  456. struct ipclite_channel *channel;
  457. struct ipclite_irq_info *irq_info;
  458. irq_info = (struct ipclite_irq_info *)data;
  459. channel = container_of(irq_info, struct ipclite_channel, irq_info[irq_info->signal_id]);
  460. IPCLITE_OS_LOG(IPCLITE_DBG, "Interrupt received from Core : %d Signal : %d\n",
  461. channel->remote_pid, irq_info->signal_id);
  462. /* Storing the debug data in debug structures */
  463. if (IS_DEBUG_CONFIG(IPCLITE_DBG_STRUCT)) {
  464. ipclite_dbg_struct->dbg_info_host[channel->remote_pid].num_intr++;
  465. ipclite_dbg_struct->dbg_info_overall.last_recv_host_id = channel->remote_pid;
  466. ipclite_dbg_struct->dbg_info_overall.last_sigid_recv = irq_info->signal_id;
  467. }
  468. if (irq_info->signal_id == IPCLITE_MSG_SIGNAL) {
  469. for (;;) {
  470. avail = ipclite_rx_avail(channel);
  471. if (avail < sizeof(msg))
  472. break;
  473. ret = ipclite_rx_data(channel, avail);
  474. }
  475. IPCLITE_OS_LOG(IPCLITE_DBG, "checking messages in rx_fifo done\n");
  476. } else if (irq_info->signal_id == IPCLITE_VERSION_SIGNAL) {
  477. IPCLITE_OS_LOG(IPCLITE_DBG, "Versioning is not enabled using IPCC signals\n");
  478. } else if (irq_info->signal_id == IPCLITE_TEST_SIGNAL) {
  479. for (;;) {
  480. avail = ipclite_rx_avail(channel);
  481. if (avail < sizeof(msg))
  482. break;
  483. ret = ipclite_rx_test_data(channel, avail);
  484. }
  485. IPCLITE_OS_LOG(IPCLITE_DBG, "checking messages in rx_fifo done\n");
  486. } else {
  487. IPCLITE_OS_LOG(IPCLITE_ERR, "Wrong Interrupt Signal from core : %d signal : %d\n",
  488. channel->remote_pid, irq_info->signal_id);
  489. }
  490. return IRQ_HANDLED;
  491. }
  492. static int ipclite_tx(struct ipclite_channel *channel,
  493. uint64_t data, size_t dlen, uint32_t ipclite_signal)
  494. {
  495. int ret = 0;
  496. unsigned long flags;
  497. if (channel->status != ACTIVE) {
  498. if (channel->status == IN_PROGRESS && *channel->gstatus_ptr == ACTIVE) {
  499. channel->status = ACTIVE;
  500. } else {
  501. IPCLITE_OS_LOG(IPCLITE_ERR, "Cannot Send, Channel not active\n");
  502. return -EOPNOTSUPP;
  503. }
  504. }
  505. spin_lock_irqsave(&channel->tx_lock, flags);
  506. if (ipclite_tx_avail(channel) < dlen) {
  507. spin_unlock_irqrestore(&channel->tx_lock, flags);
  508. ret = -EAGAIN;
  509. return ret;
  510. }
  511. ipclite_tx_write(channel, &data, dlen);
  512. mbox_send_message(channel->irq_info[ipclite_signal].mbox_chan, NULL);
  513. mbox_client_txdone(channel->irq_info[ipclite_signal].mbox_chan, 0);
  514. spin_unlock_irqrestore(&channel->tx_lock, flags);
  515. return ret;
  516. }
  517. static int ipclite_notify_core(int32_t proc_id, int32_t signal_id)
  518. {
  519. int ret = 0;
  520. struct ipclite_channel *channel;
  521. if (proc_id < 0 || proc_id >= IPCMEM_NUM_HOSTS) {
  522. IPCLITE_OS_LOG(IPCLITE_ERR, "Invalid proc_id : %d\n", proc_id);
  523. return -EINVAL;
  524. }
  525. channel = &ipclite->channel[proc_id];
  526. if (channel->status != ACTIVE) {
  527. if (channel->status == IN_PROGRESS && *channel->gstatus_ptr == ACTIVE) {
  528. channel->status = ACTIVE;
  529. } else {
  530. IPCLITE_OS_LOG(IPCLITE_ERR, "Cannot Send, Core %d is Inactive\n", proc_id);
  531. return -EOPNOTSUPP;
  532. }
  533. }
  534. ret = mbox_send_message(channel->irq_info[signal_id].mbox_chan, NULL);
  535. if (ret < 0) {
  536. IPCLITE_OS_LOG(IPCLITE_ERR,
  537. "Signal sending failed to Core : %d Signal : %d ret : %d\n",
  538. proc_id, signal_id, ret);
  539. return ret;
  540. }
  541. IPCLITE_OS_LOG(IPCLITE_DBG,
  542. "Signal send completed to core : %d signal : %d ret : %d\n",
  543. proc_id, signal_id, ret);
  544. return 0;
  545. }
  546. static int map_ipcmem(struct ipclite_info *ipclite, const char *name)
  547. {
  548. int ret = 0;
  549. struct device *dev;
  550. struct device_node *np;
  551. struct resource r;
  552. dev = ipclite->dev;
  553. np = of_parse_phandle(dev->of_node, name, 0);
  554. if (!np) {
  555. IPCLITE_OS_LOG(IPCLITE_ERR, "No %s specified\n", name);
  556. return -EINVAL;
  557. }
  558. ret = of_address_to_resource(np, 0, &r);
  559. of_node_put(np);
  560. if (ret)
  561. return ret;
  562. ipclite->ipcmem.mem.aux_base = (u64)r.start;
  563. ipclite->ipcmem.mem.size = resource_size(&r);
  564. ipclite->ipcmem.mem.virt_base = devm_ioremap_wc(dev, r.start,
  565. resource_size(&r));
  566. if (!ipclite->ipcmem.mem.virt_base)
  567. return -ENOMEM;
  568. IPCLITE_OS_LOG(IPCLITE_DBG, "aux_base = %lx, size=%d,virt_base=%p\n",
  569. ipclite->ipcmem.mem.aux_base, ipclite->ipcmem.mem.size,
  570. ipclite->ipcmem.mem.virt_base);
  571. return ret;
  572. }
  573. /**
  574. * insert_magic_number() - Inserts the magic number in toc header
  575. *
  576. * Function computes a simple checksum of the contents in toc header
  577. * and stores the result in magic_number field in the toc header
  578. */
  579. static void insert_magic_number(void)
  580. {
  581. uint32_t *block = ipclite->ipcmem.mem.virt_base;
  582. size_t size = sizeof(struct ipcmem_toc_header) / sizeof(uint32_t);
  583. for (int i = 1; i < size; i++)
  584. block[0] ^= block[i];
  585. block[0] = ~block[0];
  586. }
  587. static int32_t setup_toc(struct ipclite_mem *ipcmem)
  588. {
  589. size_t offset = 0;
  590. void *virt_base = ipcmem->mem.virt_base;
  591. struct ipcmem_offsets *offsets = &ipcmem->toc->offsets;
  592. struct ipcmem_toc_data *toc_data = &ipcmem->toc_data;
  593. /* Setup Offsets */
  594. offsets->host_info = offset += IPCMEM_TOC_VAR_OFFSET;
  595. offsets->global_entry = offset += sizeof(struct ipcmem_host_info);
  596. offsets->partition_info = offset += sizeof(struct ipcmem_partition_entry);
  597. offsets->partition_entry = offset += sizeof(struct ipcmem_partition_info);
  598. // offsets->debug = virt_base + size - 64K;
  599. /* Offset to be used for any new structure added in toc (after partition_entry) */
  600. // offsets->new_struct = offset += sizeof(struct ipcmem_partition_entry)*IPCMEM_NUM_HOSTS;
  601. IPCLITE_OS_LOG(IPCLITE_DBG, "toc_data offsets:");
  602. IPCLITE_OS_LOG(IPCLITE_DBG, "host_info = 0x%X", offsets->host_info);
  603. IPCLITE_OS_LOG(IPCLITE_DBG, "global_entry = 0x%X", offsets->global_entry);
  604. IPCLITE_OS_LOG(IPCLITE_DBG, "partition_info = 0x%X", offsets->partition_info);
  605. IPCLITE_OS_LOG(IPCLITE_DBG, "partition_entry = 0x%X", offsets->partition_entry);
  606. /* Point structures to the appropriate offset in TOC */
  607. toc_data->host_info = ADD_OFFSET(virt_base, offsets->host_info);
  608. toc_data->global_entry = ADD_OFFSET(virt_base, offsets->global_entry);
  609. toc_data->partition_info = ADD_OFFSET(virt_base, offsets->partition_info);
  610. toc_data->partition_entry = ADD_OFFSET(virt_base, offsets->partition_entry);
  611. return 0;
  612. }
  613. static void setup_global_partition(struct ipclite_mem *ipcmem, uint32_t base_offset)
  614. {
  615. /*Fill in global partition details*/
  616. ipcmem->toc_data.global_entry->base_offset = base_offset;
  617. ipcmem->toc_data.global_entry->size = GLOBAL_PARTITION_SIZE;
  618. ipcmem->toc_data.global_entry->flags = GLOBAL_PARTITION_FLAGS;
  619. ipcmem->toc_data.global_entry->host0 = IPCMEM_GLOBAL_HOST;
  620. ipcmem->toc_data.global_entry->host1 = IPCMEM_GLOBAL_HOST;
  621. ipcmem->global_partition = ADD_OFFSET(ipcmem->mem.virt_base, base_offset);
  622. IPCLITE_OS_LOG(IPCLITE_DBG, "base_offset =%x,ipcmem->global_partition = %p\n",
  623. base_offset,
  624. ipcmem->global_partition);
  625. ipcmem->global_partition->hdr = global_partition_hdr;
  626. IPCLITE_OS_LOG(IPCLITE_DBG, "hdr.type = %x,hdr.offset = %x,hdr.size = %d\n",
  627. ipcmem->global_partition->hdr.partition_type,
  628. ipcmem->global_partition->hdr.region_offset,
  629. ipcmem->global_partition->hdr.region_size);
  630. }
  631. static void update_partition(struct ipclite_mem *ipcmem, uint32_t p)
  632. {
  633. int host0 = ipcmem->toc_data.partition_entry[p].host0;
  634. int host1 = ipcmem->toc_data.partition_entry[p].host1;
  635. IPCLITE_OS_LOG(IPCLITE_DBG, "host0 = %d, host1=%d\n", host0, host1);
  636. ipcmem->partition[p] = ADD_OFFSET(ipcmem->mem.virt_base,
  637. ipcmem->toc_data.partition_entry[p].base_offset);
  638. IPCLITE_OS_LOG(IPCLITE_DBG, "partition[%d] = %p,partition_base_offset[%d]=%lx",
  639. p, ipcmem->partition[p],
  640. p, ipcmem->toc_data.partition_entry[p].base_offset);
  641. if (host0 == host1)
  642. ipcmem->partition[p]->hdr = loopback_partition_hdr;
  643. else
  644. ipcmem->partition[p]->hdr = default_partition_hdr;
  645. IPCLITE_OS_LOG(IPCLITE_DBG, "hdr.type = %x,hdr.offset = %x,hdr.size = %d",
  646. ipcmem->partition[p]->hdr.type,
  647. ipcmem->partition[p]->hdr.desc_offset,
  648. ipcmem->partition[p]->hdr.desc_size);
  649. }
  650. static int32_t setup_partitions(struct ipclite_mem *ipcmem, uint32_t base_offset)
  651. {
  652. uint32_t p, host0, host1;
  653. uint32_t num_entry = 0;
  654. /*Fill in each valid ipcmem partition table entry*/
  655. for (host0 = 0; host0 < IPCMEM_NUM_HOSTS; host0++) {
  656. if (!is_host_enabled(host0))
  657. continue;
  658. for (host1 = host0; host1 < IPCMEM_NUM_HOSTS; host1++) {
  659. if (!is_host_enabled(host1) || is_loopback_except_apps(host0, host1))
  660. continue;
  661. ipcmem->toc_data.partition_entry[num_entry].base_offset = base_offset;
  662. ipcmem->toc_data.partition_entry[num_entry].size = DEFAULT_PARTITION_SIZE;
  663. ipcmem->toc_data.partition_entry[num_entry].flags = DEFAULT_PARTITION_FLAGS;
  664. ipcmem->toc_data.partition_entry[num_entry].host0 = host0;
  665. ipcmem->toc_data.partition_entry[num_entry].host1 = host1;
  666. base_offset += DEFAULT_PARTITION_SIZE;
  667. num_entry++;
  668. }
  669. }
  670. IPCLITE_OS_LOG(IPCLITE_DBG, "total partitions = %u", num_entry);
  671. ipcmem->partition = kcalloc(num_entry, sizeof(*ipcmem->partition), GFP_KERNEL);
  672. if (!ipcmem->partition) {
  673. IPCLITE_OS_LOG(IPCLITE_ERR, "Partition Allocation failed");
  674. return -ENOMEM;
  675. }
  676. /*Update appropriate partition based on partition entries*/
  677. for (p = 0; p < num_entry; p++)
  678. update_partition(ipcmem, p);
  679. /*Set up info to parse partition entries*/
  680. ipcmem->toc_data.partition_info->num_entries = partitions = num_entry;
  681. ipcmem->toc_data.partition_info->entry_size = sizeof(struct ipcmem_partition_entry);
  682. return 0;
  683. }
  684. static int32_t ipcmem_init(struct ipclite_mem *ipcmem, struct device_node *pn)
  685. {
  686. int ret = 0;
  687. uint32_t remote_pid = 0, host_count = 0, gmem_offset = 0;
  688. struct device_node *cn;
  689. for_each_available_child_of_node(pn, cn) {
  690. of_property_read_u32(cn, "qcom,remote-pid", &remote_pid);
  691. if (remote_pid < IPCMEM_NUM_HOSTS) {
  692. enabled_hosts |= BIT_MASK(remote_pid);
  693. host_count++;
  694. }
  695. }
  696. IPCLITE_OS_LOG(IPCLITE_DBG, "enabled_hosts = 0x%X", enabled_hosts);
  697. IPCLITE_OS_LOG(IPCLITE_DBG, "host_count = %u", host_count);
  698. ipcmem->toc = ipcmem->mem.virt_base;
  699. IPCLITE_OS_LOG(IPCLITE_DBG, "toc_base = %p\n", ipcmem->toc);
  700. ret = setup_toc(ipcmem);
  701. if (ret) {
  702. IPCLITE_OS_LOG(IPCLITE_ERR, "Failed to set up toc");
  703. return ret;
  704. }
  705. /*Set up host related info*/
  706. ipcmem->toc_data.host_info->hwlock_owner = IPCMEM_INVALID_HOST;
  707. ipcmem->toc_data.host_info->configured_host = enabled_hosts;
  708. gmem_offset += IPCMEM_TOC_SIZE;
  709. setup_global_partition(ipcmem, gmem_offset);
  710. gmem_offset += GLOBAL_PARTITION_SIZE;
  711. ret = setup_partitions(ipcmem, gmem_offset);
  712. if (ret) {
  713. IPCLITE_OS_LOG(IPCLITE_ERR, "Failed to set up partitions");
  714. return ret;
  715. }
  716. /*Making sure all writes for ipcmem configurations are completed*/
  717. wmb();
  718. ipcmem->toc->hdr.init_done = IPCMEM_INIT_COMPLETED;
  719. IPCLITE_OS_LOG(IPCLITE_DBG, "Ipcmem init completed\n");
  720. return 0;
  721. }
  722. static int ipclite_channel_irq_init(struct device *parent, struct device_node *node,
  723. struct ipclite_channel *channel)
  724. {
  725. int ret = 0;
  726. u32 index = 0;
  727. struct ipclite_irq_info *irq_info;
  728. struct device *dev;
  729. char strs[MAX_CHANNEL_SIGNALS][IPCLITE_SIGNAL_LABEL_SIZE] = {
  730. "msg", "mem-init", "version", "test", "ssr", "debug"};
  731. dev = kzalloc(sizeof(*dev), GFP_KERNEL);
  732. if (!dev)
  733. return -ENOMEM;
  734. dev->parent = parent;
  735. dev->of_node = node;
  736. dev_set_name(dev, "%s:%pOFn", dev_name(parent->parent), node);
  737. IPCLITE_OS_LOG(IPCLITE_DBG, "Registering %s device\n", dev_name(parent->parent));
  738. ret = device_register(dev);
  739. if (ret) {
  740. IPCLITE_OS_LOG(IPCLITE_ERR, "failed to register ipclite child node\n");
  741. put_device(dev);
  742. return ret;
  743. }
  744. ret = of_property_read_u32(dev->of_node, "index", &index);
  745. if (ret) {
  746. IPCLITE_OS_LOG(IPCLITE_ERR, "failed to parse index\n");
  747. goto err_dev;
  748. }
  749. irq_info = &channel->irq_info[index];
  750. IPCLITE_OS_LOG(IPCLITE_DBG, "irq_info[%d]=%p\n", index, irq_info);
  751. irq_info->mbox_client.dev = dev;
  752. irq_info->mbox_client.knows_txdone = true;
  753. irq_info->mbox_chan = mbox_request_channel(&irq_info->mbox_client, 0);
  754. IPCLITE_OS_LOG(IPCLITE_DBG, "irq_info[%d].mbox_chan=%p\n", index, irq_info->mbox_chan);
  755. if (IS_ERR(irq_info->mbox_chan)) {
  756. if (PTR_ERR(irq_info->mbox_chan) != -EPROBE_DEFER)
  757. IPCLITE_OS_LOG(IPCLITE_ERR, "failed to acquire IPC channel\n");
  758. goto err_dev;
  759. }
  760. snprintf(irq_info->irqname, 32, "ipclite-signal-%s", strs[index]);
  761. irq_info->irq = of_irq_get(dev->of_node, 0);
  762. IPCLITE_OS_LOG(IPCLITE_DBG, "irq[%d] = %d\n", index, irq_info->irq);
  763. irq_info->signal_id = index;
  764. ret = devm_request_irq(dev, irq_info->irq,
  765. ipclite_intr,
  766. IRQF_NO_SUSPEND | IRQF_SHARED,
  767. irq_info->irqname, irq_info);
  768. if (ret) {
  769. IPCLITE_OS_LOG(IPCLITE_ERR, "failed to request IRQ\n");
  770. goto err_dev;
  771. }
  772. IPCLITE_OS_LOG(IPCLITE_DBG, "Interrupt init completed, ret = %d\n", ret);
  773. return ret;
  774. err_dev:
  775. device_unregister(dev);
  776. kfree(dev);
  777. return ret;
  778. }
  779. static struct ipcmem_partition_header *get_ipcmem_partition_hdr(struct ipclite_mem ipcmem, int local_pid,
  780. int remote_pid)
  781. {
  782. uint32_t p = 0, found = -1;
  783. for (p = 0; p < partitions; p++) {
  784. if (ipcmem.toc_data.partition_entry[p].host0 == local_pid
  785. && ipcmem.toc_data.partition_entry[p].host1 == remote_pid) {
  786. found = p;
  787. break;
  788. }
  789. }
  790. if (found < partitions)
  791. return (struct ipcmem_partition_header *)((char *)ipcmem.mem.virt_base +
  792. ipcmem.toc_data.partition_entry[found].base_offset);
  793. else
  794. return NULL;
  795. }
  796. static void ipclite_channel_release(struct device *dev)
  797. {
  798. IPCLITE_OS_LOG(IPCLITE_INFO, "Releasing ipclite channel\n");
  799. kfree(dev);
  800. }
  801. /* Sets up following fields of IPCLite channel structure:
  802. * remote_pid,tx_fifo, rx_fifo
  803. */
  804. static int ipclite_channel_init(struct device *parent,
  805. struct device_node *node)
  806. {
  807. int ret = 0;
  808. u32 local_pid = 0, remote_pid = 0;
  809. u32 *descs = NULL;
  810. struct ipclite_fifo *rx_fifo;
  811. struct ipclite_fifo *tx_fifo;
  812. struct device *dev;
  813. struct device_node *child;
  814. struct ipcmem_partition_header *partition_hdr;
  815. dev = kzalloc(sizeof(*dev), GFP_KERNEL);
  816. if (!dev)
  817. return -ENOMEM;
  818. dev->parent = parent;
  819. dev->of_node = node;
  820. dev->release = ipclite_channel_release;
  821. dev_set_name(dev, "%s:%pOFn", dev_name(parent->parent), node);
  822. IPCLITE_OS_LOG(IPCLITE_DBG, "Registering %s device\n", dev_name(parent->parent));
  823. ret = device_register(dev);
  824. if (ret) {
  825. IPCLITE_OS_LOG(IPCLITE_ERR, "failed to register ipclite device\n");
  826. put_device(dev);
  827. kfree(dev);
  828. return ret;
  829. }
  830. local_pid = LOCAL_HOST;
  831. ret = of_property_read_u32(dev->of_node, "qcom,remote-pid",
  832. &remote_pid);
  833. if (ret) {
  834. dev_err(dev, "failed to parse qcom,remote-pid\n");
  835. goto err_put_dev;
  836. }
  837. IPCLITE_OS_LOG(IPCLITE_DBG, "remote_pid = %d, local_pid=%d\n", remote_pid, local_pid);
  838. rx_fifo = devm_kzalloc(dev, sizeof(*rx_fifo), GFP_KERNEL);
  839. tx_fifo = devm_kzalloc(dev, sizeof(*tx_fifo), GFP_KERNEL);
  840. if (!rx_fifo || !tx_fifo) {
  841. ret = -ENOMEM;
  842. goto err_put_dev;
  843. }
  844. IPCLITE_OS_LOG(IPCLITE_DBG, "rx_fifo = %p, tx_fifo=%p\n", rx_fifo, tx_fifo);
  845. partition_hdr = get_ipcmem_partition_hdr(ipclite->ipcmem, local_pid, remote_pid);
  846. IPCLITE_OS_LOG(IPCLITE_DBG, "partition_hdr = %p\n", partition_hdr);
  847. if (!partition_hdr) {
  848. ret = -ENOMEM;
  849. goto err_put_dev;
  850. }
  851. descs = (u32 *)((char *)partition_hdr + partition_hdr->desc_offset);
  852. IPCLITE_OS_LOG(IPCLITE_DBG, "descs = %p\n", descs);
  853. if (local_pid < remote_pid) {
  854. tx_fifo->fifo = (char *)partition_hdr + partition_hdr->fifo0_offset;
  855. tx_fifo->length = partition_hdr->fifo0_size;
  856. rx_fifo->fifo = (char *)partition_hdr + partition_hdr->fifo1_offset;
  857. rx_fifo->length = partition_hdr->fifo1_size;
  858. tx_fifo->tail = &descs[0];
  859. tx_fifo->head = &descs[1];
  860. rx_fifo->tail = &descs[2];
  861. rx_fifo->head = &descs[3];
  862. } else {
  863. tx_fifo->fifo = (char *)partition_hdr + partition_hdr->fifo1_offset;
  864. tx_fifo->length = partition_hdr->fifo1_size;
  865. rx_fifo->fifo = (char *)partition_hdr + partition_hdr->fifo0_offset;
  866. rx_fifo->length = partition_hdr->fifo0_size;
  867. rx_fifo->tail = &descs[0];
  868. rx_fifo->head = &descs[1];
  869. tx_fifo->tail = &descs[2];
  870. tx_fifo->head = &descs[3];
  871. }
  872. if (partition_hdr->type == LOOPBACK_PARTITION_TYPE) {
  873. rx_fifo->tail = tx_fifo->tail;
  874. rx_fifo->head = tx_fifo->head;
  875. }
  876. /* rx_fifo->reset = ipcmem_rx_reset;*/
  877. rx_fifo->avail = ipcmem_rx_avail;
  878. rx_fifo->peak = ipcmem_rx_peak;
  879. rx_fifo->advance = ipcmem_rx_advance;
  880. /* tx_fifo->reset = ipcmem_tx_reset;*/
  881. tx_fifo->avail = ipcmem_tx_avail;
  882. tx_fifo->write = ipcmem_tx_write;
  883. *rx_fifo->tail = 0;
  884. *tx_fifo->head = 0;
  885. /*Store Channel Information*/
  886. ipclite->channel[remote_pid].remote_pid = remote_pid;
  887. ipclite->channel[remote_pid].tx_fifo = tx_fifo;
  888. ipclite->channel[remote_pid].rx_fifo = rx_fifo;
  889. ipclite->channel[remote_pid].gstatus_ptr = &partition_hdr->status;
  890. spin_lock_init(&ipclite->channel[remote_pid].tx_lock);
  891. for_each_available_child_of_node(dev->of_node, child) {
  892. ret = ipclite_channel_irq_init(dev, child,
  893. &ipclite->channel[remote_pid]);
  894. if (ret) {
  895. IPCLITE_OS_LOG(IPCLITE_ERR, "irq setup for ipclite channel failed\n");
  896. goto err_put_dev;
  897. }
  898. }
  899. /* Updating Local & Global Channel Status */
  900. if (remote_pid == IPCMEM_APPS) {
  901. *ipclite->channel[remote_pid].gstatus_ptr = ACTIVE;
  902. ipclite->channel[remote_pid].status = ACTIVE;
  903. } else {
  904. *ipclite->channel[remote_pid].gstatus_ptr = IN_PROGRESS;
  905. ipclite->channel[remote_pid].status = IN_PROGRESS;
  906. }
  907. IPCLITE_OS_LOG(IPCLITE_DBG, "Channel init completed, ret = %d\n", ret);
  908. return ret;
  909. err_put_dev:
  910. ipclite->channel[remote_pid].status = INACTIVE;
  911. device_unregister(dev);
  912. kfree(dev);
  913. return ret;
  914. }
  915. static void probe_subsystem(struct device *dev, struct device_node *np)
  916. {
  917. int ret = 0;
  918. ret = ipclite_channel_init(dev, np);
  919. if (ret)
  920. IPCLITE_OS_LOG(IPCLITE_ERR, "IPCLite Channel init failed\n");
  921. }
  922. /* IPCLite Debug related functions start */
  923. static ssize_t ipclite_dbg_lvl_write(struct kobject *kobj,
  924. struct kobj_attribute *attr, const char *buf, size_t count)
  925. {
  926. int ret = 0, host = 0;
  927. /* Parse the string from Sysfs Interface */
  928. ret = kstrtoint(buf, 0, &ipclite_debug_level);
  929. if (ret < 0) {
  930. IPCLITE_OS_LOG(IPCLITE_ERR, "Error parsing the sysfs value");
  931. return ret;
  932. }
  933. /* Check if debug structure is initialized */
  934. if (!ipclite_dbg_info) {
  935. IPCLITE_OS_LOG(IPCLITE_ERR, "Debug structures not initialized\n");
  936. return -ENOMEM;
  937. }
  938. /* Update the Global Debug variable for FW cores */
  939. ipclite_dbg_info->debug_level = ipclite_debug_level;
  940. /* Memory Barrier to make sure all writes are completed */
  941. wmb();
  942. /* Signal other cores for updating the debug information */
  943. for (host = 1; host < IPCMEM_NUM_HOSTS; host++) {
  944. if (!is_host_enabled(host))
  945. continue;
  946. ret = ipclite_notify_core(host, IPCLITE_DEBUG_SIGNAL);
  947. if (ret < 0)
  948. IPCLITE_OS_LOG(IPCLITE_ERR, "Failed to send the debug info %d\n", host);
  949. else
  950. IPCLITE_OS_LOG(IPCLITE_DBG, "Debug info sent to host %d\n", host);
  951. }
  952. return count;
  953. }
  954. static ssize_t ipclite_dbg_ctrl_write(struct kobject *kobj,
  955. struct kobj_attribute *attr, const char *buf, size_t count)
  956. {
  957. int ret = 0, host = 0;
  958. /* Parse the string from Sysfs Interface */
  959. ret = kstrtoint(buf, 0, &ipclite_debug_control);
  960. if (ret < 0) {
  961. IPCLITE_OS_LOG(IPCLITE_ERR, "Error parsing the sysfs value");
  962. return ret;
  963. }
  964. /* Check if debug structures are initialized */
  965. if (!ipclite_dbg_info || !ipclite_dbg_struct || !ipclite_dbg_inmem) {
  966. IPCLITE_OS_LOG(IPCLITE_ERR, "Debug structures not initialized\n");
  967. return -ENOMEM;
  968. }
  969. /* Update the Global Debug variable for FW cores */
  970. ipclite_dbg_info->debug_control = ipclite_debug_control;
  971. /* Memory Barrier to make sure all writes are completed */
  972. wmb();
  973. /* Signal other cores for updating the debug information */
  974. for (host = 1; host < IPCMEM_NUM_HOSTS; host++) {
  975. if (!is_host_enabled(host))
  976. continue;
  977. ret = ipclite_notify_core(host, IPCLITE_DEBUG_SIGNAL);
  978. if (ret < 0)
  979. IPCLITE_OS_LOG(IPCLITE_ERR, "Failed to send the debug info %d\n", host);
  980. else
  981. IPCLITE_OS_LOG(IPCLITE_DBG, "Debug info sent to host %d\n", host);
  982. }
  983. return count;
  984. }
  985. static ssize_t ipclite_dbg_dump_write(struct kobject *kobj,
  986. struct kobj_attribute *attr, const char *buf, size_t count)
  987. {
  988. int ret = 0;
  989. /* Parse the string from Sysfs Interface */
  990. ret = kstrtoint(buf, 0, &ipclite_debug_dump);
  991. if (ret < 0) {
  992. IPCLITE_OS_LOG(IPCLITE_ERR, "Error parsing the sysfs value");
  993. return ret;
  994. }
  995. /* Check if debug structures are initialized */
  996. if (!ipclite_dbg_info || !ipclite_dbg_struct || !ipclite_dbg_inmem) {
  997. IPCLITE_OS_LOG(IPCLITE_ERR, "Debug structures not initialized\n");
  998. return -ENOMEM;
  999. }
  1000. /* Dump the debug information */
  1001. if (ipclite_debug_dump & IPCLITE_DUMP_DBG_STRUCT)
  1002. ipclite_dump_debug_struct();
  1003. if (ipclite_debug_dump & IPCLITE_DUMP_INMEM_LOG)
  1004. ipclite_dump_inmem_logs();
  1005. return count;
  1006. }
  1007. struct kobj_attribute sysfs_dbg_lvl = __ATTR(ipclite_debug_level, 0660,
  1008. NULL, ipclite_dbg_lvl_write);
  1009. struct kobj_attribute sysfs_dbg_ctrl = __ATTR(ipclite_debug_control, 0660,
  1010. NULL, ipclite_dbg_ctrl_write);
  1011. struct kobj_attribute sysfs_dbg_dump = __ATTR(ipclite_debug_dump, 0660,
  1012. NULL, ipclite_dbg_dump_write);
  1013. static int ipclite_debug_sysfs_setup(void)
  1014. {
  1015. int ret = 0;
  1016. /* Creating a directory in /sys/kernel/ */
  1017. sysfs_kobj = kobject_create_and_add("ipclite", kernel_kobj);
  1018. if (!sysfs_kobj) {
  1019. IPCLITE_OS_LOG(IPCLITE_ERR, "Cannot create and add sysfs directory\n");
  1020. return -ENOMEM;
  1021. }
  1022. /* Creating sysfs files/interfaces for debug */
  1023. ret = sysfs_create_file(sysfs_kobj, &sysfs_dbg_lvl.attr);
  1024. if (ret) {
  1025. IPCLITE_OS_LOG(IPCLITE_ERR, "Cannot create sysfs debug level file\n");
  1026. return ret;
  1027. }
  1028. ret = sysfs_create_file(sysfs_kobj, &sysfs_dbg_ctrl.attr);
  1029. if (ret) {
  1030. IPCLITE_OS_LOG(IPCLITE_ERR, "Cannot create sysfs debug control file\n");
  1031. return ret;
  1032. }
  1033. ret = sysfs_create_file(sysfs_kobj, &sysfs_dbg_dump.attr);
  1034. if (ret) {
  1035. IPCLITE_OS_LOG(IPCLITE_ERR, "Cannot create sysfs debug dump file\n");
  1036. return ret;
  1037. }
  1038. return ret;
  1039. }
  1040. static int ipclite_debug_mem_setup(void)
  1041. {
  1042. /* Setting up the Debug Structures */
  1043. ipclite_dbg_info = (struct ipclite_debug_info *)(((char *)ipclite->ipcmem.mem.virt_base +
  1044. ipclite->ipcmem.mem.size) - DEBUG_PARTITION_SIZE);
  1045. if (!ipclite_dbg_info)
  1046. return -EADDRNOTAVAIL;
  1047. ipclite_dbg_struct = (struct ipclite_debug_struct *)
  1048. (((char *)ipclite_dbg_info + IPCLITE_DEBUG_INFO_SIZE) +
  1049. (sizeof(*ipclite_dbg_struct) * IPCMEM_APPS));
  1050. if (!ipclite_dbg_struct)
  1051. return -EADDRNOTAVAIL;
  1052. ipclite_dbg_inmem = (struct ipclite_debug_inmem_buf *)
  1053. (((char *)ipclite_dbg_info + IPCLITE_DEBUG_INFO_SIZE) +
  1054. (sizeof(*ipclite_dbg_struct) * IPCMEM_NUM_HOSTS));
  1055. if (!ipclite_dbg_inmem)
  1056. return -EADDRNOTAVAIL;
  1057. IPCLITE_OS_LOG(IPCLITE_DBG, "virtual_base_ptr = %p total_size : %d debug_size : %d\n",
  1058. ipclite->ipcmem.mem.virt_base, ipclite->ipcmem.mem.size, DEBUG_PARTITION_SIZE);
  1059. IPCLITE_OS_LOG(IPCLITE_DBG, "dbg_info : %p dbg_struct : %p dbg_inmem : %p\n",
  1060. ipclite_dbg_info, ipclite_dbg_struct, ipclite_dbg_inmem);
  1061. return 0;
  1062. }
  1063. static int ipclite_debug_setup(void)
  1064. {
  1065. int ret = 0;
  1066. /* Set up sysfs for debug */
  1067. ret = ipclite_debug_sysfs_setup();
  1068. if (ret != 0) {
  1069. IPCLITE_OS_LOG(IPCLITE_ERR, "Failed to Set up IPCLite Debug Sysfs\n");
  1070. return ret;
  1071. }
  1072. /* Mapping Debug Memory */
  1073. ret = ipclite_debug_mem_setup();
  1074. if (ret != 0) {
  1075. IPCLITE_OS_LOG(IPCLITE_ERR, "Failed to Set up IPCLite Debug Structures\n");
  1076. return ret;
  1077. }
  1078. /* Update the Global Debug variable for FW cores */
  1079. ipclite_dbg_info->debug_level = ipclite_debug_level;
  1080. ipclite_dbg_info->debug_control = ipclite_debug_control;
  1081. return ret;
  1082. }
  1083. /* IPCLite Debug related functions end */
  1084. /* IPCLite Features setup related functions start */
  1085. static int ipclite_feature_setup(struct device_node *pn)
  1086. {
  1087. int ret = 0;
  1088. uint32_t feature_mask_l = 0, feature_mask_h = 0;
  1089. /* Parse the feature related DT entries and store the values locally */
  1090. ret = of_property_read_u32(pn, "feature_mask_low", &feature_mask_l);
  1091. if (ret != 0) {
  1092. IPCLITE_OS_LOG(IPCLITE_ERR, "failed to parse feature_mask_low\n");
  1093. return ret;
  1094. }
  1095. ret = of_property_read_u32(pn, "feature_mask_high", &feature_mask_h);
  1096. if (ret != 0) {
  1097. IPCLITE_OS_LOG(IPCLITE_ERR, "failed to parse feature_mask_high\n");
  1098. return ret;
  1099. }
  1100. /* Combine feature_mask_low and feature_mask_high into 64-bit feature_mask */
  1101. feature_mask = (uint64_t) feature_mask_h << 32 | feature_mask_l;
  1102. /* Update the feature mask to TOC for FW */
  1103. ipclite->ipcmem.toc->hdr.feature_mask = feature_mask;
  1104. /* Set up Global Atomics Feature*/
  1105. if (!(IS_FEATURE_CONFIG(IPCLITE_GLOBAL_ATOMIC)))
  1106. IPCLITE_OS_LOG(IPCLITE_INFO, "IPCLite Global Atomic Support Disabled\n");
  1107. /* Set up Test Suite Feature*/
  1108. if (!(IS_FEATURE_CONFIG(IPCLITE_TEST_SUITE)))
  1109. IPCLITE_OS_LOG(IPCLITE_INFO, "IPCLite Test Suite Disabled\n");
  1110. return ret;
  1111. }
  1112. /* IPCLite Features setup related functions end */
  1113. /* API Definition Start - Minor Version 0*/
  1114. static int ipclite_init_v0(struct platform_device *pdev)
  1115. {
  1116. int ret = 0, hwlock_id = 0;
  1117. struct ipcmem_region *mem;
  1118. struct device_node *cn;
  1119. struct device_node *pn = pdev->dev.of_node;
  1120. struct ipclite_channel broadcast;
  1121. /* Allocate memory for IPCLite */
  1122. ipclite = kzalloc(sizeof(*ipclite), GFP_KERNEL);
  1123. if (!ipclite) {
  1124. IPCLITE_OS_LOG(IPCLITE_ERR, "IPCLite Memory Allocation Failed\n");
  1125. ret = -ENOMEM;
  1126. goto error;
  1127. }
  1128. ipclite->dev = &pdev->dev;
  1129. /* Parse HW Lock from DT */
  1130. hwlock_id = of_hwspin_lock_get_id(pn, 0);
  1131. if (hwlock_id < 0) {
  1132. if (hwlock_id != -EPROBE_DEFER)
  1133. dev_err(&pdev->dev, "failed to retrieve hwlock\n");
  1134. ret = hwlock_id;
  1135. goto release;
  1136. }
  1137. IPCLITE_OS_LOG(IPCLITE_DBG, "Hwlock id retrieved, hwlock_id=%d\n", hwlock_id);
  1138. /* Reserve a HWSpinLock for later use */
  1139. ipclite->hwlock = hwspin_lock_request_specific(hwlock_id);
  1140. if (!ipclite->hwlock) {
  1141. IPCLITE_OS_LOG(IPCLITE_ERR, "Failed to assign hwlock_id\n");
  1142. ret = -ENXIO;
  1143. goto release;
  1144. }
  1145. IPCLITE_OS_LOG(IPCLITE_DBG, "Hwlock id assigned successfully, hwlock=%p\n",
  1146. ipclite->hwlock);
  1147. /* Initializing Local Mutex Lock for SSR functionality */
  1148. mutex_init(&ssr_mutex);
  1149. /* Map to IPCLite Memory */
  1150. ret = map_ipcmem(ipclite, "memory-region");
  1151. if (ret) {
  1152. IPCLITE_OS_LOG(IPCLITE_ERR, "failed to map ipcmem\n");
  1153. goto release;
  1154. }
  1155. mem = &(ipclite->ipcmem.mem);
  1156. memset(mem->virt_base, 0, mem->size);
  1157. ret = ipcmem_init(&ipclite->ipcmem, pn);
  1158. if (ret) {
  1159. IPCLITE_OS_LOG(IPCLITE_ERR, "Failed to set up IPCMEM");
  1160. goto release;
  1161. }
  1162. /* Setup Channel for each Remote Subsystem */
  1163. for_each_available_child_of_node(pn, cn)
  1164. probe_subsystem(&pdev->dev, cn);
  1165. /* Broadcast init_done signal to all subsystems once mbox channels are set up */
  1166. broadcast = ipclite->channel[IPCMEM_APPS];
  1167. ret = mbox_send_message(broadcast.irq_info[IPCLITE_MEM_INIT_SIGNAL].mbox_chan, NULL);
  1168. if (ret < 0)
  1169. goto mem_release;
  1170. mbox_client_txdone(broadcast.irq_info[IPCLITE_MEM_INIT_SIGNAL].mbox_chan, 0);
  1171. /* Debug Setup */
  1172. ret = ipclite_debug_setup();
  1173. if (ret != 0) {
  1174. IPCLITE_OS_LOG(IPCLITE_ERR, "IPCLite Debug Setup Failed\n");
  1175. goto release;
  1176. }
  1177. /* Features Setup */
  1178. ret = ipclite_feature_setup(pn);
  1179. if (ret != 0) {
  1180. IPCLITE_OS_LOG(IPCLITE_ERR, "IPCLite Features Setup Failed\n");
  1181. goto release;
  1182. }
  1183. /* Update TOC with version entries for FW */
  1184. ipclite->ipcmem.toc->hdr.major_version = major_ver;
  1185. ipclite->ipcmem.toc->hdr.minor_version = minor_ver;
  1186. /* Should be called after all Global TOC related init is done */
  1187. insert_magic_number();
  1188. IPCLITE_OS_LOG(IPCLITE_INFO, "IPCLite Version : %d.%d Feature Mask : 0x%llx\n",
  1189. major_ver, minor_ver, feature_mask);
  1190. IPCLITE_OS_LOG(IPCLITE_INFO, "IPCLite Probe Completed Successfully\n");
  1191. return ret;
  1192. mem_release:
  1193. /* If the remote subsystem has already completed the init and actively
  1194. * using IPCMEM, re-assigning IPCMEM memory back to HLOS can lead to crash
  1195. * Solution: Either we don't take back the memory or make sure APPS completes
  1196. * init before any other subsystem initializes IPCLite (we won't have to send
  1197. * braodcast)
  1198. */
  1199. release:
  1200. kfree(ipclite);
  1201. ipclite = NULL;
  1202. error:
  1203. return ret;
  1204. }
  1205. static int ipclite_register_client_v0(IPCLite_Client cb_func_ptr, void *priv)
  1206. {
  1207. if (!cb_func_ptr) {
  1208. IPCLITE_OS_LOG(IPCLITE_ERR, "Invalid callback pointer\n");
  1209. return -EINVAL;
  1210. }
  1211. synx_client.callback = cb_func_ptr;
  1212. synx_client.priv_data = priv;
  1213. synx_client.reg_complete = 1;
  1214. IPCLITE_OS_LOG(IPCLITE_DBG, "Client Registration completed\n");
  1215. return 0;
  1216. }
  1217. static int ipclite_register_test_client_v0(IPCLite_Client cb_func_ptr, void *priv)
  1218. {
  1219. if (!cb_func_ptr) {
  1220. IPCLITE_OS_LOG(IPCLITE_ERR, "Invalid callback pointer\n");
  1221. return -EINVAL;
  1222. }
  1223. test_client.callback = cb_func_ptr;
  1224. test_client.priv_data = priv;
  1225. test_client.reg_complete = 1;
  1226. IPCLITE_OS_LOG(IPCLITE_DBG, "Test Client Registration Completed\n");
  1227. return 0;
  1228. }
  1229. static int ipclite_msg_send_v0(int32_t proc_id, uint64_t data)
  1230. {
  1231. int ret = 0;
  1232. /* Check for valid core id */
  1233. if (proc_id < 0 || proc_id >= IPCMEM_NUM_HOSTS) {
  1234. IPCLITE_OS_LOG(IPCLITE_ERR, "Invalid proc_id : %d\n", proc_id);
  1235. return -EINVAL;
  1236. }
  1237. /* Send the data to the core */
  1238. ret = ipclite_tx(&ipclite->channel[proc_id], data, sizeof(data), IPCLITE_MSG_SIGNAL);
  1239. if (ret < 0) {
  1240. IPCLITE_OS_LOG(IPCLITE_ERR, "Message send failed to core : %d signal:%d ret:%d\n",
  1241. proc_id, IPCLITE_MSG_SIGNAL, ret);
  1242. return ret;
  1243. }
  1244. IPCLITE_OS_LOG(IPCLITE_DBG, "Message send complete to core : %d signal : %d ret : %d\n",
  1245. proc_id, IPCLITE_MSG_SIGNAL, ret);
  1246. return ret;
  1247. }
  1248. static int ipclite_test_msg_send_v0(int32_t proc_id, uint64_t data)
  1249. {
  1250. int ret = 0;
  1251. /* Check for valid core id */
  1252. if (proc_id < 0 || proc_id >= IPCMEM_NUM_HOSTS) {
  1253. IPCLITE_OS_LOG(IPCLITE_ERR, "Invalid proc_id : %d\n", proc_id);
  1254. return -EINVAL;
  1255. }
  1256. /* Send the data to the core */
  1257. ret = ipclite_tx(&ipclite->channel[proc_id], data, sizeof(data), IPCLITE_TEST_SIGNAL);
  1258. if (ret < 0) {
  1259. IPCLITE_OS_LOG(IPCLITE_ERR, "Message send failed to core : %d signal:%d ret:%d\n",
  1260. proc_id, IPCLITE_TEST_SIGNAL, ret);
  1261. return ret;
  1262. }
  1263. IPCLITE_OS_LOG(IPCLITE_DBG, "Test Msg send complete to core : %d signal : %d ret : %d\n",
  1264. proc_id, IPCLITE_TEST_SIGNAL, ret);
  1265. return ret;
  1266. }
  1267. static int32_t get_global_partition_info_v0(struct global_region_info *global_ipcmem)
  1268. {
  1269. struct ipcmem_global_partition *global_partition;
  1270. if (!ipclite) {
  1271. IPCLITE_OS_LOG(IPCLITE_ERR, "IPCLite not initialized\n");
  1272. return -ENOMEM;
  1273. }
  1274. if (!global_ipcmem)
  1275. return -EINVAL;
  1276. global_partition = ipclite->ipcmem.global_partition;
  1277. global_ipcmem->virt_base = (void *)((char *)global_partition +
  1278. global_partition->hdr.region_offset);
  1279. global_ipcmem->size = (size_t)(global_partition->hdr.region_size);
  1280. IPCLITE_OS_LOG(IPCLITE_DBG, "base = %p, size=%lx\n", global_ipcmem->virt_base,
  1281. global_ipcmem->size);
  1282. return 0;
  1283. }
  1284. static void ipclite_recover_v0(enum ipcmem_host_type core_id)
  1285. {
  1286. int ret = 0, host = 0, host0 = 0, host1 = 0;
  1287. uint32_t p = 0;
  1288. IPCLITE_OS_LOG(IPCLITE_DBG, "IPCLite Recover - Crashed Core : %d\n", core_id);
  1289. /* verify and reset the hw mutex lock */
  1290. if (core_id == ipclite->ipcmem.toc_data.host_info->hwlock_owner) {
  1291. ipclite->ipcmem.toc_data.host_info->hwlock_owner = IPCMEM_INVALID_HOST;
  1292. hwspin_unlock_raw(ipclite->hwlock);
  1293. IPCLITE_OS_LOG(IPCLITE_DBG, "HW Lock Reset\n");
  1294. }
  1295. mutex_lock(&ssr_mutex);
  1296. /* Set the Global Channel Status to 0 to avoid Race condition */
  1297. for (p = 0; p < partitions; p++) {
  1298. host0 = ipclite->ipcmem.toc_data.partition_entry[p].host0;
  1299. host1 = ipclite->ipcmem.toc_data.partition_entry[p].host1;
  1300. if (host0 != core_id && host1 != core_id)
  1301. continue;
  1302. ipclite_global_atomic_store_i32((ipclite_atomic_int32_t *)
  1303. (&(ipclite->ipcmem.partition[p]->hdr.status)), 0);
  1304. IPCLITE_OS_LOG(IPCLITE_DBG, "Global Channel Status : [%d][%d] : %d\n",
  1305. host0, host1, ipclite->ipcmem.partition[p]->hdr.status);
  1306. }
  1307. /* Resets the TX/RX queue */
  1308. *(ipclite->channel[core_id].tx_fifo->head) = 0;
  1309. *(ipclite->channel[core_id].rx_fifo->tail) = 0;
  1310. IPCLITE_OS_LOG(IPCLITE_DBG, "TX Fifo Reset : %d\n",
  1311. *(ipclite->channel[core_id].tx_fifo->head));
  1312. IPCLITE_OS_LOG(IPCLITE_DBG, "RX Fifo Reset : %d\n",
  1313. *(ipclite->channel[core_id].rx_fifo->tail));
  1314. /* Increment the Global Channel Status for APPS and crashed core*/
  1315. ipclite_global_atomic_inc((ipclite_atomic_int32_t *)
  1316. ipclite->channel[core_id].gstatus_ptr);
  1317. ipclite->channel[core_id].status = *ipclite->channel[core_id].gstatus_ptr;
  1318. /* Update other cores about SSR */
  1319. for (host = 1; host < IPCMEM_NUM_HOSTS; host++) {
  1320. if (!is_host_enabled(host) || host == core_id)
  1321. continue;
  1322. ret = ipclite_notify_core(host, IPCLITE_SSR_SIGNAL);
  1323. if (ret < 0)
  1324. IPCLITE_OS_LOG(IPCLITE_ERR, "Failed to send SSR update to core %d\n", host);
  1325. else
  1326. IPCLITE_OS_LOG(IPCLITE_DBG, "SSR update sent to core %d\n", host);
  1327. }
  1328. mutex_unlock(&ssr_mutex);
  1329. /* Dump the debug information */
  1330. if (ipclite_debug_dump & IPCLITE_DUMP_SSR) {
  1331. ipclite_dump_debug_struct();
  1332. ipclite_dump_inmem_logs();
  1333. }
  1334. }
  1335. /* API Definition End - Minor Version 0*/
  1336. /* Versioned Functions Start */
  1337. int ipclite_init(struct platform_device *pdev)
  1338. {
  1339. if (api_list_t.init == NULL) {
  1340. IPCLITE_OS_LOG(IPCLITE_ERR, "Unassigned function : %s", __func__);
  1341. return -EINVAL;
  1342. }
  1343. return api_list_t.init(pdev);
  1344. }
  1345. int ipclite_register_client(IPCLite_Client cb_func_ptr, void *priv)
  1346. {
  1347. if (api_list_t.register_client == NULL) {
  1348. IPCLITE_OS_LOG(IPCLITE_ERR, "Unassigned function : %s", __func__);
  1349. return -EINVAL;
  1350. }
  1351. return api_list_t.register_client(cb_func_ptr, priv);
  1352. }
  1353. EXPORT_SYMBOL(ipclite_register_client);
  1354. int ipclite_register_test_client(IPCLite_Client cb_func_ptr, void *priv)
  1355. {
  1356. if (api_list_t.register_test_client == NULL) {
  1357. IPCLITE_OS_LOG(IPCLITE_ERR, "Unassigned function : %s", __func__);
  1358. return -EINVAL;
  1359. }
  1360. return api_list_t.register_test_client(cb_func_ptr, priv);
  1361. }
  1362. EXPORT_SYMBOL(ipclite_register_test_client);
  1363. int ipclite_msg_send(int32_t proc_id, uint64_t data)
  1364. {
  1365. if (api_list_t.msg_send == NULL) {
  1366. IPCLITE_OS_LOG(IPCLITE_ERR, "Unassigned function : %s", __func__);
  1367. return -EINVAL;
  1368. }
  1369. return api_list_t.msg_send(proc_id, data);
  1370. }
  1371. EXPORT_SYMBOL(ipclite_msg_send);
  1372. int ipclite_test_msg_send(int32_t proc_id, uint64_t data)
  1373. {
  1374. if (api_list_t.test_msg_send == NULL) {
  1375. IPCLITE_OS_LOG(IPCLITE_ERR, "Unassigned function : %s", __func__);
  1376. return -EINVAL;
  1377. }
  1378. return api_list_t.test_msg_send(proc_id, data);
  1379. }
  1380. EXPORT_SYMBOL(ipclite_test_msg_send);
  1381. void ipclite_recover(enum ipcmem_host_type core_id)
  1382. {
  1383. if (api_list_t.recover == NULL) {
  1384. IPCLITE_OS_LOG(IPCLITE_ERR, "Unassigned function : %s", __func__);
  1385. return;
  1386. }
  1387. api_list_t.recover(core_id);
  1388. }
  1389. EXPORT_SYMBOL(ipclite_recover);
  1390. int32_t get_global_partition_info(struct global_region_info *global_ipcmem)
  1391. {
  1392. if (api_list_t.partition_info == NULL) {
  1393. IPCLITE_OS_LOG(IPCLITE_ERR, "Unassigned function : %s", __func__);
  1394. return -EINVAL;
  1395. }
  1396. return api_list_t.partition_info(global_ipcmem);
  1397. }
  1398. EXPORT_SYMBOL(get_global_partition_info);
  1399. /* Versioned Functions End */
  1400. /* List of APIs based on the version */
  1401. struct ipclite_api_list api_list_version[] = {
  1402. /* Minor Version 0 */
  1403. {
  1404. .init = ipclite_init_v0,
  1405. .register_client = ipclite_register_client_v0,
  1406. .register_test_client = ipclite_register_test_client_v0,
  1407. .msg_send = ipclite_msg_send_v0,
  1408. .test_msg_send = ipclite_test_msg_send_v0,
  1409. .partition_info = get_global_partition_info_v0,
  1410. .recover = ipclite_recover_v0,
  1411. },
  1412. };
  1413. /* IPCLite Version setup related functions start */
  1414. static int ipclite_update_version_api(struct ipclite_api_list *res_str,
  1415. struct ipclite_api_list *ver_str)
  1416. {
  1417. if (res_str == NULL || ver_str == NULL)
  1418. return -EINVAL;
  1419. /* Register APIs based on the version */
  1420. res_str->init = (ver_str->init != NULL) ?
  1421. ver_str->init : res_str->init;
  1422. res_str->register_client = (ver_str->register_client != NULL) ?
  1423. ver_str->register_client : res_str->register_client;
  1424. res_str->register_test_client = (ver_str->register_test_client != NULL) ?
  1425. ver_str->register_test_client : res_str->register_test_client;
  1426. res_str->msg_send = (ver_str->msg_send != NULL) ?
  1427. ver_str->msg_send : res_str->msg_send;
  1428. res_str->test_msg_send = (ver_str->test_msg_send != NULL) ?
  1429. ver_str->test_msg_send : res_str->test_msg_send;
  1430. res_str->partition_info = (ver_str->partition_info != NULL) ?
  1431. ver_str->partition_info : res_str->partition_info;
  1432. res_str->recover = (ver_str->recover != NULL) ?
  1433. ver_str->recover : res_str->recover;
  1434. return 0;
  1435. }
  1436. static int ipclite_register_api(void)
  1437. {
  1438. int ret = 0, ver_itr = 0;
  1439. /* Register APIs based on the version */
  1440. for (ver_itr = 0; ver_itr <= minor_ver; ver_itr++) {
  1441. ret = ipclite_update_version_api(&api_list_t, &api_list_version[ver_itr]);
  1442. if (ret != 0)
  1443. return ret;
  1444. }
  1445. return ret;
  1446. }
  1447. static int ipclite_version_setup(struct device_node *pn)
  1448. {
  1449. int ret = 0;
  1450. /* Parse the version related DT entries and store the values locally */
  1451. ret = of_property_read_u32(pn, "major_version", &major_ver);
  1452. if (ret != 0) {
  1453. IPCLITE_OS_LOG(IPCLITE_ERR, "failed to parse major_vesion\n");
  1454. return ret;
  1455. }
  1456. ret = of_property_read_u32(pn, "minor_version", &minor_ver);
  1457. if (ret != 0) {
  1458. IPCLITE_OS_LOG(IPCLITE_ERR, "failed to parse minor_vesion\n");
  1459. return ret;
  1460. }
  1461. /* Verify IPCLite Version - if version does not match crash the system */
  1462. BUG_ON(major_ver != MAJOR_VERSION || minor_ver > MINOR_VERSION);
  1463. return ret;
  1464. }
  1465. /* IPCLite Version setup related functions end */
  1466. /* Start of IPCLite Init*/
  1467. static int ipclite_probe(struct platform_device *pdev)
  1468. {
  1469. int ret = 0;
  1470. /* Version Setup */
  1471. ret = ipclite_version_setup(pdev->dev.of_node);
  1472. if (ret != 0) {
  1473. IPCLITE_OS_LOG(IPCLITE_ERR, "IPCLite Version Setup Failed\n");
  1474. goto error;
  1475. }
  1476. /* Register API Setup */
  1477. ret = ipclite_register_api();
  1478. if (ret != 0) {
  1479. IPCLITE_OS_LOG(IPCLITE_ERR, "IPCLite API Registration Failed\n");
  1480. goto error;
  1481. }
  1482. /* IPCLite Init */
  1483. ret = ipclite_init(pdev);
  1484. if (ret != 0) {
  1485. IPCLITE_OS_LOG(IPCLITE_ERR, "IPCLite Init Failed\n");
  1486. goto error;
  1487. }
  1488. return ret;
  1489. error:
  1490. IPCLITE_OS_LOG(IPCLITE_ERR, "IPCLite probe failed\n");
  1491. return ret;
  1492. }
  1493. static const struct of_device_id ipclite_of_match[] = {
  1494. { .compatible = "qcom,ipclite"},
  1495. {}
  1496. };
  1497. MODULE_DEVICE_TABLE(of, ipclite_of_match);
  1498. static struct platform_driver ipclite_driver = {
  1499. .probe = ipclite_probe,
  1500. .driver = {
  1501. .name = "ipclite",
  1502. .of_match_table = ipclite_of_match,
  1503. },
  1504. };
  1505. module_platform_driver(ipclite_driver);
  1506. MODULE_DESCRIPTION("IPCLite Driver");
  1507. MODULE_LICENSE("GPL v2");
  1508. MODULE_SOFTDEP("pre: qcom_hwspinlock");