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, ®, &bit, &mask);
239 if (rc) {
240 HAL_DBG("Warning: Acquire Mux Param failed\n");
241 }
242
243 rc = PINCTRL_RectifyMuxParams(pBank, pin, ®, &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, ®, &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, ®, &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, ®, &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, ®, &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