iop_fw_load.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. * Firmware loader for ETRAX FS IO-Processor
  3. *
  4. * Copyright (C) 2004 Axis Communications AB
  5. */
  6. #include <linux/module.h>
  7. #include <linux/kernel.h>
  8. #include <linux/init.h>
  9. #include <linux/device.h>
  10. #include <linux/firmware.h>
  11. #include <hwregs/reg_rdwr.h>
  12. #include <hwregs/reg_map.h>
  13. #include <hwregs/iop/iop_reg_space.h>
  14. #include <hwregs/iop/iop_mpu_macros.h>
  15. #include <hwregs/iop/iop_mpu_defs.h>
  16. #include <hwregs/iop/iop_spu_defs.h>
  17. #include <hwregs/iop/iop_sw_cpu_defs.h>
  18. #define IOP_TIMEOUT 100
  19. #error "This driver is broken with regard to its driver core usage."
  20. #error "Please contact <greg@kroah.com> for details on how to fix it properly."
  21. static struct device iop_spu_device[2] = {
  22. { .init_name = "iop-spu0", },
  23. { .init_name = "iop-spu1", },
  24. };
  25. static struct device iop_mpu_device = {
  26. .init_name = "iop-mpu",
  27. };
  28. static int wait_mpu_idle(void)
  29. {
  30. reg_iop_mpu_r_stat mpu_stat;
  31. unsigned int timeout = IOP_TIMEOUT;
  32. do {
  33. mpu_stat = REG_RD(iop_mpu, regi_iop_mpu, r_stat);
  34. } while (mpu_stat.instr_reg_busy == regk_iop_mpu_yes && --timeout > 0);
  35. if (timeout == 0) {
  36. printk(KERN_ERR "Timeout waiting for MPU to be idle\n");
  37. return -EBUSY;
  38. }
  39. return 0;
  40. }
  41. int iop_fw_load_spu(const unsigned char *fw_name, unsigned int spu_inst)
  42. {
  43. reg_iop_sw_cpu_rw_mc_ctrl mc_ctrl = {
  44. .wr_spu0_mem = regk_iop_sw_cpu_no,
  45. .wr_spu1_mem = regk_iop_sw_cpu_no,
  46. .size = 4,
  47. .cmd = regk_iop_sw_cpu_reg_copy,
  48. .keep_owner = regk_iop_sw_cpu_yes
  49. };
  50. reg_iop_spu_rw_ctrl spu_ctrl = {
  51. .en = regk_iop_spu_no,
  52. .fsm = regk_iop_spu_no,
  53. };
  54. reg_iop_sw_cpu_r_mc_stat mc_stat;
  55. const struct firmware *fw_entry;
  56. u32 *data;
  57. unsigned int timeout;
  58. int retval, i;
  59. if (spu_inst > 1)
  60. return -ENODEV;
  61. /* get firmware */
  62. retval = request_firmware(&fw_entry,
  63. fw_name,
  64. &iop_spu_device[spu_inst]);
  65. if (retval != 0)
  66. {
  67. printk(KERN_ERR
  68. "iop_load_spu: Failed to load firmware \"%s\"\n",
  69. fw_name);
  70. return retval;
  71. }
  72. data = (u32 *) fw_entry->data;
  73. /* acquire ownership of memory controller */
  74. switch (spu_inst) {
  75. case 0:
  76. mc_ctrl.wr_spu0_mem = regk_iop_sw_cpu_yes;
  77. REG_WR(iop_spu, regi_iop_spu0, rw_ctrl, spu_ctrl);
  78. break;
  79. case 1:
  80. mc_ctrl.wr_spu1_mem = regk_iop_sw_cpu_yes;
  81. REG_WR(iop_spu, regi_iop_spu1, rw_ctrl, spu_ctrl);
  82. break;
  83. }
  84. timeout = IOP_TIMEOUT;
  85. do {
  86. REG_WR(iop_sw_cpu, regi_iop_sw_cpu, rw_mc_ctrl, mc_ctrl);
  87. mc_stat = REG_RD(iop_sw_cpu, regi_iop_sw_cpu, r_mc_stat);
  88. } while (mc_stat.owned_by_cpu == regk_iop_sw_cpu_no && --timeout > 0);
  89. if (timeout == 0) {
  90. printk(KERN_ERR "Timeout waiting to acquire MC\n");
  91. retval = -EBUSY;
  92. goto out;
  93. }
  94. /* write to SPU memory */
  95. for (i = 0; i < (fw_entry->size/4); i++) {
  96. switch (spu_inst) {
  97. case 0:
  98. REG_WR_INT(iop_spu, regi_iop_spu0, rw_seq_pc, (i*4));
  99. break;
  100. case 1:
  101. REG_WR_INT(iop_spu, regi_iop_spu1, rw_seq_pc, (i*4));
  102. break;
  103. }
  104. REG_WR_INT(iop_sw_cpu, regi_iop_sw_cpu, rw_mc_data, *data);
  105. data++;
  106. }
  107. /* release ownership of memory controller */
  108. (void) REG_RD(iop_sw_cpu, regi_iop_sw_cpu, rs_mc_data);
  109. out:
  110. release_firmware(fw_entry);
  111. return retval;
  112. }
  113. int iop_fw_load_mpu(unsigned char *fw_name)
  114. {
  115. const unsigned int start_addr = 0;
  116. reg_iop_mpu_rw_ctrl mpu_ctrl;
  117. const struct firmware *fw_entry;
  118. u32 *data;
  119. int retval, i;
  120. /* get firmware */
  121. retval = request_firmware(&fw_entry, fw_name, &iop_mpu_device);
  122. if (retval != 0)
  123. {
  124. printk(KERN_ERR
  125. "iop_load_spu: Failed to load firmware \"%s\"\n",
  126. fw_name);
  127. return retval;
  128. }
  129. data = (u32 *) fw_entry->data;
  130. /* disable MPU */
  131. mpu_ctrl.en = regk_iop_mpu_no;
  132. REG_WR(iop_mpu, regi_iop_mpu, rw_ctrl, mpu_ctrl);
  133. /* put start address in R0 */
  134. REG_WR_VECT(iop_mpu, regi_iop_mpu, rw_r, 0, start_addr);
  135. /* write to memory by executing 'SWX i, 4, R0' for each word */
  136. if ((retval = wait_mpu_idle()) != 0)
  137. goto out;
  138. REG_WR(iop_mpu, regi_iop_mpu, rw_instr, MPU_SWX_IIR_INSTR(0, 4, 0));
  139. for (i = 0; i < (fw_entry->size / 4); i++) {
  140. REG_WR_INT(iop_mpu, regi_iop_mpu, rw_immediate, *data);
  141. if ((retval = wait_mpu_idle()) != 0)
  142. goto out;
  143. data++;
  144. }
  145. out:
  146. release_firmware(fw_entry);
  147. return retval;
  148. }
  149. int iop_start_mpu(unsigned int start_addr)
  150. {
  151. reg_iop_mpu_rw_ctrl mpu_ctrl = { .en = regk_iop_mpu_yes };
  152. int retval;
  153. /* disable MPU */
  154. if ((retval = wait_mpu_idle()) != 0)
  155. goto out;
  156. REG_WR(iop_mpu, regi_iop_mpu, rw_instr, MPU_HALT());
  157. if ((retval = wait_mpu_idle()) != 0)
  158. goto out;
  159. /* set PC and wait for it to bite */
  160. if ((retval = wait_mpu_idle()) != 0)
  161. goto out;
  162. REG_WR_INT(iop_mpu, regi_iop_mpu, rw_instr, MPU_BA_I(start_addr));
  163. if ((retval = wait_mpu_idle()) != 0)
  164. goto out;
  165. /* make sure the MPU starts executing with interrupts disabled */
  166. REG_WR(iop_mpu, regi_iop_mpu, rw_instr, MPU_DI());
  167. if ((retval = wait_mpu_idle()) != 0)
  168. goto out;
  169. /* enable MPU */
  170. REG_WR(iop_mpu, regi_iop_mpu, rw_ctrl, mpu_ctrl);
  171. out:
  172. return retval;
  173. }
  174. static int __init iop_fw_load_init(void)
  175. {
  176. #if 0
  177. /*
  178. * static struct devices can not be added directly to sysfs by ignoring
  179. * the driver model infrastructure. To fix this properly, please use
  180. * the platform_bus to register these devices to be able to properly
  181. * use the firmware infrastructure.
  182. */
  183. device_initialize(&iop_spu_device[0]);
  184. kobject_set_name(&iop_spu_device[0].kobj, "iop-spu0");
  185. kobject_add(&iop_spu_device[0].kobj);
  186. device_initialize(&iop_spu_device[1]);
  187. kobject_set_name(&iop_spu_device[1].kobj, "iop-spu1");
  188. kobject_add(&iop_spu_device[1].kobj);
  189. device_initialize(&iop_mpu_device);
  190. kobject_set_name(&iop_mpu_device.kobj, "iop-mpu");
  191. kobject_add(&iop_mpu_device.kobj);
  192. #endif
  193. return 0;
  194. }
  195. static void __exit iop_fw_load_exit(void)
  196. {
  197. }
  198. module_init(iop_fw_load_init);
  199. module_exit(iop_fw_load_exit);
  200. MODULE_DESCRIPTION("ETRAX FS IO-Processor Firmware Loader");
  201. MODULE_LICENSE("GPL");
  202. EXPORT_SYMBOL(iop_fw_load_spu);
  203. EXPORT_SYMBOL(iop_fw_load_mpu);
  204. EXPORT_SYMBOL(iop_start_mpu);