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.