serial-howto.rst 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. .. SPDX-License-Identifier: GPL-2.0+
  2. How to port a serial driver to driver model
  3. ===========================================
  4. Here is a suggested approach for converting your serial driver over to driver
  5. model. Please feel free to update this file with your ideas and suggestions.
  6. - #ifdef out all your own serial driver code (#ifndef CONFIG_DM_SERIAL)
  7. - Define CONFIG_DM_SERIAL for your board, vendor or architecture
  8. - If the board does not already use driver model, you need CONFIG_DM also
  9. - Your board should then build, but will not boot since there will be no serial
  10. driver
  11. - Add the U_BOOT_DRIVER piece at the end (e.g. copy serial_s5p.c for example)
  12. - Add a private struct for the driver data - avoid using static variables
  13. - Implement each of the driver methods, perhaps by calling your old methods
  14. - You may need to adjust the function parameters so that the old and new
  15. implementations can share most of the existing code
  16. - If you convert all existing users of the driver, remove the pre-driver-model
  17. code
  18. In terms of patches a conversion series typically has these patches:
  19. - clean up / prepare the driver for conversion
  20. - add driver model code
  21. - convert at least one existing board to use driver model serial
  22. - (if no boards remain that don't use driver model) remove the old code
  23. This may be a good time to move your board to use the device tree too. Mostly
  24. this involves these steps:
  25. - define CONFIG_OF_CONTROL and CONFIG_OF_SEPARATE
  26. - add your device tree files to arch/<arch>/dts
  27. - update the Makefile there
  28. - Add stdout-path to your /chosen device tree node if it is not already there
  29. - build and get u-boot-dtb.bin so you can test it
  30. - Your drivers can now use device tree
  31. - For device tree in SPL, define CONFIG_SPL_OF_CONTROL
  32. Converting boards to CONFIG_DM_SERIAL
  33. -------------------------------------
  34. If your SoC has a serial driver that uses driver model (has U_BOOT_DRIVER() in
  35. it), then you may still find that your board has not been converted. To convert
  36. your board, enable the option and see if you can get it working.
  37. Firstly you will have a lot more success if you have a method of debugging your
  38. board, such as a JTAG connection. Failing that the debug UART is useful,
  39. although since you are trying to get the UART driver running, it will interfere
  40. with your efforts eventually.
  41. Secondly, while the UART is a relatively simple peripheral, it may need quite a
  42. few pieces to be up and running before it will work, such as the correct pin
  43. muxing, clocks, power domains and possibly even GPIOs, if an external
  44. transceiver is used. Look at other boards that use the same SoC, for clues as to
  45. what is needed.
  46. Thirdly, when added tags, put them in a xxx-u-boot.dtsi file, where xxx is your
  47. board name, or SoC name. There may already be a file for your SoC which contains
  48. what you need. U-Boot automatically includes these files: see :ref:`dttweaks`.
  49. Here are some things you might need to consider:
  50. 1. The serial driver itself needs to be present before relocation, so that the
  51. U-Boot banner appears. Make sure it has a bootph-all tag in the device
  52. tree, so that the serial driver is bound when U-Boot starts.
  53. For example, on iMX8::
  54. lpuart3: serial@5a090000 {
  55. compatible = "fsl,imx8qm-lpuart";
  56. ...
  57. };
  58. put this in your xxx-u-boot.dtsi file::
  59. &lpuart3 {
  60. bootph-some-ram;
  61. };
  62. 2. If your serial port requires a particular pinmux configuration, you may need
  63. a pinctrl driver. This needs to have a bootph-all tag also. Take care
  64. that any subnodes have the same tag, if they are needed to make the correct
  65. pinctrl available.
  66. For example, on RK3288, the UART2 uses uart2_xfer::
  67. uart2: serial@ff690000 {
  68. ...
  69. pinctrl-0 = <&uart2_xfer>;
  70. };
  71. which is defined as follows::
  72. pinctrl: pinctrl {
  73. compatible = "rockchip,rk3228-pinctrl";
  74. uart2: uart2 {
  75. uart2_xfer: uart2-xfer {
  76. rockchip,pins = <1 RK_PC2 RK_FUNC_2 &pcfg_pull_up>,
  77. <1 RK_PC3 RK_FUNC_2 &pcfg_pull_none>;
  78. };
  79. ...
  80. };
  81. This means you must make the uart2-xfer node available as well as all its
  82. parents, so put this in your xxx-u-boot.dtsi file::
  83. &pinctrl {
  84. bootph-all;
  85. };
  86. &uart2 {
  87. bootph-all;
  88. };
  89. &uart2_xfer {
  90. bootph-all;
  91. };
  92. 3. The same applies to power domains. For example, if a particular power domain
  93. must be enabled for the serial port to work, you need to ensure it is
  94. available before relocation:
  95. For example, on iMX8, put this in your xxx-u-boot.dtsi file::
  96. &pd_dma {
  97. bootph-some-ram;
  98. };
  99. &pd_dma_lpuart3 {
  100. bootph-some-ram;
  101. };
  102. 4. The same applies to clocks, in the same way. Make sure that when your driver
  103. requests a clock, typically with clk_get_by_index(), it is available.
  104. Generally a failure to find a required device will cause an error which you can
  105. catch, if you have the debug UART working. U-Boot outputs serial data to the
  106. debug UART until the point where the real serial driver takes over. This point
  107. is marked by gd->flags having the GD_FLG_SERIAL_READY flag set. This change
  108. happens in serial_init() in serial-uclass.c so until that point the debug UART
  109. is used. You can see the relevant code in putc()
  110. , for example::
  111. /* if we don't have a console yet, use the debug UART */
  112. if (IS_ENABLED(CONFIG_DEBUG_UART) && !(gd->flags & GD_FLG_SERIAL_READY)) {
  113. printch(c);
  114. return;
  115. }
  116. ... carries on to use the console / serial driver
  117. Note that in device_probe() the call to pinctrl_select_state() silently fails
  118. if the pinctrl driver fails. You can add a temporary check there if needed.
  119. Why do we have all these tags? The problem is that before relocation we don't
  120. want to bind all the drivers since memory is limited and the CPU may be running
  121. at a slow speed. So many boards will fail to boot without this optimisation, or
  122. may take a long time to start up (e.g. hundreds of milliseconds). The tags tell
  123. U-Boot which drivers to bind.
  124. The good news is that this problem is normally solved by the SoC, so that any
  125. boards that use it will work as normal. But in some cases there are multiple
  126. UARTs or multiple pinmux options, which means that each board may need to do
  127. some customisation.
  128. Serial in SPL
  129. -------------
  130. A similar process is needed in SPL, but in this case the bootph-pre-ram or
  131. bootph-pre-sram tags are used. Add these in the same way as above, to ensure
  132. that the SPL device tree contains the required nodes (see spl/u-boot-spl.dtb
  133. for what it actually contains).
  134. Removing old code
  135. -----------------
  136. In some cases there may be initialisation code that is no-longer needed when
  137. driver model is used, such as setting up the pin muxing, or enabling a clock.
  138. Be sure to remove this.
  139. Example patch
  140. -------------
  141. See this serial_patch_ for iMX7.
  142. .. _serial_patch: https://patchwork.ozlabs.org/project/uboot/patch/20220314232406.1945308-1-festevam@gmail.com/