1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
24b565793SJoe Hershberger /*
34b565793SJoe Hershberger * Freescale MPC83xx GPIO handling.
44b565793SJoe Hershberger */
54b565793SJoe Hershberger
64b565793SJoe Hershberger #include <common.h>
74b565793SJoe Hershberger #include <mpc83xx.h>
84b565793SJoe Hershberger #include <asm/gpio.h>
94b565793SJoe Hershberger #include <asm/io.h>
104b565793SJoe Hershberger
114b565793SJoe Hershberger #ifndef CONFIG_MPC83XX_GPIO_0_INIT_DIRECTION
124b565793SJoe Hershberger #define CONFIG_MPC83XX_GPIO_0_INIT_DIRECTION 0
134b565793SJoe Hershberger #endif
144b565793SJoe Hershberger #ifndef CONFIG_MPC83XX_GPIO_1_INIT_DIRECTION
154b565793SJoe Hershberger #define CONFIG_MPC83XX_GPIO_1_INIT_DIRECTION 0
164b565793SJoe Hershberger #endif
174b565793SJoe Hershberger #ifndef CONFIG_MPC83XX_GPIO_0_INIT_OPEN_DRAIN
184b565793SJoe Hershberger #define CONFIG_MPC83XX_GPIO_0_INIT_OPEN_DRAIN 0
194b565793SJoe Hershberger #endif
204b565793SJoe Hershberger #ifndef CONFIG_MPC83XX_GPIO_1_INIT_OPEN_DRAIN
214b565793SJoe Hershberger #define CONFIG_MPC83XX_GPIO_1_INIT_OPEN_DRAIN 0
224b565793SJoe Hershberger #endif
234b565793SJoe Hershberger #ifndef CONFIG_MPC83XX_GPIO_0_INIT_VALUE
244b565793SJoe Hershberger #define CONFIG_MPC83XX_GPIO_0_INIT_VALUE 0
254b565793SJoe Hershberger #endif
264b565793SJoe Hershberger #ifndef CONFIG_MPC83XX_GPIO_1_INIT_VALUE
274b565793SJoe Hershberger #define CONFIG_MPC83XX_GPIO_1_INIT_VALUE 0
284b565793SJoe Hershberger #endif
294b565793SJoe Hershberger
304b565793SJoe Hershberger static unsigned int gpio_output_value[MPC83XX_GPIO_CTRLRS];
314b565793SJoe Hershberger
324b565793SJoe Hershberger /*
334b565793SJoe Hershberger * Generic_GPIO primitives.
344b565793SJoe Hershberger */
354b565793SJoe Hershberger
gpio_request(unsigned gpio,const char * label)364b565793SJoe Hershberger int gpio_request(unsigned gpio, const char *label)
374b565793SJoe Hershberger {
384b565793SJoe Hershberger if (gpio >= MAX_NUM_GPIOS)
394b565793SJoe Hershberger return -1;
404b565793SJoe Hershberger
414b565793SJoe Hershberger return 0;
424b565793SJoe Hershberger }
434b565793SJoe Hershberger
gpio_free(unsigned gpio)444b565793SJoe Hershberger int gpio_free(unsigned gpio)
454b565793SJoe Hershberger {
464b565793SJoe Hershberger /* Do not set to input */
474b565793SJoe Hershberger return 0;
484b565793SJoe Hershberger }
494b565793SJoe Hershberger
504b565793SJoe Hershberger /* set GPIO pin 'gpio' as an input */
gpio_direction_input(unsigned gpio)514b565793SJoe Hershberger int gpio_direction_input(unsigned gpio)
524b565793SJoe Hershberger {
534b565793SJoe Hershberger immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
544b565793SJoe Hershberger unsigned int ctrlr;
554b565793SJoe Hershberger unsigned int line;
564b565793SJoe Hershberger unsigned int line_mask;
574b565793SJoe Hershberger
584b565793SJoe Hershberger /* 32-bits per controller */
594b565793SJoe Hershberger ctrlr = gpio >> 5;
604b565793SJoe Hershberger line = gpio & (0x1F);
614b565793SJoe Hershberger
624b565793SJoe Hershberger /* Big endian */
634b565793SJoe Hershberger line_mask = 1 << (31 - line);
644b565793SJoe Hershberger
654b565793SJoe Hershberger clrbits_be32(&im->gpio[ctrlr].dir, line_mask);
664b565793SJoe Hershberger
674b565793SJoe Hershberger return 0;
684b565793SJoe Hershberger }
694b565793SJoe Hershberger
704b565793SJoe Hershberger /* set GPIO pin 'gpio' as an output, with polarity 'value' */
gpio_direction_output(unsigned gpio,int value)714b565793SJoe Hershberger int gpio_direction_output(unsigned gpio, int value)
724b565793SJoe Hershberger {
734b565793SJoe Hershberger immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
744b565793SJoe Hershberger unsigned int ctrlr;
754b565793SJoe Hershberger unsigned int line;
764b565793SJoe Hershberger unsigned int line_mask;
774b565793SJoe Hershberger
784b565793SJoe Hershberger if (value != 0 && value != 1) {
794b565793SJoe Hershberger printf("Error: Value parameter must be 0 or 1.\n");
804b565793SJoe Hershberger return -1;
814b565793SJoe Hershberger }
824b565793SJoe Hershberger
834b565793SJoe Hershberger gpio_set_value(gpio, value);
844b565793SJoe Hershberger
854b565793SJoe Hershberger /* 32-bits per controller */
864b565793SJoe Hershberger ctrlr = gpio >> 5;
874b565793SJoe Hershberger line = gpio & (0x1F);
884b565793SJoe Hershberger
894b565793SJoe Hershberger /* Big endian */
904b565793SJoe Hershberger line_mask = 1 << (31 - line);
914b565793SJoe Hershberger
924b565793SJoe Hershberger /* Make the line output */
934b565793SJoe Hershberger setbits_be32(&im->gpio[ctrlr].dir, line_mask);
944b565793SJoe Hershberger
954b565793SJoe Hershberger return 0;
964b565793SJoe Hershberger }
974b565793SJoe Hershberger
984b565793SJoe Hershberger /* read GPIO IN value of pin 'gpio' */
gpio_get_value(unsigned gpio)994b565793SJoe Hershberger int gpio_get_value(unsigned gpio)
1004b565793SJoe Hershberger {
1014b565793SJoe Hershberger immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
1024b565793SJoe Hershberger unsigned int ctrlr;
1034b565793SJoe Hershberger unsigned int line;
1044b565793SJoe Hershberger unsigned int line_mask;
1054b565793SJoe Hershberger
1064b565793SJoe Hershberger /* 32-bits per controller */
1074b565793SJoe Hershberger ctrlr = gpio >> 5;
1084b565793SJoe Hershberger line = gpio & (0x1F);
1094b565793SJoe Hershberger
1104b565793SJoe Hershberger /* Big endian */
1114b565793SJoe Hershberger line_mask = 1 << (31 - line);
1124b565793SJoe Hershberger
1134b565793SJoe Hershberger /* Read the value and mask off the bit */
1144b565793SJoe Hershberger return (in_be32(&im->gpio[ctrlr].dat) & line_mask) != 0;
1154b565793SJoe Hershberger }
1164b565793SJoe Hershberger
1174b565793SJoe Hershberger /* write GPIO OUT value to pin 'gpio' */
gpio_set_value(unsigned gpio,int value)1184b565793SJoe Hershberger int gpio_set_value(unsigned gpio, int value)
1194b565793SJoe Hershberger {
1204b565793SJoe Hershberger immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
1214b565793SJoe Hershberger unsigned int ctrlr;
1224b565793SJoe Hershberger unsigned int line;
1234b565793SJoe Hershberger unsigned int line_mask;
1244b565793SJoe Hershberger
1254b565793SJoe Hershberger if (value != 0 && value != 1) {
1264b565793SJoe Hershberger printf("Error: Value parameter must be 0 or 1.\n");
1274b565793SJoe Hershberger return -1;
1284b565793SJoe Hershberger }
1294b565793SJoe Hershberger
1304b565793SJoe Hershberger /* 32-bits per controller */
1314b565793SJoe Hershberger ctrlr = gpio >> 5;
1324b565793SJoe Hershberger line = gpio & (0x1F);
1334b565793SJoe Hershberger
1344b565793SJoe Hershberger /* Big endian */
1354b565793SJoe Hershberger line_mask = 1 << (31 - line);
1364b565793SJoe Hershberger
1374b565793SJoe Hershberger /* Update the local output buffer soft copy */
1384b565793SJoe Hershberger gpio_output_value[ctrlr] =
1394b565793SJoe Hershberger (gpio_output_value[ctrlr] & ~line_mask) | \
1404b565793SJoe Hershberger (value ? line_mask : 0);
1414b565793SJoe Hershberger
1424b565793SJoe Hershberger /* Write the output */
1434b565793SJoe Hershberger out_be32(&im->gpio[ctrlr].dat, gpio_output_value[ctrlr]);
1444b565793SJoe Hershberger
1454b565793SJoe Hershberger return 0;
1464b565793SJoe Hershberger }
1474b565793SJoe Hershberger
1484b565793SJoe Hershberger /* Configure GPIO registers early */
mpc83xx_gpio_init_f(void)1498121d3c5SKim Phillips void mpc83xx_gpio_init_f(void)
1504b565793SJoe Hershberger {
1514b565793SJoe Hershberger immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
1524b565793SJoe Hershberger
1534b565793SJoe Hershberger #if MPC83XX_GPIO_CTRLRS >= 1
1544b565793SJoe Hershberger out_be32(&im->gpio[0].dir, CONFIG_MPC83XX_GPIO_0_INIT_DIRECTION);
1554b565793SJoe Hershberger out_be32(&im->gpio[0].odr, CONFIG_MPC83XX_GPIO_0_INIT_OPEN_DRAIN);
1564b565793SJoe Hershberger out_be32(&im->gpio[0].dat, CONFIG_MPC83XX_GPIO_0_INIT_VALUE);
1574b565793SJoe Hershberger out_be32(&im->gpio[0].ier, 0xFFFFFFFF); /* Clear all events */
1584b565793SJoe Hershberger out_be32(&im->gpio[0].imr, 0);
1594b565793SJoe Hershberger out_be32(&im->gpio[0].icr, 0);
1604b565793SJoe Hershberger #endif
1614b565793SJoe Hershberger
1624b565793SJoe Hershberger #if MPC83XX_GPIO_CTRLRS >= 2
1634b565793SJoe Hershberger out_be32(&im->gpio[1].dir, CONFIG_MPC83XX_GPIO_1_INIT_DIRECTION);
1644b565793SJoe Hershberger out_be32(&im->gpio[1].odr, CONFIG_MPC83XX_GPIO_1_INIT_OPEN_DRAIN);
1654b565793SJoe Hershberger out_be32(&im->gpio[1].dat, CONFIG_MPC83XX_GPIO_1_INIT_VALUE);
1664b565793SJoe Hershberger out_be32(&im->gpio[1].ier, 0xFFFFFFFF); /* Clear all events */
1674b565793SJoe Hershberger out_be32(&im->gpio[1].imr, 0);
1684b565793SJoe Hershberger out_be32(&im->gpio[1].icr, 0);
1694b565793SJoe Hershberger #endif
1704b565793SJoe Hershberger }
1714b565793SJoe Hershberger
1724b565793SJoe Hershberger /* Initialize GPIO soft-copies */
mpc83xx_gpio_init_r(void)1738121d3c5SKim Phillips void mpc83xx_gpio_init_r(void)
1744b565793SJoe Hershberger {
1754b565793SJoe Hershberger #if MPC83XX_GPIO_CTRLRS >= 1
1764b565793SJoe Hershberger gpio_output_value[0] = CONFIG_MPC83XX_GPIO_0_INIT_VALUE;
1774b565793SJoe Hershberger #endif
1784b565793SJoe Hershberger
1794b565793SJoe Hershberger #if MPC83XX_GPIO_CTRLRS >= 2
1804b565793SJoe Hershberger gpio_output_value[1] = CONFIG_MPC83XX_GPIO_1_INIT_VALUE;
1814b565793SJoe Hershberger #endif
1824b565793SJoe Hershberger }
183