brcmstb_dpfe.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. /*
  2. * DDR PHY Front End (DPFE) driver for Broadcom set top box SoCs
  3. *
  4. * Copyright (c) 2017 Broadcom
  5. *
  6. * Released under the GPLv2 only.
  7. * SPDX-License-Identifier: GPL-2.0
  8. */
  9. /*
  10. * This driver provides access to the DPFE interface of Broadcom STB SoCs.
  11. * The firmware running on the DCPU inside the DDR PHY can provide current
  12. * information about the system's RAM, for instance the DRAM refresh rate.
  13. * This can be used as an indirect indicator for the DRAM's temperature.
  14. * Slower refresh rate means cooler RAM, higher refresh rate means hotter
  15. * RAM.
  16. *
  17. * Throughout the driver, we use readl_relaxed() and writel_relaxed(), which
  18. * already contain the appropriate le32_to_cpu()/cpu_to_le32() calls.
  19. *
  20. * Note regarding the loading of the firmware image: we use be32_to_cpu()
  21. * and le_32_to_cpu(), so we can support the following four cases:
  22. * - LE kernel + LE firmware image (the most common case)
  23. * - LE kernel + BE firmware image
  24. * - BE kernel + LE firmware image
  25. * - BE kernel + BE firmware image
  26. *
  27. * The DPCU always runs in big endian mode. The firwmare image, however, can
  28. * be in either format. Also, communication between host CPU and DCPU is
  29. * always in little endian.
  30. */
  31. #include <linux/delay.h>
  32. #include <linux/firmware.h>
  33. #include <linux/io.h>
  34. #include <linux/module.h>
  35. #include <linux/of_address.h>
  36. #include <linux/platform_device.h>
  37. #define DRVNAME "brcmstb-dpfe"
  38. #define FIRMWARE_NAME "dpfe.bin"
  39. /* DCPU register offsets */
  40. #define REG_DCPU_RESET 0x0
  41. #define REG_TO_DCPU_MBOX 0x10
  42. #define REG_TO_HOST_MBOX 0x14
  43. /* Macros to process offsets returned by the DCPU */
  44. #define DRAM_MSG_ADDR_OFFSET 0x0
  45. #define DRAM_MSG_TYPE_OFFSET 0x1c
  46. #define DRAM_MSG_ADDR_MASK ((1UL << DRAM_MSG_TYPE_OFFSET) - 1)
  47. #define DRAM_MSG_TYPE_MASK ((1UL << \
  48. (BITS_PER_LONG - DRAM_MSG_TYPE_OFFSET)) - 1)
  49. /* Message RAM */
  50. #define DCPU_MSG_RAM_START 0x100
  51. #define DCPU_MSG_RAM(x) (DCPU_MSG_RAM_START + (x) * sizeof(u32))
  52. /* DRAM Info Offsets & Masks */
  53. #define DRAM_INFO_INTERVAL 0x0
  54. #define DRAM_INFO_MR4 0x4
  55. #define DRAM_INFO_ERROR 0x8
  56. #define DRAM_INFO_MR4_MASK 0xff
  57. /* DRAM MR4 Offsets & Masks */
  58. #define DRAM_MR4_REFRESH 0x0 /* Refresh rate */
  59. #define DRAM_MR4_SR_ABORT 0x3 /* Self Refresh Abort */
  60. #define DRAM_MR4_PPRE 0x4 /* Post-package repair entry/exit */
  61. #define DRAM_MR4_TH_OFFS 0x5 /* Thermal Offset; vendor specific */
  62. #define DRAM_MR4_TUF 0x7 /* Temperature Update Flag */
  63. #define DRAM_MR4_REFRESH_MASK 0x7
  64. #define DRAM_MR4_SR_ABORT_MASK 0x1
  65. #define DRAM_MR4_PPRE_MASK 0x1
  66. #define DRAM_MR4_TH_OFFS_MASK 0x3
  67. #define DRAM_MR4_TUF_MASK 0x1
  68. /* DRAM Vendor Offsets & Masks */
  69. #define DRAM_VENDOR_MR5 0x0
  70. #define DRAM_VENDOR_MR6 0x4
  71. #define DRAM_VENDOR_MR7 0x8
  72. #define DRAM_VENDOR_MR8 0xc
  73. #define DRAM_VENDOR_ERROR 0x10
  74. #define DRAM_VENDOR_MASK 0xff
  75. /* Reset register bits & masks */
  76. #define DCPU_RESET_SHIFT 0x0
  77. #define DCPU_RESET_MASK 0x1
  78. #define DCPU_CLK_DISABLE_SHIFT 0x2
  79. /* DCPU return codes */
  80. #define DCPU_RET_ERROR_BIT BIT(31)
  81. #define DCPU_RET_SUCCESS 0x1
  82. #define DCPU_RET_ERR_HEADER (DCPU_RET_ERROR_BIT | BIT(0))
  83. #define DCPU_RET_ERR_INVAL (DCPU_RET_ERROR_BIT | BIT(1))
  84. #define DCPU_RET_ERR_CHKSUM (DCPU_RET_ERROR_BIT | BIT(2))
  85. #define DCPU_RET_ERR_COMMAND (DCPU_RET_ERROR_BIT | BIT(3))
  86. /* This error code is not firmware defined and only used in the driver. */
  87. #define DCPU_RET_ERR_TIMEDOUT (DCPU_RET_ERROR_BIT | BIT(4))
  88. /* Firmware magic */
  89. #define DPFE_BE_MAGIC 0xfe1010fe
  90. #define DPFE_LE_MAGIC 0xfe0101fe
  91. /* Error codes */
  92. #define ERR_INVALID_MAGIC -1
  93. #define ERR_INVALID_SIZE -2
  94. #define ERR_INVALID_CHKSUM -3
  95. /* Message types */
  96. #define DPFE_MSG_TYPE_COMMAND 1
  97. #define DPFE_MSG_TYPE_RESPONSE 2
  98. #define DELAY_LOOP_MAX 200000
  99. enum dpfe_msg_fields {
  100. MSG_HEADER,
  101. MSG_COMMAND,
  102. MSG_ARG_COUNT,
  103. MSG_ARG0,
  104. MSG_CHKSUM,
  105. MSG_FIELD_MAX /* Last entry */
  106. };
  107. enum dpfe_commands {
  108. DPFE_CMD_GET_INFO,
  109. DPFE_CMD_GET_REFRESH,
  110. DPFE_CMD_GET_VENDOR,
  111. DPFE_CMD_MAX /* Last entry */
  112. };
  113. struct dpfe_msg {
  114. u32 header;
  115. u32 command;
  116. u32 arg_count;
  117. u32 arg0;
  118. u32 chksum; /* This is the sum of all other entries. */
  119. };
  120. /*
  121. * Format of the binary firmware file:
  122. *
  123. * entry
  124. * 0 header
  125. * value: 0xfe0101fe <== little endian
  126. * 0xfe1010fe <== big endian
  127. * 1 sequence:
  128. * [31:16] total segments on this build
  129. * [15:0] this segment sequence.
  130. * 2 FW version
  131. * 3 IMEM byte size
  132. * 4 DMEM byte size
  133. * IMEM
  134. * DMEM
  135. * last checksum ==> sum of everything
  136. */
  137. struct dpfe_firmware_header {
  138. u32 magic;
  139. u32 sequence;
  140. u32 version;
  141. u32 imem_size;
  142. u32 dmem_size;
  143. };
  144. /* Things we only need during initialization. */
  145. struct init_data {
  146. unsigned int dmem_len;
  147. unsigned int imem_len;
  148. unsigned int chksum;
  149. bool is_big_endian;
  150. };
  151. /* Things we need for as long as we are active. */
  152. struct private_data {
  153. void __iomem *regs;
  154. void __iomem *dmem;
  155. void __iomem *imem;
  156. struct device *dev;
  157. unsigned int index;
  158. struct mutex lock;
  159. };
  160. static const char *error_text[] = {
  161. "Success", "Header code incorrect", "Unknown command or argument",
  162. "Incorrect checksum", "Malformed command", "Timed out",
  163. };
  164. /* List of supported firmware commands */
  165. static const u32 dpfe_commands[DPFE_CMD_MAX][MSG_FIELD_MAX] = {
  166. [DPFE_CMD_GET_INFO] = {
  167. [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
  168. [MSG_COMMAND] = 1,
  169. [MSG_ARG_COUNT] = 1,
  170. [MSG_ARG0] = 1,
  171. [MSG_CHKSUM] = 4,
  172. },
  173. [DPFE_CMD_GET_REFRESH] = {
  174. [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
  175. [MSG_COMMAND] = 2,
  176. [MSG_ARG_COUNT] = 1,
  177. [MSG_ARG0] = 1,
  178. [MSG_CHKSUM] = 5,
  179. },
  180. [DPFE_CMD_GET_VENDOR] = {
  181. [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND,
  182. [MSG_COMMAND] = 2,
  183. [MSG_ARG_COUNT] = 1,
  184. [MSG_ARG0] = 2,
  185. [MSG_CHKSUM] = 6,
  186. },
  187. };
  188. static bool is_dcpu_enabled(void __iomem *regs)
  189. {
  190. u32 val;
  191. val = readl_relaxed(regs + REG_DCPU_RESET);
  192. return !(val & DCPU_RESET_MASK);
  193. }
  194. static void __disable_dcpu(void __iomem *regs)
  195. {
  196. u32 val;
  197. if (!is_dcpu_enabled(regs))
  198. return;
  199. /* Put DCPU in reset if it's running. */
  200. val = readl_relaxed(regs + REG_DCPU_RESET);
  201. val |= (1 << DCPU_RESET_SHIFT);
  202. writel_relaxed(val, regs + REG_DCPU_RESET);
  203. }
  204. static void __enable_dcpu(void __iomem *regs)
  205. {
  206. u32 val;
  207. /* Clear mailbox registers. */
  208. writel_relaxed(0, regs + REG_TO_DCPU_MBOX);
  209. writel_relaxed(0, regs + REG_TO_HOST_MBOX);
  210. /* Disable DCPU clock gating */
  211. val = readl_relaxed(regs + REG_DCPU_RESET);
  212. val &= ~(1 << DCPU_CLK_DISABLE_SHIFT);
  213. writel_relaxed(val, regs + REG_DCPU_RESET);
  214. /* Take DCPU out of reset */
  215. val = readl_relaxed(regs + REG_DCPU_RESET);
  216. val &= ~(1 << DCPU_RESET_SHIFT);
  217. writel_relaxed(val, regs + REG_DCPU_RESET);
  218. }
  219. static unsigned int get_msg_chksum(const u32 msg[])
  220. {
  221. unsigned int sum = 0;
  222. unsigned int i;
  223. /* Don't include the last field in the checksum. */
  224. for (i = 0; i < MSG_FIELD_MAX - 1; i++)
  225. sum += msg[i];
  226. return sum;
  227. }
  228. static void __iomem *get_msg_ptr(struct private_data *priv, u32 response,
  229. char *buf, ssize_t *size)
  230. {
  231. unsigned int msg_type;
  232. unsigned int offset;
  233. void __iomem *ptr = NULL;
  234. msg_type = (response >> DRAM_MSG_TYPE_OFFSET) & DRAM_MSG_TYPE_MASK;
  235. offset = (response >> DRAM_MSG_ADDR_OFFSET) & DRAM_MSG_ADDR_MASK;
  236. /*
  237. * msg_type == 1: the offset is relative to the message RAM
  238. * msg_type == 0: the offset is relative to the data RAM (this is the
  239. * previous way of passing data)
  240. * msg_type is anything else: there's critical hardware problem
  241. */
  242. switch (msg_type) {
  243. case 1:
  244. ptr = priv->regs + DCPU_MSG_RAM_START + offset;
  245. break;
  246. case 0:
  247. ptr = priv->dmem + offset;
  248. break;
  249. default:
  250. dev_emerg(priv->dev, "invalid message reply from DCPU: %#x\n",
  251. response);
  252. if (buf && size)
  253. *size = sprintf(buf,
  254. "FATAL: communication error with DCPU\n");
  255. }
  256. return ptr;
  257. }
  258. static int __send_command(struct private_data *priv, unsigned int cmd,
  259. u32 result[])
  260. {
  261. const u32 *msg = dpfe_commands[cmd];
  262. void __iomem *regs = priv->regs;
  263. unsigned int i, chksum;
  264. int ret = 0;
  265. u32 resp;
  266. if (cmd >= DPFE_CMD_MAX)
  267. return -1;
  268. mutex_lock(&priv->lock);
  269. /* Write command and arguments to message area */
  270. for (i = 0; i < MSG_FIELD_MAX; i++)
  271. writel_relaxed(msg[i], regs + DCPU_MSG_RAM(i));
  272. /* Tell DCPU there is a command waiting */
  273. writel_relaxed(1, regs + REG_TO_DCPU_MBOX);
  274. /* Wait for DCPU to process the command */
  275. for (i = 0; i < DELAY_LOOP_MAX; i++) {
  276. /* Read response code */
  277. resp = readl_relaxed(regs + REG_TO_HOST_MBOX);
  278. if (resp > 0)
  279. break;
  280. udelay(5);
  281. }
  282. if (i == DELAY_LOOP_MAX) {
  283. resp = (DCPU_RET_ERR_TIMEDOUT & ~DCPU_RET_ERROR_BIT);
  284. ret = -ffs(resp);
  285. } else {
  286. /* Read response data */
  287. for (i = 0; i < MSG_FIELD_MAX; i++)
  288. result[i] = readl_relaxed(regs + DCPU_MSG_RAM(i));
  289. }
  290. /* Tell DCPU we are done */
  291. writel_relaxed(0, regs + REG_TO_HOST_MBOX);
  292. mutex_unlock(&priv->lock);
  293. if (ret)
  294. return ret;
  295. /* Verify response */
  296. chksum = get_msg_chksum(result);
  297. if (chksum != result[MSG_CHKSUM])
  298. resp = DCPU_RET_ERR_CHKSUM;
  299. if (resp != DCPU_RET_SUCCESS) {
  300. resp &= ~DCPU_RET_ERROR_BIT;
  301. ret = -ffs(resp);
  302. }
  303. return ret;
  304. }
  305. /* Ensure that the firmware file loaded meets all the requirements. */
  306. static int __verify_firmware(struct init_data *init,
  307. const struct firmware *fw)
  308. {
  309. const struct dpfe_firmware_header *header = (void *)fw->data;
  310. unsigned int dmem_size, imem_size, total_size;
  311. bool is_big_endian = false;
  312. const u32 *chksum_ptr;
  313. if (header->magic == DPFE_BE_MAGIC)
  314. is_big_endian = true;
  315. else if (header->magic != DPFE_LE_MAGIC)
  316. return ERR_INVALID_MAGIC;
  317. if (is_big_endian) {
  318. dmem_size = be32_to_cpu(header->dmem_size);
  319. imem_size = be32_to_cpu(header->imem_size);
  320. } else {
  321. dmem_size = le32_to_cpu(header->dmem_size);
  322. imem_size = le32_to_cpu(header->imem_size);
  323. }
  324. /* Data and instruction sections are 32 bit words. */
  325. if ((dmem_size % sizeof(u32)) != 0 || (imem_size % sizeof(u32)) != 0)
  326. return ERR_INVALID_SIZE;
  327. /*
  328. * The header + the data section + the instruction section + the
  329. * checksum must be equal to the total firmware size.
  330. */
  331. total_size = dmem_size + imem_size + sizeof(*header) +
  332. sizeof(*chksum_ptr);
  333. if (total_size != fw->size)
  334. return ERR_INVALID_SIZE;
  335. /* The checksum comes at the very end. */
  336. chksum_ptr = (void *)fw->data + sizeof(*header) + dmem_size + imem_size;
  337. init->is_big_endian = is_big_endian;
  338. init->dmem_len = dmem_size;
  339. init->imem_len = imem_size;
  340. init->chksum = (is_big_endian)
  341. ? be32_to_cpu(*chksum_ptr) : le32_to_cpu(*chksum_ptr);
  342. return 0;
  343. }
  344. /* Verify checksum by reading back the firmware from co-processor RAM. */
  345. static int __verify_fw_checksum(struct init_data *init,
  346. struct private_data *priv,
  347. const struct dpfe_firmware_header *header,
  348. u32 checksum)
  349. {
  350. u32 magic, sequence, version, sum;
  351. u32 __iomem *dmem = priv->dmem;
  352. u32 __iomem *imem = priv->imem;
  353. unsigned int i;
  354. if (init->is_big_endian) {
  355. magic = be32_to_cpu(header->magic);
  356. sequence = be32_to_cpu(header->sequence);
  357. version = be32_to_cpu(header->version);
  358. } else {
  359. magic = le32_to_cpu(header->magic);
  360. sequence = le32_to_cpu(header->sequence);
  361. version = le32_to_cpu(header->version);
  362. }
  363. sum = magic + sequence + version + init->dmem_len + init->imem_len;
  364. for (i = 0; i < init->dmem_len / sizeof(u32); i++)
  365. sum += readl_relaxed(dmem + i);
  366. for (i = 0; i < init->imem_len / sizeof(u32); i++)
  367. sum += readl_relaxed(imem + i);
  368. return (sum == checksum) ? 0 : -1;
  369. }
  370. static int __write_firmware(u32 __iomem *mem, const u32 *fw,
  371. unsigned int size, bool is_big_endian)
  372. {
  373. unsigned int i;
  374. /* Convert size to 32-bit words. */
  375. size /= sizeof(u32);
  376. /* It is recommended to clear the firmware area first. */
  377. for (i = 0; i < size; i++)
  378. writel_relaxed(0, mem + i);
  379. /* Now copy it. */
  380. if (is_big_endian) {
  381. for (i = 0; i < size; i++)
  382. writel_relaxed(be32_to_cpu(fw[i]), mem + i);
  383. } else {
  384. for (i = 0; i < size; i++)
  385. writel_relaxed(le32_to_cpu(fw[i]), mem + i);
  386. }
  387. return 0;
  388. }
  389. static int brcmstb_dpfe_download_firmware(struct platform_device *pdev,
  390. struct init_data *init)
  391. {
  392. const struct dpfe_firmware_header *header;
  393. unsigned int dmem_size, imem_size;
  394. struct device *dev = &pdev->dev;
  395. bool is_big_endian = false;
  396. struct private_data *priv;
  397. const struct firmware *fw;
  398. const u32 *dmem, *imem;
  399. const void *fw_blob;
  400. int ret;
  401. priv = platform_get_drvdata(pdev);
  402. /*
  403. * Skip downloading the firmware if the DCPU is already running and
  404. * responding to commands.
  405. */
  406. if (is_dcpu_enabled(priv->regs)) {
  407. u32 response[MSG_FIELD_MAX];
  408. ret = __send_command(priv, DPFE_CMD_GET_INFO, response);
  409. if (!ret)
  410. return 0;
  411. }
  412. ret = request_firmware(&fw, FIRMWARE_NAME, dev);
  413. /* request_firmware() prints its own error messages. */
  414. if (ret)
  415. return ret;
  416. ret = __verify_firmware(init, fw);
  417. if (ret)
  418. return -EFAULT;
  419. __disable_dcpu(priv->regs);
  420. is_big_endian = init->is_big_endian;
  421. dmem_size = init->dmem_len;
  422. imem_size = init->imem_len;
  423. /* At the beginning of the firmware blob is a header. */
  424. header = (struct dpfe_firmware_header *)fw->data;
  425. /* Void pointer to the beginning of the actual firmware. */
  426. fw_blob = fw->data + sizeof(*header);
  427. /* IMEM comes right after the header. */
  428. imem = fw_blob;
  429. /* DMEM follows after IMEM. */
  430. dmem = fw_blob + imem_size;
  431. ret = __write_firmware(priv->dmem, dmem, dmem_size, is_big_endian);
  432. if (ret)
  433. return ret;
  434. ret = __write_firmware(priv->imem, imem, imem_size, is_big_endian);
  435. if (ret)
  436. return ret;
  437. ret = __verify_fw_checksum(init, priv, header, init->chksum);
  438. if (ret)
  439. return ret;
  440. __enable_dcpu(priv->regs);
  441. return 0;
  442. }
  443. static ssize_t generic_show(unsigned int command, u32 response[],
  444. struct device *dev, char *buf)
  445. {
  446. struct private_data *priv;
  447. int ret;
  448. priv = dev_get_drvdata(dev);
  449. if (!priv)
  450. return sprintf(buf, "ERROR: driver private data not set\n");
  451. ret = __send_command(priv, command, response);
  452. if (ret < 0)
  453. return sprintf(buf, "ERROR: %s\n", error_text[-ret]);
  454. return 0;
  455. }
  456. static ssize_t show_info(struct device *dev, struct device_attribute *devattr,
  457. char *buf)
  458. {
  459. u32 response[MSG_FIELD_MAX];
  460. unsigned int info;
  461. ssize_t ret;
  462. ret = generic_show(DPFE_CMD_GET_INFO, response, dev, buf);
  463. if (ret)
  464. return ret;
  465. info = response[MSG_ARG0];
  466. return sprintf(buf, "%u.%u.%u.%u\n",
  467. (info >> 24) & 0xff,
  468. (info >> 16) & 0xff,
  469. (info >> 8) & 0xff,
  470. info & 0xff);
  471. }
  472. static ssize_t show_refresh(struct device *dev,
  473. struct device_attribute *devattr, char *buf)
  474. {
  475. u32 response[MSG_FIELD_MAX];
  476. void __iomem *info;
  477. struct private_data *priv;
  478. u8 refresh, sr_abort, ppre, thermal_offs, tuf;
  479. u32 mr4;
  480. ssize_t ret;
  481. ret = generic_show(DPFE_CMD_GET_REFRESH, response, dev, buf);
  482. if (ret)
  483. return ret;
  484. priv = dev_get_drvdata(dev);
  485. info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret);
  486. if (!info)
  487. return ret;
  488. mr4 = readl_relaxed(info + DRAM_INFO_MR4) & DRAM_INFO_MR4_MASK;
  489. refresh = (mr4 >> DRAM_MR4_REFRESH) & DRAM_MR4_REFRESH_MASK;
  490. sr_abort = (mr4 >> DRAM_MR4_SR_ABORT) & DRAM_MR4_SR_ABORT_MASK;
  491. ppre = (mr4 >> DRAM_MR4_PPRE) & DRAM_MR4_PPRE_MASK;
  492. thermal_offs = (mr4 >> DRAM_MR4_TH_OFFS) & DRAM_MR4_TH_OFFS_MASK;
  493. tuf = (mr4 >> DRAM_MR4_TUF) & DRAM_MR4_TUF_MASK;
  494. return sprintf(buf, "%#x %#x %#x %#x %#x %#x %#x\n",
  495. readl_relaxed(info + DRAM_INFO_INTERVAL),
  496. refresh, sr_abort, ppre, thermal_offs, tuf,
  497. readl_relaxed(info + DRAM_INFO_ERROR));
  498. }
  499. static ssize_t store_refresh(struct device *dev, struct device_attribute *attr,
  500. const char *buf, size_t count)
  501. {
  502. u32 response[MSG_FIELD_MAX];
  503. struct private_data *priv;
  504. void __iomem *info;
  505. unsigned long val;
  506. int ret;
  507. if (kstrtoul(buf, 0, &val) < 0)
  508. return -EINVAL;
  509. priv = dev_get_drvdata(dev);
  510. ret = __send_command(priv, DPFE_CMD_GET_REFRESH, response);
  511. if (ret)
  512. return ret;
  513. info = get_msg_ptr(priv, response[MSG_ARG0], NULL, NULL);
  514. if (!info)
  515. return -EIO;
  516. writel_relaxed(val, info + DRAM_INFO_INTERVAL);
  517. return count;
  518. }
  519. static ssize_t show_vendor(struct device *dev, struct device_attribute *devattr,
  520. char *buf)
  521. {
  522. u32 response[MSG_FIELD_MAX];
  523. struct private_data *priv;
  524. void __iomem *info;
  525. ssize_t ret;
  526. ret = generic_show(DPFE_CMD_GET_VENDOR, response, dev, buf);
  527. if (ret)
  528. return ret;
  529. priv = dev_get_drvdata(dev);
  530. info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret);
  531. if (!info)
  532. return ret;
  533. return sprintf(buf, "%#x %#x %#x %#x %#x\n",
  534. readl_relaxed(info + DRAM_VENDOR_MR5) & DRAM_VENDOR_MASK,
  535. readl_relaxed(info + DRAM_VENDOR_MR6) & DRAM_VENDOR_MASK,
  536. readl_relaxed(info + DRAM_VENDOR_MR7) & DRAM_VENDOR_MASK,
  537. readl_relaxed(info + DRAM_VENDOR_MR8) & DRAM_VENDOR_MASK,
  538. readl_relaxed(info + DRAM_VENDOR_ERROR) &
  539. DRAM_VENDOR_MASK);
  540. }
  541. static int brcmstb_dpfe_resume(struct platform_device *pdev)
  542. {
  543. struct init_data init;
  544. return brcmstb_dpfe_download_firmware(pdev, &init);
  545. }
  546. static DEVICE_ATTR(dpfe_info, 0444, show_info, NULL);
  547. static DEVICE_ATTR(dpfe_refresh, 0644, show_refresh, store_refresh);
  548. static DEVICE_ATTR(dpfe_vendor, 0444, show_vendor, NULL);
  549. static struct attribute *dpfe_attrs[] = {
  550. &dev_attr_dpfe_info.attr,
  551. &dev_attr_dpfe_refresh.attr,
  552. &dev_attr_dpfe_vendor.attr,
  553. NULL
  554. };
  555. ATTRIBUTE_GROUPS(dpfe);
  556. static int brcmstb_dpfe_probe(struct platform_device *pdev)
  557. {
  558. struct device *dev = &pdev->dev;
  559. struct private_data *priv;
  560. struct device *dpfe_dev;
  561. struct init_data init;
  562. struct resource *res;
  563. u32 index;
  564. int ret;
  565. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  566. if (!priv)
  567. return -ENOMEM;
  568. mutex_init(&priv->lock);
  569. platform_set_drvdata(pdev, priv);
  570. /* Cell index is optional; default to 0 if not present. */
  571. ret = of_property_read_u32(dev->of_node, "cell-index", &index);
  572. if (ret)
  573. index = 0;
  574. res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpfe-cpu");
  575. priv->regs = devm_ioremap_resource(dev, res);
  576. if (IS_ERR(priv->regs)) {
  577. dev_err(dev, "couldn't map DCPU registers\n");
  578. return -ENODEV;
  579. }
  580. res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpfe-dmem");
  581. priv->dmem = devm_ioremap_resource(dev, res);
  582. if (IS_ERR(priv->dmem)) {
  583. dev_err(dev, "Couldn't map DCPU data memory\n");
  584. return -ENOENT;
  585. }
  586. res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpfe-imem");
  587. priv->imem = devm_ioremap_resource(dev, res);
  588. if (IS_ERR(priv->imem)) {
  589. dev_err(dev, "Couldn't map DCPU instruction memory\n");
  590. return -ENOENT;
  591. }
  592. ret = brcmstb_dpfe_download_firmware(pdev, &init);
  593. if (ret)
  594. goto err;
  595. dpfe_dev = devm_kzalloc(dev, sizeof(*dpfe_dev), GFP_KERNEL);
  596. if (!dpfe_dev) {
  597. ret = -ENOMEM;
  598. goto err;
  599. }
  600. priv->dev = dpfe_dev;
  601. priv->index = index;
  602. dpfe_dev->parent = dev;
  603. dpfe_dev->groups = dpfe_groups;
  604. dpfe_dev->of_node = dev->of_node;
  605. dev_set_drvdata(dpfe_dev, priv);
  606. dev_set_name(dpfe_dev, "dpfe%u", index);
  607. ret = device_register(dpfe_dev);
  608. if (ret)
  609. goto err;
  610. dev_info(dev, "registered.\n");
  611. return 0;
  612. err:
  613. dev_err(dev, "failed to initialize -- error %d\n", ret);
  614. return ret;
  615. }
  616. static const struct of_device_id brcmstb_dpfe_of_match[] = {
  617. { .compatible = "brcm,dpfe-cpu", },
  618. {}
  619. };
  620. MODULE_DEVICE_TABLE(of, brcmstb_dpfe_of_match);
  621. static struct platform_driver brcmstb_dpfe_driver = {
  622. .driver = {
  623. .name = DRVNAME,
  624. .of_match_table = brcmstb_dpfe_of_match,
  625. },
  626. .probe = brcmstb_dpfe_probe,
  627. .resume = brcmstb_dpfe_resume,
  628. };
  629. module_platform_driver(brcmstb_dpfe_driver);
  630. MODULE_AUTHOR("Markus Mayer <mmayer@broadcom.com>");
  631. MODULE_DESCRIPTION("BRCMSTB DDR PHY Front End Driver");
  632. MODULE_LICENSE("GPL");