firmware.c 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. /*
  2. * Copyright (C) 2017 Linaro Ltd.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 and
  6. * only version 2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. */
  14. #include <linux/device.h>
  15. #include <linux/firmware.h>
  16. #include <linux/kernel.h>
  17. #include <linux/io.h>
  18. #include <linux/of.h>
  19. #include <linux/of_address.h>
  20. #include <linux/qcom_scm.h>
  21. #include <linux/sizes.h>
  22. #include <linux/soc/qcom/mdt_loader.h>
  23. #include "firmware.h"
  24. #define VENUS_PAS_ID 9
  25. #define VENUS_FW_MEM_SIZE (6 * SZ_1M)
  26. int venus_boot(struct device *dev, const char *fwname)
  27. {
  28. const struct firmware *mdt;
  29. struct device_node *node;
  30. phys_addr_t mem_phys;
  31. struct resource r;
  32. ssize_t fw_size;
  33. size_t mem_size;
  34. void *mem_va;
  35. int ret;
  36. if (!IS_ENABLED(CONFIG_QCOM_MDT_LOADER) || !qcom_scm_is_available())
  37. return -EPROBE_DEFER;
  38. node = of_parse_phandle(dev->of_node, "memory-region", 0);
  39. if (!node) {
  40. dev_err(dev, "no memory-region specified\n");
  41. return -EINVAL;
  42. }
  43. ret = of_address_to_resource(node, 0, &r);
  44. if (ret)
  45. return ret;
  46. mem_phys = r.start;
  47. mem_size = resource_size(&r);
  48. if (mem_size < VENUS_FW_MEM_SIZE)
  49. return -EINVAL;
  50. mem_va = memremap(r.start, mem_size, MEMREMAP_WC);
  51. if (!mem_va) {
  52. dev_err(dev, "unable to map memory region: %pa+%zx\n",
  53. &r.start, mem_size);
  54. return -ENOMEM;
  55. }
  56. ret = request_firmware(&mdt, fwname, dev);
  57. if (ret < 0)
  58. goto err_unmap;
  59. fw_size = qcom_mdt_get_size(mdt);
  60. if (fw_size < 0) {
  61. ret = fw_size;
  62. release_firmware(mdt);
  63. goto err_unmap;
  64. }
  65. ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, mem_va, mem_phys,
  66. mem_size, NULL);
  67. release_firmware(mdt);
  68. if (ret)
  69. goto err_unmap;
  70. ret = qcom_scm_pas_auth_and_reset(VENUS_PAS_ID);
  71. if (ret)
  72. goto err_unmap;
  73. err_unmap:
  74. memunmap(mem_va);
  75. return ret;
  76. }
  77. int venus_shutdown(struct device *dev)
  78. {
  79. return qcom_scm_pas_shutdown(VENUS_PAS_ID);
  80. }