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