本文共 2510 字,大约阅读时间需要 8 分钟。
int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console)这个函数用于parse bios 传递过来的spcr表,来设置串口输出其源码分析如下:int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console){ static char opts[64]; struct acpi_table_spcr *table; acpi_status status; char *uart; char *iotype; int baud_rate; int err; if (acpi_disabled) return -ENODEV; #首先找到SPCR这个表的指针 status = acpi_get_table(ACPI_SIG_SPCR, 0, (struct acpi_table_header **)&table); if (ACPI_FAILURE(status)) return -ENOENT; #如果spcr 版本小于2则退出 if (table->header.revision < 2) pr_info("SPCR table version %d\n", table->header.revision); #根据space_id 来决定uart使用的io是16/32 bits if (table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { switch (ACPI_ACCESS_BIT_WIDTH(( table->serial_port.access_width))) { default: pr_err("Unexpected SPCR Access Width. Defaulting to byte size\n"); /* fall through */ case 8: iotype = "mmio"; break; case 16: iotype = "mmio16"; break; case 32: iotype = "mmio32"; break; } } else iotype = "io"; #设置uart确定的name,这里就是给uart这个字符串赋值 switch (table->interface_type) { case ACPI_DBG2_ARM_SBSA_32BIT: iotype = "mmio32"; /* fall through */ case ACPI_DBG2_ARM_PL011: case ACPI_DBG2_ARM_SBSA_GENERIC: case ACPI_DBG2_BCM2835: uart = "pl011"; break; case ACPI_DBG2_16550_COMPATIBLE: case ACPI_DBG2_16550_SUBSET: uart = "uart"; break; default: err = -ENOENT; goto done; } #根据spcr 来决定波特率 switch (table->baud_rate) { case 3: baud_rate = 9600; break; case 4: baud_rate = 19200; break; case 6: baud_rate = 57600; break; case 7: baud_rate = 115200; break; default: err = -ENOENT; goto done; } #这两款驱动有bug,这里是修复bug if (qdf2400_erratum_44_present(&table->header)) { qdf2400_e44_present = true; if (enable_earlycon) uart = "qdf2400_e44"; } if (xgene_8250_erratum_present(table)) { iotype = "mmio32"; /* for xgene v1 and v2 we don't know the clock rate of the * UART so don't attempt to change to the baud rate state * in the table because driver cannot calculate the dividers */ snprintf(opts, sizeof(opts), "%s,%s,0x%llx", uart, iotype, table->serial_port.address); } else { snprintf(opts, sizeof(opts), "%s,%s,0x%llx,%d", uart, iotype, table->serial_port.address, baud_rate); }#从开机log中可以看到console这个子串 pr_info("console: %s\n", opts);#是否使用earlycon if (enable_earlycon) setup_earlycon(opts);#添加preferr console if (enable_console) err = add_preferred_console(uart, 0, opts + strlen(uart) + 1); else err = 0;done: acpi_put_table((struct acpi_table_header *)table); return err;}
转载地址:http://ncnmi.baihongyu.com/