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