drivers/tty/hvc/hvc_opal.c

Source file repositories/reference/linux-study-clean/drivers/tty/hvc/hvc_opal.c

File Facts

System
Linux kernel
Corpus path
drivers/tty/hvc/hvc_opal.c
Extension
.c
Size
10173 bytes
Lines
418
Domain
Driver Families
Bucket
drivers/tty
Inferred role
Driver Families: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

device_initcall(hvc_opal_init);

static void udbg_opal_putc(char c)
{
	unsigned int termno = hvc_opal_boot_termno;
	int count = -1;

	if (c == '\n')
		udbg_opal_putc('\r');

	do {
		switch(hvc_opal_boot_priv.proto) {
		case HV_PROTOCOL_RAW:
			count = opal_put_chars(termno, &c, 1);
			break;
		case HV_PROTOCOL_HVSI:
			count = hvc_opal_hvsi_put_chars(termno, &c, 1);
			break;
		}

		/* This is needed for the cosole to flush
		 * when there aren't any interrupts.
		 */
		opal_flush_console(termno);
	} while(count == 0 || count == -EAGAIN);
}

static int udbg_opal_getc_poll(void)
{
	unsigned int termno = hvc_opal_boot_termno;
	int rc = 0;
	char c;

	switch(hvc_opal_boot_priv.proto) {
	case HV_PROTOCOL_RAW:
		rc = opal_get_chars(termno, &c, 1);
		break;
	case HV_PROTOCOL_HVSI:
		rc = hvc_opal_hvsi_get_chars(termno, &c, 1);
		break;
	}
	if (!rc)
		return -1;
	return c;
}

static int udbg_opal_getc(void)
{
	int ch;
	for (;;) {
		ch = udbg_opal_getc_poll();
		if (ch != -1)
			return ch;
	}
}

static void udbg_init_opal_common(void)
{
	udbg_putc = udbg_opal_putc;
	udbg_getc = udbg_opal_getc;
	udbg_getc_poll = udbg_opal_getc_poll;
}

void __init hvc_opal_init_early(void)
{
	struct device_node *stdout_node = of_node_get(of_stdout);
	const __be32 *termno;
	const struct hv_ops *ops;
	u32 index;

	/* If the console wasn't in /chosen, try /ibm,opal */
	if (!stdout_node) {
		struct device_node *opal, *np;

		/* Current OPAL takeover doesn't provide the stdout
		 * path, so we hard wire it
		 */
		opal = of_find_node_by_path("/ibm,opal/consoles");
		if (opal) {
			pr_devel("hvc_opal: Found consoles in new location\n");
		} else {
			opal = of_find_node_by_path("/ibm,opal");
			if (opal)
				pr_devel("hvc_opal: "
					 "Found consoles in old location\n");
		}
		if (!opal)
			return;
		for_each_child_of_node(opal, np) {
			if (of_node_name_eq(np, "serial")) {

Annotation

Implementation Notes