1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*
3  * Copyright (c) 2020-2021 Rockchip Electronics Co., Ltd.
4  */
5 
6 #include "hal_base.h"
7 
8 #if defined(HAL_PINCTRL_MODULE_ENABLED) && (defined(RKMCU_PISCES) || defined(RKMCU_KOALA) || defined(SOC_RK1808) || defined(RKMCU_RK2108) || defined(RKMCU_RK2206))
9 
10 /** @addtogroup RK_HAL_Driver
11  *  @{
12  */
13 
14 /** @addtogroup PINCTRL
15  *  @{
16  */
17 
18 /** @defgroup PINCTRL_How_To_Use How To Use
19  *  @{
20 
21  The pinctrl setting registers actually is bus grf registers, which include
22  iomux, drive strength, pull mode, slew rate and schmitt trigger.
23 
24  The pinctrl driver provides APIs:
25    - HAL_PINCTRL_SetPinIOMUX to set pin iomux
26    - HAL_PINCTRL_SetPinParam to set pin drive/pull/slewrate/schmitt
27 
28  Example:
29 
30      HAL_PINCTRL_SetIOMUX(GPIO_BANK0,
31                           GPIO_PIN_A0 | // I2S_IN_SCLK
32                           GPIO_PIN_A1 | // I2S_IN_LRCK
33                           GPIO_PIN_A2 | // I2S_IN_SDI0
34                           GPIO_PIN_A3,  // I2S_IN_SDI1
35                           PIN_CONFIG_MUX_FUNC2);
36 
37      HAL_PINCTRL_SetParam(GPIO_BANK0,
38                           GPIO_PIN_A0 | // I2S_IN_SCLK
39                           GPIO_PIN_A1 | // I2S_IN_LRCK
40                           GPIO_PIN_A2 | // I2S_IN_SDI0
41                           GPIO_PIN_A3,  // I2S_IN_SDI1
42                           PIN_CONFIG_PUL_DOWN |
43                           PIN_CONFIG_DRV_LEVEL2 |
44                           PIN_CONFIG_SRT_FAST |
45                           PIN_CONFIG_SMT_ENABLE);
46  @} */
47 
48 /** @defgroup PINCTRL_Private_Definition Private Definition
49  *  @{
50  */
51 /********************* Private MACRO Definition ******************************/
52 #define PIN_READ(r)           (*(volatile uint32_t *)(r))
53 #define PIN_WRITE(r, b, w, v) (*(volatile uint32_t *)(r) = (((w) << (16) | (v)) << (b)))
54 
55 /********************* Private Variable Definition ***************************/
56 __WEAK const struct HAL_PINCTRL_DEV g_pinDev;
57 
58 /********************* Private Function Definition ***************************/
59 
PINCTRL_GetInfo(void)60 static const struct HAL_PINCTRL_DEV *PINCTRL_GetInfo(void)
61 {
62     return &g_pinDev;
63 }
64 
65 /**
66  * @brief  Acquire params for iomux setting.
67  * @param  pBank: point to pin bank info.
68  * @param  pin: pin index, 0~31.
69  * @param  mux: func data.
70  * @return HAL_Status.
71  */
PINCTRL_AcquireMuxRoute(const struct PINCTRL_BANK_INFO * pBank,uint8_t pin,uint32_t mux)72 static HAL_Status PINCTRL_AcquireMuxRoute(const struct PINCTRL_BANK_INFO *pBank, uint8_t pin, uint32_t mux)
73 {
74     const struct HAL_PINCTRL_DEV *ctrl = PINCTRL_GetInfo();
75     const struct PINCTRL_MUX_ROUTE_DATA *data;
76     uint32_t i, reg = 0;
77     HAL_Status rc = HAL_OK;
78 
79     if (ctrl->muxRouteDataNum == 0) {
80         rc = HAL_ERROR;
81         goto exit;
82     }
83 
84     for (i = 0; i < ctrl->muxRouteDataNum; i++) {
85         data = &ctrl->muxRouteData[i];
86         if (data->bank == pBank->channel &&
87             data->pin & (1 << pin) && data->func == mux) {
88             break;
89         }
90     }
91 
92     if (i >= ctrl->muxRouteDataNum) {
93         rc = HAL_ERROR;
94         goto exit;
95     }
96 
97     reg = pBank->grfBase + data->routeReg;
98     *(volatile uint32_t *)(reg) = data->routeVal;
99 
100     HAL_DBG("setting route %08lx = %08lx, %08lx\n", reg, data->routeVal, *(volatile uint32_t *)(reg));
101 exit:
102 
103     return rc;
104 }
105 
106 /**
107  * @brief  Rectify params for iomux setting.
108  * @param  pBank: point to pin bank info.
109  * @param  pin: pin index, 0~31.
110  * @param  reg: to get reg offset of the pin.
111  * @param  bit: to get bit offset of the pin.
112  * @param  mask: to get mask bits of the pin.
113  * @return HAL_Status.
114  */
PINCTRL_RectifyMuxParams(const struct PINCTRL_BANK_INFO * pBank,uint8_t pin,uint32_t * reg,uint8_t * bit,uint32_t * mask)115 static HAL_Status PINCTRL_RectifyMuxParams(const struct PINCTRL_BANK_INFO *pBank, uint8_t pin,
116                                            uint32_t *reg, uint8_t *bit, uint32_t *mask)
117 {
118     const struct HAL_PINCTRL_DEV *ctrl = PINCTRL_GetInfo();
119     const struct PINCTRL_MUX_RECAL_DATA *data;
120     uint32_t i;
121     HAL_Status rc = HAL_OK;
122 
123     if (ctrl->muxRecalDataNum == 0) {
124         rc = HAL_ERROR;
125         goto exit;
126     }
127 
128     for (i = 0; i < ctrl->muxRecalDataNum; i++) {
129         data = &ctrl->muxRecalData[i];
130         if (data->bank == pBank->channel &&
131             data->pin == pin) {
132             break;
133         }
134     }
135 
136     if (i >= ctrl->muxRecalDataNum) {
137         rc = HAL_ERROR;
138         goto exit;
139     }
140 
141     *reg = data->reg;
142     *mask = data->mask;
143     *bit = data->bit;
144 exit:
145 
146     return rc;
147 }
148 
149 /**
150  * @brief  Core function to get params.
151  * @param  pBank: point to pin bank info.
152  * @param  pin: pin index, 0~31.
153  * @param  id: get params for @ref ePIN_GRF_INFO_ID.
154  * @param  reg: to get reg offset of the pin.
155  * @param  bit: to get bit offset of the pin.
156  * @param  mask: to get mask bits of the pin.
157  * @return HAL_Status: HAL_OK for success to get param.
158  */
PINCTRL_AcquireParam(const struct PINCTRL_BANK_INFO * pBank,uint8_t pin,ePIN_GRF_INFO_ID id,uint32_t * reg,uint8_t * bit,uint32_t * mask)159 static HAL_Status PINCTRL_AcquireParam(const struct PINCTRL_BANK_INFO *pBank, uint8_t pin,
160                                        ePIN_GRF_INFO_ID id,
161                                        uint32_t *reg, uint8_t *bit, uint32_t *mask)
162 {
163     uint8_t paramBit = pBank->GRFInfo[id].bitsPerPin;
164     uint8_t paramPin = pBank->GRFInfo[id].pinsPerReg;
165     uint32_t regVal, mskVal;
166     uint8_t bitVal;
167 
168     /* The '0' value means nothing to set */
169     if (paramBit <= 0) {
170         return HAL_ERROR;
171     }
172 
173     /* GRF(PMUGRF) address + mux offset + pin offset */
174     regVal = pBank->grfBase;
175     regVal += pBank->GRFInfo[id].offset;
176     regVal += (pin / paramPin) * 4;
177 
178     bitVal = (pin % paramPin) * paramBit;
179     mskVal = (0x1U << paramBit) - 0x1U;
180 
181     *reg = regVal;
182     *bit = bitVal;
183     *mask = mskVal;
184 
185     return HAL_OK;
186 }
187 
188 #if defined(RKMCU_RK2206)
189 #define GRF_SARADC_IEN_EN(x)   ((0x0U << GRF_SOC_CON15_GRF_SARADC_IEN_SHIFT) << (x))
190 #define GRF_SARADC_IEN_DIS(x)  ((0x1U << GRF_SOC_CON15_GRF_SARADC_IEN_SHIFT) << (x))
191 #define GRF_SARADC_IEN_MASK(x) ((0x1U << GRF_SOC_CON15_GRF_SARADC_IEN_SHIFT) << (x))
192 #define IS_MUX_SARADC(m)       ((m) == PIN_CONFIG_MUX_FUNC1)
193 
194 /**
195  * @brief  Extra iomux for GPIO0_C0-GPIO0_C7 on rk2206 SoCs.
196  * @param  pBank: point to pin bank info.
197  * @param  pin: pin index, 0~31.
198  * @param  arg: multi params defined in @ref ePINCTRL_configParam,
199  */
PINCTRL_ExtraSet(const struct PINCTRL_BANK_INFO * pBank,uint8_t pin,uint32_t arg)200 static void PINCTRL_ExtraSet(const struct PINCTRL_BANK_INFO *pBank, uint8_t pin, uint32_t arg)
201 {
202     if (pin < 16 || pin > 23 || (pBank->channel != GPIO_BANK0)) {
203         return;
204     }
205 
206     if (IS_MUX_SARADC(arg)) {
207         WRITE_REG_MASK_WE(GRF->SOC_CON15,
208                           GRF_SARADC_IEN_MASK(pin - 16),
209                           GRF_SARADC_IEN_DIS(pin - 16));
210     } else {
211         WRITE_REG_MASK_WE(GRF->SOC_CON15,
212                           GRF_SARADC_IEN_MASK(pin - 16),
213                           GRF_SARADC_IEN_EN(pin - 16));
214     }
215 }
216 #else
PINCTRL_ExtraSet(const struct PINCTRL_BANK_INFO * pBank,uint8_t pin,uint32_t arg)217 static inline void PINCTRL_ExtraSet(const struct PINCTRL_BANK_INFO *pBank, uint8_t pin, uint32_t arg)
218 {
219 }
220 #endif
221 
222 /**
223  * @brief  Private function to set iomux for one pin.
224  * @param  pBank: point to pin bank info.
225  * @param  pin: pin index, 0~31.
226  * @param  param: mux value  to set.
227  * @return HAL_Status.
228  */
PINCTRL_SetMux(const struct PINCTRL_BANK_INFO * pBank,uint8_t pin,uint8_t param)229 static HAL_Status PINCTRL_SetMux(const struct PINCTRL_BANK_INFO *pBank,
230                                  uint8_t pin, uint8_t param)
231 {
232     uint32_t reg = 0, mask = 0;
233     uint8_t bit = 0;
234     HAL_Status rc = HAL_OK;
235 
236     HAL_DBG("setting GPIO%d-%d to %d\n", pBank->channel, pin, param);
237 
238     rc = PINCTRL_AcquireParam(pBank, pin, GRF_MUX_INFO, &reg, &bit, &mask);
239     if (rc) {
240         HAL_DBG("Warning: Acquire Mux Param failed\n");
241     }
242 
243     rc = PINCTRL_RectifyMuxParams(pBank, pin, &reg, &bit, &mask);
244     if (rc == HAL_OK) {
245         HAL_DBG("Warning: Param is rectified\n");
246     }
247 
248     PIN_WRITE(reg, bit, mask, param);
249 
250     rc = PINCTRL_AcquireMuxRoute(pBank, pin, param);
251     if (rc == HAL_OK) {
252         HAL_DBG("setting route for GPIO%d-%d\n", pBank->channel, pin);
253     }
254 
255     return HAL_OK;
256 }
257 
258 /**
259  * @brief  Set a new drive strength for a pin.
260  * @param  pBank: point to pin bank info.
261  * @param  pin: pin index, 0~31.
262  * @param  param: drive strength to set.
263  * @return HAL_Status.
264  */
PINCTRL_SetDrive(const struct PINCTRL_BANK_INFO * pBank,uint8_t pin,uint8_t param)265 static uint32_t PINCTRL_SetDrive(const struct PINCTRL_BANK_INFO *pBank,
266                                  uint8_t pin, uint8_t param)
267 {
268     uint32_t reg = 0, mask = 0;
269     uint8_t bit = 0;
270     HAL_Status rc = HAL_OK;
271 
272     HAL_DBG("setting GPIO%d-%d drive to %d\n", pBank->channel, pin, param);
273 
274     rc = PINCTRL_AcquireParam(pBank, pin, GRF_DRV_INFO, &reg, &bit, &mask);
275     if (rc) {
276         goto exit;
277     }
278 
279     PIN_WRITE(reg, bit, mask, param);
280 exit:
281 
282     return rc;
283 }
284 
285 /**
286  * @brief  Set a new pull mode for a pin.
287  * @param  pBank: point to pin bank info.
288  * @param  pin: pin index, 0~31.
289  * @param  param: pull mode to set.
290  * @return HAL_Status.
291  */
PINCTRL_SetPull(const struct PINCTRL_BANK_INFO * pBank,uint8_t pin,uint8_t param)292 static HAL_Status PINCTRL_SetPull(const struct PINCTRL_BANK_INFO *pBank,
293                                   uint8_t pin, uint8_t param)
294 {
295     uint32_t reg = 0, mask = 0;
296     uint8_t bit = 0;
297     HAL_Status rc = HAL_OK;
298 
299     HAL_DBG("setting GPIO%d-%d pull to %d\n", pBank->channel, pin, param);
300 
301     rc = PINCTRL_AcquireParam(pBank, pin, GRF_PUL_INFO, &reg, &bit, &mask);
302     if (rc) {
303         goto exit;
304     }
305 
306     PIN_WRITE(reg, bit, mask, param);
307 exit:
308 
309     return rc;
310 }
311 
312 /**
313  * @brief  Enable schmitt trigger for a pin.
314  * @param  pBank: point to pin bank info.
315  * @param  pin: pin index, 0~31.
316  * @param  param: schmitt trigger enable or not.
317  * @return HAL_Status.
318  */
PINCTRL_SetSchmitt(const struct PINCTRL_BANK_INFO * pBank,uint8_t pin,uint8_t param)319 static HAL_Status PINCTRL_SetSchmitt(const struct PINCTRL_BANK_INFO *pBank,
320                                      uint8_t pin, uint8_t param)
321 {
322     uint32_t reg = 0, mask = 0;
323     uint8_t bit = 0;
324     HAL_Status rc = HAL_OK;
325 
326     HAL_DBG("setting GPIO%d-%d schmitt to %d\n", pBank->channel, pin, param);
327 
328     rc = PINCTRL_AcquireParam(pBank, pin, GRF_SMT_INFO, &reg, &bit, &mask);
329     if (rc) {
330         goto exit;
331     }
332 
333     PIN_WRITE(reg, bit, mask, param);
334 exit:
335 
336     return rc;
337 }
338 
339 /**
340  * @brief  Change slew rate for a pin.
341  * @param  pBank: point to pin bank info.
342  * @param  pin: pin index, 0~31.
343  * @param  param: slew rate fast or slow
344  * @return HAL_Status.
345  */
PINCTRL_SetSlewRate(const struct PINCTRL_BANK_INFO * pBank,uint8_t pin,uint8_t param)346 static HAL_Status PINCTRL_SetSlewRate(const struct PINCTRL_BANK_INFO *pBank,
347                                       uint8_t pin, uint8_t param)
348 {
349     uint32_t reg = 0, mask = 0;
350     uint8_t bit = 0;
351     HAL_Status rc = HAL_OK;
352 
353     HAL_DBG("setting GPIO%d-%d slewrate to %d\n", pBank->channel, pin, param);
354 
355     rc = PINCTRL_AcquireParam(pBank, pin, GRF_SRT_INFO, &reg, &bit, &mask);
356     if (rc) {
357         goto exit;
358     }
359 
360     PIN_WRITE(reg, bit, mask, param);
361 exit:
362 
363     return rc;
364 }
365 
366 /**
367  * @brief  Private function to configure one pin.
368  * @param  bank: pin bank channel defined in @ref eGPIO_bankId.
369  * @param  pin: pin index, 0~31.
370  * @param  param: multi params defined in @ref ePINCTRL_configParam,
371  * @return HAL_Status.
372  */
PINCTRL_SetParam(const struct PINCTRL_BANK_INFO * pBank,uint8_t pin,uint32_t param)373 static HAL_Status PINCTRL_SetParam(const struct PINCTRL_BANK_INFO *pBank,
374                                    uint8_t pin, uint32_t param)
375 {
376     HAL_Status rc = HAL_OK;
377 
378     if (param & FLAG_PUL) {
379         rc |= PINCTRL_SetPull(pBank, pin, (uint8_t)((param & MASK_PUL) >> SHIFT_PUL));
380     }
381 
382     if (param & FLAG_DRV) {
383         rc |= PINCTRL_SetDrive(pBank, pin, (uint8_t)((param & MASK_DRV) >> SHIFT_DRV));
384     }
385 
386     if (param & FLAG_SMT) {
387         rc |= PINCTRL_SetSchmitt(pBank, pin, (uint8_t)((param & MASK_SMT) >> SHIFT_SMT));
388     }
389 
390     if (param & FLAG_SRT) {
391         rc |= PINCTRL_SetSlewRate(pBank, pin, (uint8_t)((param & MASK_SRT) >> SHIFT_SRT));
392     }
393 
394     return rc;
395 }
396 
397 /**
398  * @brief  Private function to configure one pin.
399  * @param  bank: pin bank channel defined in @ref eGPIO_bankId.
400  * @param  pin: pin index, 0~31.
401  * @param  param: multi params defined in @ref ePINCTRL_configParam,
402  * @return HAL_Status.
403  */
PINCTRL_SetPinParam(eGPIO_bankId bank,uint8_t pin,uint32_t param)404 static HAL_Status PINCTRL_SetPinParam(eGPIO_bankId bank, uint8_t pin, uint32_t param)
405 {
406     const struct HAL_PINCTRL_DEV *ctrl = PINCTRL_GetInfo();
407 
408     return PINCTRL_SetParam(&ctrl->banks[bank], pin, param);
409 }
410 
411 /**
412  * @brief  Private function to set iomux for one pin.
413  * @param  bank: pin bank channel defined in @ref eGPIO_bankId.
414  * @param  pin: pin index, 0~31.
415  * @param  param: PIN_CONFIG_MUX_* defined in @ref ePINCTRL_configParam.
416  * @return HAL_Status.
417  */
PINCTRL_SetPinIOMUX(eGPIO_bankId bank,uint8_t pin,uint32_t param)418 static HAL_Status PINCTRL_SetPinIOMUX(eGPIO_bankId bank, uint8_t pin, uint32_t param)
419 {
420     const struct HAL_PINCTRL_DEV *ctrl = PINCTRL_GetInfo();
421 
422     PINCTRL_ExtraSet(&ctrl->banks[bank], pin, param);
423 
424     return PINCTRL_SetMux(&ctrl->banks[bank], pin, (uint8_t)((param & MASK_MUX) >> SHIFT_MUX));
425 }
426 
427 /** @} */
428 /********************* Public Function Definition ****************************/
429 
430 /** @defgroup PINCTRL_Exported_Functions_Group1 Suspend and Resume Functions
431 
432  This section provides functions allowing to suspend and resume the module:
433 
434  *  @{
435  */
436 
HAL_PINCTRL_Suspend(void)437 HAL_Status HAL_PINCTRL_Suspend(void)
438 {
439     return HAL_OK;
440 }
441 
HAL_PINCTRL_Resume(void)442 HAL_Status HAL_PINCTRL_Resume(void)
443 {
444     return HAL_OK;
445 }
446 /** @} */
447 
448 /** @defgroup PINCTRL_Exported_Functions_Group2 Init and DeInit Functions
449 
450  This section provides functions allowing to init and deinit the module:
451 
452  *  @{
453  */
454 
HAL_PINCTRL_Init(void)455 HAL_Status HAL_PINCTRL_Init(void)
456 {
457 #ifdef RKMCU_PISCES
458     HAL_PINCTRL_SetIOMUX(GPIO_BANK0, GPIO_PIN_ALL & ~(
459                              GPIO_PIN_C7 | // UART0_RX
460                              GPIO_PIN_D0 | // UART0_TX
461                              GPIO_PIN_D5 | // MIPI_SWITCH_CTRL
462                              GPIO_PIN_D6), // AUD_BY_CTRL
463                          PIN_CONFIG_MUX_FUNC0);
464     HAL_PINCTRL_SetIOMUX(GPIO_BANK1, GPIO_PIN_ALL & ~(
465                              GPIO_PIN_A0 | // LCD_IN_RESET_N
466                              GPIO_PIN_A1 | // LCD_IN_TE
467                              GPIO_PIN_A2 | // LCD_OUT_RESETN
468                              GPIO_PIN_A3 | // LCD_OUT_TE
469                              GPIO_PIN_A5 | // BOOT_DEV_SEL
470                              GPIO_PIN_A6 | // M4_DSP_JTAG_SEL
471                              GPIO_PIN_B2), // CLK_IN_SEL
472                          PIN_CONFIG_MUX_FUNC0);
473 
474     HAL_PINCTRL_SetParam(GPIO_BANK0, GPIO_PIN_ALL & ~(
475                              GPIO_PIN_D5 | // MIPI_SWITCH_CTRL
476                              GPIO_PIN_D6), // AUD_BY_CTRL
477                          PIN_CONFIG_PUL_NORMAL);
478     HAL_PINCTRL_SetParam(GPIO_BANK1, GPIO_PIN_ALL & ~(
479                              GPIO_PIN_A5 | // BOOT_DEV_SEL
480                              GPIO_PIN_A6 | // M4_DSP_JTAG_SEL
481                              GPIO_PIN_B2), // CLK_IN_SEL
482                          PIN_CONFIG_PUL_NORMAL);
483 #endif
484 
485     return HAL_OK;
486 }
487 
HAL_PINCTRL_DeInit(void)488 HAL_Status HAL_PINCTRL_DeInit(void)
489 {
490     return HAL_OK;
491 }
492 /** @} */
493 
494 /** @defgroup PINCTRL_Exported_Functions_Group3 State and Errors Functions
495 
496  This section provides functions allowing to get the status of the module:
497 
498  *  @{
499  */
500 
501 /**
502  * @brief  Public function to configure for multi pins.
503  * @param  bank: pin bank channel defined in ref eGPIO_bankId.
504  * @param  mPins: multi pins defined in @ref ePINCTRL_GPIO_PINS.
505  * @param  param: multi params defined in @ref ePINCTRL_configParam,
506  * @return HAL_Status.
507  */
HAL_PINCTRL_SetParam(eGPIO_bankId bank,uint32_t mPins,ePINCTRL_configParam param)508 HAL_Status HAL_PINCTRL_SetParam(eGPIO_bankId bank, uint32_t mPins, ePINCTRL_configParam param)
509 {
510     uint8_t pin;
511     HAL_Status rc = HAL_OK;
512 
513     HAL_ASSERT(bank < GPIO_BANK_NUM);
514     HAL_ASSERT(IS_GPIO_PIN(mPins));
515 
516     for (pin = 0; pin < 32; pin++) {
517         if (mPins & (1 << pin)) {
518             rc = PINCTRL_SetPinParam(bank, pin, param);
519             if (rc) {
520                 return rc;
521             }
522         }
523     }
524 
525     return rc;
526 }
527 
528 /**
529  * @brief  Public function to set iomux for multi pins.
530  * @param  bank: pin bank channel defined in ref eGPIO_bankId.
531  * @param  mPins: multi pins defined in @ref ePINCTRL_GPIO_PINS.
532  * @param  param: param PIN_CONFIG_MUX_* defined in @ref ePINCTRL_configParam.
533  * @return HAL_Status.
534  */
HAL_PINCTRL_SetIOMUX(eGPIO_bankId bank,uint32_t mPins,ePINCTRL_configParam param)535 HAL_Status HAL_PINCTRL_SetIOMUX(eGPIO_bankId bank, uint32_t mPins, ePINCTRL_configParam param)
536 {
537     uint8_t pin;
538     HAL_Status rc;
539 
540     HAL_ASSERT(bank < GPIO_BANK_NUM);
541 
542     for (pin = 0; pin < 32; pin++) {
543         if (mPins & (1 << pin)) {
544             rc = PINCTRL_SetPinIOMUX(bank, pin, param);
545             if (rc) {
546                 return rc;
547             }
548         }
549     }
550 
551     return HAL_OK;
552 }
553 /** @} */
554 
555 /** @defgroup PINCTRL_Exported_Functions_Group4 IO Functions
556 
557  This section provides functions allowing to IO controlling:
558 
559  *  @{
560  */
561 
562 /** @} */
563 
564 /** @} */
565 
566 /** @} */
567 
568 #endif /* HAL_PINCTRL_MODULE_ENABLED */
569