SSD_PADMUX
1. What is Padmux¶
Padmux is a linux platform driver located in kernel\drivers\sstar\padmux. Because of the multiplexing of gpio pins, usually the same gpio can be used for different functions, so we use the padmux driver to uniformly configure the gpio pin functions that need to be used when booting.
2. PadMux Driver¶
The Padmux driver is defined as follows:
2. static struct platform_driver sstar_padmux_driver = { 3. .driver = { 4. .name = "padmux", 5. .owner = THIS_MODULE, 6. .of_match_table = sstar_padmux_of_match, 7. .pm = &sstar_padmux_pm_ops, 8. }, 9. .probe = sstar_padmux_probe, 10. };
The members who need to pay attention are as follows, which will be introduced separately below.
sstar_padmux_of_match
sstar_padmux_pm_ops
sstar_padmux_probe
2.1. sstar_padmux_of_match¶
Used to match the gpio table device that needs to be configured at boot:
1. static const struct of_device_id sstar_padmux_of_match[] = { 2. { .compatible = "sstar-padmux" }, 3. { }, 4. };
Match the device in dts (for example: kernel\arch\arm\boot\dts pioneer3-ssc020a-s01a-demo-padmux.dtsi) through sstar-padmux:
1. padmux { 2. compatible = "sstar-padmux"; 3. schematic = 4. 5. //i2c1_mode_8, and set i2c-padmux = <8> int pioneer-demo.dtsi 6. <PAD_KEY8 PINMUX_FOR_I2C1_MODE_8 MDRV_PUSE_I2C1_SCL>, 7. <PAD_KEY9 PINMUX_FOR_I2C1_MODE_8 MDRV_PUSE_I2C1_SDA>, 8. <PAD_SR_IO16 PINMUX_FOR_GPIO_MODE MDRV_PUSE_AIO_AMP_PWR >, 9. 10. //SPI1 mode 6 11. <PAD_KEY10 PINMUX_FOR_SPI1_MODE_6 MDRV_PUSE_SPI1_CZ>, 12. <PAD_KEY11 PINMUX_FOR_SPI1_MODE_6 MDRV_PUSE_SPI1_CK>, 13. <PAD_KEY12 PINMUX_FOR_SPI1_MODE_6 MDRV_PUSE_SPI1_DI>, 14. <PAD_KEY13 PINMUX_FOR_SPI1_MODE_6 MDRV_PUSE_SPI1_DO>, 15. 16. //pwm for backlight 17. <PAD_SR_IO08 PINMUX_FOR_PWM0_MODE_3 MDRV_PUSE_PWM0>, 18. 19. <GPIO_NR PINMUX_FOR_UNKNOWN_MODE MDRV_PUSE_NA>; 20. 21. status = "ok"; // ok or disable 22. };
2.2. sstar_padmux_pm_ops¶
Implement the resume and suspend functions corresponding to str standby:
1. static const struct dev_pm_ops sstar_padmux_pm_ops = { 2. .suspend_late = sstar_padmux_suspend, 3. .resume_early = sstar_padmux_resume, 4. };
2.3. sstar_padmux_probe¶
After matching the padmux device, the system will call sstar_padmux_probe to configure the gpio function:
1. static int sstar_padmux_probe(struct platform_device *pdev) 2. { 3. _mdrv_padmux_dts(pdev->dev.of_node); 4. return 0; 5. } 6. static int _mdrv_padmux_dts(struct device_node* np) 7. { 8. int nPad; 9. 10. if (0 >= (nPad = of_property_count_elems_of_size(np, PADINFO_NAME, sizeof(pad_info_t)))) 11. { 12. PAD_PRINT("[%s][%d] invalid dts of padmux.schematic\n", __FUNCTION__, __LINE__); 13. return -1; 14. } 15. if (NULL == (_pPadInfo = kmalloc(nPad*sizeof(pad_info_t), GFP_KERNEL))) 16. { 17. PAD_PRINT("[%s][%d] kmalloc fail\n", __FUNCTION__, __LINE__); 18. return -1; 19. } 20. if (of_property_read_u32_array(np, PADINFO_NAME, (u32*)_pPadInfo, nPad*sizeof(pad_info_t)/sizeof(U32))) 21. { 22. PAD_PRINT("[%s][%d] of_property_read_u32_array fail\n", __FUNCTION__, __LINE__); 23. kfree(_pPadInfo); 24. _pPadInfo = NULL; 25. return -1; 26. } 27. _nPad = nPad; 28. 29. { 30. int i; 31. PAD_PRINT("[%s][%d] *******************************\n", __FUNCTION__, __LINE__); 32. for (i = 0; i < _nPad; i++) 33. { 34. PAD_PRINT("[%s][%d] (PadId, Mode, Puse) = (%d, 0x%02x, 0x%08x)\n", __FUNCTION__, __LINE__, 35. _pPadInfo[i].u32PadId, 36. _pPadInfo[i].u32Mode, 37. _pPadInfo[i].u32Puse); 38. MDrv_GPIO_PadVal_Set((U8)_pPadInfo[i].u32PadId & 0xFF, _pPadInfo[i].u32Mode); 39. } 40. PAD_PRINT("[%s][%d] *******************************\n", __FUNCTION__, __LINE__); 41. } 42. 43. return 0; 44. }
Finally, configure gpio to the corresponding function through MDrv_GPIO_PadVal_Set:
kernel\drivers\sstar\gpio mdrv_gpio.c
1. int MDrv_GPIO_PadVal_Set(U8 u8IndexGPIO, U32 u32PadMode) 2. { 3. return MHal_GPIO_PadVal_Set(u8IndexGPIO, u32PadMode); 4. }
kernel\drivers\sstar\gpio\pioneer3 mhal_gpio.c
1. int MHal_GPIO_PadVal_Set(U8 u8IndexGPIO, U32 u32PadMode) 2. { 3. return HalPadSetVal((U32)u8IndexGPIO, u32PadMode); 4. }
kernel\drivers\sstar\gpio\pioneer3 mhal_pinmux.c
1. S32 HalPadSetVal(U32 u32PadID, U32 u32Mode) 2. { 3. if (FALSE == _HalCheckPin(u32PadID)) { 4. return FALSE; 5. } 6. if(u32PadID>=PAD_ETH_RN && u32PadID <= PAD_SAR_GPIO3) 7. return HalPadSetMode_MISC(u32PadID, u32Mode); 8. return HalPadSetMode_General(u32PadID, u32Mode); 9. } 10. static S32 HalPadSetMode_General(U32 u32PadID, U32 u32Mode) 11. { 12. U32 u32RegAddr = 0; 13. U16 u16RegVal = 0; 14. U8 u8ModeIsFind = 0; 15. U16 i = 0; 16. 17. for (i = 0; i < sizeof(m_stPadMuxTbl)/sizeof(struct stPadMux); i++) 18. { 19. if (u32PadID == m_stPadMuxTbl[i].padID) 20. { 21. u32RegAddr = _RIUA_16BIT(m_stPadMuxTbl[i].base, m_stPadMuxTbl[i].offset); 22. 23. if (u32Mode == m_stPadMuxTbl[i].mode) 24. { 25. u16RegVal = _GPIO_R_WORD_MASK(u32RegAddr, 0xFFFF); 26. u16RegVal &= ~(m_stPadMuxTbl[i].mask); 27. u16RegVal |= m_stPadMuxTbl[i].val; // CHECK Multi-Pad Mode 28. 29. _GPIO_W_WORD_MASK(u32RegAddr, u16RegVal, 0xFFFF); 30. 31. u8ModeIsFind = 1; 32. #if (ENABLE_CHECK_ALL_PAD_CONFLICT == 0) 33. break; 34. #endif 35. } 36. else 37. { //Clear high priority setting 38. u16RegVal = _GPIO_R_WORD_MASK(u32RegAddr, m_stPadMuxTbl[i].mask); 39. if (u16RegVal == m_stPadMuxTbl[i].val) 40. { 41. printk(KERN_INFO"[Padmux]reset PAD%d(reg 0x%x:%x; mask0x%x) t0 %s (org: %s)\n", 42. u32PadID, 43. m_stPadMuxTbl[i].base, 44. m_stPadMuxTbl[i].offset, 45. m_stPadMuxTbl[i].mask, 46. m_stPadModeInfoTbl[u32Mode].u8PadName, 47. m_stPadModeInfoTbl[m_stPadMuxTbl[i].mode].u8PadName); 48. if (m_stPadMuxTbl[i].val != 0) 49. { 50. _GPIO_W_WORD_MASK(u32RegAddr, 0, m_stPadMuxTbl[i].mask); 51. } 52. else 53. { 54. _GPIO_W_WORD_MASK(u32RegAddr, m_stPadMuxTbl[i].mask, m_stPadMuxTbl[i].mask); 55. } 56. } 57. } 58. } 59. } 60. 61. return (u8ModeIsFind) ? 0 : -1; 62. }
Find the reg corresponding to the gpio and mode settings that need to be configured in m_stPadMuxTbl.
Take PAD_TTL4 configured as PINMUX_FOR_PWM0_MODE_4 as an example:
When configured in dts padmux:
<PAD_TTL4 PINMUX_FOR_PWM0_MODE_4 MDRV_PUSE_PWM0>,
During probe, bit2 of register bank 0x103c offset 0x65 is set to 1 according to the register setting of m_stPadMuxTbl:
1. #define PADTOP_BANK 0x103C00 2. #define REG_PWM0_MODE 0x65 3. #define REG_PWM0_MODE_MASK BIT0|BIT1|BIT2|BIT3 4. {PAD_TTL4, PADTOP_BANK, REG_PWM0_MODE, REG_PWM0_MODE_MASK, BIT2, PINMUX_FOR_PWM0_MODE_4},
You can check whether the settings take effect by reading reg on the board:
3. How to use PadMux¶
Through the introduction of the padmux driver above, we know that as long as the padmux driver is enabled, and the pin to be configured and the corresponding mode are written in the dts, the function corresponding to the gpio will be configured when the padmux probe is turned on. It should be noted that the pamdux driver depends on the gpio driver, so both drivers must be built into the kernel. At present, the default configuration of the public board, gpio and padmux, have buildin enabled by default:
1. CONFIG_MS_GPIO=y 2. CONFIG_MS_PADMUX=y
The following describes how to configure the corresponding gpio function in the padmux of dts.
3.1. Which padmux dts file to use¶
Which padmux dts file is used is determined by the kernel config file according to the following follow.
kernel\arch\arm\configs\pioneer3_ssc020a_s01a_demo_defconfig:
1. CONFIG_SS_DTB_NAME="pioneer3-ssc020a-s01a-demo"
kernel\arch\arm\boot\dts\pioneer3-ssc020a-s01a-demo.dts:
1. #include "pioneer3.dtsi" 2. #include "pioneer3-demo.dtsi" 3. #include "pioneer3-ssc020a-s01a-demo-padmux.dtsi"
kernel\arch\arm\boot\dts\pioneer3-ssc020a-s01a-demo-padmux.dtsi
3.2. Configure gpio mode¶
According to the hardware release information SSDXXX HW CheckList V03.xlsx of the SDK release, find the padmux column:
The above figure takes the configuration of PAD_TTL4 as PWM0 as an example, you can see that PAD_TTL4 can only be configured as pwm0 mode 4 to configure it as PWM0, so the configuration in padmux dts is as follows:
<PAD_TTL4 PINMUX_FOR_PWM0_MODE_4 MDRV_PUSE_PWM0>,
Among them, MDRV_PUSE_PWM0 is generally only used as an explanation comment and has no special purpose unless the corresponding function driver has special settings. Other i2c, spi, uart, ttl, mipi settings can also refer to hw checklist configuration in padmux dts.
4. Notes¶
The same gpio pin can only be multiplexed into one function, and cannot be configured into two functions in padmux at the same time. If the function configured in padmux does not take effect, you need to confirm whether it is configured with other functions in dts.