| // SPDX-License-Identifier: GPL-2.0+ |
| /* |
| * Freescale MPC83xx GPIO handling. |
| */ |
| |
| #include <common.h> |
| #include <malloc.h> |
| #include <mpc83xx.h> |
| #include <asm/gpio.h> |
| #include <asm/io.h> |
| |
| #ifndef CFG_MPC83XX_GPIO_0_INIT_DIRECTION |
| #define CFG_MPC83XX_GPIO_0_INIT_DIRECTION 0 |
| #endif |
| #ifndef CFG_MPC83XX_GPIO_1_INIT_DIRECTION |
| #define CFG_MPC83XX_GPIO_1_INIT_DIRECTION 0 |
| #endif |
| #ifndef CFG_MPC83XX_GPIO_0_INIT_OPEN_DRAIN |
| #define CFG_MPC83XX_GPIO_0_INIT_OPEN_DRAIN 0 |
| #endif |
| #ifndef CFG_MPC83XX_GPIO_1_INIT_OPEN_DRAIN |
| #define CFG_MPC83XX_GPIO_1_INIT_OPEN_DRAIN 0 |
| #endif |
| #ifndef CFG_MPC83XX_GPIO_0_INIT_VALUE |
| #define CFG_MPC83XX_GPIO_0_INIT_VALUE 0 |
| #endif |
| #ifndef CFG_MPC83XX_GPIO_1_INIT_VALUE |
| #define CFG_MPC83XX_GPIO_1_INIT_VALUE 0 |
| #endif |
| |
| static unsigned int gpio_output_value[MPC83XX_GPIO_CTRLRS]; |
| |
| /* |
| * Generic_GPIO primitives. |
| */ |
| |
| int gpio_request(unsigned gpio, const char *label) |
| { |
| if (gpio >= MAX_NUM_GPIOS) |
| return -1; |
| |
| return 0; |
| } |
| |
| int gpio_free(unsigned gpio) |
| { |
| /* Do not set to input */ |
| return 0; |
| } |
| |
| /* set GPIO pin 'gpio' as an input */ |
| int gpio_direction_input(unsigned gpio) |
| { |
| immap_t *im = (immap_t *)CONFIG_SYS_IMMR; |
| unsigned int ctrlr; |
| unsigned int line; |
| unsigned int line_mask; |
| |
| /* 32-bits per controller */ |
| ctrlr = gpio >> 5; |
| line = gpio & (0x1F); |
| |
| /* Big endian */ |
| line_mask = 1 << (31 - line); |
| |
| clrbits_be32(&im->gpio[ctrlr].dir, line_mask); |
| |
| return 0; |
| } |
| |
| /* set GPIO pin 'gpio' as an output, with polarity 'value' */ |
| int gpio_direction_output(unsigned gpio, int value) |
| { |
| immap_t *im = (immap_t *)CONFIG_SYS_IMMR; |
| unsigned int ctrlr; |
| unsigned int line; |
| unsigned int line_mask; |
| |
| if (value != 0 && value != 1) { |
| printf("Error: Value parameter must be 0 or 1.\n"); |
| return -1; |
| } |
| |
| gpio_set_value(gpio, value); |
| |
| /* 32-bits per controller */ |
| ctrlr = gpio >> 5; |
| line = gpio & (0x1F); |
| |
| /* Big endian */ |
| line_mask = 1 << (31 - line); |
| |
| /* Make the line output */ |
| setbits_be32(&im->gpio[ctrlr].dir, line_mask); |
| |
| return 0; |
| } |
| |
| /* read GPIO IN value of pin 'gpio' */ |
| int gpio_get_value(unsigned gpio) |
| { |
| immap_t *im = (immap_t *)CONFIG_SYS_IMMR; |
| unsigned int ctrlr; |
| unsigned int line; |
| unsigned int line_mask; |
| |
| /* 32-bits per controller */ |
| ctrlr = gpio >> 5; |
| line = gpio & (0x1F); |
| |
| /* Big endian */ |
| line_mask = 1 << (31 - line); |
| |
| /* Read the value and mask off the bit */ |
| return (in_be32(&im->gpio[ctrlr].dat) & line_mask) != 0; |
| } |
| |
| /* write GPIO OUT value to pin 'gpio' */ |
| int gpio_set_value(unsigned gpio, int value) |
| { |
| immap_t *im = (immap_t *)CONFIG_SYS_IMMR; |
| unsigned int ctrlr; |
| unsigned int line; |
| unsigned int line_mask; |
| |
| if (value != 0 && value != 1) { |
| printf("Error: Value parameter must be 0 or 1.\n"); |
| return -1; |
| } |
| |
| /* 32-bits per controller */ |
| ctrlr = gpio >> 5; |
| line = gpio & (0x1F); |
| |
| /* Big endian */ |
| line_mask = 1 << (31 - line); |
| |
| /* Update the local output buffer soft copy */ |
| gpio_output_value[ctrlr] = |
| (gpio_output_value[ctrlr] & ~line_mask) | \ |
| (value ? line_mask : 0); |
| |
| /* Write the output */ |
| out_be32(&im->gpio[ctrlr].dat, gpio_output_value[ctrlr]); |
| |
| return 0; |
| } |
| |
| /* Configure GPIO registers early */ |
| void mpc83xx_gpio_init_f(void) |
| { |
| immap_t *im = (immap_t *)CONFIG_SYS_IMMR; |
| |
| #if MPC83XX_GPIO_CTRLRS >= 1 |
| out_be32(&im->gpio[0].dir, CFG_MPC83XX_GPIO_0_INIT_DIRECTION); |
| out_be32(&im->gpio[0].odr, CFG_MPC83XX_GPIO_0_INIT_OPEN_DRAIN); |
| out_be32(&im->gpio[0].dat, CFG_MPC83XX_GPIO_0_INIT_VALUE); |
| out_be32(&im->gpio[0].ier, 0xFFFFFFFF); /* Clear all events */ |
| out_be32(&im->gpio[0].imr, 0); |
| out_be32(&im->gpio[0].icr, 0); |
| #endif |
| |
| #if MPC83XX_GPIO_CTRLRS >= 2 |
| out_be32(&im->gpio[1].dir, CFG_MPC83XX_GPIO_1_INIT_DIRECTION); |
| out_be32(&im->gpio[1].odr, CFG_MPC83XX_GPIO_1_INIT_OPEN_DRAIN); |
| out_be32(&im->gpio[1].dat, CFG_MPC83XX_GPIO_1_INIT_VALUE); |
| out_be32(&im->gpio[1].ier, 0xFFFFFFFF); /* Clear all events */ |
| out_be32(&im->gpio[1].imr, 0); |
| out_be32(&im->gpio[1].icr, 0); |
| #endif |
| } |
| |
| /* Initialize GPIO soft-copies */ |
| void mpc83xx_gpio_init_r(void) |
| { |
| #if MPC83XX_GPIO_CTRLRS >= 1 |
| gpio_output_value[0] = CFG_MPC83XX_GPIO_0_INIT_VALUE; |
| #endif |
| |
| #if MPC83XX_GPIO_CTRLRS >= 2 |
| gpio_output_value[1] = CFG_MPC83XX_GPIO_1_INIT_VALUE; |
| #endif |
| } |