ti_sci.c 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662
  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_setup_ops() - Setup the operations structures
  1255. * @info: pointer to TISCI pointer
  1256. */
  1257. static void ti_sci_setup_ops(struct ti_sci_info *info)
  1258. {
  1259. struct ti_sci_ops *ops = &info->handle.ops;
  1260. struct ti_sci_board_ops *bops = &ops->board_ops;
  1261. struct ti_sci_dev_ops *dops = &ops->dev_ops;
  1262. struct ti_sci_clk_ops *cops = &ops->clk_ops;
  1263. struct ti_sci_core_ops *core_ops = &ops->core_ops;
  1264. bops->board_config = ti_sci_cmd_set_board_config;
  1265. bops->board_config_rm = ti_sci_cmd_set_board_config_rm;
  1266. bops->board_config_security = ti_sci_cmd_set_board_config_security;
  1267. bops->board_config_pm = ti_sci_cmd_set_board_config_pm;
  1268. dops->get_device = ti_sci_cmd_get_device;
  1269. dops->idle_device = ti_sci_cmd_idle_device;
  1270. dops->put_device = ti_sci_cmd_put_device;
  1271. dops->is_valid = ti_sci_cmd_dev_is_valid;
  1272. dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt;
  1273. dops->is_idle = ti_sci_cmd_dev_is_idle;
  1274. dops->is_stop = ti_sci_cmd_dev_is_stop;
  1275. dops->is_on = ti_sci_cmd_dev_is_on;
  1276. dops->is_transitioning = ti_sci_cmd_dev_is_trans;
  1277. dops->set_device_resets = ti_sci_cmd_set_device_resets;
  1278. dops->get_device_resets = ti_sci_cmd_get_device_resets;
  1279. cops->get_clock = ti_sci_cmd_get_clock;
  1280. cops->idle_clock = ti_sci_cmd_idle_clock;
  1281. cops->put_clock = ti_sci_cmd_put_clock;
  1282. cops->is_auto = ti_sci_cmd_clk_is_auto;
  1283. cops->is_on = ti_sci_cmd_clk_is_on;
  1284. cops->is_off = ti_sci_cmd_clk_is_off;
  1285. cops->set_parent = ti_sci_cmd_clk_set_parent;
  1286. cops->get_parent = ti_sci_cmd_clk_get_parent;
  1287. cops->get_num_parents = ti_sci_cmd_clk_get_num_parents;
  1288. cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq;
  1289. cops->set_freq = ti_sci_cmd_clk_set_freq;
  1290. cops->get_freq = ti_sci_cmd_clk_get_freq;
  1291. core_ops->reboot_device = ti_sci_cmd_core_reboot;
  1292. }
  1293. /**
  1294. * ti_sci_get_handle_from_sysfw() - Get the TI SCI handle of the SYSFW
  1295. * @dev: Pointer to the SYSFW device
  1296. *
  1297. * Return: pointer to handle if successful, else EINVAL if invalid conditions
  1298. * are encountered.
  1299. */
  1300. const
  1301. struct ti_sci_handle *ti_sci_get_handle_from_sysfw(struct udevice *sci_dev)
  1302. {
  1303. if (!sci_dev)
  1304. return ERR_PTR(-EINVAL);
  1305. struct ti_sci_info *info = dev_get_priv(sci_dev);
  1306. if (!info)
  1307. return ERR_PTR(-EINVAL);
  1308. struct ti_sci_handle *handle = &info->handle;
  1309. if (!handle)
  1310. return ERR_PTR(-EINVAL);
  1311. return handle;
  1312. }
  1313. /**
  1314. * ti_sci_get_handle() - Get the TI SCI handle for a device
  1315. * @dev: Pointer to device for which we want SCI handle
  1316. *
  1317. * Return: pointer to handle if successful, else EINVAL if invalid conditions
  1318. * are encountered.
  1319. */
  1320. const struct ti_sci_handle *ti_sci_get_handle(struct udevice *dev)
  1321. {
  1322. if (!dev)
  1323. return ERR_PTR(-EINVAL);
  1324. struct udevice *sci_dev = dev_get_parent(dev);
  1325. return ti_sci_get_handle_from_sysfw(sci_dev);
  1326. }
  1327. /**
  1328. * ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle
  1329. * @dev: device node
  1330. * @propname: property name containing phandle on TISCI node
  1331. *
  1332. * Return: pointer to handle if successful, else appropriate error value.
  1333. */
  1334. const struct ti_sci_handle *ti_sci_get_by_phandle(struct udevice *dev,
  1335. const char *property)
  1336. {
  1337. struct ti_sci_info *entry, *info = NULL;
  1338. u32 phandle, err;
  1339. ofnode node;
  1340. err = ofnode_read_u32(dev_ofnode(dev), property, &phandle);
  1341. if (err)
  1342. return ERR_PTR(err);
  1343. node = ofnode_get_by_phandle(phandle);
  1344. if (!ofnode_valid(node))
  1345. return ERR_PTR(-EINVAL);
  1346. list_for_each_entry(entry, &ti_sci_list, list)
  1347. if (ofnode_equal(dev_ofnode(entry->dev), node)) {
  1348. info = entry;
  1349. break;
  1350. }
  1351. if (!info)
  1352. return ERR_PTR(-ENODEV);
  1353. return &info->handle;
  1354. }
  1355. /**
  1356. * ti_sci_of_to_info() - generate private data from device tree
  1357. * @dev: corresponding system controller interface device
  1358. * @info: pointer to driver specific private data
  1359. *
  1360. * Return: 0 if all goes good, else appropriate error message.
  1361. */
  1362. static int ti_sci_of_to_info(struct udevice *dev, struct ti_sci_info *info)
  1363. {
  1364. int ret;
  1365. ret = mbox_get_by_name(dev, "tx", &info->chan_tx);
  1366. if (ret) {
  1367. dev_err(dev, "%s: Acquiring Tx channel failed. ret = %d\n",
  1368. __func__, ret);
  1369. return ret;
  1370. }
  1371. ret = mbox_get_by_name(dev, "rx", &info->chan_rx);
  1372. if (ret) {
  1373. dev_err(dev, "%s: Acquiring Rx channel failed. ret = %d\n",
  1374. __func__, ret);
  1375. return ret;
  1376. }
  1377. /* Notify channel is optional. Enable only if populated */
  1378. ret = mbox_get_by_name(dev, "notify", &info->chan_notify);
  1379. if (ret) {
  1380. dev_dbg(dev, "%s: Acquiring notify channel failed. ret = %d\n",
  1381. __func__, ret);
  1382. }
  1383. info->host_id = dev_read_u32_default(dev, "ti,host-id",
  1384. info->desc->host_id);
  1385. info->is_secure = dev_read_bool(dev, "ti,secure-host");
  1386. return 0;
  1387. }
  1388. /**
  1389. * ti_sci_probe() - Basic probe
  1390. * @dev: corresponding system controller interface device
  1391. *
  1392. * Return: 0 if all goes good, else appropriate error message.
  1393. */
  1394. static int ti_sci_probe(struct udevice *dev)
  1395. {
  1396. struct ti_sci_info *info;
  1397. int ret;
  1398. debug("%s(dev=%p)\n", __func__, dev);
  1399. info = dev_get_priv(dev);
  1400. info->desc = (void *)dev_get_driver_data(dev);
  1401. ret = ti_sci_of_to_info(dev, info);
  1402. if (ret) {
  1403. dev_err(dev, "%s: Probe failed with error %d\n", __func__, ret);
  1404. return ret;
  1405. }
  1406. info->dev = dev;
  1407. info->seq = 0xA;
  1408. list_add_tail(&info->list, &ti_sci_list);
  1409. ti_sci_setup_ops(info);
  1410. ret = ti_sci_cmd_get_revision(&info->handle);
  1411. return ret;
  1412. }
  1413. /* Description for AM654 */
  1414. static const struct ti_sci_desc ti_sci_sysfw_am654_desc = {
  1415. .host_id = 4,
  1416. .max_rx_timeout_us = 1000000,
  1417. .max_msg_size = 60,
  1418. };
  1419. static const struct udevice_id ti_sci_ids[] = {
  1420. {
  1421. .compatible = "ti,k2g-sci",
  1422. .data = (ulong)&ti_sci_sysfw_am654_desc
  1423. },
  1424. { /* Sentinel */ },
  1425. };
  1426. U_BOOT_DRIVER(ti_sci) = {
  1427. .name = "ti_sci",
  1428. .id = UCLASS_FIRMWARE,
  1429. .of_match = ti_sci_ids,
  1430. .probe = ti_sci_probe,
  1431. .priv_auto_alloc_size = sizeof(struct ti_sci_info),
  1432. };