riscv.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2022, NVIDIA Corporation.
  4. */
  5. #include <linux/dev_printk.h>
  6. #include <linux/device.h>
  7. #include <linux/iopoll.h>
  8. #include <linux/of.h>
  9. #include "riscv.h"
  10. #define RISCV_CPUCTL 0x4388
  11. #define RISCV_CPUCTL_STARTCPU_TRUE (1 << 0)
  12. #define RISCV_BR_RETCODE 0x465c
  13. #define RISCV_BR_RETCODE_RESULT_V(x) ((x) & 0x3)
  14. #define RISCV_BR_RETCODE_RESULT_PASS_V 3
  15. #define RISCV_BCR_CTRL 0x4668
  16. #define RISCV_BCR_CTRL_CORE_SELECT_RISCV (1 << 4)
  17. #define RISCV_BCR_DMACFG 0x466c
  18. #define RISCV_BCR_DMACFG_TARGET_LOCAL_FB (0 << 0)
  19. #define RISCV_BCR_DMACFG_LOCK_LOCKED (1 << 31)
  20. #define RISCV_BCR_DMAADDR_PKCPARAM_LO 0x4670
  21. #define RISCV_BCR_DMAADDR_PKCPARAM_HI 0x4674
  22. #define RISCV_BCR_DMAADDR_FMCCODE_LO 0x4678
  23. #define RISCV_BCR_DMAADDR_FMCCODE_HI 0x467c
  24. #define RISCV_BCR_DMAADDR_FMCDATA_LO 0x4680
  25. #define RISCV_BCR_DMAADDR_FMCDATA_HI 0x4684
  26. #define RISCV_BCR_DMACFG_SEC 0x4694
  27. #define RISCV_BCR_DMACFG_SEC_GSCID(v) ((v) << 16)
  28. static void riscv_writel(struct tegra_drm_riscv *riscv, u32 value, u32 offset)
  29. {
  30. writel(value, riscv->regs + offset);
  31. }
  32. int tegra_drm_riscv_read_descriptors(struct tegra_drm_riscv *riscv)
  33. {
  34. struct tegra_drm_riscv_descriptor *bl = &riscv->bl_desc;
  35. struct tegra_drm_riscv_descriptor *os = &riscv->os_desc;
  36. const struct device_node *np = riscv->dev->of_node;
  37. int err;
  38. #define READ_PROP(name, location) \
  39. err = of_property_read_u32(np, name, location); \
  40. if (err) { \
  41. dev_err(riscv->dev, "failed to read " name ": %d\n", err); \
  42. return err; \
  43. }
  44. READ_PROP("nvidia,bl-manifest-offset", &bl->manifest_offset);
  45. READ_PROP("nvidia,bl-code-offset", &bl->code_offset);
  46. READ_PROP("nvidia,bl-data-offset", &bl->data_offset);
  47. READ_PROP("nvidia,os-manifest-offset", &os->manifest_offset);
  48. READ_PROP("nvidia,os-code-offset", &os->code_offset);
  49. READ_PROP("nvidia,os-data-offset", &os->data_offset);
  50. #undef READ_PROP
  51. if (bl->manifest_offset == 0 && bl->code_offset == 0 &&
  52. bl->data_offset == 0 && os->manifest_offset == 0 &&
  53. os->code_offset == 0 && os->data_offset == 0) {
  54. dev_err(riscv->dev, "descriptors not available\n");
  55. return -EINVAL;
  56. }
  57. return 0;
  58. }
  59. int tegra_drm_riscv_boot_bootrom(struct tegra_drm_riscv *riscv, phys_addr_t image_address,
  60. u32 gscid, const struct tegra_drm_riscv_descriptor *desc)
  61. {
  62. phys_addr_t addr;
  63. int err;
  64. u32 val;
  65. riscv_writel(riscv, RISCV_BCR_CTRL_CORE_SELECT_RISCV, RISCV_BCR_CTRL);
  66. addr = image_address + desc->manifest_offset;
  67. riscv_writel(riscv, lower_32_bits(addr >> 8), RISCV_BCR_DMAADDR_PKCPARAM_LO);
  68. riscv_writel(riscv, upper_32_bits(addr >> 8), RISCV_BCR_DMAADDR_PKCPARAM_HI);
  69. addr = image_address + desc->code_offset;
  70. riscv_writel(riscv, lower_32_bits(addr >> 8), RISCV_BCR_DMAADDR_FMCCODE_LO);
  71. riscv_writel(riscv, upper_32_bits(addr >> 8), RISCV_BCR_DMAADDR_FMCCODE_HI);
  72. addr = image_address + desc->data_offset;
  73. riscv_writel(riscv, lower_32_bits(addr >> 8), RISCV_BCR_DMAADDR_FMCDATA_LO);
  74. riscv_writel(riscv, upper_32_bits(addr >> 8), RISCV_BCR_DMAADDR_FMCDATA_HI);
  75. riscv_writel(riscv, RISCV_BCR_DMACFG_SEC_GSCID(gscid), RISCV_BCR_DMACFG_SEC);
  76. riscv_writel(riscv,
  77. RISCV_BCR_DMACFG_TARGET_LOCAL_FB | RISCV_BCR_DMACFG_LOCK_LOCKED, RISCV_BCR_DMACFG);
  78. riscv_writel(riscv, RISCV_CPUCTL_STARTCPU_TRUE, RISCV_CPUCTL);
  79. err = readl_poll_timeout(
  80. riscv->regs + RISCV_BR_RETCODE, val,
  81. RISCV_BR_RETCODE_RESULT_V(val) == RISCV_BR_RETCODE_RESULT_PASS_V,
  82. 10, 100000);
  83. if (err) {
  84. dev_err(riscv->dev, "error during bootrom execution. BR_RETCODE=%d\n", val);
  85. return err;
  86. }
  87. return 0;
  88. }