stratix10-rsu.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2018-2019, Intel Corporation
  4. */
  5. #include <linux/arm-smccc.h>
  6. #include <linux/bitfield.h>
  7. #include <linux/completion.h>
  8. #include <linux/kobject.h>
  9. #include <linux/module.h>
  10. #include <linux/mutex.h>
  11. #include <linux/of.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/firmware/intel/stratix10-svc-client.h>
  14. #include <linux/string.h>
  15. #include <linux/sysfs.h>
  16. #define RSU_STATE_MASK GENMASK_ULL(31, 0)
  17. #define RSU_VERSION_MASK GENMASK_ULL(63, 32)
  18. #define RSU_ERROR_LOCATION_MASK GENMASK_ULL(31, 0)
  19. #define RSU_ERROR_DETAIL_MASK GENMASK_ULL(63, 32)
  20. #define RSU_DCMF0_MASK GENMASK_ULL(31, 0)
  21. #define RSU_DCMF1_MASK GENMASK_ULL(63, 32)
  22. #define RSU_DCMF2_MASK GENMASK_ULL(31, 0)
  23. #define RSU_DCMF3_MASK GENMASK_ULL(63, 32)
  24. #define RSU_DCMF0_STATUS_MASK GENMASK_ULL(15, 0)
  25. #define RSU_DCMF1_STATUS_MASK GENMASK_ULL(31, 16)
  26. #define RSU_DCMF2_STATUS_MASK GENMASK_ULL(47, 32)
  27. #define RSU_DCMF3_STATUS_MASK GENMASK_ULL(63, 48)
  28. #define RSU_TIMEOUT (msecs_to_jiffies(SVC_RSU_REQUEST_TIMEOUT_MS))
  29. #define INVALID_RETRY_COUNTER 0xFF
  30. #define INVALID_DCMF_VERSION 0xFF
  31. #define INVALID_DCMF_STATUS 0xFFFFFFFF
  32. #define INVALID_SPT_ADDRESS 0x0
  33. #define RSU_GET_SPT_CMD 0x5A
  34. #define RSU_GET_SPT_RESP_LEN (4 * sizeof(unsigned int))
  35. typedef void (*rsu_callback)(struct stratix10_svc_client *client,
  36. struct stratix10_svc_cb_data *data);
  37. /**
  38. * struct stratix10_rsu_priv - rsu data structure
  39. * @chan: pointer to the allocated service channel
  40. * @client: active service client
  41. * @completion: state for callback completion
  42. * @lock: a mutex to protect callback completion state
  43. * @status.current_image: address of image currently running in flash
  44. * @status.fail_image: address of failed image in flash
  45. * @status.version: the interface version number of RSU firmware
  46. * @status.state: the state of RSU system
  47. * @status.error_details: error code
  48. * @status.error_location: the error offset inside the image that failed
  49. * @dcmf_version.dcmf0: Quartus dcmf0 version
  50. * @dcmf_version.dcmf1: Quartus dcmf1 version
  51. * @dcmf_version.dcmf2: Quartus dcmf2 version
  52. * @dcmf_version.dcmf3: Quartus dcmf3 version
  53. * @dcmf_status.dcmf0: dcmf0 status
  54. * @dcmf_status.dcmf1: dcmf1 status
  55. * @dcmf_status.dcmf2: dcmf2 status
  56. * @dcmf_status.dcmf3: dcmf3 status
  57. * @retry_counter: the current image's retry counter
  58. * @max_retry: the preset max retry value
  59. * @spt0_address: address of spt0
  60. * @spt1_address: address of spt1
  61. * @get_spt_response_buf: response from sdm for get_spt command
  62. */
  63. struct stratix10_rsu_priv {
  64. struct stratix10_svc_chan *chan;
  65. struct stratix10_svc_client client;
  66. struct completion completion;
  67. struct mutex lock;
  68. struct {
  69. unsigned long current_image;
  70. unsigned long fail_image;
  71. unsigned int version;
  72. unsigned int state;
  73. unsigned int error_details;
  74. unsigned int error_location;
  75. } status;
  76. struct {
  77. unsigned int dcmf0;
  78. unsigned int dcmf1;
  79. unsigned int dcmf2;
  80. unsigned int dcmf3;
  81. } dcmf_version;
  82. struct {
  83. unsigned int dcmf0;
  84. unsigned int dcmf1;
  85. unsigned int dcmf2;
  86. unsigned int dcmf3;
  87. } dcmf_status;
  88. unsigned int retry_counter;
  89. unsigned int max_retry;
  90. unsigned long spt0_address;
  91. unsigned long spt1_address;
  92. unsigned int *get_spt_response_buf;
  93. };
  94. /**
  95. * rsu_status_callback() - Status callback from Intel Service Layer
  96. * @client: pointer to service client
  97. * @data: pointer to callback data structure
  98. *
  99. * Callback from Intel service layer for RSU status request. Status is
  100. * only updated after a system reboot, so a get updated status call is
  101. * made during driver probe.
  102. */
  103. static void rsu_status_callback(struct stratix10_svc_client *client,
  104. struct stratix10_svc_cb_data *data)
  105. {
  106. struct stratix10_rsu_priv *priv = client->priv;
  107. struct arm_smccc_res *res = (struct arm_smccc_res *)data->kaddr1;
  108. if (data->status == BIT(SVC_STATUS_OK)) {
  109. priv->status.version = FIELD_GET(RSU_VERSION_MASK,
  110. res->a2);
  111. priv->status.state = FIELD_GET(RSU_STATE_MASK, res->a2);
  112. priv->status.fail_image = res->a1;
  113. priv->status.current_image = res->a0;
  114. priv->status.error_location =
  115. FIELD_GET(RSU_ERROR_LOCATION_MASK, res->a3);
  116. priv->status.error_details =
  117. FIELD_GET(RSU_ERROR_DETAIL_MASK, res->a3);
  118. } else {
  119. dev_err(client->dev, "COMMAND_RSU_STATUS returned 0x%lX\n",
  120. res->a0);
  121. priv->status.version = 0;
  122. priv->status.state = 0;
  123. priv->status.fail_image = 0;
  124. priv->status.current_image = 0;
  125. priv->status.error_location = 0;
  126. priv->status.error_details = 0;
  127. }
  128. complete(&priv->completion);
  129. }
  130. /**
  131. * rsu_command_callback() - Update callback from Intel Service Layer
  132. * @client: pointer to client
  133. * @data: pointer to callback data structure
  134. *
  135. * Callback from Intel service layer for RSU commands.
  136. */
  137. static void rsu_command_callback(struct stratix10_svc_client *client,
  138. struct stratix10_svc_cb_data *data)
  139. {
  140. struct stratix10_rsu_priv *priv = client->priv;
  141. if (data->status == BIT(SVC_STATUS_NO_SUPPORT))
  142. dev_warn(client->dev, "Secure FW doesn't support notify\n");
  143. else if (data->status == BIT(SVC_STATUS_ERROR))
  144. dev_err(client->dev, "Failure, returned status is %lu\n",
  145. BIT(data->status));
  146. complete(&priv->completion);
  147. }
  148. /**
  149. * rsu_retry_callback() - Callback from Intel service layer for getting
  150. * the current image's retry counter from the firmware
  151. * @client: pointer to client
  152. * @data: pointer to callback data structure
  153. *
  154. * Callback from Intel service layer for retry counter, which is used by
  155. * user to know how many times the images is still allowed to reload
  156. * itself before giving up and starting RSU fail-over flow.
  157. */
  158. static void rsu_retry_callback(struct stratix10_svc_client *client,
  159. struct stratix10_svc_cb_data *data)
  160. {
  161. struct stratix10_rsu_priv *priv = client->priv;
  162. unsigned int *counter = (unsigned int *)data->kaddr1;
  163. if (data->status == BIT(SVC_STATUS_OK))
  164. priv->retry_counter = *counter;
  165. else if (data->status == BIT(SVC_STATUS_NO_SUPPORT))
  166. dev_warn(client->dev, "Secure FW doesn't support retry\n");
  167. else
  168. dev_err(client->dev, "Failed to get retry counter %lu\n",
  169. BIT(data->status));
  170. complete(&priv->completion);
  171. }
  172. /**
  173. * rsu_max_retry_callback() - Callback from Intel service layer for getting
  174. * the max retry value from the firmware
  175. * @client: pointer to client
  176. * @data: pointer to callback data structure
  177. *
  178. * Callback from Intel service layer for max retry.
  179. */
  180. static void rsu_max_retry_callback(struct stratix10_svc_client *client,
  181. struct stratix10_svc_cb_data *data)
  182. {
  183. struct stratix10_rsu_priv *priv = client->priv;
  184. unsigned int *max_retry = (unsigned int *)data->kaddr1;
  185. if (data->status == BIT(SVC_STATUS_OK))
  186. priv->max_retry = *max_retry;
  187. else if (data->status == BIT(SVC_STATUS_NO_SUPPORT))
  188. dev_warn(client->dev, "Secure FW doesn't support max retry\n");
  189. else
  190. dev_err(client->dev, "Failed to get max retry %lu\n",
  191. BIT(data->status));
  192. complete(&priv->completion);
  193. }
  194. /**
  195. * rsu_dcmf_version_callback() - Callback from Intel service layer for getting
  196. * the DCMF version
  197. * @client: pointer to client
  198. * @data: pointer to callback data structure
  199. *
  200. * Callback from Intel service layer for DCMF version number
  201. */
  202. static void rsu_dcmf_version_callback(struct stratix10_svc_client *client,
  203. struct stratix10_svc_cb_data *data)
  204. {
  205. struct stratix10_rsu_priv *priv = client->priv;
  206. unsigned long long *value1 = (unsigned long long *)data->kaddr1;
  207. unsigned long long *value2 = (unsigned long long *)data->kaddr2;
  208. if (data->status == BIT(SVC_STATUS_OK)) {
  209. priv->dcmf_version.dcmf0 = FIELD_GET(RSU_DCMF0_MASK, *value1);
  210. priv->dcmf_version.dcmf1 = FIELD_GET(RSU_DCMF1_MASK, *value1);
  211. priv->dcmf_version.dcmf2 = FIELD_GET(RSU_DCMF2_MASK, *value2);
  212. priv->dcmf_version.dcmf3 = FIELD_GET(RSU_DCMF3_MASK, *value2);
  213. } else
  214. dev_err(client->dev, "failed to get DCMF version\n");
  215. complete(&priv->completion);
  216. }
  217. /**
  218. * rsu_dcmf_status_callback() - Callback from Intel service layer for getting
  219. * the DCMF status
  220. * @client: pointer to client
  221. * @data: pointer to callback data structure
  222. *
  223. * Callback from Intel service layer for DCMF status
  224. */
  225. static void rsu_dcmf_status_callback(struct stratix10_svc_client *client,
  226. struct stratix10_svc_cb_data *data)
  227. {
  228. struct stratix10_rsu_priv *priv = client->priv;
  229. unsigned long long *value = (unsigned long long *)data->kaddr1;
  230. if (data->status == BIT(SVC_STATUS_OK)) {
  231. priv->dcmf_status.dcmf0 = FIELD_GET(RSU_DCMF0_STATUS_MASK,
  232. *value);
  233. priv->dcmf_status.dcmf1 = FIELD_GET(RSU_DCMF1_STATUS_MASK,
  234. *value);
  235. priv->dcmf_status.dcmf2 = FIELD_GET(RSU_DCMF2_STATUS_MASK,
  236. *value);
  237. priv->dcmf_status.dcmf3 = FIELD_GET(RSU_DCMF3_STATUS_MASK,
  238. *value);
  239. } else
  240. dev_err(client->dev, "failed to get DCMF status\n");
  241. complete(&priv->completion);
  242. }
  243. static void rsu_get_spt_callback(struct stratix10_svc_client *client,
  244. struct stratix10_svc_cb_data *data)
  245. {
  246. struct stratix10_rsu_priv *priv = client->priv;
  247. unsigned long *mbox_err = (unsigned long *)data->kaddr1;
  248. unsigned long *resp_len = (unsigned long *)data->kaddr2;
  249. if (data->status != BIT(SVC_STATUS_OK) || (*mbox_err) ||
  250. (*resp_len != RSU_GET_SPT_RESP_LEN))
  251. goto error;
  252. priv->spt0_address = priv->get_spt_response_buf[0];
  253. priv->spt0_address <<= 32;
  254. priv->spt0_address |= priv->get_spt_response_buf[1];
  255. priv->spt1_address = priv->get_spt_response_buf[2];
  256. priv->spt1_address <<= 32;
  257. priv->spt1_address |= priv->get_spt_response_buf[3];
  258. goto complete;
  259. error:
  260. dev_err(client->dev, "failed to get SPTs\n");
  261. complete:
  262. stratix10_svc_free_memory(priv->chan, priv->get_spt_response_buf);
  263. priv->get_spt_response_buf = NULL;
  264. complete(&priv->completion);
  265. }
  266. /**
  267. * rsu_send_msg() - send a message to Intel service layer
  268. * @priv: pointer to rsu private data
  269. * @command: RSU status or update command
  270. * @arg: the request argument, the bitstream address or notify status
  271. * @callback: function pointer for the callback (status or update)
  272. *
  273. * Start an Intel service layer transaction to perform the SMC call that
  274. * is necessary to get RSU boot log or set the address of bitstream to
  275. * boot after reboot.
  276. *
  277. * Returns 0 on success or -ETIMEDOUT on error.
  278. */
  279. static int rsu_send_msg(struct stratix10_rsu_priv *priv,
  280. enum stratix10_svc_command_code command,
  281. unsigned long arg,
  282. rsu_callback callback)
  283. {
  284. struct stratix10_svc_client_msg msg;
  285. int ret;
  286. mutex_lock(&priv->lock);
  287. reinit_completion(&priv->completion);
  288. priv->client.receive_cb = callback;
  289. msg.command = command;
  290. if (arg)
  291. msg.arg[0] = arg;
  292. if (command == COMMAND_MBOX_SEND_CMD) {
  293. msg.arg[1] = 0;
  294. msg.payload = NULL;
  295. msg.payload_length = 0;
  296. msg.payload_output = priv->get_spt_response_buf;
  297. msg.payload_length_output = RSU_GET_SPT_RESP_LEN;
  298. }
  299. ret = stratix10_svc_send(priv->chan, &msg);
  300. if (ret < 0)
  301. goto status_done;
  302. ret = wait_for_completion_interruptible_timeout(&priv->completion,
  303. RSU_TIMEOUT);
  304. if (!ret) {
  305. dev_err(priv->client.dev,
  306. "timeout waiting for SMC call\n");
  307. ret = -ETIMEDOUT;
  308. goto status_done;
  309. } else if (ret < 0) {
  310. dev_err(priv->client.dev,
  311. "error %d waiting for SMC call\n", ret);
  312. goto status_done;
  313. } else {
  314. ret = 0;
  315. }
  316. status_done:
  317. stratix10_svc_done(priv->chan);
  318. mutex_unlock(&priv->lock);
  319. return ret;
  320. }
  321. /*
  322. * This driver exposes some optional features of the Intel Stratix 10 SoC FPGA.
  323. * The sysfs interfaces exposed here are FPGA Remote System Update (RSU)
  324. * related. They allow user space software to query the configuration system
  325. * status and to request optional reboot behavior specific to Intel FPGAs.
  326. */
  327. static ssize_t current_image_show(struct device *dev,
  328. struct device_attribute *attr, char *buf)
  329. {
  330. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  331. if (!priv)
  332. return -ENODEV;
  333. return sprintf(buf, "0x%08lx\n", priv->status.current_image);
  334. }
  335. static ssize_t fail_image_show(struct device *dev,
  336. struct device_attribute *attr, char *buf)
  337. {
  338. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  339. if (!priv)
  340. return -ENODEV;
  341. return sprintf(buf, "0x%08lx\n", priv->status.fail_image);
  342. }
  343. static ssize_t version_show(struct device *dev, struct device_attribute *attr,
  344. char *buf)
  345. {
  346. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  347. if (!priv)
  348. return -ENODEV;
  349. return sprintf(buf, "0x%08x\n", priv->status.version);
  350. }
  351. static ssize_t state_show(struct device *dev, struct device_attribute *attr,
  352. char *buf)
  353. {
  354. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  355. if (!priv)
  356. return -ENODEV;
  357. return sprintf(buf, "0x%08x\n", priv->status.state);
  358. }
  359. static ssize_t error_location_show(struct device *dev,
  360. struct device_attribute *attr, char *buf)
  361. {
  362. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  363. if (!priv)
  364. return -ENODEV;
  365. return sprintf(buf, "0x%08x\n", priv->status.error_location);
  366. }
  367. static ssize_t error_details_show(struct device *dev,
  368. struct device_attribute *attr, char *buf)
  369. {
  370. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  371. if (!priv)
  372. return -ENODEV;
  373. return sprintf(buf, "0x%08x\n", priv->status.error_details);
  374. }
  375. static ssize_t retry_counter_show(struct device *dev,
  376. struct device_attribute *attr, char *buf)
  377. {
  378. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  379. if (!priv)
  380. return -ENODEV;
  381. return sprintf(buf, "0x%08x\n", priv->retry_counter);
  382. }
  383. static ssize_t max_retry_show(struct device *dev,
  384. struct device_attribute *attr, char *buf)
  385. {
  386. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  387. if (!priv)
  388. return -ENODEV;
  389. return scnprintf(buf, sizeof(priv->max_retry),
  390. "0x%08x\n", priv->max_retry);
  391. }
  392. static ssize_t dcmf0_show(struct device *dev,
  393. struct device_attribute *attr, char *buf)
  394. {
  395. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  396. if (!priv)
  397. return -ENODEV;
  398. return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf0);
  399. }
  400. static ssize_t dcmf1_show(struct device *dev,
  401. struct device_attribute *attr, char *buf)
  402. {
  403. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  404. if (!priv)
  405. return -ENODEV;
  406. return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf1);
  407. }
  408. static ssize_t dcmf2_show(struct device *dev,
  409. struct device_attribute *attr, char *buf)
  410. {
  411. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  412. if (!priv)
  413. return -ENODEV;
  414. return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf2);
  415. }
  416. static ssize_t dcmf3_show(struct device *dev,
  417. struct device_attribute *attr, char *buf)
  418. {
  419. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  420. if (!priv)
  421. return -ENODEV;
  422. return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf3);
  423. }
  424. static ssize_t dcmf0_status_show(struct device *dev,
  425. struct device_attribute *attr, char *buf)
  426. {
  427. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  428. if (!priv)
  429. return -ENODEV;
  430. if (priv->dcmf_status.dcmf0 == INVALID_DCMF_STATUS)
  431. return -EIO;
  432. return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf0);
  433. }
  434. static ssize_t dcmf1_status_show(struct device *dev,
  435. struct device_attribute *attr, char *buf)
  436. {
  437. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  438. if (!priv)
  439. return -ENODEV;
  440. if (priv->dcmf_status.dcmf1 == INVALID_DCMF_STATUS)
  441. return -EIO;
  442. return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf1);
  443. }
  444. static ssize_t dcmf2_status_show(struct device *dev,
  445. struct device_attribute *attr, char *buf)
  446. {
  447. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  448. if (!priv)
  449. return -ENODEV;
  450. if (priv->dcmf_status.dcmf2 == INVALID_DCMF_STATUS)
  451. return -EIO;
  452. return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf2);
  453. }
  454. static ssize_t dcmf3_status_show(struct device *dev,
  455. struct device_attribute *attr, char *buf)
  456. {
  457. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  458. if (!priv)
  459. return -ENODEV;
  460. if (priv->dcmf_status.dcmf3 == INVALID_DCMF_STATUS)
  461. return -EIO;
  462. return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf3);
  463. }
  464. static ssize_t reboot_image_store(struct device *dev,
  465. struct device_attribute *attr,
  466. const char *buf, size_t count)
  467. {
  468. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  469. unsigned long address;
  470. int ret;
  471. if (!priv)
  472. return -ENODEV;
  473. ret = kstrtoul(buf, 0, &address);
  474. if (ret)
  475. return ret;
  476. ret = rsu_send_msg(priv, COMMAND_RSU_UPDATE,
  477. address, rsu_command_callback);
  478. if (ret) {
  479. dev_err(dev, "Error, RSU update returned %i\n", ret);
  480. return ret;
  481. }
  482. return count;
  483. }
  484. static ssize_t notify_store(struct device *dev,
  485. struct device_attribute *attr,
  486. const char *buf, size_t count)
  487. {
  488. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  489. unsigned long status;
  490. int ret;
  491. if (!priv)
  492. return -ENODEV;
  493. ret = kstrtoul(buf, 0, &status);
  494. if (ret)
  495. return ret;
  496. ret = rsu_send_msg(priv, COMMAND_RSU_NOTIFY,
  497. status, rsu_command_callback);
  498. if (ret) {
  499. dev_err(dev, "Error, RSU notify returned %i\n", ret);
  500. return ret;
  501. }
  502. /* to get the updated state */
  503. ret = rsu_send_msg(priv, COMMAND_RSU_STATUS,
  504. 0, rsu_status_callback);
  505. if (ret) {
  506. dev_err(dev, "Error, getting RSU status %i\n", ret);
  507. return ret;
  508. }
  509. ret = rsu_send_msg(priv, COMMAND_RSU_RETRY, 0, rsu_retry_callback);
  510. if (ret) {
  511. dev_err(dev, "Error, getting RSU retry %i\n", ret);
  512. return ret;
  513. }
  514. return count;
  515. }
  516. static ssize_t spt0_address_show(struct device *dev,
  517. struct device_attribute *attr, char *buf)
  518. {
  519. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  520. if (!priv)
  521. return -ENODEV;
  522. if (priv->spt0_address == INVALID_SPT_ADDRESS)
  523. return -EIO;
  524. return scnprintf(buf, PAGE_SIZE, "0x%08lx\n", priv->spt0_address);
  525. }
  526. static ssize_t spt1_address_show(struct device *dev,
  527. struct device_attribute *attr, char *buf)
  528. {
  529. struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
  530. if (!priv)
  531. return -ENODEV;
  532. if (priv->spt1_address == INVALID_SPT_ADDRESS)
  533. return -EIO;
  534. return scnprintf(buf, PAGE_SIZE, "0x%08lx\n", priv->spt1_address);
  535. }
  536. static DEVICE_ATTR_RO(current_image);
  537. static DEVICE_ATTR_RO(fail_image);
  538. static DEVICE_ATTR_RO(state);
  539. static DEVICE_ATTR_RO(version);
  540. static DEVICE_ATTR_RO(error_location);
  541. static DEVICE_ATTR_RO(error_details);
  542. static DEVICE_ATTR_RO(retry_counter);
  543. static DEVICE_ATTR_RO(max_retry);
  544. static DEVICE_ATTR_RO(dcmf0);
  545. static DEVICE_ATTR_RO(dcmf1);
  546. static DEVICE_ATTR_RO(dcmf2);
  547. static DEVICE_ATTR_RO(dcmf3);
  548. static DEVICE_ATTR_RO(dcmf0_status);
  549. static DEVICE_ATTR_RO(dcmf1_status);
  550. static DEVICE_ATTR_RO(dcmf2_status);
  551. static DEVICE_ATTR_RO(dcmf3_status);
  552. static DEVICE_ATTR_WO(reboot_image);
  553. static DEVICE_ATTR_WO(notify);
  554. static DEVICE_ATTR_RO(spt0_address);
  555. static DEVICE_ATTR_RO(spt1_address);
  556. static struct attribute *rsu_attrs[] = {
  557. &dev_attr_current_image.attr,
  558. &dev_attr_fail_image.attr,
  559. &dev_attr_state.attr,
  560. &dev_attr_version.attr,
  561. &dev_attr_error_location.attr,
  562. &dev_attr_error_details.attr,
  563. &dev_attr_retry_counter.attr,
  564. &dev_attr_max_retry.attr,
  565. &dev_attr_dcmf0.attr,
  566. &dev_attr_dcmf1.attr,
  567. &dev_attr_dcmf2.attr,
  568. &dev_attr_dcmf3.attr,
  569. &dev_attr_dcmf0_status.attr,
  570. &dev_attr_dcmf1_status.attr,
  571. &dev_attr_dcmf2_status.attr,
  572. &dev_attr_dcmf3_status.attr,
  573. &dev_attr_reboot_image.attr,
  574. &dev_attr_notify.attr,
  575. &dev_attr_spt0_address.attr,
  576. &dev_attr_spt1_address.attr,
  577. NULL
  578. };
  579. ATTRIBUTE_GROUPS(rsu);
  580. static int stratix10_rsu_probe(struct platform_device *pdev)
  581. {
  582. struct device *dev = &pdev->dev;
  583. struct stratix10_rsu_priv *priv;
  584. int ret;
  585. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  586. if (!priv)
  587. return -ENOMEM;
  588. priv->client.dev = dev;
  589. priv->client.receive_cb = NULL;
  590. priv->client.priv = priv;
  591. priv->status.current_image = 0;
  592. priv->status.fail_image = 0;
  593. priv->status.error_location = 0;
  594. priv->status.error_details = 0;
  595. priv->status.version = 0;
  596. priv->status.state = 0;
  597. priv->retry_counter = INVALID_RETRY_COUNTER;
  598. priv->dcmf_version.dcmf0 = INVALID_DCMF_VERSION;
  599. priv->dcmf_version.dcmf1 = INVALID_DCMF_VERSION;
  600. priv->dcmf_version.dcmf2 = INVALID_DCMF_VERSION;
  601. priv->dcmf_version.dcmf3 = INVALID_DCMF_VERSION;
  602. priv->dcmf_status.dcmf0 = INVALID_DCMF_STATUS;
  603. priv->dcmf_status.dcmf1 = INVALID_DCMF_STATUS;
  604. priv->dcmf_status.dcmf2 = INVALID_DCMF_STATUS;
  605. priv->dcmf_status.dcmf3 = INVALID_DCMF_STATUS;
  606. priv->max_retry = INVALID_RETRY_COUNTER;
  607. priv->spt0_address = INVALID_SPT_ADDRESS;
  608. priv->spt1_address = INVALID_SPT_ADDRESS;
  609. mutex_init(&priv->lock);
  610. priv->chan = stratix10_svc_request_channel_byname(&priv->client,
  611. SVC_CLIENT_RSU);
  612. if (IS_ERR(priv->chan)) {
  613. dev_err(dev, "couldn't get service channel %s\n",
  614. SVC_CLIENT_RSU);
  615. return PTR_ERR(priv->chan);
  616. }
  617. init_completion(&priv->completion);
  618. platform_set_drvdata(pdev, priv);
  619. /* get the initial state from firmware */
  620. ret = rsu_send_msg(priv, COMMAND_RSU_STATUS,
  621. 0, rsu_status_callback);
  622. if (ret) {
  623. dev_err(dev, "Error, getting RSU status %i\n", ret);
  624. stratix10_svc_free_channel(priv->chan);
  625. }
  626. /* get DCMF version from firmware */
  627. ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_VERSION,
  628. 0, rsu_dcmf_version_callback);
  629. if (ret) {
  630. dev_err(dev, "Error, getting DCMF version %i\n", ret);
  631. stratix10_svc_free_channel(priv->chan);
  632. }
  633. ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_STATUS,
  634. 0, rsu_dcmf_status_callback);
  635. if (ret) {
  636. dev_err(dev, "Error, getting DCMF status %i\n", ret);
  637. stratix10_svc_free_channel(priv->chan);
  638. }
  639. ret = rsu_send_msg(priv, COMMAND_RSU_RETRY, 0, rsu_retry_callback);
  640. if (ret) {
  641. dev_err(dev, "Error, getting RSU retry %i\n", ret);
  642. stratix10_svc_free_channel(priv->chan);
  643. }
  644. ret = rsu_send_msg(priv, COMMAND_RSU_MAX_RETRY, 0,
  645. rsu_max_retry_callback);
  646. if (ret) {
  647. dev_err(dev, "Error, getting RSU max retry %i\n", ret);
  648. stratix10_svc_free_channel(priv->chan);
  649. }
  650. priv->get_spt_response_buf =
  651. stratix10_svc_allocate_memory(priv->chan, RSU_GET_SPT_RESP_LEN);
  652. if (IS_ERR(priv->get_spt_response_buf)) {
  653. dev_err(dev, "failed to allocate get spt buffer\n");
  654. } else {
  655. ret = rsu_send_msg(priv, COMMAND_MBOX_SEND_CMD,
  656. RSU_GET_SPT_CMD, rsu_get_spt_callback);
  657. if (ret) {
  658. dev_err(dev, "Error, getting SPT table %i\n", ret);
  659. stratix10_svc_free_channel(priv->chan);
  660. }
  661. }
  662. return ret;
  663. }
  664. static void stratix10_rsu_remove(struct platform_device *pdev)
  665. {
  666. struct stratix10_rsu_priv *priv = platform_get_drvdata(pdev);
  667. stratix10_svc_free_channel(priv->chan);
  668. }
  669. static struct platform_driver stratix10_rsu_driver = {
  670. .probe = stratix10_rsu_probe,
  671. .remove_new = stratix10_rsu_remove,
  672. .driver = {
  673. .name = "stratix10-rsu",
  674. .dev_groups = rsu_groups,
  675. },
  676. };
  677. module_platform_driver(stratix10_rsu_driver);
  678. MODULE_LICENSE("GPL v2");
  679. MODULE_DESCRIPTION("Intel Remote System Update Driver");
  680. MODULE_AUTHOR("Richard Gong <richard.gong@intel.com>");