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