[U-Boot] [PATCH v2] NS16550: buffer reads

Graeme Russ graeme.russ at gmail.com
Wed Oct 26 11:18:41 CEST 2011


Hi Wolfgang,

On 26/10/11 18:00, Wolfgang Denk wrote:
> Dear Graeme,
> 
> In message <CALButCKQ_bgpOZquozzQnU01v41Y+uWo8ELLNqSE15D30p52ug at mail.gmail.com> you wrote:
>>
>> Well, I have the feeling than an console API might be in order. The way
>> U-Boot is structured at the moment, serial I/O is kind of taken for
>> granted to 'just exist' and nobody needs to really be self-aware that
>> they use it...
> 
> Indeed. All we need is a working set of srdin/stdout/stderr.  Keep in
> mind that anything couldbe attached - not only a serial line.
> 
>>           ... The same cannot be said of users of USB and Network -
>> Net is a good example - all 'users' of net call NetLoop() which does
>> an eth_init()...do stuff...eth_halt()
> 
> Driver API...
> 
>> So maybe a serial API which 'users' must 'wake up' and 'sleep'...
> 
> Arghhh...
> 
>>  - console_configure() - Set parameters (port, baud rate etc)
>>  - console_wake() - Prepare the console (could be serial, USB, netconsole)
>>  - console_flush() - Throw away any buffered characters
>>  - console_getc(), console_putc(), console_tstc() - Self explainatory
>>  - console_sleep() - Shut the console down (send XOFF, turn of USB etc)
> 
> Forget it.  We will not have a separate and completely non-standard "serial API".
> If anything gets changed here, then in the context of a general driver
> API cleanup, or at least based on a design for such a generic driver
> API.

Funny, I wrote that without the code in front of me. But look at this...

struct serial_device {
	char name[NAMESIZE];

	int  (*init) (void);
	int  (*uninit) (void);
	void (*setbrg) (void);
	int (*getc) (void);
	int (*tstc) (void);
	void (*putc) (const char c);
	void (*puts) (const char *s);
#if CONFIG_POST & CONFIG_SYS_POST_UART
	void (*loop) (int);
#endif

	struct serial_device *next;
};

and

struct stdio_dev {
	int	flags;		/* Device flags: input/output/system	*/
	int	ext;		/* Supported extensions			*/
	char	name[16]	/* Device name				*/

/* GENERAL functions */

	int (*start) (void);	/* To start the device		*/
	int (*stop) (void);	/* To stop the device		*/

/* OUTPUT functions */

	void (*putc) (const char c);	/* To put a char	*/
	void (*puts) (const char *s);	/* To put a string	*/

/* INPUT functions */

	int (*tstc) (void);		/* To test if a char is ready...*/
	int (*getc) (void);		/* To get that char		*/

/* Other functions */

	void *priv;			/* Private extensions		*/
	struct list_head list;
};

and

void serial_stdio_init (void)
{
	struct stdio_dev dev;
	struct serial_device *s = serial_devices;

	while (s) {
		memset (&dev, 0, sizeof (dev));

		strcpy (dev.name, s->name);
		dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT;

		dev.start = s->init;
		dev.stop = s->uninit;
		dev.putc = s->putc;
		dev.puts = s->puts;
		dev.getc = s->getc;
		dev.tstc = s->tstc;

		stdio_register (&dev);

		s = s->next;
	}
}

and mpc512x has this gem

int close_port(int num)
{
	struct stdio_dev *port;
	int ret;
	char name[7];

	if (num < 0 || num > 11)
		return -1;

	sprintf(name, "psc%d", num);
	port = stdio_get_by_name(name);
	if (!port)
		return -1;

	ret = port->stop();
	clear_bit(num, &initialized);

	return ret;
}

stdio_dev->start() is called in console_setfile() which is called by
console_init_r(). stdio_dev->stop() is never called apart from in the above
mpc512x example.

As I said, stdio is, unlike other devices, taken for granted - It gets
setup during console_init_r() and is assumed to be in-volatile from then on.

So the hooks are already there - All that would be needed is a hook to
allow console users to ultimately call stdio_dev->start when they want to
start using stdio and stdio_dev->stop when they are finished. Of course the
physical device itself is hidden and could be serial, USB, Ethernet, VGA,
Braille display - whatever.

Hmmm, stdio_open() and stdio_close()

>> UART like your SPI example. The command line interpreter calls
>> console_sleep() to release the serial UART resource before the command
>> which uses the multiplexed device wakes that device, does it's thing and
>> shuts the device down before returning to the command line interpreter
>> which wakes up the serial UART...
> 
> Sorry, but that's crappy by design.

When resources are tight - The eNET board has 8-bit CF ports instead of 16
bit because of board space and FPGA limitation which necessitated a slight
mod to the Linux CF driver. Crappy yes, but hey, when given lemons

Regards,

Graeme


More information about the U-Boot mailing list