xref: /openbmc/u-boot/common/iomux.c (revision 52cb4d4fb3487313f5a72ea740f527a4aefaa365)
116a28ef2SGary Jennejohn /*
216a28ef2SGary Jennejohn  * (C) Copyright 2008
316a28ef2SGary Jennejohn  * Gary Jennejohn, DENX Software Engineering GmbH, garyj@denx.de.
416a28ef2SGary Jennejohn  *
516a28ef2SGary Jennejohn  * See file CREDITS for list of people who contributed to this
616a28ef2SGary Jennejohn  * project.
716a28ef2SGary Jennejohn  *
816a28ef2SGary Jennejohn  * This program is free software; you can redistribute it and/or
916a28ef2SGary Jennejohn  * modify it under the terms of the GNU General Public License as
1016a28ef2SGary Jennejohn  * published by the Free Software Foundation; either version 2 of
1116a28ef2SGary Jennejohn  * the License, or (at your option) any later version.
1216a28ef2SGary Jennejohn  *
1316a28ef2SGary Jennejohn  * This program is distributed in the hope that it will be useful,
1416a28ef2SGary Jennejohn  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1516a28ef2SGary Jennejohn  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
1616a28ef2SGary Jennejohn  * GNU General Public License for more details.
1716a28ef2SGary Jennejohn  *
1816a28ef2SGary Jennejohn  * You should have received a copy of the GNU General Public License
1916a28ef2SGary Jennejohn  * along with this program; if not, write to the Free Software
2016a28ef2SGary Jennejohn  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
2116a28ef2SGary Jennejohn  * MA 02111-1307 USA
2216a28ef2SGary Jennejohn  */
2316a28ef2SGary Jennejohn 
2416a28ef2SGary Jennejohn #include <common.h>
2516a28ef2SGary Jennejohn #include <serial.h>
2616a28ef2SGary Jennejohn #include <malloc.h>
2716a28ef2SGary Jennejohn 
2816a28ef2SGary Jennejohn #ifdef CONFIG_CONSOLE_MUX
2916a28ef2SGary Jennejohn void iomux_printdevs(const int console)
3016a28ef2SGary Jennejohn {
3116a28ef2SGary Jennejohn 	int i;
32*52cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	struct stdio_dev *dev;
3316a28ef2SGary Jennejohn 
3416a28ef2SGary Jennejohn 	for (i = 0; i < cd_count[console]; i++) {
3516a28ef2SGary Jennejohn 		dev = console_devices[console][i];
3616a28ef2SGary Jennejohn 		printf("%s ", dev->name);
3716a28ef2SGary Jennejohn 	}
3816a28ef2SGary Jennejohn 	printf("\n");
3916a28ef2SGary Jennejohn }
4016a28ef2SGary Jennejohn 
4116a28ef2SGary Jennejohn /* This tries to preserve the old list if an error occurs. */
4216a28ef2SGary Jennejohn int iomux_doenv(const int console, const char *arg)
4316a28ef2SGary Jennejohn {
4416a28ef2SGary Jennejohn 	char *console_args, *temp, **start;
4516a28ef2SGary Jennejohn 	int i, j, k, io_flag, cs_idx, repeat;
46*52cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	struct stdio_dev *dev;
47*52cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	struct stdio_dev **cons_set;
4816a28ef2SGary Jennejohn 
4916a28ef2SGary Jennejohn 	console_args = strdup(arg);
5016a28ef2SGary Jennejohn 	if (console_args == NULL)
5116a28ef2SGary Jennejohn 		return 1;
5216a28ef2SGary Jennejohn 	/*
5316a28ef2SGary Jennejohn 	 * Check whether a comma separated list of devices was
5416a28ef2SGary Jennejohn 	 * entered and count how many devices were entered.
5516a28ef2SGary Jennejohn 	 * The array start[] has pointers to the beginning of
5616a28ef2SGary Jennejohn 	 * each device name (up to MAX_CONSARGS devices).
5716a28ef2SGary Jennejohn 	 *
5816a28ef2SGary Jennejohn 	 * Have to do this twice - once to count the number of
5916a28ef2SGary Jennejohn 	 * commas and then again to populate start.
6016a28ef2SGary Jennejohn 	 */
6116a28ef2SGary Jennejohn 	i = 0;
6216a28ef2SGary Jennejohn 	temp = console_args;
6316a28ef2SGary Jennejohn 	for (;;) {
6416a28ef2SGary Jennejohn 		temp = strchr(temp, ',');
6516a28ef2SGary Jennejohn 		if (temp != NULL) {
6616a28ef2SGary Jennejohn 			i++;
6716a28ef2SGary Jennejohn 			temp++;
6816a28ef2SGary Jennejohn 			continue;
6916a28ef2SGary Jennejohn 		}
7016a28ef2SGary Jennejohn 		/* There's always one entry more than the number of commas. */
7116a28ef2SGary Jennejohn 		i++;
7216a28ef2SGary Jennejohn 		break;
7316a28ef2SGary Jennejohn 	}
7416a28ef2SGary Jennejohn 	start = (char **)malloc(i * sizeof(char *));
7516a28ef2SGary Jennejohn 	if (start == NULL) {
7616a28ef2SGary Jennejohn 		free(console_args);
7716a28ef2SGary Jennejohn 		return 1;
7816a28ef2SGary Jennejohn 	}
7916a28ef2SGary Jennejohn 	i = 0;
8016a28ef2SGary Jennejohn 	start[0] = console_args;
8116a28ef2SGary Jennejohn 	for (;;) {
8216a28ef2SGary Jennejohn 		temp = strchr(start[i++], ',');
8316a28ef2SGary Jennejohn 		if (temp == NULL)
8416a28ef2SGary Jennejohn 			break;
8516a28ef2SGary Jennejohn 		*temp = '\0';
8616a28ef2SGary Jennejohn 		start[i] = temp + 1;
8716a28ef2SGary Jennejohn 	}
88*52cb4d4fSJean-Christophe PLAGNIOL-VILLARD 	cons_set = (struct stdio_dev **)calloc(i, sizeof(struct stdio_dev *));
8916a28ef2SGary Jennejohn 	if (cons_set == NULL) {
9016a28ef2SGary Jennejohn 		free(start);
9116a28ef2SGary Jennejohn 		free(console_args);
9216a28ef2SGary Jennejohn 		return 1;
9316a28ef2SGary Jennejohn 	}
9416a28ef2SGary Jennejohn 
9516a28ef2SGary Jennejohn 	switch (console) {
9616a28ef2SGary Jennejohn 	case stdin:
9716a28ef2SGary Jennejohn 		io_flag = DEV_FLAGS_INPUT;
9816a28ef2SGary Jennejohn 		break;
9916a28ef2SGary Jennejohn 	case stdout:
10016a28ef2SGary Jennejohn 	case stderr:
10116a28ef2SGary Jennejohn 		io_flag = DEV_FLAGS_OUTPUT;
10216a28ef2SGary Jennejohn 		break;
10316a28ef2SGary Jennejohn 	default:
10416a28ef2SGary Jennejohn 		free(start);
10516a28ef2SGary Jennejohn 		free(console_args);
10616a28ef2SGary Jennejohn 		free(cons_set);
10716a28ef2SGary Jennejohn 		return 1;
10816a28ef2SGary Jennejohn 	}
10916a28ef2SGary Jennejohn 
11016a28ef2SGary Jennejohn 	cs_idx = 0;
11116a28ef2SGary Jennejohn 	for (j = 0; j < i; j++) {
11216a28ef2SGary Jennejohn 		/*
11316a28ef2SGary Jennejohn 		 * Check whether the device exists and is valid.
11416a28ef2SGary Jennejohn 		 * console_assign() also calls search_device(),
11516a28ef2SGary Jennejohn 		 * but I need the pointer to the device.
11616a28ef2SGary Jennejohn 		 */
11716a28ef2SGary Jennejohn 		dev = search_device(io_flag, start[j]);
11816a28ef2SGary Jennejohn 		if (dev == NULL)
11916a28ef2SGary Jennejohn 			continue;
12016a28ef2SGary Jennejohn 		/*
12116a28ef2SGary Jennejohn 		 * Prevent multiple entries for a device.
12216a28ef2SGary Jennejohn 		 */
12316a28ef2SGary Jennejohn 		 repeat = 0;
12416a28ef2SGary Jennejohn 		 for (k = 0; k < cs_idx; k++) {
12516a28ef2SGary Jennejohn 			if (dev == cons_set[k]) {
12616a28ef2SGary Jennejohn 				repeat++;
12716a28ef2SGary Jennejohn 				break;
12816a28ef2SGary Jennejohn 			}
12916a28ef2SGary Jennejohn 		 }
13016a28ef2SGary Jennejohn 		 if (repeat)
13116a28ef2SGary Jennejohn 			continue;
13216a28ef2SGary Jennejohn 		/*
13316a28ef2SGary Jennejohn 		 * Try assigning the specified device.
13416a28ef2SGary Jennejohn 		 * This could screw up the console settings for apps.
13516a28ef2SGary Jennejohn 		 */
13616a28ef2SGary Jennejohn 		if (console_assign(console, start[j]) < 0)
13716a28ef2SGary Jennejohn 			continue;
13816a28ef2SGary Jennejohn #ifdef CONFIG_SERIAL_MULTI
13916a28ef2SGary Jennejohn 		/*
14016a28ef2SGary Jennejohn 		 * This was taken from common/cmd_nvedit.c.
14116a28ef2SGary Jennejohn 		 * This will never work because serial_assign() returns
14216a28ef2SGary Jennejohn 		 * 1 upon error, not -1.
14316a28ef2SGary Jennejohn 		 * This would almost always return an error anyway because
14416a28ef2SGary Jennejohn 		 * serial_assign() expects the name of a serial device, like
14516a28ef2SGary Jennejohn 		 * serial_smc, but the user generally only wants to set serial.
14616a28ef2SGary Jennejohn 		 */
14716a28ef2SGary Jennejohn 		if (serial_assign(start[j]) < 0)
14816a28ef2SGary Jennejohn 			continue;
14916a28ef2SGary Jennejohn #endif
15016a28ef2SGary Jennejohn 		cons_set[cs_idx++] = dev;
15116a28ef2SGary Jennejohn 	}
15216a28ef2SGary Jennejohn 	free(console_args);
15316a28ef2SGary Jennejohn 	free(start);
15416a28ef2SGary Jennejohn 	/* failed to set any console */
15516a28ef2SGary Jennejohn 	if (cs_idx == 0) {
15616a28ef2SGary Jennejohn 		free(cons_set);
15716a28ef2SGary Jennejohn 		return 1;
15816a28ef2SGary Jennejohn 	} else {
15916a28ef2SGary Jennejohn 		/* Works even if console_devices[console] is NULL. */
16016a28ef2SGary Jennejohn 		console_devices[console] =
161*52cb4d4fSJean-Christophe PLAGNIOL-VILLARD 			(struct stdio_dev **)realloc(console_devices[console],
162*52cb4d4fSJean-Christophe PLAGNIOL-VILLARD 			cs_idx * sizeof(struct stdio_dev *));
16316a28ef2SGary Jennejohn 		if (console_devices[console] == NULL) {
16416a28ef2SGary Jennejohn 			free(cons_set);
16516a28ef2SGary Jennejohn 			return 1;
16616a28ef2SGary Jennejohn 		}
16716a28ef2SGary Jennejohn 		memcpy(console_devices[console], cons_set, cs_idx *
168*52cb4d4fSJean-Christophe PLAGNIOL-VILLARD 			sizeof(struct stdio_dev *));
16916a28ef2SGary Jennejohn 
17016a28ef2SGary Jennejohn 		cd_count[console] = cs_idx;
17116a28ef2SGary Jennejohn 	}
17216a28ef2SGary Jennejohn 	free(cons_set);
17316a28ef2SGary Jennejohn 	return 0;
17416a28ef2SGary Jennejohn }
17516a28ef2SGary Jennejohn #endif /* CONFIG_CONSOLE_MUX */
176