ipclite.c 47 KB

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