xref: /openbmc/u-boot/common/iomux.c (revision 24b852a7a2b8eca71789100983bdb5104cc00696)
116a28ef2SGary Jennejohn /*
216a28ef2SGary Jennejohn  * (C) Copyright 2008
316a28ef2SGary Jennejohn  * Gary Jennejohn, DENX Software Engineering GmbH, garyj@denx.de.
416a28ef2SGary Jennejohn  *
51a459660SWolfgang Denk  * SPDX-License-Identifier:	GPL-2.0+
616a28ef2SGary Jennejohn  */
716a28ef2SGary Jennejohn 
816a28ef2SGary Jennejohn #include <common.h>
9*24b852a7SSimon Glass #include <console.h>
1016a28ef2SGary Jennejohn #include <serial.h>
1116a28ef2SGary Jennejohn #include <malloc.h>
1216a28ef2SGary Jennejohn 
1316a28ef2SGary Jennejohn #ifdef CONFIG_CONSOLE_MUX
1416a28ef2SGary Jennejohn void iomux_printdevs(const int console)
1516a28ef2SGary Jennejohn {
1616a28ef2SGary Jennejohn 	int i;
1752cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	struct stdio_dev *dev;
1816a28ef2SGary Jennejohn 
1916a28ef2SGary Jennejohn 	for (i = 0; i < cd_count[console]; i++) {
2016a28ef2SGary Jennejohn 		dev = console_devices[console][i];
2116a28ef2SGary Jennejohn 		printf("%s ", dev->name);
2216a28ef2SGary Jennejohn 	}
2316a28ef2SGary Jennejohn 	printf("\n");
2416a28ef2SGary Jennejohn }
2516a28ef2SGary Jennejohn 
2616a28ef2SGary Jennejohn /* This tries to preserve the old list if an error occurs. */
2716a28ef2SGary Jennejohn int iomux_doenv(const int console, const char *arg)
2816a28ef2SGary Jennejohn {
2916a28ef2SGary Jennejohn 	char *console_args, *temp, **start;
3016a28ef2SGary Jennejohn 	int i, j, k, io_flag, cs_idx, repeat;
3152cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	struct stdio_dev *dev;
3252cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	struct stdio_dev **cons_set;
3316a28ef2SGary Jennejohn 
3416a28ef2SGary Jennejohn 	console_args = strdup(arg);
3516a28ef2SGary Jennejohn 	if (console_args == NULL)
3616a28ef2SGary Jennejohn 		return 1;
3716a28ef2SGary Jennejohn 	/*
3816a28ef2SGary Jennejohn 	 * Check whether a comma separated list of devices was
3916a28ef2SGary Jennejohn 	 * entered and count how many devices were entered.
4016a28ef2SGary Jennejohn 	 * The array start[] has pointers to the beginning of
4116a28ef2SGary Jennejohn 	 * each device name (up to MAX_CONSARGS devices).
4216a28ef2SGary Jennejohn 	 *
4316a28ef2SGary Jennejohn 	 * Have to do this twice - once to count the number of
4416a28ef2SGary Jennejohn 	 * commas and then again to populate start.
4516a28ef2SGary Jennejohn 	 */
4616a28ef2SGary Jennejohn 	i = 0;
4716a28ef2SGary Jennejohn 	temp = console_args;
4816a28ef2SGary Jennejohn 	for (;;) {
4916a28ef2SGary Jennejohn 		temp = strchr(temp, ',');
5016a28ef2SGary Jennejohn 		if (temp != NULL) {
5116a28ef2SGary Jennejohn 			i++;
5216a28ef2SGary Jennejohn 			temp++;
5316a28ef2SGary Jennejohn 			continue;
5416a28ef2SGary Jennejohn 		}
5516a28ef2SGary Jennejohn 		/* There's always one entry more than the number of commas. */
5616a28ef2SGary Jennejohn 		i++;
5716a28ef2SGary Jennejohn 		break;
5816a28ef2SGary Jennejohn 	}
5916a28ef2SGary Jennejohn 	start = (char **)malloc(i * sizeof(char *));
6016a28ef2SGary Jennejohn 	if (start == NULL) {
6116a28ef2SGary Jennejohn 		free(console_args);
6216a28ef2SGary Jennejohn 		return 1;
6316a28ef2SGary Jennejohn 	}
6416a28ef2SGary Jennejohn 	i = 0;
6516a28ef2SGary Jennejohn 	start[0] = console_args;
6616a28ef2SGary Jennejohn 	for (;;) {
6716a28ef2SGary Jennejohn 		temp = strchr(start[i++], ',');
6816a28ef2SGary Jennejohn 		if (temp == NULL)
6916a28ef2SGary Jennejohn 			break;
7016a28ef2SGary Jennejohn 		*temp = '\0';
7116a28ef2SGary Jennejohn 		start[i] = temp + 1;
7216a28ef2SGary Jennejohn 	}
7352cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	cons_set = (struct stdio_dev **)calloc(i, sizeof(struct stdio_dev *));
7416a28ef2SGary Jennejohn 	if (cons_set == NULL) {
7516a28ef2SGary Jennejohn 		free(start);
7616a28ef2SGary Jennejohn 		free(console_args);
7716a28ef2SGary Jennejohn 		return 1;
7816a28ef2SGary Jennejohn 	}
7916a28ef2SGary Jennejohn 
8016a28ef2SGary Jennejohn 	switch (console) {
8116a28ef2SGary Jennejohn 	case stdin:
8216a28ef2SGary Jennejohn 		io_flag = DEV_FLAGS_INPUT;
8316a28ef2SGary Jennejohn 		break;
8416a28ef2SGary Jennejohn 	case stdout:
8516a28ef2SGary Jennejohn 	case stderr:
8616a28ef2SGary Jennejohn 		io_flag = DEV_FLAGS_OUTPUT;
8716a28ef2SGary Jennejohn 		break;
8816a28ef2SGary Jennejohn 	default:
8916a28ef2SGary Jennejohn 		free(start);
9016a28ef2SGary Jennejohn 		free(console_args);
9116a28ef2SGary Jennejohn 		free(cons_set);
9216a28ef2SGary Jennejohn 		return 1;
9316a28ef2SGary Jennejohn 	}
9416a28ef2SGary Jennejohn 
9516a28ef2SGary Jennejohn 	cs_idx = 0;
9616a28ef2SGary Jennejohn 	for (j = 0; j < i; j++) {
9716a28ef2SGary Jennejohn 		/*
9816a28ef2SGary Jennejohn 		 * Check whether the device exists and is valid.
9916a28ef2SGary Jennejohn 		 * console_assign() also calls search_device(),
10016a28ef2SGary Jennejohn 		 * but I need the pointer to the device.
10116a28ef2SGary Jennejohn 		 */
10216a28ef2SGary Jennejohn 		dev = search_device(io_flag, start[j]);
10316a28ef2SGary Jennejohn 		if (dev == NULL)
10416a28ef2SGary Jennejohn 			continue;
10516a28ef2SGary Jennejohn 		/*
10616a28ef2SGary Jennejohn 		 * Prevent multiple entries for a device.
10716a28ef2SGary Jennejohn 		 */
10816a28ef2SGary Jennejohn 		 repeat = 0;
10916a28ef2SGary Jennejohn 		 for (k = 0; k < cs_idx; k++) {
11016a28ef2SGary Jennejohn 			if (dev == cons_set[k]) {
11116a28ef2SGary Jennejohn 				repeat++;
11216a28ef2SGary Jennejohn 				break;
11316a28ef2SGary Jennejohn 			}
11416a28ef2SGary Jennejohn 		 }
11516a28ef2SGary Jennejohn 		 if (repeat)
11616a28ef2SGary Jennejohn 			continue;
11716a28ef2SGary Jennejohn 		/*
11816a28ef2SGary Jennejohn 		 * Try assigning the specified device.
11916a28ef2SGary Jennejohn 		 * This could screw up the console settings for apps.
12016a28ef2SGary Jennejohn 		 */
12116a28ef2SGary Jennejohn 		if (console_assign(console, start[j]) < 0)
12216a28ef2SGary Jennejohn 			continue;
12316a28ef2SGary Jennejohn 		cons_set[cs_idx++] = dev;
12416a28ef2SGary Jennejohn 	}
12516a28ef2SGary Jennejohn 	free(console_args);
12616a28ef2SGary Jennejohn 	free(start);
12716a28ef2SGary Jennejohn 	/* failed to set any console */
12816a28ef2SGary Jennejohn 	if (cs_idx == 0) {
12916a28ef2SGary Jennejohn 		free(cons_set);
13016a28ef2SGary Jennejohn 		return 1;
13116a28ef2SGary Jennejohn 	} else {
13216a28ef2SGary Jennejohn 		/* Works even if console_devices[console] is NULL. */
13316a28ef2SGary Jennejohn 		console_devices[console] =
13452cb4d4fSJean-Christophe PLAGNIOL-VILLARD 			(struct stdio_dev **)realloc(console_devices[console],
13552cb4d4fSJean-Christophe PLAGNIOL-VILLARD 			cs_idx * sizeof(struct stdio_dev *));
13616a28ef2SGary Jennejohn 		if (console_devices[console] == NULL) {
13716a28ef2SGary Jennejohn 			free(cons_set);
13816a28ef2SGary Jennejohn 			return 1;
13916a28ef2SGary Jennejohn 		}
14016a28ef2SGary Jennejohn 		memcpy(console_devices[console], cons_set, cs_idx *
14152cb4d4fSJean-Christophe PLAGNIOL-VILLARD 			sizeof(struct stdio_dev *));
14216a28ef2SGary Jennejohn 
14316a28ef2SGary Jennejohn 		cd_count[console] = cs_idx;
14416a28ef2SGary Jennejohn 	}
14516a28ef2SGary Jennejohn 	free(cons_set);
14616a28ef2SGary Jennejohn 	return 0;
14716a28ef2SGary Jennejohn }
14816a28ef2SGary Jennejohn #endif /* CONFIG_CONSOLE_MUX */
149