ti_sci.c 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Texas Instruments System Control Interface Protocol Driver
  4. * Based on drivers/firmware/ti_sci.c from Linux.
  5. *
  6. * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
  7. * Lokesh Vutla <lokeshvutla@ti.com>
  8. */
  9. #include <common.h>
  10. #include <dm.h>
  11. #include <errno.h>
  12. #include <mailbox.h>
  13. #include <dm/device.h>
  14. #include <linux/err.h>
  15. #include <linux/soc/ti/k3-sec-proxy.h>
  16. #include <linux/soc/ti/ti_sci_protocol.h>
  17. #include "ti_sci.h"
  18. /* List of all TI SCI devices active in system */
  19. static LIST_HEAD(ti_sci_list);
  20. /**
  21. * struct ti_sci_xfer - Structure representing a message flow
  22. * @tx_message: Transmit message
  23. * @rx_len: Receive message length
  24. */
  25. struct ti_sci_xfer {
  26. struct k3_sec_proxy_msg tx_message;
  27. u8 rx_len;
  28. };
  29. /**
  30. * struct ti_sci_desc - Description of SoC integration
  31. * @host_id: Host identifier representing the compute entity
  32. * @max_rx_timeout_us: Timeout for communication with SoC (in Microseconds)
  33. * @max_msg_size: Maximum size of data per message that can be handled.
  34. */
  35. struct ti_sci_desc {
  36. u8 host_id;
  37. int max_rx_timeout_us;
  38. int max_msg_size;
  39. };
  40. /**
  41. * struct ti_sci_info - Structure representing a TI SCI instance
  42. * @dev: Device pointer
  43. * @desc: SoC description for this instance
  44. * @handle: Instance of TI SCI handle to send to clients.
  45. * @chan_tx: Transmit mailbox channel
  46. * @chan_rx: Receive mailbox channel
  47. * @xfer: xfer info
  48. * @list: list head
  49. * @is_secure: Determines if the communication is through secure threads.
  50. * @host_id: Host identifier representing the compute entity
  51. * @seq: Seq id used for verification for tx and rx message.
  52. */
  53. struct ti_sci_info {
  54. struct udevice *dev;
  55. const struct ti_sci_desc *desc;
  56. struct ti_sci_handle handle;
  57. struct mbox_chan chan_tx;
  58. struct mbox_chan chan_rx;
  59. struct mbox_chan chan_notify;
  60. struct ti_sci_xfer xfer;
  61. struct list_head list;
  62. bool is_secure;
  63. u8 host_id;
  64. u8 seq;
  65. };
  66. #define handle_to_ti_sci_info(h) container_of(h, struct ti_sci_info, handle)
  67. /**
  68. * ti_sci_setup_one_xfer() - Setup one message type
  69. * @info: Pointer to SCI entity information
  70. * @msg_type: Message type
  71. * @msg_flags: Flag to set for the message
  72. * @buf: Buffer to be send to mailbox channel
  73. * @tx_message_size: transmit message size
  74. * @rx_message_size: receive message size
  75. *
  76. * Helper function which is used by various command functions that are
  77. * exposed to clients of this driver for allocating a message traffic event.
  78. *
  79. * Return: Corresponding ti_sci_xfer pointer if all went fine,
  80. * else appropriate error pointer.
  81. */
  82. static struct ti_sci_xfer *ti_sci_setup_one_xfer(struct ti_sci_info *info,
  83. u16 msg_type, u32 msg_flags,
  84. u32 *buf,
  85. size_t tx_message_size,
  86. size_t rx_message_size)
  87. {
  88. struct ti_sci_xfer *xfer = &info->xfer;
  89. struct ti_sci_msg_hdr *hdr;
  90. /* Ensure we have sane transfer sizes */
  91. if (rx_message_size > info->desc->max_msg_size ||
  92. tx_message_size > info->desc->max_msg_size ||
  93. rx_message_size < sizeof(*hdr) || tx_message_size < sizeof(*hdr))
  94. return ERR_PTR(-ERANGE);
  95. info->seq = ~info->seq;
  96. xfer->tx_message.buf = buf;
  97. xfer->tx_message.len = tx_message_size;
  98. xfer->rx_len = (u8)rx_message_size;
  99. hdr = (struct ti_sci_msg_hdr *)buf;
  100. hdr->seq = info->seq;
  101. hdr->type = msg_type;
  102. hdr->host = info->host_id;
  103. hdr->flags = msg_flags;
  104. return xfer;
  105. }
  106. /**
  107. * ti_sci_get_response() - Receive response from mailbox channel
  108. * @info: Pointer to SCI entity information
  109. * @xfer: Transfer to initiate and wait for response
  110. * @chan: Channel to receive the response
  111. *
  112. * Return: -ETIMEDOUT in case of no response, if transmit error,
  113. * return corresponding error, else if all goes well,
  114. * return 0.
  115. */
  116. static inline int ti_sci_get_response(struct ti_sci_info *info,
  117. struct ti_sci_xfer *xfer,
  118. struct mbox_chan *chan)
  119. {
  120. struct k3_sec_proxy_msg *msg = &xfer->tx_message;
  121. struct ti_sci_secure_msg_hdr *secure_hdr;
  122. struct ti_sci_msg_hdr *hdr;
  123. int ret;
  124. /* Receive the response */
  125. ret = mbox_recv(chan, msg, info->desc->max_rx_timeout_us);
  126. if (ret) {
  127. dev_err(info->dev, "%s: Message receive failed. ret = %d\n",
  128. __func__, ret);
  129. return ret;
  130. }
  131. /* ToDo: Verify checksum */
  132. if (info->is_secure) {
  133. secure_hdr = (struct ti_sci_secure_msg_hdr *)msg->buf;
  134. msg->buf = (u32 *)((void *)msg->buf + sizeof(*secure_hdr));
  135. }
  136. /* msg is updated by mailbox driver */
  137. hdr = (struct ti_sci_msg_hdr *)msg->buf;
  138. /* Sanity check for message response */
  139. if (hdr->seq != info->seq) {
  140. dev_dbg(info->dev, "%s: Message for %d is not expected\n",
  141. __func__, hdr->seq);
  142. return ret;
  143. }
  144. if (msg->len > info->desc->max_msg_size) {
  145. dev_err(info->dev, "%s: Unable to handle %zu xfer (max %d)\n",
  146. __func__, msg->len, info->desc->max_msg_size);
  147. return -EINVAL;
  148. }
  149. if (msg->len < xfer->rx_len) {
  150. dev_err(info->dev, "%s: Recv xfer %zu < expected %d length\n",
  151. __func__, msg->len, xfer->rx_len);
  152. }
  153. return ret;
  154. }
  155. /**
  156. * ti_sci_do_xfer() - Do one transfer
  157. * @info: Pointer to SCI entity information
  158. * @xfer: Transfer to initiate and wait for response
  159. *
  160. * Return: 0 if all went fine, else return appropriate error.
  161. */
  162. static inline int ti_sci_do_xfer(struct ti_sci_info *info,
  163. struct ti_sci_xfer *xfer)
  164. {
  165. struct k3_sec_proxy_msg *msg = &xfer->tx_message;
  166. u8 secure_buf[info->desc->max_msg_size];
  167. struct ti_sci_secure_msg_hdr secure_hdr;
  168. int ret;
  169. if (info->is_secure) {
  170. /* ToDo: get checksum of the entire message */
  171. secure_hdr.checksum = 0;
  172. secure_hdr.reserved = 0;
  173. memcpy(&secure_buf[sizeof(secure_hdr)], xfer->tx_message.buf,
  174. xfer->tx_message.len);
  175. xfer->tx_message.buf = (u32 *)secure_buf;
  176. xfer->tx_message.len += sizeof(secure_hdr);
  177. xfer->rx_len += sizeof(secure_hdr);
  178. }
  179. /* Send the message */
  180. ret = mbox_send(&info->chan_tx, msg);
  181. if (ret) {
  182. dev_err(info->dev, "%s: Message sending failed. ret = %d\n",
  183. __func__, ret);
  184. return ret;
  185. }
  186. return ti_sci_get_response(info, xfer, &info->chan_rx);
  187. }
  188. /**
  189. * ti_sci_cmd_get_revision() - command to get the revision of the SCI entity
  190. * @handle: pointer to TI SCI handle
  191. *
  192. * Updates the SCI information in the internal data structure.
  193. *
  194. * Return: 0 if all went fine, else return appropriate error.
  195. */
  196. static int ti_sci_cmd_get_revision(struct ti_sci_handle *handle)
  197. {
  198. struct ti_sci_msg_resp_version *rev_info;
  199. struct ti_sci_version_info *ver;
  200. struct ti_sci_msg_hdr hdr;
  201. struct ti_sci_info *info;
  202. struct ti_sci_xfer *xfer;
  203. int ret;
  204. if (IS_ERR(handle))
  205. return PTR_ERR(handle);
  206. if (!handle)
  207. return -EINVAL;
  208. info = handle_to_ti_sci_info(handle);
  209. xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_VERSION, 0x0,
  210. (u32 *)&hdr, sizeof(struct ti_sci_msg_hdr),
  211. sizeof(*rev_info));
  212. if (IS_ERR(xfer)) {
  213. ret = PTR_ERR(xfer);
  214. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  215. return ret;
  216. }
  217. ret = ti_sci_do_xfer(info, xfer);
  218. if (ret) {
  219. dev_err(info->dev, "Mbox communication fail %d\n", ret);
  220. return ret;
  221. }
  222. rev_info = (struct ti_sci_msg_resp_version *)xfer->tx_message.buf;
  223. ver = &handle->version;
  224. ver->abi_major = rev_info->abi_major;
  225. ver->abi_minor = rev_info->abi_minor;
  226. ver->firmware_revision = rev_info->firmware_revision;
  227. strncpy(ver->firmware_description, rev_info->firmware_description,
  228. sizeof(ver->firmware_description));
  229. return 0;
  230. }
  231. /**
  232. * ti_sci_is_response_ack() - Generic ACK/NACK message checkup
  233. * @r: pointer to response buffer
  234. *
  235. * Return: true if the response was an ACK, else returns false.
  236. */
  237. static inline bool ti_sci_is_response_ack(void *r)
  238. {
  239. struct ti_sci_msg_hdr *hdr = r;
  240. return hdr->flags & TI_SCI_FLAG_RESP_GENERIC_ACK ? true : false;
  241. }
  242. /**
  243. * cmd_set_board_config_using_msg() - Common command to send board configuration
  244. * message
  245. * @handle: pointer to TI SCI handle
  246. * @msg_type: One of the TISCI message types to set board configuration
  247. * @addr: Address where the board config structure is located
  248. * @size: Size of the board config structure
  249. *
  250. * Return: 0 if all went well, else returns appropriate error value.
  251. */
  252. static int cmd_set_board_config_using_msg(const struct ti_sci_handle *handle,
  253. u16 msg_type, u64 addr, u32 size)
  254. {
  255. struct ti_sci_msg_board_config req;
  256. struct ti_sci_msg_hdr *resp;
  257. struct ti_sci_info *info;
  258. struct ti_sci_xfer *xfer;
  259. int ret = 0;
  260. if (IS_ERR(handle))
  261. return PTR_ERR(handle);
  262. if (!handle)
  263. return -EINVAL;
  264. info = handle_to_ti_sci_info(handle);
  265. xfer = ti_sci_setup_one_xfer(info, msg_type,
  266. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  267. (u32 *)&req, sizeof(req), sizeof(*resp));
  268. if (IS_ERR(xfer)) {
  269. ret = PTR_ERR(xfer);
  270. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  271. return ret;
  272. }
  273. req.boardcfgp_high = (addr >> 32) & 0xffffffff;
  274. req.boardcfgp_low = addr & 0xffffffff;
  275. req.boardcfg_size = size;
  276. ret = ti_sci_do_xfer(info, xfer);
  277. if (ret) {
  278. dev_err(info->dev, "Mbox send fail %d\n", ret);
  279. return ret;
  280. }
  281. resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
  282. if (!ti_sci_is_response_ack(resp))
  283. return -ENODEV;
  284. return ret;
  285. }
  286. /**
  287. * ti_sci_cmd_set_board_config() - Command to send board configuration message
  288. * @handle: pointer to TI SCI handle
  289. * @addr: Address where the board config structure is located
  290. * @size: Size of the board config structure
  291. *
  292. * Return: 0 if all went well, else returns appropriate error value.
  293. */
  294. static int ti_sci_cmd_set_board_config(const struct ti_sci_handle *handle,
  295. u64 addr, u32 size)
  296. {
  297. return cmd_set_board_config_using_msg(handle,
  298. TI_SCI_MSG_BOARD_CONFIG,
  299. addr, size);
  300. }
  301. /**
  302. * ti_sci_cmd_set_board_config_rm() - Command to send board resource
  303. * management configuration
  304. * @handle: pointer to TI SCI handle
  305. * @addr: Address where the board RM config structure is located
  306. * @size: Size of the RM config structure
  307. *
  308. * Return: 0 if all went well, else returns appropriate error value.
  309. */
  310. static
  311. int ti_sci_cmd_set_board_config_rm(const struct ti_sci_handle *handle,
  312. u64 addr, u32 size)
  313. {
  314. return cmd_set_board_config_using_msg(handle,
  315. TI_SCI_MSG_BOARD_CONFIG_RM,
  316. addr, size);
  317. }
  318. /**
  319. * ti_sci_cmd_set_board_config_security() - Command to send board security
  320. * configuration message
  321. * @handle: pointer to TI SCI handle
  322. * @addr: Address where the board security config structure is located
  323. * @size: Size of the security config structure
  324. *
  325. * Return: 0 if all went well, else returns appropriate error value.
  326. */
  327. static
  328. int ti_sci_cmd_set_board_config_security(const struct ti_sci_handle *handle,
  329. u64 addr, u32 size)
  330. {
  331. return cmd_set_board_config_using_msg(handle,
  332. TI_SCI_MSG_BOARD_CONFIG_SECURITY,
  333. addr, size);
  334. }
  335. /**
  336. * ti_sci_cmd_set_board_config_pm() - Command to send board power and clock
  337. * configuration message
  338. * @handle: pointer to TI SCI handle
  339. * @addr: Address where the board PM config structure is located
  340. * @size: Size of the PM config structure
  341. *
  342. * Return: 0 if all went well, else returns appropriate error value.
  343. */
  344. static int ti_sci_cmd_set_board_config_pm(const struct ti_sci_handle *handle,
  345. u64 addr, u32 size)
  346. {
  347. return cmd_set_board_config_using_msg(handle,
  348. TI_SCI_MSG_BOARD_CONFIG_PM,
  349. addr, size);
  350. }
  351. /**
  352. * ti_sci_set_device_state() - Set device state helper
  353. * @handle: pointer to TI SCI handle
  354. * @id: Device identifier
  355. * @flags: flags to setup for the device
  356. * @state: State to move the device to
  357. *
  358. * Return: 0 if all went well, else returns appropriate error value.
  359. */
  360. static int ti_sci_set_device_state(const struct ti_sci_handle *handle,
  361. u32 id, u32 flags, u8 state)
  362. {
  363. struct ti_sci_msg_req_set_device_state req;
  364. struct ti_sci_msg_hdr *resp;
  365. struct ti_sci_info *info;
  366. struct ti_sci_xfer *xfer;
  367. int ret = 0;
  368. if (IS_ERR(handle))
  369. return PTR_ERR(handle);
  370. if (!handle)
  371. return -EINVAL;
  372. info = handle_to_ti_sci_info(handle);
  373. xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_STATE,
  374. flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  375. (u32 *)&req, sizeof(req), sizeof(*resp));
  376. if (IS_ERR(xfer)) {
  377. ret = PTR_ERR(xfer);
  378. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  379. return ret;
  380. }
  381. req.id = id;
  382. req.state = state;
  383. ret = ti_sci_do_xfer(info, xfer);
  384. if (ret) {
  385. dev_err(info->dev, "Mbox send fail %d\n", ret);
  386. return ret;
  387. }
  388. resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
  389. if (!ti_sci_is_response_ack(resp))
  390. return -ENODEV;
  391. return ret;
  392. }
  393. /**
  394. * ti_sci_get_device_state() - Get device state helper
  395. * @handle: Handle to the device
  396. * @id: Device Identifier
  397. * @clcnt: Pointer to Context Loss Count
  398. * @resets: pointer to resets
  399. * @p_state: pointer to p_state
  400. * @c_state: pointer to c_state
  401. *
  402. * Return: 0 if all went fine, else return appropriate error.
  403. */
  404. static int ti_sci_get_device_state(const struct ti_sci_handle *handle,
  405. u32 id, u32 *clcnt, u32 *resets,
  406. u8 *p_state, u8 *c_state)
  407. {
  408. struct ti_sci_msg_resp_get_device_state *resp;
  409. struct ti_sci_msg_req_get_device_state req;
  410. struct ti_sci_info *info;
  411. struct ti_sci_xfer *xfer;
  412. int ret = 0;
  413. if (IS_ERR(handle))
  414. return PTR_ERR(handle);
  415. if (!handle)
  416. return -EINVAL;
  417. if (!clcnt && !resets && !p_state && !c_state)
  418. return -EINVAL;
  419. info = handle_to_ti_sci_info(handle);
  420. /* Response is expected, so need of any flags */
  421. xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_DEVICE_STATE, 0,
  422. (u32 *)&req, sizeof(req), sizeof(*resp));
  423. if (IS_ERR(xfer)) {
  424. ret = PTR_ERR(xfer);
  425. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  426. return ret;
  427. }
  428. req.id = id;
  429. ret = ti_sci_do_xfer(info, xfer);
  430. if (ret) {
  431. dev_err(dev, "Mbox send fail %d\n", ret);
  432. return ret;
  433. }
  434. resp = (struct ti_sci_msg_resp_get_device_state *)xfer->tx_message.buf;
  435. if (!ti_sci_is_response_ack(resp))
  436. return -ENODEV;
  437. if (clcnt)
  438. *clcnt = resp->context_loss_count;
  439. if (resets)
  440. *resets = resp->resets;
  441. if (p_state)
  442. *p_state = resp->programmed_state;
  443. if (c_state)
  444. *c_state = resp->current_state;
  445. return ret;
  446. }
  447. /**
  448. * ti_sci_cmd_get_device() - command to request for device managed by TISCI
  449. * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
  450. * @id: Device Identifier
  451. *
  452. * Request for the device - NOTE: the client MUST maintain integrity of
  453. * usage count by balancing get_device with put_device. No refcounting is
  454. * managed by driver for that purpose.
  455. *
  456. * NOTE: The request is for exclusive access for the processor.
  457. *
  458. * Return: 0 if all went fine, else return appropriate error.
  459. */
  460. static int ti_sci_cmd_get_device(const struct ti_sci_handle *handle, u32 id)
  461. {
  462. return ti_sci_set_device_state(handle, id,
  463. MSG_FLAG_DEVICE_EXCLUSIVE,
  464. MSG_DEVICE_SW_STATE_ON);
  465. }
  466. /**
  467. * ti_sci_cmd_idle_device() - Command to idle a device managed by TISCI
  468. * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
  469. * @id: Device Identifier
  470. *
  471. * Request for the device - NOTE: the client MUST maintain integrity of
  472. * usage count by balancing get_device with put_device. No refcounting is
  473. * managed by driver for that purpose.
  474. *
  475. * Return: 0 if all went fine, else return appropriate error.
  476. */
  477. static int ti_sci_cmd_idle_device(const struct ti_sci_handle *handle, u32 id)
  478. {
  479. return ti_sci_set_device_state(handle, id,
  480. MSG_FLAG_DEVICE_EXCLUSIVE,
  481. MSG_DEVICE_SW_STATE_RETENTION);
  482. }
  483. /**
  484. * ti_sci_cmd_put_device() - command to release a device managed by TISCI
  485. * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
  486. * @id: Device Identifier
  487. *
  488. * Request for the device - NOTE: the client MUST maintain integrity of
  489. * usage count by balancing get_device with put_device. No refcounting is
  490. * managed by driver for that purpose.
  491. *
  492. * Return: 0 if all went fine, else return appropriate error.
  493. */
  494. static int ti_sci_cmd_put_device(const struct ti_sci_handle *handle, u32 id)
  495. {
  496. return ti_sci_set_device_state(handle, id,
  497. 0, MSG_DEVICE_SW_STATE_AUTO_OFF);
  498. }
  499. /**
  500. * ti_sci_cmd_dev_is_valid() - Is the device valid
  501. * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
  502. * @id: Device Identifier
  503. *
  504. * Return: 0 if all went fine and the device ID is valid, else return
  505. * appropriate error.
  506. */
  507. static int ti_sci_cmd_dev_is_valid(const struct ti_sci_handle *handle, u32 id)
  508. {
  509. u8 unused;
  510. /* check the device state which will also tell us if the ID is valid */
  511. return ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &unused);
  512. }
  513. /**
  514. * ti_sci_cmd_dev_get_clcnt() - Get context loss counter
  515. * @handle: Pointer to TISCI handle
  516. * @id: Device Identifier
  517. * @count: Pointer to Context Loss counter to populate
  518. *
  519. * Return: 0 if all went fine, else return appropriate error.
  520. */
  521. static int ti_sci_cmd_dev_get_clcnt(const struct ti_sci_handle *handle, u32 id,
  522. u32 *count)
  523. {
  524. return ti_sci_get_device_state(handle, id, count, NULL, NULL, NULL);
  525. }
  526. /**
  527. * ti_sci_cmd_dev_is_idle() - Check if the device is requested to be idle
  528. * @handle: Pointer to TISCI handle
  529. * @id: Device Identifier
  530. * @r_state: true if requested to be idle
  531. *
  532. * Return: 0 if all went fine, else return appropriate error.
  533. */
  534. static int ti_sci_cmd_dev_is_idle(const struct ti_sci_handle *handle, u32 id,
  535. bool *r_state)
  536. {
  537. int ret;
  538. u8 state;
  539. if (!r_state)
  540. return -EINVAL;
  541. ret = ti_sci_get_device_state(handle, id, NULL, NULL, &state, NULL);
  542. if (ret)
  543. return ret;
  544. *r_state = (state == MSG_DEVICE_SW_STATE_RETENTION);
  545. return 0;
  546. }
  547. /**
  548. * ti_sci_cmd_dev_is_stop() - Check if the device is requested to be stopped
  549. * @handle: Pointer to TISCI handle
  550. * @id: Device Identifier
  551. * @r_state: true if requested to be stopped
  552. * @curr_state: true if currently stopped.
  553. *
  554. * Return: 0 if all went fine, else return appropriate error.
  555. */
  556. static int ti_sci_cmd_dev_is_stop(const struct ti_sci_handle *handle, u32 id,
  557. bool *r_state, bool *curr_state)
  558. {
  559. int ret;
  560. u8 p_state, c_state;
  561. if (!r_state && !curr_state)
  562. return -EINVAL;
  563. ret =
  564. ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state);
  565. if (ret)
  566. return ret;
  567. if (r_state)
  568. *r_state = (p_state == MSG_DEVICE_SW_STATE_AUTO_OFF);
  569. if (curr_state)
  570. *curr_state = (c_state == MSG_DEVICE_HW_STATE_OFF);
  571. return 0;
  572. }
  573. /**
  574. * ti_sci_cmd_dev_is_on() - Check if the device is requested to be ON
  575. * @handle: Pointer to TISCI handle
  576. * @id: Device Identifier
  577. * @r_state: true if requested to be ON
  578. * @curr_state: true if currently ON and active
  579. *
  580. * Return: 0 if all went fine, else return appropriate error.
  581. */
  582. static int ti_sci_cmd_dev_is_on(const struct ti_sci_handle *handle, u32 id,
  583. bool *r_state, bool *curr_state)
  584. {
  585. int ret;
  586. u8 p_state, c_state;
  587. if (!r_state && !curr_state)
  588. return -EINVAL;
  589. ret =
  590. ti_sci_get_device_state(handle, id, NULL, NULL, &p_state, &c_state);
  591. if (ret)
  592. return ret;
  593. if (r_state)
  594. *r_state = (p_state == MSG_DEVICE_SW_STATE_ON);
  595. if (curr_state)
  596. *curr_state = (c_state == MSG_DEVICE_HW_STATE_ON);
  597. return 0;
  598. }
  599. /**
  600. * ti_sci_cmd_dev_is_trans() - Check if the device is currently transitioning
  601. * @handle: Pointer to TISCI handle
  602. * @id: Device Identifier
  603. * @curr_state: true if currently transitioning.
  604. *
  605. * Return: 0 if all went fine, else return appropriate error.
  606. */
  607. static int ti_sci_cmd_dev_is_trans(const struct ti_sci_handle *handle, u32 id,
  608. bool *curr_state)
  609. {
  610. int ret;
  611. u8 state;
  612. if (!curr_state)
  613. return -EINVAL;
  614. ret = ti_sci_get_device_state(handle, id, NULL, NULL, NULL, &state);
  615. if (ret)
  616. return ret;
  617. *curr_state = (state == MSG_DEVICE_HW_STATE_TRANS);
  618. return 0;
  619. }
  620. /**
  621. * ti_sci_cmd_set_device_resets() - command to set resets for device managed
  622. * by TISCI
  623. * @handle: Pointer to TISCI handle as retrieved by *ti_sci_get_handle
  624. * @id: Device Identifier
  625. * @reset_state: Device specific reset bit field
  626. *
  627. * Return: 0 if all went fine, else return appropriate error.
  628. */
  629. static int ti_sci_cmd_set_device_resets(const struct ti_sci_handle *handle,
  630. u32 id, u32 reset_state)
  631. {
  632. struct ti_sci_msg_req_set_device_resets req;
  633. struct ti_sci_msg_hdr *resp;
  634. struct ti_sci_info *info;
  635. struct ti_sci_xfer *xfer;
  636. int ret = 0;
  637. if (IS_ERR(handle))
  638. return PTR_ERR(handle);
  639. if (!handle)
  640. return -EINVAL;
  641. info = handle_to_ti_sci_info(handle);
  642. xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_DEVICE_RESETS,
  643. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  644. (u32 *)&req, sizeof(req), sizeof(*resp));
  645. if (IS_ERR(xfer)) {
  646. ret = PTR_ERR(xfer);
  647. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  648. return ret;
  649. }
  650. req.id = id;
  651. req.resets = reset_state;
  652. ret = ti_sci_do_xfer(info, xfer);
  653. if (ret) {
  654. dev_err(info->dev, "Mbox send fail %d\n", ret);
  655. return ret;
  656. }
  657. resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
  658. if (!ti_sci_is_response_ack(resp))
  659. return -ENODEV;
  660. return ret;
  661. }
  662. /**
  663. * ti_sci_cmd_get_device_resets() - Get reset state for device managed
  664. * by TISCI
  665. * @handle: Pointer to TISCI handle
  666. * @id: Device Identifier
  667. * @reset_state: Pointer to reset state to populate
  668. *
  669. * Return: 0 if all went fine, else return appropriate error.
  670. */
  671. static int ti_sci_cmd_get_device_resets(const struct ti_sci_handle *handle,
  672. u32 id, u32 *reset_state)
  673. {
  674. return ti_sci_get_device_state(handle, id, NULL, reset_state, NULL,
  675. NULL);
  676. }
  677. /**
  678. * ti_sci_set_clock_state() - Set clock state helper
  679. * @handle: pointer to TI SCI handle
  680. * @dev_id: Device identifier this request is for
  681. * @clk_id: Clock identifier for the device for this request.
  682. * Each device has it's own set of clock inputs. This indexes
  683. * which clock input to modify.
  684. * @flags: Header flags as needed
  685. * @state: State to request for the clock.
  686. *
  687. * Return: 0 if all went well, else returns appropriate error value.
  688. */
  689. static int ti_sci_set_clock_state(const struct ti_sci_handle *handle,
  690. u32 dev_id, u8 clk_id,
  691. u32 flags, u8 state)
  692. {
  693. struct ti_sci_msg_req_set_clock_state req;
  694. struct ti_sci_msg_hdr *resp;
  695. struct ti_sci_info *info;
  696. struct ti_sci_xfer *xfer;
  697. int ret = 0;
  698. if (IS_ERR(handle))
  699. return PTR_ERR(handle);
  700. if (!handle)
  701. return -EINVAL;
  702. info = handle_to_ti_sci_info(handle);
  703. xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_STATE,
  704. flags | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  705. (u32 *)&req, sizeof(req), sizeof(*resp));
  706. if (IS_ERR(xfer)) {
  707. ret = PTR_ERR(xfer);
  708. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  709. return ret;
  710. }
  711. req.dev_id = dev_id;
  712. req.clk_id = clk_id;
  713. req.request_state = state;
  714. ret = ti_sci_do_xfer(info, xfer);
  715. if (ret) {
  716. dev_err(info->dev, "Mbox send fail %d\n", ret);
  717. return ret;
  718. }
  719. resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
  720. if (!ti_sci_is_response_ack(resp))
  721. return -ENODEV;
  722. return ret;
  723. }
  724. /**
  725. * ti_sci_cmd_get_clock_state() - Get clock state helper
  726. * @handle: pointer to TI SCI handle
  727. * @dev_id: Device identifier this request is for
  728. * @clk_id: Clock identifier for the device for this request.
  729. * Each device has it's own set of clock inputs. This indexes
  730. * which clock input to modify.
  731. * @programmed_state: State requested for clock to move to
  732. * @current_state: State that the clock is currently in
  733. *
  734. * Return: 0 if all went well, else returns appropriate error value.
  735. */
  736. static int ti_sci_cmd_get_clock_state(const struct ti_sci_handle *handle,
  737. u32 dev_id, u8 clk_id,
  738. u8 *programmed_state, u8 *current_state)
  739. {
  740. struct ti_sci_msg_resp_get_clock_state *resp;
  741. struct ti_sci_msg_req_get_clock_state req;
  742. struct ti_sci_info *info;
  743. struct ti_sci_xfer *xfer;
  744. int ret = 0;
  745. if (IS_ERR(handle))
  746. return PTR_ERR(handle);
  747. if (!handle)
  748. return -EINVAL;
  749. if (!programmed_state && !current_state)
  750. return -EINVAL;
  751. info = handle_to_ti_sci_info(handle);
  752. xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_STATE,
  753. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  754. (u32 *)&req, sizeof(req), sizeof(*resp));
  755. if (IS_ERR(xfer)) {
  756. ret = PTR_ERR(xfer);
  757. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  758. return ret;
  759. }
  760. req.dev_id = dev_id;
  761. req.clk_id = clk_id;
  762. ret = ti_sci_do_xfer(info, xfer);
  763. if (ret) {
  764. dev_err(info->dev, "Mbox send fail %d\n", ret);
  765. return ret;
  766. }
  767. resp = (struct ti_sci_msg_resp_get_clock_state *)xfer->tx_message.buf;
  768. if (!ti_sci_is_response_ack(resp))
  769. return -ENODEV;
  770. if (programmed_state)
  771. *programmed_state = resp->programmed_state;
  772. if (current_state)
  773. *current_state = resp->current_state;
  774. return ret;
  775. }
  776. /**
  777. * ti_sci_cmd_get_clock() - Get control of a clock from TI SCI
  778. * @handle: pointer to TI SCI handle
  779. * @dev_id: Device identifier this request is for
  780. * @clk_id: Clock identifier for the device for this request.
  781. * Each device has it's own set of clock inputs. This indexes
  782. * which clock input to modify.
  783. * @needs_ssc: 'true' if Spread Spectrum clock is desired, else 'false'
  784. * @can_change_freq: 'true' if frequency change is desired, else 'false'
  785. * @enable_input_term: 'true' if input termination is desired, else 'false'
  786. *
  787. * Return: 0 if all went well, else returns appropriate error value.
  788. */
  789. static int ti_sci_cmd_get_clock(const struct ti_sci_handle *handle, u32 dev_id,
  790. u8 clk_id, bool needs_ssc, bool can_change_freq,
  791. bool enable_input_term)
  792. {
  793. u32 flags = 0;
  794. flags |= needs_ssc ? MSG_FLAG_CLOCK_ALLOW_SSC : 0;
  795. flags |= can_change_freq ? MSG_FLAG_CLOCK_ALLOW_FREQ_CHANGE : 0;
  796. flags |= enable_input_term ? MSG_FLAG_CLOCK_INPUT_TERM : 0;
  797. return ti_sci_set_clock_state(handle, dev_id, clk_id, flags,
  798. MSG_CLOCK_SW_STATE_REQ);
  799. }
  800. /**
  801. * ti_sci_cmd_idle_clock() - Idle a clock which is in our control
  802. * @handle: pointer to TI SCI handle
  803. * @dev_id: Device identifier this request is for
  804. * @clk_id: Clock identifier for the device for this request.
  805. * Each device has it's own set of clock inputs. This indexes
  806. * which clock input to modify.
  807. *
  808. * NOTE: This clock must have been requested by get_clock previously.
  809. *
  810. * Return: 0 if all went well, else returns appropriate error value.
  811. */
  812. static int ti_sci_cmd_idle_clock(const struct ti_sci_handle *handle,
  813. u32 dev_id, u8 clk_id)
  814. {
  815. return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
  816. MSG_CLOCK_SW_STATE_UNREQ);
  817. }
  818. /**
  819. * ti_sci_cmd_put_clock() - Release a clock from our control back to TISCI
  820. * @handle: pointer to TI SCI handle
  821. * @dev_id: Device identifier this request is for
  822. * @clk_id: Clock identifier for the device for this request.
  823. * Each device has it's own set of clock inputs. This indexes
  824. * which clock input to modify.
  825. *
  826. * NOTE: This clock must have been requested by get_clock previously.
  827. *
  828. * Return: 0 if all went well, else returns appropriate error value.
  829. */
  830. static int ti_sci_cmd_put_clock(const struct ti_sci_handle *handle,
  831. u32 dev_id, u8 clk_id)
  832. {
  833. return ti_sci_set_clock_state(handle, dev_id, clk_id, 0,
  834. MSG_CLOCK_SW_STATE_AUTO);
  835. }
  836. /**
  837. * ti_sci_cmd_clk_is_auto() - Is the clock being auto managed
  838. * @handle: pointer to TI SCI handle
  839. * @dev_id: Device identifier this request is for
  840. * @clk_id: Clock identifier for the device for this request.
  841. * Each device has it's own set of clock inputs. This indexes
  842. * which clock input to modify.
  843. * @req_state: state indicating if the clock is auto managed
  844. *
  845. * Return: 0 if all went well, else returns appropriate error value.
  846. */
  847. static int ti_sci_cmd_clk_is_auto(const struct ti_sci_handle *handle,
  848. u32 dev_id, u8 clk_id, bool *req_state)
  849. {
  850. u8 state = 0;
  851. int ret;
  852. if (!req_state)
  853. return -EINVAL;
  854. ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id, &state, NULL);
  855. if (ret)
  856. return ret;
  857. *req_state = (state == MSG_CLOCK_SW_STATE_AUTO);
  858. return 0;
  859. }
  860. /**
  861. * ti_sci_cmd_clk_is_on() - Is the clock ON
  862. * @handle: pointer to TI SCI handle
  863. * @dev_id: Device identifier this request is for
  864. * @clk_id: Clock identifier for the device for this request.
  865. * Each device has it's own set of clock inputs. This indexes
  866. * which clock input to modify.
  867. * @req_state: state indicating if the clock is managed by us and enabled
  868. * @curr_state: state indicating if the clock is ready for operation
  869. *
  870. * Return: 0 if all went well, else returns appropriate error value.
  871. */
  872. static int ti_sci_cmd_clk_is_on(const struct ti_sci_handle *handle, u32 dev_id,
  873. u8 clk_id, bool *req_state, bool *curr_state)
  874. {
  875. u8 c_state = 0, r_state = 0;
  876. int ret;
  877. if (!req_state && !curr_state)
  878. return -EINVAL;
  879. ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
  880. &r_state, &c_state);
  881. if (ret)
  882. return ret;
  883. if (req_state)
  884. *req_state = (r_state == MSG_CLOCK_SW_STATE_REQ);
  885. if (curr_state)
  886. *curr_state = (c_state == MSG_CLOCK_HW_STATE_READY);
  887. return 0;
  888. }
  889. /**
  890. * ti_sci_cmd_clk_is_off() - Is the clock OFF
  891. * @handle: pointer to TI SCI handle
  892. * @dev_id: Device identifier this request is for
  893. * @clk_id: Clock identifier for the device for this request.
  894. * Each device has it's own set of clock inputs. This indexes
  895. * which clock input to modify.
  896. * @req_state: state indicating if the clock is managed by us and disabled
  897. * @curr_state: state indicating if the clock is NOT ready for operation
  898. *
  899. * Return: 0 if all went well, else returns appropriate error value.
  900. */
  901. static int ti_sci_cmd_clk_is_off(const struct ti_sci_handle *handle, u32 dev_id,
  902. u8 clk_id, bool *req_state, bool *curr_state)
  903. {
  904. u8 c_state = 0, r_state = 0;
  905. int ret;
  906. if (!req_state && !curr_state)
  907. return -EINVAL;
  908. ret = ti_sci_cmd_get_clock_state(handle, dev_id, clk_id,
  909. &r_state, &c_state);
  910. if (ret)
  911. return ret;
  912. if (req_state)
  913. *req_state = (r_state == MSG_CLOCK_SW_STATE_UNREQ);
  914. if (curr_state)
  915. *curr_state = (c_state == MSG_CLOCK_HW_STATE_NOT_READY);
  916. return 0;
  917. }
  918. /**
  919. * ti_sci_cmd_clk_set_parent() - Set the clock source of a specific device clock
  920. * @handle: pointer to TI SCI handle
  921. * @dev_id: Device identifier this request is for
  922. * @clk_id: Clock identifier for the device for this request.
  923. * Each device has it's own set of clock inputs. This indexes
  924. * which clock input to modify.
  925. * @parent_id: Parent clock identifier to set
  926. *
  927. * Return: 0 if all went well, else returns appropriate error value.
  928. */
  929. static int ti_sci_cmd_clk_set_parent(const struct ti_sci_handle *handle,
  930. u32 dev_id, u8 clk_id, u8 parent_id)
  931. {
  932. struct ti_sci_msg_req_set_clock_parent req;
  933. struct ti_sci_msg_hdr *resp;
  934. struct ti_sci_info *info;
  935. struct ti_sci_xfer *xfer;
  936. int ret = 0;
  937. if (IS_ERR(handle))
  938. return PTR_ERR(handle);
  939. if (!handle)
  940. return -EINVAL;
  941. info = handle_to_ti_sci_info(handle);
  942. xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_PARENT,
  943. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  944. (u32 *)&req, sizeof(req), sizeof(*resp));
  945. if (IS_ERR(xfer)) {
  946. ret = PTR_ERR(xfer);
  947. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  948. return ret;
  949. }
  950. req.dev_id = dev_id;
  951. req.clk_id = clk_id;
  952. req.parent_id = parent_id;
  953. ret = ti_sci_do_xfer(info, xfer);
  954. if (ret) {
  955. dev_err(info->dev, "Mbox send fail %d\n", ret);
  956. return ret;
  957. }
  958. resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
  959. if (!ti_sci_is_response_ack(resp))
  960. return -ENODEV;
  961. return ret;
  962. }
  963. /**
  964. * ti_sci_cmd_clk_get_parent() - Get current parent clock source
  965. * @handle: pointer to TI SCI handle
  966. * @dev_id: Device identifier this request is for
  967. * @clk_id: Clock identifier for the device for this request.
  968. * Each device has it's own set of clock inputs. This indexes
  969. * which clock input to modify.
  970. * @parent_id: Current clock parent
  971. *
  972. * Return: 0 if all went well, else returns appropriate error value.
  973. */
  974. static int ti_sci_cmd_clk_get_parent(const struct ti_sci_handle *handle,
  975. u32 dev_id, u8 clk_id, u8 *parent_id)
  976. {
  977. struct ti_sci_msg_resp_get_clock_parent *resp;
  978. struct ti_sci_msg_req_get_clock_parent req;
  979. struct ti_sci_info *info;
  980. struct ti_sci_xfer *xfer;
  981. int ret = 0;
  982. if (IS_ERR(handle))
  983. return PTR_ERR(handle);
  984. if (!handle || !parent_id)
  985. return -EINVAL;
  986. info = handle_to_ti_sci_info(handle);
  987. xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_PARENT,
  988. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  989. (u32 *)&req, sizeof(req), sizeof(*resp));
  990. if (IS_ERR(xfer)) {
  991. ret = PTR_ERR(xfer);
  992. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  993. return ret;
  994. }
  995. req.dev_id = dev_id;
  996. req.clk_id = clk_id;
  997. ret = ti_sci_do_xfer(info, xfer);
  998. if (ret) {
  999. dev_err(info->dev, "Mbox send fail %d\n", ret);
  1000. return ret;
  1001. }
  1002. resp = (struct ti_sci_msg_resp_get_clock_parent *)xfer->tx_message.buf;
  1003. if (!ti_sci_is_response_ack(resp))
  1004. ret = -ENODEV;
  1005. else
  1006. *parent_id = resp->parent_id;
  1007. return ret;
  1008. }
  1009. /**
  1010. * ti_sci_cmd_clk_get_num_parents() - Get num parents of the current clk source
  1011. * @handle: pointer to TI SCI handle
  1012. * @dev_id: Device identifier this request is for
  1013. * @clk_id: Clock identifier for the device for this request.
  1014. * Each device has it's own set of clock inputs. This indexes
  1015. * which clock input to modify.
  1016. * @num_parents: Returns he number of parents to the current clock.
  1017. *
  1018. * Return: 0 if all went well, else returns appropriate error value.
  1019. */
  1020. static int ti_sci_cmd_clk_get_num_parents(const struct ti_sci_handle *handle,
  1021. u32 dev_id, u8 clk_id,
  1022. u8 *num_parents)
  1023. {
  1024. struct ti_sci_msg_resp_get_clock_num_parents *resp;
  1025. struct ti_sci_msg_req_get_clock_num_parents req;
  1026. struct ti_sci_info *info;
  1027. struct ti_sci_xfer *xfer;
  1028. int ret = 0;
  1029. if (IS_ERR(handle))
  1030. return PTR_ERR(handle);
  1031. if (!handle || !num_parents)
  1032. return -EINVAL;
  1033. info = handle_to_ti_sci_info(handle);
  1034. xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_NUM_CLOCK_PARENTS,
  1035. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  1036. (u32 *)&req, sizeof(req), sizeof(*resp));
  1037. if (IS_ERR(xfer)) {
  1038. ret = PTR_ERR(xfer);
  1039. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  1040. return ret;
  1041. }
  1042. req.dev_id = dev_id;
  1043. req.clk_id = clk_id;
  1044. ret = ti_sci_do_xfer(info, xfer);
  1045. if (ret) {
  1046. dev_err(info->dev, "Mbox send fail %d\n", ret);
  1047. return ret;
  1048. }
  1049. resp = (struct ti_sci_msg_resp_get_clock_num_parents *)
  1050. xfer->tx_message.buf;
  1051. if (!ti_sci_is_response_ack(resp))
  1052. ret = -ENODEV;
  1053. else
  1054. *num_parents = resp->num_parents;
  1055. return ret;
  1056. }
  1057. /**
  1058. * ti_sci_cmd_clk_get_match_freq() - Find a good match for frequency
  1059. * @handle: pointer to TI SCI handle
  1060. * @dev_id: Device identifier this request is for
  1061. * @clk_id: Clock identifier for the device for this request.
  1062. * Each device has it's own set of clock inputs. This indexes
  1063. * which clock input to modify.
  1064. * @min_freq: The minimum allowable frequency in Hz. This is the minimum
  1065. * allowable programmed frequency and does not account for clock
  1066. * tolerances and jitter.
  1067. * @target_freq: The target clock frequency in Hz. A frequency will be
  1068. * processed as close to this target frequency as possible.
  1069. * @max_freq: The maximum allowable frequency in Hz. This is the maximum
  1070. * allowable programmed frequency and does not account for clock
  1071. * tolerances and jitter.
  1072. * @match_freq: Frequency match in Hz response.
  1073. *
  1074. * Return: 0 if all went well, else returns appropriate error value.
  1075. */
  1076. static int ti_sci_cmd_clk_get_match_freq(const struct ti_sci_handle *handle,
  1077. u32 dev_id, u8 clk_id, u64 min_freq,
  1078. u64 target_freq, u64 max_freq,
  1079. u64 *match_freq)
  1080. {
  1081. struct ti_sci_msg_resp_query_clock_freq *resp;
  1082. struct ti_sci_msg_req_query_clock_freq req;
  1083. struct ti_sci_info *info;
  1084. struct ti_sci_xfer *xfer;
  1085. int ret = 0;
  1086. if (IS_ERR(handle))
  1087. return PTR_ERR(handle);
  1088. if (!handle || !match_freq)
  1089. return -EINVAL;
  1090. info = handle_to_ti_sci_info(handle);
  1091. xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_QUERY_CLOCK_FREQ,
  1092. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  1093. (u32 *)&req, sizeof(req), sizeof(*resp));
  1094. if (IS_ERR(xfer)) {
  1095. ret = PTR_ERR(xfer);
  1096. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  1097. return ret;
  1098. }
  1099. req.dev_id = dev_id;
  1100. req.clk_id = clk_id;
  1101. req.min_freq_hz = min_freq;
  1102. req.target_freq_hz = target_freq;
  1103. req.max_freq_hz = max_freq;
  1104. ret = ti_sci_do_xfer(info, xfer);
  1105. if (ret) {
  1106. dev_err(info->dev, "Mbox send fail %d\n", ret);
  1107. return ret;
  1108. }
  1109. resp = (struct ti_sci_msg_resp_query_clock_freq *)xfer->tx_message.buf;
  1110. if (!ti_sci_is_response_ack(resp))
  1111. ret = -ENODEV;
  1112. else
  1113. *match_freq = resp->freq_hz;
  1114. return ret;
  1115. }
  1116. /**
  1117. * ti_sci_cmd_clk_set_freq() - Set a frequency for clock
  1118. * @handle: pointer to TI SCI handle
  1119. * @dev_id: Device identifier this request is for
  1120. * @clk_id: Clock identifier for the device for this request.
  1121. * Each device has it's own set of clock inputs. This indexes
  1122. * which clock input to modify.
  1123. * @min_freq: The minimum allowable frequency in Hz. This is the minimum
  1124. * allowable programmed frequency and does not account for clock
  1125. * tolerances and jitter.
  1126. * @target_freq: The target clock frequency in Hz. A frequency will be
  1127. * processed as close to this target frequency as possible.
  1128. * @max_freq: The maximum allowable frequency in Hz. This is the maximum
  1129. * allowable programmed frequency and does not account for clock
  1130. * tolerances and jitter.
  1131. *
  1132. * Return: 0 if all went well, else returns appropriate error value.
  1133. */
  1134. static int ti_sci_cmd_clk_set_freq(const struct ti_sci_handle *handle,
  1135. u32 dev_id, u8 clk_id, u64 min_freq,
  1136. u64 target_freq, u64 max_freq)
  1137. {
  1138. struct ti_sci_msg_req_set_clock_freq req;
  1139. struct ti_sci_msg_hdr *resp;
  1140. struct ti_sci_info *info;
  1141. struct ti_sci_xfer *xfer;
  1142. int ret = 0;
  1143. if (IS_ERR(handle))
  1144. return PTR_ERR(handle);
  1145. if (!handle)
  1146. return -EINVAL;
  1147. info = handle_to_ti_sci_info(handle);
  1148. xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SET_CLOCK_FREQ,
  1149. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  1150. (u32 *)&req, sizeof(req), sizeof(*resp));
  1151. if (IS_ERR(xfer)) {
  1152. ret = PTR_ERR(xfer);
  1153. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  1154. return ret;
  1155. }
  1156. req.dev_id = dev_id;
  1157. req.clk_id = clk_id;
  1158. req.min_freq_hz = min_freq;
  1159. req.target_freq_hz = target_freq;
  1160. req.max_freq_hz = max_freq;
  1161. ret = ti_sci_do_xfer(info, xfer);
  1162. if (ret) {
  1163. dev_err(info->dev, "Mbox send fail %d\n", ret);
  1164. return ret;
  1165. }
  1166. resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
  1167. if (!ti_sci_is_response_ack(resp))
  1168. return -ENODEV;
  1169. return ret;
  1170. }
  1171. /**
  1172. * ti_sci_cmd_clk_get_freq() - Get current frequency
  1173. * @handle: pointer to TI SCI handle
  1174. * @dev_id: Device identifier this request is for
  1175. * @clk_id: Clock identifier for the device for this request.
  1176. * Each device has it's own set of clock inputs. This indexes
  1177. * which clock input to modify.
  1178. * @freq: Currently frequency in Hz
  1179. *
  1180. * Return: 0 if all went well, else returns appropriate error value.
  1181. */
  1182. static int ti_sci_cmd_clk_get_freq(const struct ti_sci_handle *handle,
  1183. u32 dev_id, u8 clk_id, u64 *freq)
  1184. {
  1185. struct ti_sci_msg_resp_get_clock_freq *resp;
  1186. struct ti_sci_msg_req_get_clock_freq req;
  1187. struct ti_sci_info *info;
  1188. struct ti_sci_xfer *xfer;
  1189. int ret = 0;
  1190. if (IS_ERR(handle))
  1191. return PTR_ERR(handle);
  1192. if (!handle || !freq)
  1193. return -EINVAL;
  1194. info = handle_to_ti_sci_info(handle);
  1195. xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_GET_CLOCK_FREQ,
  1196. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  1197. (u32 *)&req, sizeof(req), sizeof(*resp));
  1198. if (IS_ERR(xfer)) {
  1199. ret = PTR_ERR(xfer);
  1200. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  1201. return ret;
  1202. }
  1203. req.dev_id = dev_id;
  1204. req.clk_id = clk_id;
  1205. ret = ti_sci_do_xfer(info, xfer);
  1206. if (ret) {
  1207. dev_err(info->dev, "Mbox send fail %d\n", ret);
  1208. return ret;
  1209. }
  1210. resp = (struct ti_sci_msg_resp_get_clock_freq *)xfer->tx_message.buf;
  1211. if (!ti_sci_is_response_ack(resp))
  1212. ret = -ENODEV;
  1213. else
  1214. *freq = resp->freq_hz;
  1215. return ret;
  1216. }
  1217. /**
  1218. * ti_sci_cmd_core_reboot() - Command to request system reset
  1219. * @handle: pointer to TI SCI handle
  1220. *
  1221. * Return: 0 if all went well, else returns appropriate error value.
  1222. */
  1223. static int ti_sci_cmd_core_reboot(const struct ti_sci_handle *handle)
  1224. {
  1225. struct ti_sci_msg_req_reboot req;
  1226. struct ti_sci_msg_hdr *resp;
  1227. struct ti_sci_info *info;
  1228. struct ti_sci_xfer *xfer;
  1229. int ret = 0;
  1230. if (IS_ERR(handle))
  1231. return PTR_ERR(handle);
  1232. if (!handle)
  1233. return -EINVAL;
  1234. info = handle_to_ti_sci_info(handle);
  1235. xfer = ti_sci_setup_one_xfer(info, TI_SCI_MSG_SYS_RESET,
  1236. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  1237. (u32 *)&req, sizeof(req), sizeof(*resp));
  1238. if (IS_ERR(xfer)) {
  1239. ret = PTR_ERR(xfer);
  1240. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  1241. return ret;
  1242. }
  1243. ret = ti_sci_do_xfer(info, xfer);
  1244. if (ret) {
  1245. dev_err(dev, "Mbox send fail %d\n", ret);
  1246. return ret;
  1247. }
  1248. resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
  1249. if (!ti_sci_is_response_ack(resp))
  1250. return -ENODEV;
  1251. return ret;
  1252. }
  1253. /**
  1254. * ti_sci_cmd_proc_request() - Command to request a physical processor control
  1255. * @handle: Pointer to TI SCI handle
  1256. * @proc_id: Processor ID this request is for
  1257. *
  1258. * Return: 0 if all went well, else returns appropriate error value.
  1259. */
  1260. static int ti_sci_cmd_proc_request(const struct ti_sci_handle *handle,
  1261. u8 proc_id)
  1262. {
  1263. struct ti_sci_msg_req_proc_request req;
  1264. struct ti_sci_msg_hdr *resp;
  1265. struct ti_sci_info *info;
  1266. struct ti_sci_xfer *xfer;
  1267. int ret = 0;
  1268. if (IS_ERR(handle))
  1269. return PTR_ERR(handle);
  1270. if (!handle)
  1271. return -EINVAL;
  1272. info = handle_to_ti_sci_info(handle);
  1273. xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_REQUEST,
  1274. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  1275. (u32 *)&req, sizeof(req), sizeof(*resp));
  1276. if (IS_ERR(xfer)) {
  1277. ret = PTR_ERR(xfer);
  1278. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  1279. return ret;
  1280. }
  1281. req.processor_id = proc_id;
  1282. ret = ti_sci_do_xfer(info, xfer);
  1283. if (ret) {
  1284. dev_err(info->dev, "Mbox send fail %d\n", ret);
  1285. return ret;
  1286. }
  1287. resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
  1288. if (!ti_sci_is_response_ack(resp))
  1289. ret = -ENODEV;
  1290. return ret;
  1291. }
  1292. /**
  1293. * ti_sci_cmd_proc_release() - Command to release a physical processor control
  1294. * @handle: Pointer to TI SCI handle
  1295. * @proc_id: Processor ID this request is for
  1296. *
  1297. * Return: 0 if all went well, else returns appropriate error value.
  1298. */
  1299. static int ti_sci_cmd_proc_release(const struct ti_sci_handle *handle,
  1300. u8 proc_id)
  1301. {
  1302. struct ti_sci_msg_req_proc_release req;
  1303. struct ti_sci_msg_hdr *resp;
  1304. struct ti_sci_info *info;
  1305. struct ti_sci_xfer *xfer;
  1306. int ret = 0;
  1307. if (IS_ERR(handle))
  1308. return PTR_ERR(handle);
  1309. if (!handle)
  1310. return -EINVAL;
  1311. info = handle_to_ti_sci_info(handle);
  1312. xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_RELEASE,
  1313. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  1314. (u32 *)&req, sizeof(req), sizeof(*resp));
  1315. if (IS_ERR(xfer)) {
  1316. ret = PTR_ERR(xfer);
  1317. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  1318. return ret;
  1319. }
  1320. req.processor_id = proc_id;
  1321. ret = ti_sci_do_xfer(info, xfer);
  1322. if (ret) {
  1323. dev_err(info->dev, "Mbox send fail %d\n", ret);
  1324. return ret;
  1325. }
  1326. resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
  1327. if (!ti_sci_is_response_ack(resp))
  1328. ret = -ENODEV;
  1329. return ret;
  1330. }
  1331. /**
  1332. * ti_sci_cmd_proc_handover() - Command to handover a physical processor
  1333. * control to a host in the processor's access
  1334. * control list.
  1335. * @handle: Pointer to TI SCI handle
  1336. * @proc_id: Processor ID this request is for
  1337. * @host_id: Host ID to get the control of the processor
  1338. *
  1339. * Return: 0 if all went well, else returns appropriate error value.
  1340. */
  1341. static int ti_sci_cmd_proc_handover(const struct ti_sci_handle *handle,
  1342. u8 proc_id, u8 host_id)
  1343. {
  1344. struct ti_sci_msg_req_proc_handover req;
  1345. struct ti_sci_msg_hdr *resp;
  1346. struct ti_sci_info *info;
  1347. struct ti_sci_xfer *xfer;
  1348. int ret = 0;
  1349. if (IS_ERR(handle))
  1350. return PTR_ERR(handle);
  1351. if (!handle)
  1352. return -EINVAL;
  1353. info = handle_to_ti_sci_info(handle);
  1354. xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_HANDOVER,
  1355. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  1356. (u32 *)&req, sizeof(req), sizeof(*resp));
  1357. if (IS_ERR(xfer)) {
  1358. ret = PTR_ERR(xfer);
  1359. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  1360. return ret;
  1361. }
  1362. req.processor_id = proc_id;
  1363. req.host_id = host_id;
  1364. ret = ti_sci_do_xfer(info, xfer);
  1365. if (ret) {
  1366. dev_err(info->dev, "Mbox send fail %d\n", ret);
  1367. return ret;
  1368. }
  1369. resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
  1370. if (!ti_sci_is_response_ack(resp))
  1371. ret = -ENODEV;
  1372. return ret;
  1373. }
  1374. /**
  1375. * ti_sci_cmd_set_proc_boot_cfg() - Command to set the processor boot
  1376. * configuration flags
  1377. * @handle: Pointer to TI SCI handle
  1378. * @proc_id: Processor ID this request is for
  1379. * @config_flags_set: Configuration flags to be set
  1380. * @config_flags_clear: Configuration flags to be cleared.
  1381. *
  1382. * Return: 0 if all went well, else returns appropriate error value.
  1383. */
  1384. static int ti_sci_cmd_set_proc_boot_cfg(const struct ti_sci_handle *handle,
  1385. u8 proc_id, u64 bootvector,
  1386. u32 config_flags_set,
  1387. u32 config_flags_clear)
  1388. {
  1389. struct ti_sci_msg_req_set_proc_boot_config req;
  1390. struct ti_sci_msg_hdr *resp;
  1391. struct ti_sci_info *info;
  1392. struct ti_sci_xfer *xfer;
  1393. int ret = 0;
  1394. if (IS_ERR(handle))
  1395. return PTR_ERR(handle);
  1396. if (!handle)
  1397. return -EINVAL;
  1398. info = handle_to_ti_sci_info(handle);
  1399. xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_SET_PROC_BOOT_CONFIG,
  1400. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  1401. (u32 *)&req, sizeof(req), sizeof(*resp));
  1402. if (IS_ERR(xfer)) {
  1403. ret = PTR_ERR(xfer);
  1404. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  1405. return ret;
  1406. }
  1407. req.processor_id = proc_id;
  1408. req.bootvector_low = bootvector & TISCI_ADDR_LOW_MASK;
  1409. req.bootvector_high = (bootvector & TISCI_ADDR_HIGH_MASK) >>
  1410. TISCI_ADDR_HIGH_SHIFT;
  1411. req.config_flags_set = config_flags_set;
  1412. req.config_flags_clear = config_flags_clear;
  1413. ret = ti_sci_do_xfer(info, xfer);
  1414. if (ret) {
  1415. dev_err(info->dev, "Mbox send fail %d\n", ret);
  1416. return ret;
  1417. }
  1418. resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
  1419. if (!ti_sci_is_response_ack(resp))
  1420. ret = -ENODEV;
  1421. return ret;
  1422. }
  1423. /**
  1424. * ti_sci_cmd_set_proc_boot_ctrl() - Command to set the processor boot
  1425. * control flags
  1426. * @handle: Pointer to TI SCI handle
  1427. * @proc_id: Processor ID this request is for
  1428. * @control_flags_set: Control flags to be set
  1429. * @control_flags_clear: Control flags to be cleared
  1430. *
  1431. * Return: 0 if all went well, else returns appropriate error value.
  1432. */
  1433. static int ti_sci_cmd_set_proc_boot_ctrl(const struct ti_sci_handle *handle,
  1434. u8 proc_id, u32 control_flags_set,
  1435. u32 control_flags_clear)
  1436. {
  1437. struct ti_sci_msg_req_set_proc_boot_ctrl req;
  1438. struct ti_sci_msg_hdr *resp;
  1439. struct ti_sci_info *info;
  1440. struct ti_sci_xfer *xfer;
  1441. int ret = 0;
  1442. if (IS_ERR(handle))
  1443. return PTR_ERR(handle);
  1444. if (!handle)
  1445. return -EINVAL;
  1446. info = handle_to_ti_sci_info(handle);
  1447. xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_SET_PROC_BOOT_CTRL,
  1448. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  1449. (u32 *)&req, sizeof(req), sizeof(*resp));
  1450. if (IS_ERR(xfer)) {
  1451. ret = PTR_ERR(xfer);
  1452. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  1453. return ret;
  1454. }
  1455. req.processor_id = proc_id;
  1456. req.control_flags_set = control_flags_set;
  1457. req.control_flags_clear = control_flags_clear;
  1458. ret = ti_sci_do_xfer(info, xfer);
  1459. if (ret) {
  1460. dev_err(info->dev, "Mbox send fail %d\n", ret);
  1461. return ret;
  1462. }
  1463. resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
  1464. if (!ti_sci_is_response_ack(resp))
  1465. ret = -ENODEV;
  1466. return ret;
  1467. }
  1468. /**
  1469. * ti_sci_cmd_proc_auth_boot_image() - Command to authenticate and load the
  1470. * image and then set the processor configuration flags.
  1471. * @handle: Pointer to TI SCI handle
  1472. * @proc_id: Processor ID this request is for
  1473. * @cert_addr: Memory address at which payload image certificate is located.
  1474. *
  1475. * Return: 0 if all went well, else returns appropriate error value.
  1476. */
  1477. static int ti_sci_cmd_proc_auth_boot_image(const struct ti_sci_handle *handle,
  1478. u8 proc_id, u64 cert_addr)
  1479. {
  1480. struct ti_sci_msg_req_proc_auth_boot_image req;
  1481. struct ti_sci_msg_hdr *resp;
  1482. struct ti_sci_info *info;
  1483. struct ti_sci_xfer *xfer;
  1484. int ret = 0;
  1485. if (IS_ERR(handle))
  1486. return PTR_ERR(handle);
  1487. if (!handle)
  1488. return -EINVAL;
  1489. info = handle_to_ti_sci_info(handle);
  1490. xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_PROC_AUTH_BOOT_IMIAGE,
  1491. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  1492. (u32 *)&req, sizeof(req), sizeof(*resp));
  1493. if (IS_ERR(xfer)) {
  1494. ret = PTR_ERR(xfer);
  1495. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  1496. return ret;
  1497. }
  1498. req.processor_id = proc_id;
  1499. req.cert_addr_low = cert_addr & TISCI_ADDR_LOW_MASK;
  1500. req.cert_addr_high = (cert_addr & TISCI_ADDR_HIGH_MASK) >>
  1501. TISCI_ADDR_HIGH_SHIFT;
  1502. ret = ti_sci_do_xfer(info, xfer);
  1503. if (ret) {
  1504. dev_err(info->dev, "Mbox send fail %d\n", ret);
  1505. return ret;
  1506. }
  1507. resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf;
  1508. if (!ti_sci_is_response_ack(resp))
  1509. ret = -ENODEV;
  1510. return ret;
  1511. }
  1512. /**
  1513. * ti_sci_cmd_get_proc_boot_status() - Command to get the processor boot status
  1514. * @handle: Pointer to TI SCI handle
  1515. * @proc_id: Processor ID this request is for
  1516. *
  1517. * Return: 0 if all went well, else returns appropriate error value.
  1518. */
  1519. static int ti_sci_cmd_get_proc_boot_status(const struct ti_sci_handle *handle,
  1520. u8 proc_id, u64 *bv, u32 *cfg_flags,
  1521. u32 *ctrl_flags, u32 *sts_flags)
  1522. {
  1523. struct ti_sci_msg_resp_get_proc_boot_status *resp;
  1524. struct ti_sci_msg_req_get_proc_boot_status req;
  1525. struct ti_sci_info *info;
  1526. struct ti_sci_xfer *xfer;
  1527. int ret = 0;
  1528. if (IS_ERR(handle))
  1529. return PTR_ERR(handle);
  1530. if (!handle)
  1531. return -EINVAL;
  1532. info = handle_to_ti_sci_info(handle);
  1533. xfer = ti_sci_setup_one_xfer(info, TISCI_MSG_GET_PROC_BOOT_STATUS,
  1534. TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
  1535. (u32 *)&req, sizeof(req), sizeof(*resp));
  1536. if (IS_ERR(xfer)) {
  1537. ret = PTR_ERR(xfer);
  1538. dev_err(info->dev, "Message alloc failed(%d)\n", ret);
  1539. return ret;
  1540. }
  1541. req.processor_id = proc_id;
  1542. ret = ti_sci_do_xfer(info, xfer);
  1543. if (ret) {
  1544. dev_err(info->dev, "Mbox send fail %d\n", ret);
  1545. return ret;
  1546. }
  1547. resp = (struct ti_sci_msg_resp_get_proc_boot_status *)
  1548. xfer->tx_message.buf;
  1549. if (!ti_sci_is_response_ack(resp))
  1550. return -ENODEV;
  1551. *bv = (resp->bootvector_low & TISCI_ADDR_LOW_MASK) |
  1552. (((u64)resp->bootvector_high <<
  1553. TISCI_ADDR_HIGH_SHIFT) & TISCI_ADDR_HIGH_MASK);
  1554. *cfg_flags = resp->config_flags;
  1555. *ctrl_flags = resp->control_flags;
  1556. *sts_flags = resp->status_flags;
  1557. return ret;
  1558. }
  1559. /*
  1560. * ti_sci_setup_ops() - Setup the operations structures
  1561. * @info: pointer to TISCI pointer
  1562. */
  1563. static void ti_sci_setup_ops(struct ti_sci_info *info)
  1564. {
  1565. struct ti_sci_ops *ops = &info->handle.ops;
  1566. struct ti_sci_board_ops *bops = &ops->board_ops;
  1567. struct ti_sci_dev_ops *dops = &ops->dev_ops;
  1568. struct ti_sci_clk_ops *cops = &ops->clk_ops;
  1569. struct ti_sci_core_ops *core_ops = &ops->core_ops;
  1570. struct ti_sci_proc_ops *pops = &ops->proc_ops;
  1571. bops->board_config = ti_sci_cmd_set_board_config;
  1572. bops->board_config_rm = ti_sci_cmd_set_board_config_rm;
  1573. bops->board_config_security = ti_sci_cmd_set_board_config_security;
  1574. bops->board_config_pm = ti_sci_cmd_set_board_config_pm;
  1575. dops->get_device = ti_sci_cmd_get_device;
  1576. dops->idle_device = ti_sci_cmd_idle_device;
  1577. dops->put_device = ti_sci_cmd_put_device;
  1578. dops->is_valid = ti_sci_cmd_dev_is_valid;
  1579. dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt;
  1580. dops->is_idle = ti_sci_cmd_dev_is_idle;
  1581. dops->is_stop = ti_sci_cmd_dev_is_stop;
  1582. dops->is_on = ti_sci_cmd_dev_is_on;
  1583. dops->is_transitioning = ti_sci_cmd_dev_is_trans;
  1584. dops->set_device_resets = ti_sci_cmd_set_device_resets;
  1585. dops->get_device_resets = ti_sci_cmd_get_device_resets;
  1586. cops->get_clock = ti_sci_cmd_get_clock;
  1587. cops->idle_clock = ti_sci_cmd_idle_clock;
  1588. cops->put_clock = ti_sci_cmd_put_clock;
  1589. cops->is_auto = ti_sci_cmd_clk_is_auto;
  1590. cops->is_on = ti_sci_cmd_clk_is_on;
  1591. cops->is_off = ti_sci_cmd_clk_is_off;
  1592. cops->set_parent = ti_sci_cmd_clk_set_parent;
  1593. cops->get_parent = ti_sci_cmd_clk_get_parent;
  1594. cops->get_num_parents = ti_sci_cmd_clk_get_num_parents;
  1595. cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq;
  1596. cops->set_freq = ti_sci_cmd_clk_set_freq;
  1597. cops->get_freq = ti_sci_cmd_clk_get_freq;
  1598. core_ops->reboot_device = ti_sci_cmd_core_reboot;
  1599. pops->proc_request = ti_sci_cmd_proc_request;
  1600. pops->proc_release = ti_sci_cmd_proc_release;
  1601. pops->proc_handover = ti_sci_cmd_proc_handover;
  1602. pops->set_proc_boot_cfg = ti_sci_cmd_set_proc_boot_cfg;
  1603. pops->set_proc_boot_ctrl = ti_sci_cmd_set_proc_boot_ctrl;
  1604. pops->proc_auth_boot_image = ti_sci_cmd_proc_auth_boot_image;
  1605. pops->get_proc_boot_status = ti_sci_cmd_get_proc_boot_status;
  1606. }
  1607. /**
  1608. * ti_sci_get_handle_from_sysfw() - Get the TI SCI handle of the SYSFW
  1609. * @dev: Pointer to the SYSFW device
  1610. *
  1611. * Return: pointer to handle if successful, else EINVAL if invalid conditions
  1612. * are encountered.
  1613. */
  1614. const
  1615. struct ti_sci_handle *ti_sci_get_handle_from_sysfw(struct udevice *sci_dev)
  1616. {
  1617. if (!sci_dev)
  1618. return ERR_PTR(-EINVAL);
  1619. struct ti_sci_info *info = dev_get_priv(sci_dev);
  1620. if (!info)
  1621. return ERR_PTR(-EINVAL);
  1622. struct ti_sci_handle *handle = &info->handle;
  1623. if (!handle)
  1624. return ERR_PTR(-EINVAL);
  1625. return handle;
  1626. }
  1627. /**
  1628. * ti_sci_get_handle() - Get the TI SCI handle for a device
  1629. * @dev: Pointer to device for which we want SCI handle
  1630. *
  1631. * Return: pointer to handle if successful, else EINVAL if invalid conditions
  1632. * are encountered.
  1633. */
  1634. const struct ti_sci_handle *ti_sci_get_handle(struct udevice *dev)
  1635. {
  1636. if (!dev)
  1637. return ERR_PTR(-EINVAL);
  1638. struct udevice *sci_dev = dev_get_parent(dev);
  1639. return ti_sci_get_handle_from_sysfw(sci_dev);
  1640. }
  1641. /**
  1642. * ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle
  1643. * @dev: device node
  1644. * @propname: property name containing phandle on TISCI node
  1645. *
  1646. * Return: pointer to handle if successful, else appropriate error value.
  1647. */
  1648. const struct ti_sci_handle *ti_sci_get_by_phandle(struct udevice *dev,
  1649. const char *property)
  1650. {
  1651. struct ti_sci_info *entry, *info = NULL;
  1652. u32 phandle, err;
  1653. ofnode node;
  1654. err = ofnode_read_u32(dev_ofnode(dev), property, &phandle);
  1655. if (err)
  1656. return ERR_PTR(err);
  1657. node = ofnode_get_by_phandle(phandle);
  1658. if (!ofnode_valid(node))
  1659. return ERR_PTR(-EINVAL);
  1660. list_for_each_entry(entry, &ti_sci_list, list)
  1661. if (ofnode_equal(dev_ofnode(entry->dev), node)) {
  1662. info = entry;
  1663. break;
  1664. }
  1665. if (!info)
  1666. return ERR_PTR(-ENODEV);
  1667. return &info->handle;
  1668. }
  1669. /**
  1670. * ti_sci_of_to_info() - generate private data from device tree
  1671. * @dev: corresponding system controller interface device
  1672. * @info: pointer to driver specific private data
  1673. *
  1674. * Return: 0 if all goes good, else appropriate error message.
  1675. */
  1676. static int ti_sci_of_to_info(struct udevice *dev, struct ti_sci_info *info)
  1677. {
  1678. int ret;
  1679. ret = mbox_get_by_name(dev, "tx", &info->chan_tx);
  1680. if (ret) {
  1681. dev_err(dev, "%s: Acquiring Tx channel failed. ret = %d\n",
  1682. __func__, ret);
  1683. return ret;
  1684. }
  1685. ret = mbox_get_by_name(dev, "rx", &info->chan_rx);
  1686. if (ret) {
  1687. dev_err(dev, "%s: Acquiring Rx channel failed. ret = %d\n",
  1688. __func__, ret);
  1689. return ret;
  1690. }
  1691. /* Notify channel is optional. Enable only if populated */
  1692. ret = mbox_get_by_name(dev, "notify", &info->chan_notify);
  1693. if (ret) {
  1694. dev_dbg(dev, "%s: Acquiring notify channel failed. ret = %d\n",
  1695. __func__, ret);
  1696. }
  1697. info->host_id = dev_read_u32_default(dev, "ti,host-id",
  1698. info->desc->host_id);
  1699. info->is_secure = dev_read_bool(dev, "ti,secure-host");
  1700. return 0;
  1701. }
  1702. /**
  1703. * ti_sci_probe() - Basic probe
  1704. * @dev: corresponding system controller interface device
  1705. *
  1706. * Return: 0 if all goes good, else appropriate error message.
  1707. */
  1708. static int ti_sci_probe(struct udevice *dev)
  1709. {
  1710. struct ti_sci_info *info;
  1711. int ret;
  1712. debug("%s(dev=%p)\n", __func__, dev);
  1713. info = dev_get_priv(dev);
  1714. info->desc = (void *)dev_get_driver_data(dev);
  1715. ret = ti_sci_of_to_info(dev, info);
  1716. if (ret) {
  1717. dev_err(dev, "%s: Probe failed with error %d\n", __func__, ret);
  1718. return ret;
  1719. }
  1720. info->dev = dev;
  1721. info->seq = 0xA;
  1722. list_add_tail(&info->list, &ti_sci_list);
  1723. ti_sci_setup_ops(info);
  1724. ret = ti_sci_cmd_get_revision(&info->handle);
  1725. return ret;
  1726. }
  1727. /* Description for AM654 */
  1728. static const struct ti_sci_desc ti_sci_sysfw_am654_desc = {
  1729. .host_id = 4,
  1730. .max_rx_timeout_us = 1000000,
  1731. .max_msg_size = 60,
  1732. };
  1733. static const struct udevice_id ti_sci_ids[] = {
  1734. {
  1735. .compatible = "ti,k2g-sci",
  1736. .data = (ulong)&ti_sci_sysfw_am654_desc
  1737. },
  1738. { /* Sentinel */ },
  1739. };
  1740. U_BOOT_DRIVER(ti_sci) = {
  1741. .name = "ti_sci",
  1742. .id = UCLASS_FIRMWARE,
  1743. .of_match = ti_sci_ids,
  1744. .probe = ti_sci_probe,
  1745. .priv_auto_alloc_size = sizeof(struct ti_sci_info),
  1746. };