if (!strncmp(s, "ttyS", 4))
s += 4;
port = simple_strtoul(s, &e, 10); if (port > 1 || s == e)
port = 0;
early_serial_base = bases[port];
}
s += strcspn(s, ","); if (*s == ',')
s++;
}
if (*s) {
baud = simple_strtoull(s, &e, 0);
if (baud == 0 || s == e)
baud = DEFAULT_BAUD;
}
/* Convert from baud to divisor value */
divisor = 115200 / baud;
/* Set up the HW */
early_serial_hw_init(divisor);
}
static __noendbr void mem32_serial_out(unsignedlong addr, int offset, int value)
{
u32 __iomem *vaddr = (u32 __iomem *)addr; /* shift implied by pointer type */
writel(value, vaddr + offset);
}
ANNOTATE_NOENDBR_SYM(mem32_serial_out);
static __noendbr unsignedint mem32_serial_in(unsignedlong addr, int offset)
{
u32 __iomem *vaddr = (u32 __iomem *)addr; /* shift implied by pointer type */ return readl(vaddr + offset);
}
ANNOTATE_NOENDBR_SYM(mem32_serial_in);
/* * early_mmio_serial_init() - Initialize MMIO-based early serial console. * @s: MMIO-based serial specification.
*/ static __init void early_mmio_serial_init(char *s)
{ unsignedlong baudrate; unsignedlong membase; char *e;
if (*s == ',')
s++;
if (!strncmp(s, "0x", 2)) { /* NB: only 32-bit addresses are supported. */
membase = simple_strtoul(s, &e, 16);
early_serial_base = (unsignedlong)early_ioremap(membase, PAGE_SIZE);
if (!strncmp(s, "nocfg", 5)) {
baudrate = 0;
} else {
baudrate = simple_strtoul(s, &e, 0); if (baudrate == 0 || s == e)
baudrate = DEFAULT_BAUD;
}
if (baudrate)
early_serial_hw_init(115200 / baudrate);
}
#ifdef CONFIG_PCI /* * early_pci_serial_init() * * This function is invoked when the early_printk param starts with "pciserial" * The rest of the param should be "[force],B:D.F,baud", where B, D & F describe * the location of a PCI device that must be a UART device. "force" is optional * and overrides the use of an UART device with a wrong PCI class code.
*/ static __init void early_pci_serial_init(char *s)
{ unsigned divisor; unsignedlong baud = DEFAULT_BAUD;
u8 bus, slot, func;
u32 classcode, bar0;
u16 cmdreg; char *e; int force = 0;
if (*s == ',')
++s;
if (*s == 0) return;
/* Force the use of an UART device with wrong class code */ if (!strncmp(s, "force,", 6)) {
force = 1;
s += 6;
}
/* * Part the param to get the BDF values
*/
bus = (u8)simple_strtoul(s, &e, 16);
s = e; if (*s != ':') return;
++s;
slot = (u8)simple_strtoul(s, &e, 16);
s = e; if (*s != '.') return;
++s;
func = (u8)simple_strtoul(s, &e, 16);
s = e;
/* A baud might be following */ if (*s == ',')
s++;
/* * Find the device from the BDF
*/
cmdreg = read_pci_config(bus, slot, func, PCI_COMMAND);
classcode = read_pci_config(bus, slot, func, PCI_CLASS_REVISION);
bar0 = read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_0);
/* * Verify it is a 16550-UART type device
*/ if (((classcode >> 16 != PCI_CLASS_COMMUNICATION_MODEM) &&
(classcode >> 16 != PCI_CLASS_COMMUNICATION_SERIAL)) ||
(((classcode >> 8) & 0xff) != PCI_SERIAL_16550_COMPATIBLE)) { if (!force) return;
}
/* * Determine if it is IO or memory mapped
*/ if ((bar0 & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { /* it is IO mapped */
early_serial_base = bar0 & PCI_BASE_ADDRESS_IO_MASK;
write_pci_config(bus, slot, func, PCI_COMMAND,
cmdreg|PCI_COMMAND_IO);
} else { /* It is memory mapped - assume 32-bit alignment */
static_call_update(serial_in, mem32_serial_in);
static_call_update(serial_out, mem32_serial_out); /* WARNING! assuming the address is always in the first 4G */
early_serial_base =
(unsignedlong)early_ioremap(bar0 & PCI_BASE_ADDRESS_MEM_MASK, 0x10); #ifdefined(CONFIG_KEXEC_CORE) && defined(CONFIG_X86_64)
kexec_debug_8250_mmio32 = bar0 & PCI_BASE_ADDRESS_MEM_MASK; #endif
write_pci_config(bus, slot, func, PCI_COMMAND,
cmdreg|PCI_COMMAND_MEMORY);
}
/* * Initialize the hardware
*/ if (*s) { if (strcmp(s, "nocfg") == 0) /* Sometimes, we want to leave the UART alone * and assume the BIOS has set it up correctly. * "nocfg" tells us this is the case, and we * should do no more setup.
*/ return; if (kstrtoul(s, 0, &baud) < 0 || baud == 0)
baud = DEFAULT_BAUD;
}
/* Convert from baud to divisor value */
divisor = 115200 / baud;
/* Set up the HW */
early_serial_hw_init(divisor);
} #endif
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.