RE: [PATCH u-boot 4/4] eth/r8152: support RTL8153B/RTL8154B
Marek Vasut [mailto:ma...@denx.de] > Sent: Friday, June 12, 2020 7:53 PM [...] > Try this: > > ocp_data = r8152_efuse_read(tp, 0x7d); > ocp_data = (ocp_data & 0x1fff0) >> 1) | (ocp_data & 0x7); > if (data != 0x) > ocp_reg_write(tp, OCP_ADC_IOFFSET, data); I think you mean ocp_data = r8152_efuse_read(tp, 0x7d); ocp_data = ((ocp_data & 0x1fff0) >> 1) | (ocp_data & 0x7); if (ocp_data != 0x) ocp_reg_write(tp, OCP_ADC_IOFFSET, ocp_data); > That should work, no ? Or does it generate compiler warnings ? It shows no warning. Best Regards, Hayes
Re: [PATCH 0/2] omap4: panda: convert to device model
On 14/06/2020 16:49, Lokesh Vutla wrote: Hi Tero, On 02/06/20 4:49 pm, Tero Kristo wrote: Hi, As there is looming death to OMAP4 Panda board u-boot support, I decided to take a shot and convert it to device model myself. With these patches it boots up fine, and there are no DM_SPL conversion complaints during compile time anymore. I think USB ethernet does not work anymore with this, but its better than dropping the support for the board completely. USB itself appears working, so it should be relatively easy for someone to fix the networking support if they need it. I see the below warning with these patches: board/ti/panda/panda.c:329:35: warning: ‘struct ehci_hcor’ declared inside parameter list will not be visible outside of this definition or declaration 329 | struct ehci_hccr **hccr, struct ehci_hcor **hcor) | ^ board/ti/panda/panda.c:329:10: warning: ‘struct ehci_hccr’ declared inside parameter list will not be visible outside of this definition or declaration 329 | struct ehci_hccr **hccr, struct ehci_hcor **hcor) | ^ board/ti/panda/panda.c: In function ‘ehci_hcd_init’: board/ti/panda/panda.c:339:8: warning: implicit declaration of function ‘omap_ehci_hcd_init’; did you mean ‘ehci_hcd_init’? [-Wimplicit-function-declaration] 339 | ret = omap_ehci_hcd_init(index, &usbhs_bdata, hccr, hcor); |^~ |ehci_hcd_init board/ti/panda/panda.c: In function ‘ehci_hcd_stop’: board/ti/panda/panda.c:348:9: warning: implicit declaration of function ‘omap_ehci_hcd_stop’; did you mean ‘ehci_hcd_stop’? [-Wimplicit-function-declaration] 348 | return omap_ehci_hcd_stop(); | ^~ | ehci_hcd_stop Yeah, I actually see these also. I think we could maybe drop all the offending code as I did later with the omap5-uevm. On omap5, USB seemed to work even without these. Maybe some USB expert can comment on these (Vignesh)? -Tero Thanks and regards, Lokesh -Tero -- -- Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
Re: [PATCH] net: eth-uclass: Fix message if mac is coming from DT or ROM
Hi Tom, On 12. 06. 20 17:00, Tom Rini wrote: > On Mon, Mar 16, 2020 at 11:39:18AM +0100, Michal Simek wrote: > >> When local-mac-address DT property is specified it is reported the same way >> as address read from eeprom/ROM. Show properly if mac address is coming >> from DT or ROM. >> >> Signed-off-by: Michal Simek > > In looking over the queue of networking patches, I think I prefer > http://patchwork.ozlabs.org/project/uboot/patch/2020060321.9574-3-andre.przyw...@arm.com/ > which just removes the message entirely and is consistent with the > non-DM case. > My patch is already in your tree. The patch you pointed me too is just removing one message. Thanks, Michal
Re: [PATCH] arm: dts: socfpga: l2c-310 full line of zeros error @kernel boot
Am 12.06.2020 um 22:27 schrieb Dinh Nguyen: On 6/12/20 6:41 AM, Marek Vasut wrote: On 6/12/20 1:04 PM, Nico Becker wrote: Am 12.06.2020 um 07:51 schrieb Nico Becker: Am 11.06.2020 um 03:51 schrieb Tan, Ley Foon: -Original Message- From: Dinh Nguyen Sent: Thursday, June 11, 2020 2:55 AM To: Marek Vasut ; Nico Becker ; u-boot@lists.denx.de Cc: simon.k.r.goldschm...@gmail.com; Tan, Ley Foon Subject: Re: [PATCH] arm: dts: socfpga: l2c-310 full line of zeros error @kernel boot On 6/10/20 8:23 AM, Marek Vasut wrote: On 6/10/20 3:21 PM, Nico Becker wrote: Am 10.06.2020 um 15:19 schrieb Marek Vasut: On 6/10/20 3:14 PM, Nico Becker wrote: if i remove the arm,shared-override option in the dts file, the kernel boot without an error. With the option the kernel boots with the following error: dmesg --level=err L2C-310: enabling full line of zeros but not enabled in Cortex-A9 i ve no idea why the parameter have an effect on that. i try several kernels, allays the same behavior. diff --git a/arch/arm/dts/socfpga.dtsi b/arch/arm/dts/socfpga.dtsi index eda558f2fe..c2173416c7 100644 --- a/arch/arm/dts/socfpga.dtsi +++ b/arch/arm/dts/socfpga.dtsi @@ -719,7 +719,6 @@ arm,data-latency = <2 1 1>; prefetch-data = <1>; prefetch-instr = <1>; - arm,shared-override; arm,double-linefill = <1>; arm,double-linefill-incr = <0>; arm,double-linefill-wrap = <1>; Do you use latest u-boot/master or some older version ? Which one? sorry, i forget it. i use v2020.01 Should be OK I think. Hm, I suspect this is another fun with the ACTLR/CPACR registers, like 937db7188e3a5ab8f802eff9b57854189379667a . Ley, any ideas ? I just tested with 2020.07-rc4-00022-gbe79009f3b along with linux v5.7, and I no longer see the error. Yes, I also just tested 2020.04 uboot and 5.4.23-lts kernel, also didn't see this error. What kernel version you are using? Regards Ley Foon hello, i use kernel 4.14.126-rt62-ltsi. greetings i try the u-boot version v2020.07-rc4 without the patch, and everything seems okay, no error at boot. i ve no idea why the error at boot time is gone with the 2020.07-rc4 version. does anyone have any idea why? thanks, greetings You can try git bisect between the two versions to find out which patch caused this. This is the patch that fixed it: commit f62782fb2999dd8109a3ffe9ee0a51e54ab034ab Author: Ley Foon Tan Date: Fri Apr 17 14:45:35 2020 +0800 cache: l2x0: Fix write to incorrect shared-override bit The existing code write bit-0 for shared attribute override enable bit. It should be bit-22 based on cache controller specification [1]. [1] http://infocenter.arm.com/help/topic/com.arm.doc.ddi0246f/DDI0246F_l2c310_r3p2_trm.pdf Signed-off-by: Ley Foon Tan Dinh hello, thanks a lot! i try the git bisect method, i was 13 builds away. next time i check first the changelog greetings
Re: [PATCH 6/6] checkpatch.pl: Request if() instead #ifdef
Hi Akashi, On Sun, 14 Jun 2020 at 20:59, AKASHI Takahiro wrote: > > On Thu, Jun 04, 2020 at 07:39:35PM -0400, Tom Rini wrote: > > On Fri, May 22, 2020 at 04:32:40PM -0600, Simon Glass wrote: > > > > > There is a lot of use of #ifdefs in U-Boot. In an effort reduce this, > > > suggest using the compile-time construct. > > > > > > Signed-off-by: Simon Glass > > > > Applied to u-boot/master, thanks! > > This check is simple, but IMHO, too simple. > It will generate false-positive, or pointless, warnings > for some common use cases. Say, > > In an include header, > #ifdef CONFIG_xxx > extern int foo_data; > int foo(void); > #endif We should try to avoid this in header files. But I sent a patch earlier today to turn off the check for header files and device tree. > > Or in a C file (foo_common.c), > #ifdef CONFIG_xxx_a > int foo_a(void) > ... > #endif > #ifdef CONFIG_xxx_b > int foo_b(void) > ... > #endif > Perhaps the if() could be inside those functions in some cases? > Or, > > struct baa baa_list[] = { > #ifdef CONFIG_xxx > data_xxx, > #endif I'm not sure how to handle this one. > ... > > They are harmless and can be ignored, but also annoying. > Can you sophisticate this check? Yes I agree we should avoid false negatives. It is better not to have a check than have one that is unreliable. > > In addition, if I want to stick to this rule, there can co-exist > an "old" style and "new" style of code in a single file. > (particularly tons of examples in UEFI subsystem) > > How should we deal with this? Convert it? > > Thanks, > -Takahiro Akashi Regards, Simon
[PATCH v1 43/43] acpi: Enable ACPI table generation by default on x86
This should ideally be used by all x86 boards in U-Boot. Enable it by default. If some boards don't use it, the cost is small. Signed-off-by: Simon Glass --- arch/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/Kconfig b/arch/Kconfig index a11f872938..650bc0dbca 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -190,6 +190,7 @@ config X86 imply PCH imply RTC_MC146818 imply IRQ + imply ACPIGEN # Thing to enable for when SPL/TPL are enabled: SPL imply SPL_DM -- 2.27.0.290.gba653c62da-goog
[PATCH v1 42/43] x86: Rename board_final_cleanup() to board_final_init()
This function sounds like something that is called when U-Boot is about to jump to Linux. In fact it is an init function. Rename it to reduce confusion. Signed-off-by: Simon Glass --- arch/x86/cpu/coreboot/coreboot.c | 4 ++-- arch/x86/cpu/cpu.c | 8 arch/x86/cpu/efi/app.c | 2 +- arch/x86/cpu/quark/quark.c | 2 +- arch/x86/lib/fsp/fsp_common.c| 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index d44db1347b..22a93254a9 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -42,7 +42,7 @@ int print_cpuinfo(void) return default_print_cpuinfo(); } -static void board_final_cleanup(void) +static void board_final_init(void) { /* * Un-cache the ROM so the kernel has one @@ -80,7 +80,7 @@ int last_stage_init(void) if (CONFIG_IS_ENABLED(USB_KEYBOARD)) usb_init(); - board_final_cleanup(); + board_final_init(); return 0; } diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 9bc243ebc8..69c14189d1 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -182,10 +182,10 @@ void show_boot_progress(int val) #if !defined(CONFIG_SYS_COREBOOT) && !defined(CONFIG_EFI_STUB) /* - * Implement a weak default function for boards that optionally - * need to clean up the system before jumping to the kernel. + * Implement a weak default function for boards that need to do some final init + * before the system is ready. */ -__weak void board_final_cleanup(void) +__weak void board_final_init(void) { } @@ -193,7 +193,7 @@ int last_stage_init(void) { struct acpi_fadt __maybe_unused *fadt; - board_final_cleanup(); + board_final_init(); if (IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)) { fadt = acpi_find_fadt(); diff --git a/arch/x86/cpu/efi/app.c b/arch/x86/cpu/efi/app.c index 10677ecbc2..f754489784 100644 --- a/arch/x86/cpu/efi/app.c +++ b/arch/x86/cpu/efi/app.c @@ -24,7 +24,7 @@ int print_cpuinfo(void) return default_print_cpuinfo(); } -void board_final_cleanup(void) +void board_final_init(void) { } diff --git a/arch/x86/cpu/quark/quark.c b/arch/x86/cpu/quark/quark.c index ddad02e375..30b4711b9a 100644 --- a/arch/x86/cpu/quark/quark.c +++ b/arch/x86/cpu/quark/quark.c @@ -363,7 +363,7 @@ int arch_misc_init(void) return 0; } -void board_final_cleanup(void) +void board_final_init(void) { struct quark_rcba *rcba; u32 base, val; diff --git a/arch/x86/lib/fsp/fsp_common.c b/arch/x86/lib/fsp/fsp_common.c index 8e3082d4c8..ea52954725 100644 --- a/arch/x86/lib/fsp/fsp_common.c +++ b/arch/x86/lib/fsp/fsp_common.c @@ -47,7 +47,7 @@ int fsp_init_phase_pci(void) return status ? -EPERM : 0; } -void board_final_cleanup(void) +void board_final_init(void) { u32 status; -- 2.27.0.290.gba653c62da-goog
[PATCH v1 41/43] x86: acpi: Correct the version of the MADT
Currently U-Boot implements version 2 but reports version 4. Correct it. Signed-off-by: Simon Glass --- arch/x86/lib/acpi_table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index b6ba547b6a..6e3276c6f6 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -155,7 +155,7 @@ static void acpi_create_madt(struct acpi_madt *madt) /* Fill out header fields */ acpi_fill_header(header, "APIC"); header->length = sizeof(struct acpi_madt); - header->revision = 4; + header->revision = 2; madt->lapic_addr = LAPIC_DEFAULT_BASE; madt->flags = ACPI_MADT_PCAT_COMPAT; -- 2.27.0.290.gba653c62da-goog
[PATCH v1 40/43] x86: Drop setup_pcat_compatibility()
This function does not exist anymore. Drop it from the header file. Signed-off-by: Simon Glass --- arch/x86/include/asm/u-boot-x86.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index bd3f44014c..d732661f6d 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -83,8 +83,6 @@ int default_print_cpuinfo(void); /* Set up a UART which can be used with printch(), printhex8(), etc. */ int setup_internal_uart(int enable); -void setup_pcat_compatibility(void); - void isa_unmap_rom(u32 addr); u32 isa_map_rom(u32 bus_addr, int size); -- 2.27.0.290.gba653c62da-goog
[PATCH v1 38/43] x86: mp: Allow use of mp_run_on_cpus() without MP
At present if MP is not enabled (e.g. booting from coreboot) the 'mtrr' command does not work correctly. It is not easy to make it work for all CPUs, since coreboot has halted them and we would need to start them up again, but it is easy enough to make them work on the boot CPU. Update the code to avoid assuming that the MP init routine has completed, so that this can work. Signed-off-by: Simon Glass --- arch/x86/cpu/mp_init.c | 12 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index ef33a38017..c0ae24686e 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -454,7 +454,7 @@ static int get_bsp(struct udevice **devp, int *cpu_countp) if (cpu_countp) *cpu_countp = ret; - return dev->req_seq; + return dev->req_seq >= 0 ? dev->req_seq : 0; } static struct mp_callback *read_callback(struct mp_callback **slot) @@ -589,9 +589,6 @@ int mp_run_on_cpus(int cpu_select, mp_run_func func, void *arg) int num_cpus; int ret; - if (!(gd->flags & GD_FLG_SMP_INIT)) - return -ENXIO; - ret = get_bsp(&dev, &num_cpus); if (ret < 0) return log_msg_ret("bsp", ret); @@ -601,6 +598,13 @@ int mp_run_on_cpus(int cpu_select, mp_run_func func, void *arg) func(arg); } + if (!(gd->flags & GD_FLG_SMP_INIT)) { + /* Allow use of this function on the BSP only */ + if (cpu_select == MP_SELECT_BSP || !cpu_select) + return 0; + return -ENXIO; + } + /* Allow up to 1 second for all APs to finish */ ret = run_ap_work(&lcb, dev, num_cpus, 1000 /* ms */); if (ret) -- 2.27.0.290.gba653c62da-goog
[PATCH v1 39/43] x86: Update the comment about booting for FSP2
The comment here applies only to FSP1, so update it. Signed-off-by: Simon Glass --- arch/x86/cpu/start.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index 01524635e9..4ad515ce08 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -124,6 +124,7 @@ car_init_ret: #endif #else /* +* Instructions for FSP1, but not FSP2: * U-Boot enters here twice. For the first time it comes from * car_init_done() with esp points to a temporary stack and esi * set to zero. For the second time it comes from fsp_init_done() -- 2.27.0.290.gba653c62da-goog
[PATCH v1 36/43] x86: apl: Adjust FSP-M code to avoid hard-coded address
Update this code to calculate the address to use, rather than hard-coding it. Obtain the requested stack size from the FSP. Signed-off-by: Simon Glass --- arch/x86/cpu/apollolake/fsp_m.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/x86/cpu/apollolake/fsp_m.c b/arch/x86/cpu/apollolake/fsp_m.c index 65461d85b8..cef937573b 100644 --- a/arch/x86/cpu/apollolake/fsp_m.c +++ b/arch/x86/cpu/apollolake/fsp_m.c @@ -24,9 +24,11 @@ int fspm_update_config(struct udevice *dev, struct fspm_upd *upd) cache_ret = prepare_mrc_cache(upd); if (cache_ret && cache_ret != -ENOENT) return log_msg_ret("mrc", cache_ret); - arch->stack_base = (void *)0xfef96000; + arch->stack_base = (void *)(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE - +arch->stack_size); arch->boot_loader_tolum_size = 0; - arch->boot_mode = FSP_BOOT_WITH_FULL_CONFIGURATION; + arch->boot_mode = cache_ret ? FSP_BOOT_WITH_FULL_CONFIGURATION : + FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES; node = dev_ofnode(dev); if (!ofnode_valid(node)) -- 2.27.0.290.gba653c62da-goog
[PATCH v1 37/43] x86: Store the coreboot table address in global_data
At present this information is used to locate and parse the tables but is not stored. Store it so that we can display it to the user, e.g. with the 'bdinfo' command. Signed-off-by: Simon Glass --- arch/x86/cpu/coreboot/tables.c | 8 +++- arch/x86/cpu/i386/cpu.c| 7 ++- arch/x86/include/asm/global_data.h | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/x86/cpu/coreboot/tables.c b/arch/x86/cpu/coreboot/tables.c index a5d31d1dea..1594b4a8b2 100644 --- a/arch/x86/cpu/coreboot/tables.c +++ b/arch/x86/cpu/coreboot/tables.c @@ -10,6 +10,8 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + /* * This needs to be in the .data section so that it's copied over during * relocation. By default it's put in the .bss section which is simply filled @@ -243,6 +245,10 @@ int get_coreboot_info(struct sysinfo_t *info) if (addr < 0) return addr; ret = cb_parse_header((void *)addr, 0x1000, info); + if (!ret) + return -ENOENT; + gd->arch.coreboot_table = addr; + gd->flags |= GD_FLG_SKIP_LL_INIT; - return ret == 1 ? 0 : -ENOENT; + return 0; } diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c index fca3f79b69..8f342dd06e 100644 --- a/arch/x86/cpu/i386/cpu.c +++ b/arch/x86/cpu/i386/cpu.c @@ -456,10 +456,15 @@ int x86_cpu_init_f(void) int x86_cpu_reinit_f(void) { + long addr; + setup_identity(); setup_pci_ram_top(); - if (locate_coreboot_table() >= 0) + addr = locate_coreboot_table(); + if (addr >= 0) { + gd->arch.coreboot_table = addr; gd->flags |= GD_FLG_SKIP_LL_INIT; + } return 0; } diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 5bc251c0dd..3e4044593c 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -123,6 +123,7 @@ struct arch_global_data { #endif void *itss_priv;/* Private ITSS data pointer */ ulong acpi_start; /* Start address of ACPI tables */ + ulong coreboot_table; /* Address of coreboot table */ }; #endif -- 2.27.0.290.gba653c62da-goog
[PATCH v1 35/43] x86: Add debugging to table writing
Writing tables is currently pretty opaque. Add a bit of debugging to the process so we can see what tables are written and where they start/end in memory. Signed-off-by: Simon Glass --- arch/x86/lib/tables.c | 38 -- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/arch/x86/lib/tables.c b/arch/x86/lib/tables.c index 574d331d76..7bad5dd303 100644 --- a/arch/x86/lib/tables.c +++ b/arch/x86/lib/tables.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -20,21 +21,32 @@ */ typedef ulong (*table_write)(ulong addr); -static table_write table_write_funcs[] = { +/** + * struct table_info - Information about each table to write + * + * @name: Name of table (for debugging) + * @write: Function to call to write this table + */ +struct table_info { + const char *name; + table_write write; +}; + +static struct table_info table_list[] = { #ifdef CONFIG_GENERATE_PIRQ_TABLE - write_pirq_routing_table, + { "pirq", write_pirq_routing_table }, #endif #ifdef CONFIG_GENERATE_SFI_TABLE - write_sfi_table, + { "sfi", write_sfi_table, }, #endif #ifdef CONFIG_GENERATE_MP_TABLE - write_mp_table, + { "mp", write_mp_table, }, #endif #ifdef CONFIG_GENERATE_ACPI_TABLE - write_acpi_tables, + { "acpi", write_acpi_tables, }, #endif #ifdef CONFIG_GENERATE_SMBIOS_TABLE - write_smbios_table, + { "smbios", write_smbios_table, }, #endif }; @@ -58,19 +70,22 @@ void write_tables(void) u32 rom_table_end; #ifdef CONFIG_SEABIOS u32 high_table, table_size; - struct memory_area cfg_tables[ARRAY_SIZE(table_write_funcs) + 1]; + struct memory_area cfg_tables[ARRAY_SIZE(table_list) + 1]; #endif int i; - for (i = 0; i < ARRAY_SIZE(table_write_funcs); i++) { - rom_table_end = table_write_funcs[i](rom_table_start); + debug("Writing tables to %x:\n", rom_table_start); + for (i = 0; i < ARRAY_SIZE(table_list); i++) { + const struct table_info *table = &table_list[i]; + + rom_table_end = table->write(rom_table_start); rom_table_end = ALIGN(rom_table_end, ROM_TABLE_ALIGN); #ifdef CONFIG_SEABIOS table_size = rom_table_end - rom_table_start; high_table = (u32)high_table_malloc(table_size); if (high_table) { - table_write_funcs[i](high_table); + table->write(high_table); cfg_tables[i].start = high_table; cfg_tables[i].size = table_size; @@ -79,6 +94,8 @@ void write_tables(void) } #endif + debug("- wrote '%s' to %x, end %x\n", table->name, + rom_table_start, rom_table_end); rom_table_start = rom_table_end; } @@ -87,4 +104,5 @@ void write_tables(void) cfg_tables[i].size = 0; write_coreboot_table(CB_TABLE_ADDR, cfg_tables); #endif + debug("- done writing tables\n"); } -- 2.27.0.290.gba653c62da-goog
[PATCH v1 34/43] x86: apl: Fix save/restore of ITSS priorities
The FSP-S changes the ITSS priorities. The code that tries to save it before running FSP-S and restore it afterwards does not work as U-Boot relocates in between the save and restore. This means that the driver data saved before relocation is lost and the new driver just sees zeroes. Fix this by allocating space in the relocated memory for the ITSS data. Save it there and access it from the driver after relocation. This fixes interrupt handling on coral. Signed-off-by: Simon Glass --- arch/x86/cpu/apollolake/fsp_s.c| 11 +-- arch/x86/cpu/cpu.c | 13 + arch/x86/cpu/intel_common/itss.c | 25 +++-- arch/x86/include/asm/global_data.h | 1 + arch/x86/include/asm/itss.h| 2 +- drivers/misc/irq-uclass.c | 2 +- 6 files changed, 44 insertions(+), 10 deletions(-) diff --git a/arch/x86/cpu/apollolake/fsp_s.c b/arch/x86/cpu/apollolake/fsp_s.c index 3a54297a28..e54b0ac104 100644 --- a/arch/x86/cpu/apollolake/fsp_s.c +++ b/arch/x86/cpu/apollolake/fsp_s.c @@ -160,11 +160,6 @@ int arch_fsps_preinit(void) ret = irq_first_device_type(X86_IRQT_ITSS, &itss); if (ret) return log_msg_ret("no itss", ret); - /* -* Snapshot the current GPIO IRQ polarities. FSP is setting a default -* policy that doesn't honour boards' requirements -*/ - irq_snapshot_polarities(itss); /* * Clear the GPI interrupt status and enable registers. These @@ -203,7 +198,11 @@ int arch_fsp_init_r(void) ret = irq_first_device_type(X86_IRQT_ITSS, &itss); if (ret) return log_msg_ret("no itss", ret); - /* Restore GPIO IRQ polarities back to previous settings */ + + /* +* Restore GPIO IRQ polarities back to previous settings. This was +* stored in reserve_arch() - see X86_IRQT_ITSS +*/ irq_restore_polarities(itss); /* soc_init() */ diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index baa7dae172..9bc243ebc8 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -274,6 +275,9 @@ int cpu_init_r(void) #ifndef CONFIG_EFI_STUB int reserve_arch(void) { + struct udevice *itss; + int ret; + if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) mrccache_reserve(); @@ -291,6 +295,15 @@ int reserve_arch(void) fsp_save_s3_stack(); } } + ret = irq_first_device_type(X86_IRQT_ITSS, &itss); + if (!ret) { + /* +* Snapshot the current GPIO IRQ polarities. FSP-S is about to +* run and will set a default policy that doesn't honour boards' +* requirements +*/ + irq_snapshot_polarities(itss); + } return 0; } diff --git a/arch/x86/cpu/intel_common/itss.c b/arch/x86/cpu/intel_common/itss.c index 963afa8f5b..fe84ebe29f 100644 --- a/arch/x86/cpu/intel_common/itss.c +++ b/arch/x86/cpu/intel_common/itss.c @@ -65,14 +65,23 @@ static int snapshot_polarities(struct udevice *dev) int i; reg_start = start / IRQS_PER_IPC; - reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC; + reg_end = DIV_ROUND_UP(end, IRQS_PER_IPC); + log_info("ITSS IRQ Polarities snapshot %p\n", priv->irq_snapshot); for (i = reg_start; i < reg_end; i++) { uint reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i; priv->irq_snapshot[i] = pcr_read32(dev, reg); + log_debug(" - %d, reg %x: irq_snapshot[i] %x\n", i, reg, + priv->irq_snapshot[i]); } + /* Save the snapshot for use after relocation */ + gd->start_addr_sp -= sizeof(*priv); + gd->start_addr_sp &= ~0xf; + gd->arch.itss_priv = (void *)gd->start_addr_sp; + memcpy(gd->arch.itss_priv, priv, sizeof(*priv)); + return 0; } @@ -91,16 +100,26 @@ static void show_polarities(struct udevice *dev, const char *msg) static int restore_polarities(struct udevice *dev) { struct itss_priv *priv = dev_get_priv(dev); + struct itss_priv *old_priv; const int start = GPIO_IRQ_START; const int end = GPIO_IRQ_END; int reg_start; int reg_end; int i; + /* Get the snapshot which was stored by the pre-reloc device */ + old_priv = gd->arch.itss_priv; + if (!old_priv) + return log_msg_ret("priv", -EFAULT); + memcpy(priv->irq_snapshot, old_priv->irq_snapshot, + sizeof(priv->irq_snapshot)); + show_polarities(dev, "Before"); + log_info("priv->irq_snapshot %p\n", priv->irq_snapshot); reg_start = start / IRQS_PER_IPC; - reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC; + reg_end = DIV_ROUND_UP(end, IRQS_PER_IPC); + for (i = reg_start; i < r
[PATCH v1 33/43] x86: irq: Support flags for acpi_gpe
This binding currently has a flags cell but it is not used. Make use of it to create ACPI tables for interrupts. Signed-off-by: Simon Glass --- arch/x86/cpu/acpi_gpe.c | 26 +++ .../interrupt-controller/x86-irq.h| 14 ++ 2 files changed, 40 insertions(+) create mode 100644 include/dt-bindings/interrupt-controller/x86-irq.h diff --git a/arch/x86/cpu/acpi_gpe.c b/arch/x86/cpu/acpi_gpe.c index 8aa2009bd6..70badb15a3 100644 --- a/arch/x86/cpu/acpi_gpe.c +++ b/arch/x86/cpu/acpi_gpe.c @@ -8,7 +8,10 @@ #include #include #include +#include #include +#include +#include /** * struct acpi_gpe_priv - private driver information @@ -62,13 +65,36 @@ static int acpi_gpe_ofdata_to_platdata(struct udevice *dev) static int acpi_gpe_of_xlate(struct irq *irq, struct ofnode_phandle_args *args) { irq->id = args->args[0]; + irq->flags = args->args[1]; return 0; } +#if CONFIG_IS_ENABLED(ACPIGEN) +static int acpi_gpe_get_acpi(const struct irq *irq, struct acpi_irq *acpi_irq) +{ + memset(acpi_irq, '\0', sizeof(*acpi_irq)); + acpi_irq->pin = irq->id; + acpi_irq->mode = irq->flags & IRQ_TYPE_EDGE_BOTH ? + ACPI_IRQ_EDGE_TRIGGERED : ACPI_IRQ_LEVEL_TRIGGERED; + acpi_irq->polarity = irq->flags & +(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_LEVEL_LOW) ? +ACPI_IRQ_ACTIVE_LOW : ACPI_IRQ_ACTIVE_HIGH; + acpi_irq->shared = irq->flags & X86_IRQ_TYPE_SHARED ? + ACPI_IRQ_SHARED : ACPI_IRQ_EXCLUSIVE; + acpi_irq->wake = irq->flags & X86_IRQ_TYPE_WAKE ? ACPI_IRQ_WAKE : + ACPI_IRQ_NO_WAKE; + + return 0; +} +#endif + static const struct irq_ops acpi_gpe_ops = { .read_and_clear = acpi_gpe_read_and_clear, .of_xlate = acpi_gpe_of_xlate, +#if CONFIG_IS_ENABLED(ACPIGEN) + .get_acpi = acpi_gpe_get_acpi, +#endif }; static const struct udevice_id acpi_gpe_ids[] = { diff --git a/include/dt-bindings/interrupt-controller/x86-irq.h b/include/dt-bindings/interrupt-controller/x86-irq.h new file mode 100644 index 00..9e0b4612e1 --- /dev/null +++ b/include/dt-bindings/interrupt-controller/x86-irq.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2019 Google LLC + * + * This provides additional flags used by x86. + */ + +#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_X86_IRQ_H +#define _DT_BINDINGS_INTERRUPT_CONTROLLER_X86_IRQ_H + +#define X86_IRQ_TYPE_SHARED(1 << 4) +#define X86_IRQ_TYPE_WAKE (1 << 5) + +#endif -- 2.27.0.290.gba653c62da-goog
[PATCH v1 32/43] pmc: Move common registers to the header file
These registers need to be accesses from ACPI code, so move them to the header file. Signed-off-by: Simon Glass --- drivers/power/acpi_pmc/acpi-pmc-uclass.c | 9 - include/power/acpi_pmc.h | 14 ++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/power/acpi_pmc/acpi-pmc-uclass.c b/drivers/power/acpi_pmc/acpi-pmc-uclass.c index 1c79f835c6..828963d8a0 100644 --- a/drivers/power/acpi_pmc/acpi-pmc-uclass.c +++ b/drivers/power/acpi_pmc/acpi-pmc-uclass.c @@ -15,15 +15,6 @@ #include #include -enum { - PM1_STS = 0x00, - PM1_EN = 0x02, - PM1_CNT = 0x04, - - GPE0_STS= 0x20, - GPE0_EN = 0x30, -}; - struct tco_regs { u32 tco_rld; u32 tco_sts; diff --git a/include/power/acpi_pmc.h b/include/power/acpi_pmc.h index 1f50c23f5f..5fbf745136 100644 --- a/include/power/acpi_pmc.h +++ b/include/power/acpi_pmc.h @@ -6,10 +6,22 @@ #ifndef __ACPI_PMC_H #define __ACPI_PMC_H +#ifndef __ACPI__ + enum { GPE0_REG_MAX= 4, }; +enum { + PM1_STS = 0x00, + PM1_EN = 0x02, + PM1_CNT = 0x04, + PM1_TMR = 0x08, + + GPE0_STS= 0x20, + GPE0_EN = 0x30, +}; + /** * struct acpi_pmc_upriv - holds common data for the x86 PMC * @@ -182,4 +194,6 @@ void pmc_dump_info(struct udevice *dev); */ int pmc_gpe_init(struct udevice *dev); +#endif /* !__ACPI__ */ + #endif -- 2.27.0.290.gba653c62da-goog
[PATCH v1 30/43] x86: apl: Support set_hide() in p2sb driver
Add support for this new method in the driver and in the fsp-s setup. Signed-off-by: Simon Glass --- arch/x86/cpu/apollolake/fsp_s.c | 26 +++--- arch/x86/cpu/intel_common/p2sb.c | 30 ++ 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/arch/x86/cpu/apollolake/fsp_s.c b/arch/x86/cpu/apollolake/fsp_s.c index 0f5520fc7d..3a54297a28 100644 --- a/arch/x86/cpu/apollolake/fsp_s.c +++ b/arch/x86/cpu/apollolake/fsp_s.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -21,10 +22,11 @@ #include #include #include +#include #include #include +#include #include -#include #define PCH_P2SB_E00xe0 #define HIDE_BIT BIT(0) @@ -59,12 +61,6 @@ int fsps_update_config(struct udevice *dev, ulong rom_offset, return fsp_s_update_config_from_dtb(node, cfg); } -static void p2sb_set_hide_bit(pci_dev_t dev, int hide) -{ - pci_x86_clrset_config(dev, PCH_P2SB_E0 + 1, HIDE_BIT, - hide ? HIDE_BIT : 0, PCI_SIZE_8); -} - /* Configure package power limits */ static int set_power_limits(struct udevice *dev) { @@ -137,15 +133,15 @@ static int set_power_limits(struct udevice *dev) int p2sb_unhide(void) { - pci_dev_t dev = PCI_BDF(0, 0xd, 0); - ulong val; - - p2sb_set_hide_bit(dev, 0); - - pci_x86_read_config(dev, PCI_VENDOR_ID, &val, PCI_SIZE_16); + struct udevice *dev; + int ret; - if (val != PCI_VENDOR_ID_INTEL) - return log_msg_ret("p2sb unhide", -EIO); + ret = uclass_find_first_device(UCLASS_P2SB, &dev); + if (ret) + return log_msg_ret("p2sb", ret); + ret = p2sb_set_hide(dev, false); + if (ret) + return log_msg_ret("hide", ret); return 0; } diff --git a/arch/x86/cpu/intel_common/p2sb.c b/arch/x86/cpu/intel_common/p2sb.c index ec35d04ae5..ebf8f62aea 100644 --- a/arch/x86/cpu/intel_common/p2sb.c +++ b/arch/x86/cpu/intel_common/p2sb.c @@ -16,6 +16,9 @@ #include #include +#define PCH_P2SB_E00xe0 +#define HIDE_BIT BIT(0) + struct p2sb_platdata { #if CONFIG_IS_ENABLED(OF_PLATDATA) struct dtd_intel_p2sb dtplat; @@ -127,6 +130,29 @@ static int p2sb_probe(struct udevice *dev) return 0; } +static void p2sb_set_hide_bit(struct udevice *dev, bool hide) +{ + dm_pci_clrset_config8(dev, PCH_P2SB_E0 + 1, HIDE_BIT, + hide ? HIDE_BIT : 0); +} + +static int intel_p2sb_set_hide(struct udevice *dev, bool hide) +{ + u16 vendor; + + if (!CONFIG_IS_ENABLED(PCI)) + return -EPERM; + p2sb_set_hide_bit(dev, hide); + + dm_pci_read_config16(dev, PCI_VENDOR_ID, &vendor); + if (hide && vendor != 0x) + return log_msg_ret("hide", -EEXIST); + else if (!hide && vendor != PCI_VENDOR_ID_INTEL) + return log_msg_ret("unhide", -ENOMEDIUM); + + return 0; +} + static int p2sb_child_post_bind(struct udevice *dev) { #if !CONFIG_IS_ENABLED(OF_PLATDATA) @@ -143,6 +169,10 @@ static int p2sb_child_post_bind(struct udevice *dev) return 0; } +struct p2sb_ops p2sb_ops = { + .set_hide = intel_p2sb_set_hide, +}; + static const struct udevice_id p2sb_ids[] = { { .compatible = "intel,p2sb" }, { } -- 2.27.0.290.gba653c62da-goog
[PATCH v1 29/43] p2sb: Add a method to hide the bus
The P2SB bus needs to be hidden in some cases so that it does not get auto-configured by Linux. Add a method for this. Signed-off-by: Simon Glass --- drivers/misc/p2sb-uclass.c | 10 ++ include/p2sb.h | 25 - 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/drivers/misc/p2sb-uclass.c b/drivers/misc/p2sb-uclass.c index d5fe12ebd8..b5219df46b 100644 --- a/drivers/misc/p2sb-uclass.c +++ b/drivers/misc/p2sb-uclass.c @@ -18,6 +18,16 @@ #define PCR_COMMON_IOSF_1_01 +int p2sb_set_hide(struct udevice *dev, bool hide) +{ + struct p2sb_ops *ops = p2sb_get_ops(dev); + + if (!ops->set_hide) + return -ENOSYS; + + return ops->set_hide(dev, hide); +} + void *pcr_reg_address(struct udevice *dev, uint offset) { struct p2sb_child_platdata *pplat = dev_get_parent_platdata(dev); diff --git a/include/p2sb.h b/include/p2sb.h index 74eb08b7ff..93e1155dca 100644 --- a/include/p2sb.h +++ b/include/p2sb.h @@ -31,13 +31,36 @@ struct p2sb_uc_priv { }; /** - * struct p2sb_ops - Operations for the P2SB (none at present) + * struct p2sb_ops - Operations for the P2SB */ struct p2sb_ops { + /** +* set_hide() - Set/clear the 'hide' bit on the p2sb +* +* This device can be hidden from the PCI bus if needed. This method +* can be called before the p2sb is probed. +* +* @dev: P2SB device +* @hide: true to hide the device, false to show it +* @return 0 if OK, -ve on error +*/ + int (*set_hide)(struct udevice *dev, bool hide); }; #define p2sb_get_ops(dev)((struct p2sb_ops *)(dev)->driver->ops) +/** + * p2sb_set_hide() - Set/clear the 'hide' bit on the p2sb + * + * This device can be hidden from the PCI bus if needed. This method + * can be called before the p2sb is probed. + * + * @dev: P2SB device + * @hide: true to hide the device, false to show it + * @return 0 if OK, -ve on error + */ +int p2sb_set_hide(struct udevice *dev, bool hide); + /** * pcr_read32/16/8() - Read from a PCR device * -- 2.27.0.290.gba653c62da-goog
[PATCH v1 27/43] i2c: Add log_ret() on error
Add a few of these calls to make it easier to see where an error occurs, if CONFIG_LOG_ERROR_RETURN is enabled. Signed-off-by: Simon Glass --- drivers/i2c/i2c-uclass.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c index 8bc69e870f..2373aa2ea4 100644 --- a/drivers/i2c/i2c-uclass.c +++ b/drivers/i2c/i2c-uclass.c @@ -458,7 +458,7 @@ int i2c_set_chip_offset_len(struct udevice *dev, uint offset_len) struct dm_i2c_chip *chip = dev_get_parent_platdata(dev); if (offset_len > I2C_MAX_OFFSET_LEN) - return -EINVAL; + return log_ret(-EINVAL); chip->offset_len = offset_len; return 0; @@ -625,7 +625,7 @@ int i2c_chip_ofdata_to_platdata(struct udevice *dev, struct dm_i2c_chip *chip) if (addr == -1) { debug("%s: I2C Node '%s' has no 'reg' property %s\n", __func__, dev_read_name(dev), dev->name); - return -EINVAL; + return log_ret(-EINVAL); } chip->chip_addr = addr; -- 2.27.0.290.gba653c62da-goog
[PATCH v1 31/43] x86: apl: Hide the p2sb on exit from U-Boot
This confuses Linux's PCI probing so needs to be hidden when booting Linux. Add a remove() method to handle this. Signed-off-by: Simon Glass --- arch/x86/cpu/intel_common/p2sb.c | 14 ++ 1 file changed, 14 insertions(+) diff --git a/arch/x86/cpu/intel_common/p2sb.c b/arch/x86/cpu/intel_common/p2sb.c index ebf8f62aea..361d4c90cb 100644 --- a/arch/x86/cpu/intel_common/p2sb.c +++ b/arch/x86/cpu/intel_common/p2sb.c @@ -153,6 +153,17 @@ static int intel_p2sb_set_hide(struct udevice *dev, bool hide) return 0; } +static int p2sb_remove(struct udevice *dev) +{ + int ret; + + ret = intel_p2sb_set_hide(dev, true); + if (ret) + return log_msg_ret("hide", ret); + + return 0; +} + static int p2sb_child_post_bind(struct udevice *dev) { #if !CONFIG_IS_ENABLED(OF_PLATDATA) @@ -183,9 +194,12 @@ U_BOOT_DRIVER(p2sb_drv) = { .id = UCLASS_P2SB, .of_match = p2sb_ids, .probe = p2sb_probe, + .remove = p2sb_remove, + .ops= &p2sb_ops, .ofdata_to_platdata = p2sb_ofdata_to_platdata, .platdata_auto_alloc_size = sizeof(struct p2sb_platdata), .per_child_platdata_auto_alloc_size = sizeof(struct p2sb_child_platdata), .child_post_bind = p2sb_child_post_bind, + .flags = DM_FLAG_OS_PREPARE, }; -- 2.27.0.290.gba653c62da-goog
[PATCH v1 25/43] x86: gpio: Add support for obtaining ACPI info for a GPIO
Implement the method that converts a GPIO into the form used by ACPI, so that GPIOs can be added to ACPI tables. Signed-off-by: Simon Glass --- Changes in v1: - Use acpi_get_path() to get device path drivers/gpio/intel_gpio.c | 34 ++ 1 file changed, 34 insertions(+) diff --git a/drivers/gpio/intel_gpio.c b/drivers/gpio/intel_gpio.c index b4d5be97da..6a3a8c4cfa 100644 --- a/drivers/gpio/intel_gpio.c +++ b/drivers/gpio/intel_gpio.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include static int intel_gpio_direction_input(struct udevice *dev, uint offset) @@ -128,6 +130,35 @@ static int intel_gpio_xlate(struct udevice *orig_dev, struct gpio_desc *desc, return 0; } +#if CONFIG_IS_ENABLED(ACPIGEN) +static int intel_gpio_get_acpi(const struct gpio_desc *desc, + struct acpi_gpio *gpio) +{ + struct udevice *pinctrl; + int ret; + + if (!dm_gpio_is_valid(desc)) + return -ENOENT; + pinctrl = dev_get_parent(desc->dev); + + memset(gpio, '\0', sizeof(*gpio)); + + gpio->type = ACPI_GPIO_TYPE_IO; + gpio->pull = ACPI_GPIO_PULL_DEFAULT; + gpio->io_restrict = ACPI_GPIO_IO_RESTRICT_OUTPUT; + gpio->polarity = ACPI_GPIO_ACTIVE_HIGH; + gpio->pin_count = 1; + gpio->pins[0] = intel_pinctrl_get_acpi_pin(pinctrl, desc->offset); + gpio->pin0_addr = intel_pinctrl_get_config_reg_addr(pinctrl, + desc->offset); + ret = acpi_get_path(pinctrl, gpio->resource, sizeof(gpio->resource)); + if (ret) + return log_msg_ret("resource", ret); + + return 0; +} +#endif + static int intel_gpio_probe(struct udevice *dev) { return 0; @@ -152,6 +183,9 @@ static const struct dm_gpio_ops gpio_intel_ops = { .set_value = intel_gpio_set_value, .get_function = intel_gpio_get_function, .xlate = intel_gpio_xlate, +#if CONFIG_IS_ENABLED(ACPIGEN) + .get_acpi = intel_gpio_get_acpi, +#endif }; static const struct udevice_id intel_intel_gpio_ids[] = { -- 2.27.0.290.gba653c62da-goog
[PATCH v1 22/43] x86: Add support for building up an NHLT structure
The Intel Non-High-Definition-Audio Link Table (NHLT) table describes the audio codecs and connections in a system. Various devices can contribute information to produce the table. Add functions to allow adding to the structure that is eventually written to the ACPI tables. Also add the device-tree bindings. Signed-off-by: Simon Glass --- Changes in v1: - Add a new patch to support building up an NHLT structure arch/x86/include/asm/acpi_nhlt.h | 314 arch/x86/lib/Makefile| 1 + arch/x86/lib/acpi_nhlt.c | 482 +++ 3 files changed, 797 insertions(+) create mode 100644 arch/x86/include/asm/acpi_nhlt.h create mode 100644 arch/x86/lib/acpi_nhlt.c diff --git a/arch/x86/include/asm/acpi_nhlt.h b/arch/x86/include/asm/acpi_nhlt.h new file mode 100644 index 00..4d2573d5ff --- /dev/null +++ b/arch/x86/include/asm/acpi_nhlt.h @@ -0,0 +1,314 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2020 Google LLC + * + * Modified from coreboot nhlt.h + */ + +#ifndef _NHLT_H_ +#define _NHLT_H_ + +struct acpi_ctx; +struct nhlt; +struct nhlt_endpoint; +struct nhlt_format; +struct nhlt_format_config; + +/* + * Non HD Audio ACPI support. This table is typically used for Intel Smart + * Sound Technology DSP. It provides a way to encode opaque settings in + * the ACPI tables. + * + * While the structure fields of the NHLT structs are exposed below + * the SoC/chipset code should be the only other user manipulating the + * fields directly aside from the library itself. + * + * The NHLT table consists of endpoints which in turn contain different + * supporting stream formats. Each endpoint may contain a device specific + * configuration payload as well as each stream format. + * + * Most code should use the SoC variants of the functions because + * there is required logic needed to be performed by the SoC. The SoC + * code should be abstracting the inner details of these functions that + * specically apply to NHLT objects for that SoC. + * + * An example sequence: + * + * nhlt = nhlt_init() + * ep = nhlt_add_endpoint() + * nhlt_endpoint_append_config(ep) + * nhlt_endpoint_add_formats(ep) + * nhlt_soc_serialise() + */ + +/* Obtain an nhlt object for adding endpoints. Returns NULL on error. */ +struct nhlt *nhlt_init(void); + +/* Return the size of the NHLT table including ACPI header. */ +size_t nhlt_current_size(struct nhlt *nhlt); + +/* + * Helper functions for adding NHLT devices utilizing an nhlt_endp_descriptor + * to drive the logic. + */ + +struct nhlt_endp_descriptor { + /* NHLT endpoint types. */ + int link; + int device; + int direction; + u16 vid; + u16 did; + /* Optional endpoint specific configuration data. */ + const void *cfg; + size_t cfg_size; + /* Formats supported for endpoint. */ + const struct nhlt_format_config *formats; + size_t num_formats; +}; + +/* + * Add the number of endpoints described by each descriptor. The virtual bus + * id for each descriptor is the default value of 0. + * Returns < 0 on error, 0 on success. + */ +int nhlt_add_endpoints(struct nhlt *nhlt, + const struct nhlt_endp_descriptor *epds, + size_t num_epds); + +/* + * Add the number of endpoints associated with a single NHLT SSP instance id. + * Each endpoint described in the endpoint descriptor array uses the provided + * virtual bus id. Returns < 0 on error, 0 on success. + */ +int nhlt_add_ssp_endpoints(struct nhlt *nhlt, int virtual_bus_id, + const struct nhlt_endp_descriptor *epds, + size_t num_epds); + +/* + * Add endpoint to NHLT object. Returns NULL on error. + * + * generic nhlt_add_endpoint() is called by the SoC code to provide + * the specific assumptions/uses for NHLT for that platform. All fields + * are the NHLT enumerations found within this header file. + */ +struct nhlt_endpoint *nhlt_add_endpoint(struct nhlt *nhlt, int link_type, + int device_type, int dir, + u16 vid, u16 did); + +/* + * Append blob of configuration to the endpoint proper. Returns 0 on + * success, < 0 on error. A copy of the configuration is made so any + * resources pointed to by config can be freed after the call. + */ +int nhlt_endpoint_append_config(struct nhlt_endpoint *endpoint, + const void *config, size_t config_sz); + +/* Add a format type to the provided endpoint. Returns NULL on error. */ +struct nhlt_format *nhlt_add_format(struct nhlt_endpoint *endpoint, + int num_channels, int sample_freq_khz, + int container_bits_per_sample, + int valid_bits_per_sample, + u32 speaker_mask); + +/* + * Append blob of configuration to the format proper. Returns 0 o
[PATCH v1 21/43] x86: pinctrl: Drop the acpi_name member
This is in the device tree now, so drop the unnecessary field here. Signed-off-by: Simon Glass --- arch/x86/include/asm/intel_pinctrl.h | 2 -- drivers/pinctrl/intel/pinctrl_apl.c | 4 2 files changed, 6 deletions(-) diff --git a/arch/x86/include/asm/intel_pinctrl.h b/arch/x86/include/asm/intel_pinctrl.h index 982b2514a0..e734f4a7f0 100644 --- a/arch/x86/include/asm/intel_pinctrl.h +++ b/arch/x86/include/asm/intel_pinctrl.h @@ -99,7 +99,6 @@ struct pad_group { * groups exist inside a community * * @name: Community name - * @acpi_path: ACPI path * @num_gpi_regs: number of gpi registers in community * @max_pads_per_group: number of pads in each group; number of pads bit-mapped * in each GPI status/en and Host Own Reg @@ -120,7 +119,6 @@ struct pad_group { */ struct pad_community { const char *name; - const char *acpi_path; size_t num_gpi_regs; size_t max_pads_per_group; uint first_pad; diff --git a/drivers/pinctrl/intel/pinctrl_apl.c b/drivers/pinctrl/intel/pinctrl_apl.c index c14176d4a7..7624a9974f 100644 --- a/drivers/pinctrl/intel/pinctrl_apl.c +++ b/drivers/pinctrl/intel/pinctrl_apl.c @@ -75,7 +75,6 @@ static const struct pad_community apl_gpio_communities[] = { .gpi_smi_en_reg_0 = GPI_SMI_EN_0, .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, .name = "GPIO_GPE_N", - .acpi_path = "\\_SB.GPO0", .reset_map = rst_map, .num_reset_vals = ARRAY_SIZE(rst_map), .groups = apl_community_n_groups, @@ -94,7 +93,6 @@ static const struct pad_community apl_gpio_communities[] = { .gpi_smi_en_reg_0 = GPI_SMI_EN_0, .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, .name = "GPIO_GPE_NW", - .acpi_path = "\\_SB.GPO1", .reset_map = rst_map, .num_reset_vals = ARRAY_SIZE(rst_map), .groups = apl_community_nw_groups, @@ -113,7 +111,6 @@ static const struct pad_community apl_gpio_communities[] = { .gpi_smi_en_reg_0 = GPI_SMI_EN_0, .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, .name = "GPIO_GPE_W", - .acpi_path = "\\_SB.GPO2", .reset_map = rst_map, .num_reset_vals = ARRAY_SIZE(rst_map), .groups = apl_community_w_groups, @@ -132,7 +129,6 @@ static const struct pad_community apl_gpio_communities[] = { .gpi_smi_en_reg_0 = GPI_SMI_EN_0, .max_pads_per_group = GPIO_MAX_NUM_PER_GROUP, .name = "GPIO_GPE_SW", - .acpi_path = "\\_SB.GPO3", .reset_map = rst_map, .num_reset_vals = ARRAY_SIZE(rst_map), .groups = apl_community_sw_groups, -- 2.27.0.290.gba653c62da-goog
[PATCH v1 23/43] x86: Add error checking for csrt table generation
Generation of this table can fail, so update the function to return an error code. Signed-off-by: Simon Glass --- Changes in v1: - Add new patch to add error checking for csrt table generation arch/x86/lib/acpi_table.c | 19 +-- 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index 27869a0e5e..b6ba547b6a 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -212,13 +212,14 @@ static void acpi_create_mcfg(struct acpi_mcfg *mcfg) __weak u32 acpi_fill_csrt(u32 current) { - return current; + return 0; } -static void acpi_create_csrt(struct acpi_csrt *csrt) +static int acpi_create_csrt(struct acpi_csrt *csrt) { struct acpi_table_header *header = &(csrt->header); u32 current = (u32)csrt + sizeof(struct acpi_csrt); + uint ptr; memset((void *)csrt, 0, sizeof(struct acpi_csrt)); @@ -227,11 +228,16 @@ static void acpi_create_csrt(struct acpi_csrt *csrt) header->length = sizeof(struct acpi_csrt); header->revision = 0; - current = acpi_fill_csrt(current); + ptr = acpi_fill_csrt(current); + if (!ptr) + return -ENOENT; + current = ptr; /* (Re)calculate length and checksum */ header->length = current - (u32)csrt; header->checksum = table_compute_checksum((void *)csrt, header->length); + + return 0; } static void acpi_create_spcr(struct acpi_spcr *spcr) @@ -482,9 +488,10 @@ ulong write_acpi_tables(ulong start_addr) debug("ACPI:* CSRT\n"); csrt = ctx->current; - acpi_create_csrt(csrt); - acpi_inc_align(ctx, csrt->header.length); - acpi_add_table(ctx, csrt); + if (!acpi_create_csrt(csrt)) { + acpi_inc_align(ctx, csrt->header.length); + acpi_add_table(ctx, csrt); + } debug("ACPI:* SPCR\n"); spcr = ctx->current; -- 2.27.0.290.gba653c62da-goog
[PATCH v1 26/43] i2c: designware_i2c: Add a little more debugging
Add debugging for a few more values and also use log to show return values when something goes wrong. This makes it easier to see the root cause. Signed-off-by: Simon Glass --- Changes in v1: - Add new patch to improve designware_i2c debugging drivers/i2c/designware_i2c.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c index 3616e2105f..44a1f33398 100644 --- a/drivers/i2c/designware_i2c.c +++ b/drivers/i2c/designware_i2c.c @@ -160,9 +160,9 @@ static int dw_i2c_calc_timing(struct dw_i2c *priv, enum i2c_speed_mode mode, min_tlow_cnt = calc_counts(ic_clk, info->min_scl_lowtime_ns); min_thigh_cnt = calc_counts(ic_clk, info->min_scl_hightime_ns); - debug("dw_i2c: period %d rise %d fall %d tlow %d thigh %d spk %d\n", - period_cnt, rise_cnt, fall_cnt, min_tlow_cnt, min_thigh_cnt, - spk_cnt); + debug("dw_i2c: mode %d, ic_clk %d, speed %d, period %d rise %d fall %d tlow %d thigh %d spk %d\n", + mode, ic_clk, info->speed, period_cnt, rise_cnt, fall_cnt, + min_tlow_cnt, min_thigh_cnt, spk_cnt); /* * Back-solve for hcnt and lcnt according to the following equations: @@ -174,7 +174,7 @@ static int dw_i2c_calc_timing(struct dw_i2c *priv, enum i2c_speed_mode mode, if (hcnt < 0 || lcnt < 0) { debug("dw_i2c: bad counts. hcnt = %d lcnt = %d\n", hcnt, lcnt); - return -EINVAL; + return log_msg_ret("counts", -EINVAL); } /* @@ -713,7 +713,7 @@ static int designware_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) #if CONFIG_IS_ENABLED(CLK) rate = clk_get_rate(&i2c->clk); if (IS_ERR_VALUE(rate)) - return -EINVAL; + return log_ret(-EINVAL); #else rate = IC_CLK; #endif -- 2.27.0.290.gba653c62da-goog
[PATCH v1 28/43] i2c: designware_i2c: Support ACPI table generation
Update the PCI driver to generate ACPI information so that Linux has the full information about each I2C bus. Signed-off-by: Simon Glass --- Changes in v1: - Capitalise ACPI_OPS_PTR drivers/i2c/designware_i2c.c | 25 drivers/i2c/designware_i2c.h | 15 + drivers/i2c/designware_i2c_pci.c | 104 ++- 3 files changed, 143 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c index 44a1f33398..630938743f 100644 --- a/drivers/i2c/designware_i2c.c +++ b/drivers/i2c/designware_i2c.c @@ -333,6 +333,31 @@ static int _dw_i2c_set_bus_speed(struct dw_i2c *priv, struct i2c_regs *i2c_base, /* Restore back i2c now speed set */ if (ena == IC_ENABLE_0B) dw_i2c_enable(i2c_base, true); + if (priv) + priv->config = config; + return 0; +} + +int dw_i2c_gen_speed_config(const struct udevice *dev, int speed_hz, + struct dw_i2c_speed_config *config) +{ + struct dw_i2c *priv = dev_get_priv(dev); + ulong rate; + int ret; + +#if CONFIG_IS_ENABLED(CLK) + rate = clk_get_rate(&priv->clk); + if (IS_ERR_VALUE(rate)) + return log_msg_ret("clk", -EINVAL); +#else + rate = IC_CLK; +#endif + + ret = calc_bus_speed(priv, priv->regs, speed_hz, rate, config); + if (ret) + printf("%s: ret=%d\n", __func__, ret); + if (ret) + return log_msg_ret("calc_bus_speed", ret); return 0; } diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h index dc9a6ccb63..d87a3bff93 100644 --- a/drivers/i2c/designware_i2c.h +++ b/drivers/i2c/designware_i2c.h @@ -205,6 +205,7 @@ struct dw_i2c { #if CONFIG_IS_ENABLED(CLK) struct clk clk; #endif + struct dw_i2c_speed_config config; }; extern const struct dm_i2c_ops designware_i2c_ops; @@ -213,4 +214,18 @@ int designware_i2c_probe(struct udevice *bus); int designware_i2c_remove(struct udevice *dev); int designware_i2c_ofdata_to_platdata(struct udevice *bus); +/** + * dw_i2c_gen_speed_config() - Calculate config info from requested speed1 + * + * Calculate the speed config from the given @speed_hz and return it so that + * it can be incorporated in ACPI tables + * + * @dev: I2C bus to check + * @speed_hz: Requested speed in Hz + * @config: Returns config to use for that speed + * @return 0 if OK, -ve on error + */ +int dw_i2c_gen_speed_config(const struct udevice *dev, int speed_hz, + struct dw_i2c_speed_config *config); + #endif /* __DW_I2C_H_ */ diff --git a/drivers/i2c/designware_i2c_pci.c b/drivers/i2c/designware_i2c_pci.c index bd34ec0b47..d5108e9064 100644 --- a/drivers/i2c/designware_i2c_pci.c +++ b/drivers/i2c/designware_i2c_pci.c @@ -9,7 +9,12 @@ #include #include #include +#include +#include #include +#include +#include +#include #include "designware_i2c.h" enum { @@ -87,6 +92,8 @@ static int designware_i2c_pci_bind(struct udevice *dev) { char name[20]; + if (dev_of_valid(dev)) + return 0; /* * Create a unique device name for PCI type devices * ToDo: @@ -100,13 +107,107 @@ static int designware_i2c_pci_bind(struct udevice *dev) * be possible. We cannot use static data in drivers since they may be * used in SPL or before relocation. */ - dev->req_seq = gd->arch.dw_i2c_num_cards++; + dev->req_seq = uclass_find_next_free_req_seq(UCLASS_I2C); sprintf(name, "i2c_designware#%u", dev->req_seq); device_set_name(dev, name); return 0; } +/* + * Write ACPI object to describe speed configuration. + * + * ACPI Object: Name ("", Package () { scl_lcnt, scl_hcnt, sda_hold } + * + * SSCN: I2C_SPEED_STANDARD + * FMCN: I2C_SPEED_FAST + * FPCN: I2C_SPEED_FAST_PLUS + * HSCN: I2C_SPEED_HIGH + */ +static void dw_i2c_acpi_write_speed_config(struct acpi_ctx *ctx, + struct dw_i2c_speed_config *config) +{ + switch (config->speed_mode) { + case IC_SPEED_MODE_HIGH: + acpigen_write_name(ctx, "HSCN"); + break; + case IC_SPEED_MODE_FAST_PLUS: + acpigen_write_name(ctx, "FPCN"); + break; + case IC_SPEED_MODE_FAST: + acpigen_write_name(ctx, "FMCN"); + break; + case IC_SPEED_MODE_STANDARD: + default: + acpigen_write_name(ctx, "SSCN"); + } + + /* Package () { scl_lcnt, scl_hcnt, sda_hold } */ + acpigen_write_package(ctx, 3); + acpigen_write_word(ctx, config->scl_hcnt); + acpigen_write_word(ctx, config->scl_lcnt); + acpigen_write_dword(ctx, config->sda_hold); + acpigen_pop_len(ctx); +} + +/* + * Generate I2C timing information into the SSDT for the OS driver to consume, + * optionally applying override values provided by the caller. + */
[PATCH v1 17/43] x86: pinctrl: Add a way to get the pinctrl reg address
At present we can query the offset of a pinctrl register within the p2sb. For ACPI we need to get the actual address of the register. Add a function to handle this and rename the old one to more accurately reflect its purpose. Signed-off-by: Simon Glass --- arch/x86/include/asm/intel_pinctrl.h | 16 ++-- drivers/gpio/intel_gpio.c| 15 +++ drivers/misc/p2sb-uclass.c | 16 drivers/pinctrl/intel/pinctrl.c | 11 +-- include/p2sb.h | 9 + 5 files changed, 51 insertions(+), 16 deletions(-) diff --git a/arch/x86/include/asm/intel_pinctrl.h b/arch/x86/include/asm/intel_pinctrl.h index e2524b089d..f39ebde539 100644 --- a/arch/x86/include/asm/intel_pinctrl.h +++ b/arch/x86/include/asm/intel_pinctrl.h @@ -263,11 +263,23 @@ int pinctrl_read_pads(struct udevice *dev, ofnode node, const char *prop, int pinctrl_count_pads(struct udevice *dev, u32 *pads, int size); /** - * intel_pinctrl_get_config_reg_addr() - Get address of the pin config registers + * intel_pinctrl_get_config_reg_offset() - Get offset of pin config registers * + * This works out the register offset of a pin within the p2sb region. + * + * @dev: Pinctrl device + * @offset: GPIO offset within this device + * @return register offset of first register within the GPIO p2sb region + */ +u32 intel_pinctrl_get_config_reg_offset(struct udevice *dev, uint offset); + +/** + * intel_pinctrl_get_config_reg_offset() - Get address of pin config registers + * + * This works out the absolute address of the registers for a pin * @dev: Pinctrl device * @offset: GPIO offset within this device - * @return register offset within the GPIO p2sb region + * @return register offset of first register within the GPIO p2sb region */ u32 intel_pinctrl_get_config_reg_addr(struct udevice *dev, uint offset); diff --git a/drivers/gpio/intel_gpio.c b/drivers/gpio/intel_gpio.c index 711fea1b58..b4d5be97da 100644 --- a/drivers/gpio/intel_gpio.c +++ b/drivers/gpio/intel_gpio.c @@ -24,7 +24,9 @@ static int intel_gpio_direction_input(struct udevice *dev, uint offset) { struct udevice *pinctrl = dev_get_parent(dev); - uint config_offset = intel_pinctrl_get_config_reg_addr(pinctrl, offset); + uint config_offset; + + config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset); pcr_clrsetbits32(pinctrl, config_offset, PAD_CFG0_MODE_MASK | PAD_CFG0_TX_STATE | @@ -38,7 +40,9 @@ static int intel_gpio_direction_output(struct udevice *dev, uint offset, int value) { struct udevice *pinctrl = dev_get_parent(dev); - uint config_offset = intel_pinctrl_get_config_reg_addr(pinctrl, offset); + uint config_offset; + + config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset); pcr_clrsetbits32(pinctrl, config_offset, PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE | @@ -68,10 +72,13 @@ static int intel_gpio_get_value(struct udevice *dev, uint offset) return 0; } -static int intel_gpio_set_value(struct udevice *dev, unsigned offset, int value) +static int intel_gpio_set_value(struct udevice *dev, unsigned int offset, + int value) { struct udevice *pinctrl = dev_get_parent(dev); - uint config_offset = intel_pinctrl_get_config_reg_addr(pinctrl, offset); + uint config_offset; + + config_offset = intel_pinctrl_get_config_reg_offset(pinctrl, offset); pcr_clrsetbits32(pinctrl, config_offset, PAD_CFG0_TX_STATE, value ? PAD_CFG0_TX_STATE : 0); diff --git a/drivers/misc/p2sb-uclass.c b/drivers/misc/p2sb-uclass.c index 06b1e8d9ad..d5fe12ebd8 100644 --- a/drivers/misc/p2sb-uclass.c +++ b/drivers/misc/p2sb-uclass.c @@ -18,7 +18,7 @@ #define PCR_COMMON_IOSF_1_01 -static void *_pcr_reg_address(struct udevice *dev, uint offset) +void *pcr_reg_address(struct udevice *dev, uint offset) { struct p2sb_child_platdata *pplat = dev_get_parent_platdata(dev); struct udevice *p2sb = dev_get_parent(dev); @@ -55,7 +55,7 @@ uint pcr_read32(struct udevice *dev, uint offset) /* Ensure the PCR offset is correctly aligned */ assert(IS_ALIGNED(offset, sizeof(uint32_t))); - ptr = _pcr_reg_address(dev, offset); + ptr = pcr_reg_address(dev, offset); val = readl(ptr); unmap_sysmem(ptr); @@ -67,7 +67,7 @@ uint pcr_read16(struct udevice *dev, uint offset) /* Ensure the PCR offset is correctly aligned */ check_pcr_offset_align(offset, sizeof(uint16_t)); - return readw(_pcr_reg_address(dev, offset)); + return readw(pcr_reg_address(dev, offset)); } uint pcr_read8(struct udevice *dev, uint offset) @@ -75,7 +75,7 @@ uint pcr_read8(struct udevice *dev, uint offset) /* Ensure the PCR offset is correctly aligned */ check_pcr_offset_a
[PATCH v1 24/43] x86: apl: Use memory-mapped access for VBT
Use the new binman memory-mapping function to access the VBT, to simplify the code. Signed-off-by: Simon Glass --- arch/x86/cpu/apollolake/fsp_s.c | 19 +-- arch/x86/lib/fsp2/fsp_silicon_init.c | 1 + 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/arch/x86/cpu/apollolake/fsp_s.c b/arch/x86/cpu/apollolake/fsp_s.c index 13e6b20f08..0f5520fc7d 100644 --- a/arch/x86/cpu/apollolake/fsp_s.c +++ b/arch/x86/cpu/apollolake/fsp_s.c @@ -36,29 +36,20 @@ int fsps_update_config(struct udevice *dev, ulong rom_offset, ofnode node; if (IS_ENABLED(CONFIG_HAVE_VBT)) { - struct binman_entry vbt; - void *vbt_buf; + void *buf; int ret; - ret = binman_entry_find("intel-vbt", &vbt); + ret = binman_entry_map(ofnode_null(), "intel-vbt", &buf, NULL); if (ret) return log_msg_ret("Cannot find VBT", ret); - vbt.image_pos += rom_offset; - vbt_buf = malloc(vbt.size); - if (!vbt_buf) - return log_msg_ret("Alloc VBT", -ENOMEM); + if (*(u32 *)buf != VBT_SIGNATURE) + return log_msg_ret("VBT signature", -EINVAL); /* * Load VBT before devicetree-specific config. This only * supports memory-mapped SPI at present. */ - bootstage_start(BOOTSTAGE_ID_ACCUM_MMAP_SPI, "mmap_spi"); - memcpy(vbt_buf, (void *)vbt.image_pos, vbt.size); - bootstage_accum(BOOTSTAGE_ID_ACCUM_MMAP_SPI); - if (*(u32 *)vbt_buf != VBT_SIGNATURE) - return log_msg_ret("VBT signature", -EINVAL); - - cfg->graphics_config_ptr = (ulong)vbt_buf; + cfg->graphics_config_ptr = (ulong)buf; } node = dev_read_subnode(dev, "fsp-s"); diff --git a/arch/x86/lib/fsp2/fsp_silicon_init.c b/arch/x86/lib/fsp2/fsp_silicon_init.c index 45c0c7d90b..0f221a864f 100644 --- a/arch/x86/lib/fsp2/fsp_silicon_init.c +++ b/arch/x86/lib/fsp2/fsp_silicon_init.c @@ -32,6 +32,7 @@ int fsp_silicon_init(bool s3wake, bool use_spi_flash) &rom_offset); if (ret) return log_msg_ret("locate FSP", ret); + binman_set_rom_offset(rom_offset); gd->arch.fsp_s_hdr = hdr; /* Copy over the default config */ -- 2.27.0.290.gba653c62da-goog
[PATCH v1 20/43] x86: pinctrl: Set up itss in the probe() method
At present the itss is probed in the ofdata_to_platdata() method. This is incorrect since itss is a child of p2sb which itself needs to probe the pinctrl device. This means that p2sb is effectively not probed when the itss is probed, so we get the wrong register address from p2sb. Fix this by moving the itss probe to the correct place. Signed-off-by: Simon Glass --- drivers/pinctrl/intel/pinctrl.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/pinctrl/intel/pinctrl.c b/drivers/pinctrl/intel/pinctrl.c index 32ca303b27..ba21c9dcc2 100644 --- a/drivers/pinctrl/intel/pinctrl.c +++ b/drivers/pinctrl/intel/pinctrl.c @@ -619,15 +619,11 @@ int intel_pinctrl_ofdata_to_platdata(struct udevice *dev, { struct p2sb_child_platdata *pplat = dev_get_parent_platdata(dev); struct intel_pinctrl_priv *priv = dev_get_priv(dev); - int ret; if (!comm) { log_err("Cannot find community for pid %d\n", pplat->pid); return -EDOM; } - ret = irq_first_device_type(X86_IRQT_ITSS, &priv->itss); - if (ret) - return log_msg_ret("Cannot find ITSS", ret); priv->comm = comm; priv->num_cfgs = num_cfgs; @@ -637,8 +633,12 @@ int intel_pinctrl_ofdata_to_platdata(struct udevice *dev, int intel_pinctrl_probe(struct udevice *dev) { struct intel_pinctrl_priv *priv = dev_get_priv(dev); + int ret; priv->itss_pol_cfg = true; + ret = irq_first_device_type(X86_IRQT_ITSS, &priv->itss); + if (ret) + return log_msg_ret("Cannot find ITSS", ret); return 0; } -- 2.27.0.290.gba653c62da-goog
[PATCH v1 16/43] sound: Add an ACPI driver for Maxim MAX98357ac
This chip is used on coral and we need to generate ACPI tables for sound to make it work. Add a driver that does just this (i.e. at present does not actually support playing sound). Signed-off-by: Simon Glass --- Changes in v1: - Use acpi,ddn instead of acpi,desc - Drop the unwanted acpi_device_write_gpio_desc() - Rename max97357a to max98357a - Add NHLT support - Capitalise ACPI_OPS_PTR - Rebase to master configs/sandbox_defconfig| 1 + doc/device-tree-bindings/sound/max98357a.txt | 22 +++ drivers/sound/Kconfig| 9 ++ drivers/sound/Makefile | 1 + drivers/sound/max98357a.c| 160 +++ 5 files changed, 193 insertions(+) create mode 100644 doc/device-tree-bindings/sound/max98357a.txt create mode 100644 drivers/sound/max98357a.c diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 6368e278f2..96c6e0fcd5 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -203,6 +203,7 @@ CONFIG_SMEM=y CONFIG_SANDBOX_SMEM=y CONFIG_SOUND=y CONFIG_SOUND_DA7219=y +CONFIG_SOUND_MAX98357A=y CONFIG_SOUND_SANDBOX=y CONFIG_SANDBOX_SPI=y CONFIG_SPMI=y diff --git a/doc/device-tree-bindings/sound/max98357a.txt b/doc/device-tree-bindings/sound/max98357a.txt new file mode 100644 index 00..4bce14ce80 --- /dev/null +++ b/doc/device-tree-bindings/sound/max98357a.txt @@ -0,0 +1,22 @@ +Maxim MAX98357A audio DAC + +This node models the Maxim MAX98357A DAC. + +Required properties: +- compatible : "maxim,max98357a" + +Optional properties: +- sdmode-gpios : GPIO specifier for the chip's SD_MODE pin. +If this option is not specified then driver does not manage +the pin state (e.g. chip is always on). +- sdmode-delay : specify delay time for SD_MODE pin. +If this option is specified, which means it's required i2s clocks +ready before SD_MODE is unmuted in order to avoid the speaker pop noise. +It's observed that 5ms is sufficient. + +Example: + +max98357a { + compatible = "maxim,max98357a"; + sdmode-gpios = <&qcom_pinmux 25 0>; +}; diff --git a/drivers/sound/Kconfig b/drivers/sound/Kconfig index 7f214b97be..0948d8caab 100644 --- a/drivers/sound/Kconfig +++ b/drivers/sound/Kconfig @@ -113,6 +113,15 @@ config SOUND_MAX98095 audio data and I2C for codec control. At present it only works with the Samsung I2S driver. +config SOUND_MAX98357A + bool "Support Maxim max98357a audio codec" + depends on PCI + help + Enable the max98357a audio codec. This is connected on PCI for + audio data codec control. This is currently only capable of providing + ACPI information. A full driver (with sound in U-Boot) is currently + not available. + config SOUND_RT5677 bool "Support Realtek RT5677 audio codec" depends on SOUND diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index 8c3933ad15..9b40c8012f 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_SOUND_WM8994)+= wm8994.o obj-$(CONFIG_SOUND_MAX98088) += max98088.o maxim_codec.o obj-$(CONFIG_SOUND_MAX98090) += max98090.o maxim_codec.o obj-$(CONFIG_SOUND_MAX98095) += max98095.o maxim_codec.o +obj-$(CONFIG_SOUND_MAX98357A) += max98357a.o obj-$(CONFIG_SOUND_INTEL_HDA) += hda_codec.o obj-$(CONFIG_SOUND_I8254) += i8254_beep.o obj-$(CONFIG_SOUND_RT5677) += rt5677.o diff --git a/drivers/sound/max98357a.c b/drivers/sound/max98357a.c new file mode 100644 index 00..33fdd0ba1e --- /dev/null +++ b/drivers/sound/max98357a.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * max98357a.c -- MAX98357A Audio driver + * + * Copyright 2019 Google LLC + * Parts taken from coreboot + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_X86 +#include +#endif +#include +#include + +struct max98357a_priv { + struct gpio_desc sdmode_gpio; +}; + +static int max98357a_ofdata_to_platdata(struct udevice *dev) +{ + struct max98357a_priv *priv = dev_get_priv(dev); + int ret; + + ret = gpio_request_by_name(dev, "sdmode-gpios", 0, &priv->sdmode_gpio, + GPIOD_IS_IN); + if (ret) + return log_msg_ret("gpio", ret); + + return 0; +} + +static int max98357a_acpi_fill_ssdt(const struct udevice *dev, + struct acpi_ctx *ctx) +{ + struct max98357a_priv *priv = dev_get_priv(dev); + char scope[ACPI_PATH_MAX]; + char name[ACPI_NAME_MAX]; + char path[ACPI_PATH_MAX]; + struct acpi_dp *dp; + int ret; + + ret = acpi_device_scope(dev, scope, sizeof(scope)); + if (ret) + return log_msg_ret("scope", ret); + ret = acpi_get_name(dev, name); + if (ret) + return log_msg_ret("name", ret); + +
[PATCH v1 18/43] x86: pinctrl: Update comment for intel_pinctrl_get_pad()
Add information about what is returned on error. Signed-off-by: Simon Glass --- arch/x86/include/asm/intel_pinctrl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/include/asm/intel_pinctrl.h b/arch/x86/include/asm/intel_pinctrl.h index f39ebde539..982b2514a0 100644 --- a/arch/x86/include/asm/intel_pinctrl.h +++ b/arch/x86/include/asm/intel_pinctrl.h @@ -300,6 +300,7 @@ u32 intel_pinctrl_get_config_reg(struct udevice *dev, uint offset); * @pad: Pad to check * @devp: Returns pinctrl device containing that pad * @offsetp: Returns offset of pad within that pinctrl device + * @return 0 if OK, -ENOTBLK if pad number is invalid */ int intel_pinctrl_get_pad(uint pad, struct udevice **devp, uint *offsetp); -- 2.27.0.290.gba653c62da-goog
[PATCH v1 15/43] sound: Add an ACPI driver for Dialog Semicondutor da7219
This chip is used on coral and we need to generate ACPI tables for sound to make it work. Add a driver that does just this (i.e. at present does not actually support playing sound). Signed-off-by: Simon Glass --- Changes in v1: - Use acpi,ddn instead of acpi,desc - Add a check for invalid node - Add NHLT support - Capitalise ACPI_OPS_PTR - Rebase to master configs/sandbox_defconfig | 1 + doc/device-tree-bindings/sound/da7219.txt | 113 + drivers/sound/Kconfig | 9 ++ drivers/sound/Makefile| 1 + drivers/sound/da7219.c| 189 ++ 5 files changed, 313 insertions(+) create mode 100644 doc/device-tree-bindings/sound/da7219.txt create mode 100644 drivers/sound/da7219.c diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index cb6b4b0ee7..6368e278f2 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -202,6 +202,7 @@ CONFIG_SANDBOX_SERIAL=y CONFIG_SMEM=y CONFIG_SANDBOX_SMEM=y CONFIG_SOUND=y +CONFIG_SOUND_DA7219=y CONFIG_SOUND_SANDBOX=y CONFIG_SANDBOX_SPI=y CONFIG_SPMI=y diff --git a/doc/device-tree-bindings/sound/da7219.txt b/doc/device-tree-bindings/sound/da7219.txt new file mode 100644 index 00..5fd8a9f1e7 --- /dev/null +++ b/doc/device-tree-bindings/sound/da7219.txt @@ -0,0 +1,113 @@ +Dialog Semiconductor DA7219 Audio Codec bindings + +DA7219 is an audio codec with advanced accessory detect features. + +== + +Required properties: +- compatible : Should be "dlg,da7219" +- reg: Specifies the I2C slave address + +- interrupts : IRQ line info for DA7219. + (See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt for + further information relating to interrupt properties) + +- VDD-supply: VDD power supply for the device +- VDDMIC-supply: VDDMIC power supply for the device +- VDDIO-supply: VDDIO power supply for the device + (See Documentation/devicetree/bindings/regulator/regulator.txt for further + information relating to regulators) + +Optional properties: +- interrupt-names : Name associated with interrupt line. Should be "wakeup" if + interrupt is to be used to wake system, otherwise "irq" should be used. +- wakeup-source: Flag to indicate this device can wake system (suspend/resume). + +- #clock-cells : Should be set to '<0>', only one clock source provided; +- clock-output-names : Name given for DAI clocks output; + +- clocks : phandle and clock specifier for codec MCLK. +- clock-names : Clock name string for 'clocks' attribute, should be "mclk". + +- dlg,micbias-lvl : Voltage (mV) for Mic Bias + [<1600>, <1800>, <2000>, <2200>, <2400>, <2600>] +- dlg,mic-amp-in-sel : Mic input source type + ["diff", "se_p", "se_n"] +- dlg,mclk-name : String name of MCLK for ACPI + +Deprecated properties: +- dlg,ldo-lvl : Required internal LDO voltage (mV) level for digital engine + (LDO unavailable in production HW so property no longer required). + +== + +Child node - 'da7219_aad': + +Optional properties: +- dlg,micbias-pulse-lvl : Mic bias higher voltage pulse level (mV). + [<2800>, <2900>] +- dlg,micbias-pulse-time : Mic bias higher voltage pulse duration (ms) +- dlg,btn-cfg : Periodic button press measurements for 4-pole jack (ms) + [<2>, <5>, <10>, <50>, <100>, <200>, <500>] +- dlg,mic-det-thr : Impedance threshold for mic detection measurement (Ohms) + [<200>, <500>, <750>, <1000>] +- dlg,jack-ins-deb : Debounce time for jack insertion (ms) + [<5>, <10>, <20>, <50>, <100>, <200>, <500>, <1000>] +- dlg,jack-det-rate: Jack type detection latency (3/4 pole) + ["32ms_64ms", "64ms_128ms", "128ms_256ms", "256ms_512ms"] +- dlg,jack-rem-deb : Debounce time for jack removal (ms) + [<1>, <5>, <10>, <20>] +- dlg,a-d-btn-thr : Impedance threshold between buttons A and D + [0x0 - 0xFF] +- dlg,d-b-btn-thr : Impedance threshold between buttons D and B + [0x0 - 0xFF] +- dlg,b-c-btn-thr : Impedance threshold between buttons B and C + [0x0 - 0xFF] +- dlg,c-mic-btn-thr : Impedance threshold between button C and Mic + [0x0 - 0xFF] +- dlg,btn-avg : Number of 8-bit readings for averaged button measurement + [<1>, <2>, <4>, <8>] +- dlg,adc-1bit-rpt : Repeat count for 1-bit button measurement + [<1>, <2>, <4>, <8>] + +== + +Example: + + codec: da7219@1a { + compatible = "dlg,da7219"; + reg = <0x1a>; + + interrupt-parent = <&gpio6>; + interrupts = <11 IRQ_TYPE_LEVEL_LOW>; + + VDD-supply = <®_audio>; + VDDMIC-supply = <®_audio>; + VDDIO-supply = <®_audio>; + + #clock-cells = <0>; + clock-output-names = "dai-clks"; + + clocks = <&clks 201>; + clock-names = "mclk"; + + dlg,ldo-lvl = <1200>; + dlg,micbias-lvl = <2600>; + dlg,mic-amp-in-sel = "diff"; + +
[PATCH v1 19/43] x86: pinctrl: Add multi-ACPI control
Add a Kconfig to control whether pinctrl is represented as a single ACPI device or as multiple devices. In the latter case (the default) we should return the pin number relative to the pinctrl device. Signed-off-by: Simon Glass --- drivers/pinctrl/intel/Kconfig | 4 drivers/pinctrl/intel/pinctrl.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/drivers/pinctrl/intel/Kconfig b/drivers/pinctrl/intel/Kconfig index e62a2e0349..05a314af88 100644 --- a/drivers/pinctrl/intel/Kconfig +++ b/drivers/pinctrl/intel/Kconfig @@ -15,6 +15,10 @@ config INTEL_PINCTRL_IOSTANDBY bool default y +config INTEL_PINCTRL_MULTI_ACPI_DEVICES + bool + default y + config PINCTRL_INTEL_APL bool "Support Intel Apollo Lake (APL)" help diff --git a/drivers/pinctrl/intel/pinctrl.c b/drivers/pinctrl/intel/pinctrl.c index bf3989bf32..32ca303b27 100644 --- a/drivers/pinctrl/intel/pinctrl.c +++ b/drivers/pinctrl/intel/pinctrl.c @@ -427,6 +427,8 @@ int intel_pinctrl_get_acpi_pin(struct udevice *dev, uint offset) const struct pad_community *comm = priv->comm; int group; + if (IS_ENABLED(CONFIG_INTEL_PINCTRL_MULTI_ACPI_DEVICES)) + return offset; group = pinctrl_group_index(comm, offset); /* If pad base is not set then use GPIO number as ACPI pin number */ -- 2.27.0.290.gba653c62da-goog
[PATCH v1 13/43] acpi: Support generation of a device
Allow writing an ACPI device to the generated ACPI code. Signed-off-by: Simon Glass --- include/acpi/acpigen.h | 9 + lib/acpi/acpigen.c | 7 +++ test/dm/acpigen.c | 27 +++ 3 files changed, 43 insertions(+) diff --git a/include/acpi/acpigen.h b/include/acpi/acpigen.h index 4361a28a08..19f84dc867 100644 --- a/include/acpi/acpigen.h +++ b/include/acpi/acpigen.h @@ -56,6 +56,7 @@ enum { AND_OP = 0x7b, OR_OP = 0x7d, NOT_OP = 0x80, + DEVICE_OP = 0x82, POWER_RES_OP= 0x84, RETURN_OP = 0xa4, }; @@ -310,6 +311,14 @@ void acpigen_write_method(struct acpi_ctx *ctx, const char *name, int nargs); void acpigen_write_method_serialized(struct acpi_ctx *ctx, const char *name, int nargs); +/** + * acpigen_write_device() - Write an ACPI device + * + * @ctx: ACPI context pointer + * @name: Device name to write + */ +void acpigen_write_device(struct acpi_ctx *ctx, const char *name); + /** * acpigen_write_sta() - Write a _STA method * diff --git a/lib/acpi/acpigen.c b/lib/acpi/acpigen.c index 6f5972f1f7..5fe1f59f82 100644 --- a/lib/acpi/acpigen.c +++ b/lib/acpi/acpigen.c @@ -288,6 +288,13 @@ void acpigen_write_method_serialized(struct acpi_ctx *ctx, const char *name, ACPI_METHOD_SERIALIZED_MASK); } +void acpigen_write_device(struct acpi_ctx *ctx, const char *name) +{ + acpigen_emit_ext_op(ctx, DEVICE_OP); + acpigen_write_len_f(ctx); + acpigen_emit_namestring(ctx, name); +} + void acpigen_write_sta(struct acpi_ctx *ctx, uint status) { /* Method (_STA, 0, NotSerialized) { Return (status) } */ diff --git a/test/dm/acpigen.c b/test/dm/acpigen.c index 80697300e7..5cd7fb5657 100644 --- a/test/dm/acpigen.c +++ b/test/dm/acpigen.c @@ -983,3 +983,30 @@ static int dm_test_acpi_resource_template(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_acpi_resource_template, 0); + +/* Test writing a device */ +static int dm_test_acpi_device(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + ptr = acpigen_get_current(ctx); + + acpigen_write_device(ctx, "\\_SB." ACPI_TEST_DEV_NAME); + acpigen_pop_len(ctx); + + ut_asserteq(EXT_OP_PREFIX, *ptr++); + ut_asserteq(DEVICE_OP, *ptr++); + ut_asserteq(0xd, get_length(ptr)); + ptr += 3; + ut_asserteq(ROOT_PREFIX, *ptr++); + ut_asserteq(DUAL_NAME_PREFIX, *ptr++); + ptr += 8; + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_device, 0); -- 2.27.0.290.gba653c62da-goog
[PATCH v1 12/43] x86: Add bindings for NHLT
Add devicetree bindings for the Intel Non-High-Definition-Audio Link Table (NHLT). Signed-off-by: Simon Glass --- include/dt-bindings/sound/nhlt.h | 23 +++ 1 file changed, 23 insertions(+) create mode 100644 include/dt-bindings/sound/nhlt.h diff --git a/include/dt-bindings/sound/nhlt.h b/include/dt-bindings/sound/nhlt.h new file mode 100644 index 00..c33f874966 --- /dev/null +++ b/include/dt-bindings/sound/nhlt.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2019 Google LLC + */ + +#ifndef _DT_BINDINGS_SOUND_NHLT_H +#define _DT_BINDINGS_SOUND_NHLT_H + +#define NHLT_VID 0x8086 +#define NHLT_DID_DMIC 0xae20 +#define NHLT_DID_BT0xae30 +#define NHLT_DID_SSP 0xae34 + +/* Hardware links available to use for codecs */ +#define AUDIO_LINK_SSP00 +#define AUDIO_LINK_SSP11 +#define AUDIO_LINK_SSP22 +#define AUDIO_LINK_SSP33 +#define AUDIO_LINK_SSP44 +#define AUDIO_LINK_SSP55 +#define AUDIO_LINK_DMIC6 + +#endif /* _DT_BINDINGS_SOUND_NHLT_H */ -- 2.27.0.290.gba653c62da-goog
[PATCH v1 11/43] acpi: mmc: Generate ACPI info for the PCI SD Card
Write required information into the SSDT to describe the SD card card-detect pin. Since the required GPIO properties are not present in the device-tree binding, set them manually for now. Signed-off-by: Simon Glass --- Changes in v1: - Capitalise ACPI_OPS_PTR configs/sandbox_defconfig | 2 + drivers/mmc/pci_mmc.c | 78 ++- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 982075c568..cb6b4b0ee7 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -143,7 +143,9 @@ CONFIG_P2SB=y CONFIG_PWRSEQ=y CONFIG_SPL_PWRSEQ=y CONFIG_I2C_EEPROM=y +CONFIG_MMC_PCI=y CONFIG_MMC_SANDBOX=y +CONFIG_MMC_SDHCI=y CONFIG_MTD=y CONFIG_SPI_FLASH_SANDBOX=y CONFIG_SPI_FLASH_ATMEL=y diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c index 404264a697..0c45e1b893 100644 --- a/drivers/mmc/pci_mmc.c +++ b/drivers/mmc/pci_mmc.c @@ -7,10 +7,15 @@ #include #include #include +#include #include #include #include -#include +#include +#include +#include +#include +#include struct pci_mmc_plat { struct mmc_config cfg; @@ -20,6 +25,7 @@ struct pci_mmc_plat { struct pci_mmc_priv { struct sdhci_host host; void *base; + struct gpio_desc cd_gpio; }; static int pci_mmc_probe(struct udevice *dev) @@ -44,6 +50,15 @@ static int pci_mmc_probe(struct udevice *dev) return sdhci_probe(dev); } +static int pci_mmc_ofdata_to_platdata(struct udevice *dev) +{ + struct pci_mmc_priv *priv = dev_get_priv(dev); + + gpio_request_by_name(dev, "cd-gpios", 0, &priv->cd_gpio, GPIOD_IS_IN); + + return 0; +} + static int pci_mmc_bind(struct udevice *dev) { struct pci_mmc_plat *plat = dev_get_platdata(dev); @@ -51,14 +66,75 @@ static int pci_mmc_bind(struct udevice *dev) return sdhci_bind(dev, &plat->mmc, &plat->cfg); } +static int pci_mmc_acpi_fill_ssdt(const struct udevice *dev, + struct acpi_ctx *ctx) +{ + struct pci_mmc_priv *priv = dev_get_priv(dev); + char path[ACPI_PATH_MAX]; + struct acpi_gpio gpio; + struct acpi_dp *dp; + int ret; + + if (!dev_of_valid(dev)) + return 0; + + ret = gpio_get_acpi(&priv->cd_gpio, &gpio); + if (ret) + return log_msg_ret("gpio", ret); + gpio.type = ACPI_GPIO_TYPE_INTERRUPT; + gpio.pull = ACPI_GPIO_PULL_NONE; + gpio.irq.mode = ACPI_IRQ_EDGE_TRIGGERED; + gpio.irq.polarity = ACPI_IRQ_ACTIVE_BOTH; + gpio.irq.shared = ACPI_IRQ_SHARED; + gpio.irq.wake = ACPI_IRQ_WAKE; + gpio.interrupt_debounce_timeout = 1; /* 100ms */ + + /* Use device path as the Scope for the SSDT */ + ret = acpi_device_path(dev, path, sizeof(path)); + if (ret) + return log_msg_ret("path", ret); + acpigen_write_scope(ctx, path); + acpigen_write_name(ctx, "_CRS"); + + /* Write GpioInt() as default (if set) or custom from devicetree */ + acpigen_write_resourcetemplate_header(ctx); + acpi_device_write_gpio(ctx, &gpio); + acpigen_write_resourcetemplate_footer(ctx); + + /* Bind the cd-gpio name to the GpioInt() resource */ + dp = acpi_dp_new_table("_DSD"); + if (!dp) + return -ENOMEM; + acpi_dp_add_gpio(dp, "cd-gpio", path, 0, 0, 1); + ret = acpi_dp_write(ctx, dp); + if (ret) + return log_msg_ret("cd", ret); + + acpigen_pop_len(ctx); + + return 0; +} + +struct acpi_ops pci_mmc_acpi_ops = { + .fill_ssdt = pci_mmc_acpi_fill_ssdt, +}; + +static const struct udevice_id pci_mmc_match[] = { + { .compatible = "intel,apl-sd" }, + { } +}; + U_BOOT_DRIVER(pci_mmc) = { .name = "pci_mmc", .id = UCLASS_MMC, + .of_match = pci_mmc_match, .bind = pci_mmc_bind, + .ofdata_to_platdata = pci_mmc_ofdata_to_platdata, .probe = pci_mmc_probe, .ops= &sdhci_ops, .priv_auto_alloc_size = sizeof(struct pci_mmc_priv), .platdata_auto_alloc_size = sizeof(struct pci_mmc_plat), + ACPI_OPS_PTR(&pci_mmc_acpi_ops) }; static struct pci_device_id mmc_supported[] = { -- 2.27.0.290.gba653c62da-goog
[PATCH v1 14/43] acpi: Support writing named values
Allow writing named integers and strings to the generated ACPI code. Signed-off-by: Simon Glass --- include/acpi/acpigen.h | 72 ++ lib/acpi/acpigen.c | 49 ++ test/dm/acpigen.c | 78 ++ 3 files changed, 199 insertions(+) diff --git a/include/acpi/acpigen.h b/include/acpi/acpigen.h index 19f84dc867..01620fd36b 100644 --- a/include/acpi/acpigen.h +++ b/include/acpi/acpigen.h @@ -231,6 +231,78 @@ void acpigen_write_one(struct acpi_ctx *ctx); */ void acpigen_write_integer(struct acpi_ctx *ctx, u64 data); +/** + * acpigen_write_name_zero() - Write a named zero value + * + * @ctx: ACPI context pointer + * @name: Name of the value + */ +void acpigen_write_name_zero(struct acpi_ctx *ctx, const char *name); + +/** + * acpigen_write_name_one() - Write a named one value + * + * @ctx: ACPI context pointer + * @name: Name of the value + */ +void acpigen_write_name_one(struct acpi_ctx *ctx, const char *name); + +/** + * acpigen_write_name_byte() - Write a named byte value + * + * @ctx: ACPI context pointer + * @name: Name of the value + * @val: Value to write + */ +void acpigen_write_name_byte(struct acpi_ctx *ctx, const char *name, uint val); + +/** + * acpigen_write_name_word() - Write a named word value + * + * @ctx: ACPI context pointer + * @name: Name of the value + * @val: Value to write + */ +void acpigen_write_name_word(struct acpi_ctx *ctx, const char *name, uint val); + +/** + * acpigen_write_name_dword() - Write a named dword value + * + * @ctx: ACPI context pointer + * @name: Name of the value + * @val: Value to write + */ +void acpigen_write_name_dword(struct acpi_ctx *ctx, const char *name, uint val); + +/** + * acpigen_write_name_qword() - Write a named qword value + * + * @ctx: ACPI context pointer + * @name: Name of the value + * @val: Value to write + */ +void acpigen_write_name_qword(struct acpi_ctx *ctx, const char *name, u64 val); + +/** + * acpigen_write_name_integer() - Write a named integer value + * + * @ctx: ACPI context pointer + * @name: Name of the value + * @val: Value to write + */ +void acpigen_write_name_integer(struct acpi_ctx *ctx, const char *name, + u64 val); + +/** + * acpigen_write_name_string() - Write a named string value + * + * @ctx: ACPI context pointer + * @name: Name of the value + * @string: String to write + */ +void acpigen_write_name_string(struct acpi_ctx *ctx, const char *name, + const char *string); + /** * acpigen_write_string() - Write a string * diff --git a/lib/acpi/acpigen.c b/lib/acpi/acpigen.c index 5fe1f59f82..86af88d1bc 100644 --- a/lib/acpi/acpigen.c +++ b/lib/acpi/acpigen.c @@ -142,6 +142,55 @@ void acpigen_write_integer(struct acpi_ctx *ctx, u64 data) acpigen_write_qword(ctx, data); } +void acpigen_write_name_zero(struct acpi_ctx *ctx, const char *name) +{ + acpigen_write_name(ctx, name); + acpigen_write_zero(ctx); +} + +void acpigen_write_name_one(struct acpi_ctx *ctx, const char *name) +{ + acpigen_write_name(ctx, name); + acpigen_write_one(ctx); +} + +void acpigen_write_name_byte(struct acpi_ctx *ctx, const char *name, uint val) +{ + acpigen_write_name(ctx, name); + acpigen_write_byte(ctx, val); +} + +void acpigen_write_name_word(struct acpi_ctx *ctx, const char *name, uint val) +{ + acpigen_write_name(ctx, name); + acpigen_write_word(ctx, val); +} + +void acpigen_write_name_dword(struct acpi_ctx *ctx, const char *name, uint val) +{ + acpigen_write_name(ctx, name); + acpigen_write_dword(ctx, val); +} + +void acpigen_write_name_qword(struct acpi_ctx *ctx, const char *name, u64 val) +{ + acpigen_write_name(ctx, name); + acpigen_write_qword(ctx, val); +} + +void acpigen_write_name_integer(struct acpi_ctx *ctx, const char *name, u64 val) +{ + acpigen_write_name(ctx, name); + acpigen_write_integer(ctx, val); +} + +void acpigen_write_name_string(struct acpi_ctx *ctx, const char *name, + const char *string) +{ + acpigen_write_name(ctx, name); + acpigen_write_string(ctx, string); +} + void acpigen_emit_stream(struct acpi_ctx *ctx, const char *data, int size) { int i; diff --git a/test/dm/acpigen.c b/test/dm/acpigen.c index 5cd7fb5657..4fcd155b93 100644 --- a/test/dm/acpigen.c +++ b/test/dm/acpigen.c @@ -1010,3 +1010,81 @@ static int dm_test_acpi_device(struct unit_test_state *uts) return 0; } DM_TEST(dm_test_acpi_device, 0); + +/* Test writing named values */ +static int dm_test_acpi_write_name(struct unit_test_state *uts) +{ + const char *name = "\\_SB." ACPI_TEST_DEV_NAME; + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + ptr = acpigen_get_current(ctx); + + acpigen_write_name_zero(ctx, name); + acpigen_write_name_one(ctx, name); + acpigen_writ
[PATCH v1 08/43] acpi: Export functions to write sized values
At present only acpigen_write_integer() is exported for use by other code. But in some cases it is useful to call the specific function depending on the size of the value. Export these functions and add a test. Signed-off-by: Simon Glass --- include/acpi/acpigen.h | 46 ++ test/dm/acpigen.c | 45 - 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/include/acpi/acpigen.h b/include/acpi/acpigen.h index d68dca5dde..7c117c1cf6 100644 --- a/include/acpi/acpigen.h +++ b/include/acpi/acpigen.h @@ -169,6 +169,52 @@ void acpigen_pop_len(struct acpi_ctx *ctx); */ char *acpigen_write_package(struct acpi_ctx *ctx, int nr_el); +/** + * acpigen_write_byte() - Write a byte + * + * @ctx: ACPI context pointer + * @data: Value to write + */ +void acpigen_write_byte(struct acpi_ctx *ctx, unsigned int data); + +/** + * acpigen_write_word() - Write a word + * + * @ctx: ACPI context pointer + * @data: Value to write + */ +void acpigen_write_word(struct acpi_ctx *ctx, unsigned int data); + +/** + * acpigen_write_dword() - Write a dword + * + * @ctx: ACPI context pointer + * @data: Value to write + */ +void acpigen_write_dword(struct acpi_ctx *ctx, unsigned int data); + +/** + * acpigen_write_qword() - Write a qword + * + * @ctx: ACPI context pointer + * @data: Value to write + */ +void acpigen_write_qword(struct acpi_ctx *ctx, u64 data); + +/** + * acpigen_write_zero() - Write zero + * + * @ctx: ACPI context pointer + */ +void acpigen_write_zero(struct acpi_ctx *ctx); + +/** + * acpigen_write_one() - Write one + * + * @ctx: ACPI context pointer + */ +void acpigen_write_one(struct acpi_ctx *ctx); + /** * acpigen_write_integer() - Write an integer * diff --git a/test/dm/acpigen.c b/test/dm/acpigen.c index ea2033a27c..0322dd4f60 100644 --- a/test/dm/acpigen.c +++ b/test/dm/acpigen.c @@ -861,5 +861,48 @@ static int dm_test_acpi_power_seq(struct unit_test_state *uts) return 0; } - DM_TEST(dm_test_acpi_power_seq, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); + +/* Test writing values */ +static int dm_test_acpi_write_values(struct unit_test_state *uts) +{ + struct acpi_ctx *ctx; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + ptr = acpigen_get_current(ctx); + + acpigen_write_zero(ctx); + acpigen_write_one(ctx); + acpigen_write_byte(ctx, TEST_INT8); + acpigen_write_word(ctx, TEST_INT16); + acpigen_write_dword(ctx, TEST_INT32); + acpigen_write_qword(ctx, TEST_INT64); + + ut_asserteq(ZERO_OP, *ptr++); + + ut_asserteq(ONE_OP, *ptr++); + + ut_asserteq(BYTE_PREFIX, *ptr++); + ut_asserteq(TEST_INT8, *ptr++); + + ut_asserteq(WORD_PREFIX, *ptr++); + ut_asserteq(TEST_INT16, get_unaligned((u16 *)ptr)); + ptr += 2; + + ut_asserteq(DWORD_PREFIX, *ptr++); + ut_asserteq(TEST_INT32, get_unaligned((u32 *)ptr)); + ptr += 4; + + ut_asserteq(QWORD_PREFIX, *ptr++); + ut_asserteq_64(TEST_INT64, get_unaligned((u64 *)ptr)); + ptr += 8; + + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_write_values, 0); + -- 2.27.0.290.gba653c62da-goog
[PATCH v1 10/43] acpi: Support generation of a generic register
Allow writing out a generic register. Signed-off-by: Simon Glass --- include/acpi/acpi_device.h | 1 + include/acpi/acpigen.h | 28 +++ lib/acpi/acpigen.c | 71 ++ test/dm/acpigen.c | 46 4 files changed, 146 insertions(+) diff --git a/include/acpi/acpi_device.h b/include/acpi/acpi_device.h index d076b452b5..474ac8955f 100644 --- a/include/acpi/acpi_device.h +++ b/include/acpi/acpi_device.h @@ -20,6 +20,7 @@ struct udevice; /* ACPI descriptor values for common descriptors: SERIAL_BUS means I2C */ #define ACPI_DESCRIPTOR_LARGE BIT(7) +#define ACPI_DESCRIPTOR_REGISTER (ACPI_DESCRIPTOR_LARGE | 2) #define ACPI_DESCRIPTOR_INTERRUPT (ACPI_DESCRIPTOR_LARGE | 9) #define ACPI_DESCRIPTOR_GPIO (ACPI_DESCRIPTOR_LARGE | 12) #define ACPI_DESCRIPTOR_SERIAL_BUS (ACPI_DESCRIPTOR_LARGE | 14) diff --git a/include/acpi/acpigen.h b/include/acpi/acpigen.h index af66c9828f..4361a28a08 100644 --- a/include/acpi/acpigen.h +++ b/include/acpi/acpigen.h @@ -13,6 +13,7 @@ #include struct acpi_ctx; +struct acpi_gen_regaddr; struct acpi_gpio; /* Top 4 bits of the value used to indicate a three-byte length value */ @@ -21,6 +22,8 @@ struct acpi_gpio; #define ACPI_METHOD_NARGS_MASK 0x7 #define ACPI_METHOD_SERIALIZED_MASKBIT(3) +#define ACPI_END_TAG 0x79 + /* ACPI Op/Prefix codes */ enum { ZERO_OP = 0x00, @@ -315,6 +318,31 @@ void acpigen_write_method_serialized(struct acpi_ctx *ctx, const char *name, */ void acpigen_write_sta(struct acpi_ctx *ctx, uint status); +/** + * acpigen_write_resourcetemplate_header() - Write a ResourceTemplate header + * + * @ctx: ACPI context pointer + */ +void acpigen_write_resourcetemplate_header(struct acpi_ctx *ctx); + +/** + * acpigen_write_resourcetemplate_footer() - Write a ResourceTemplate footer + * + * @ctx: ACPI context pointer + */ +void acpigen_write_resourcetemplate_footer(struct acpi_ctx *ctx); + +/** + * acpigen_write_register_resource() - Write a register resource + * + * This writes a header, the address information and a footer + * + * @ctx: ACPI context pointer + * @addr: Address to write + */ +void acpigen_write_register_resource(struct acpi_ctx *ctx, +const struct acpi_gen_regaddr *addr); + /** * acpigen_write_sleep() - Write a sleep operation * diff --git a/lib/acpi/acpigen.c b/lib/acpi/acpigen.c index 77d6434806..6f5972f1f7 100644 --- a/lib/acpi/acpigen.c +++ b/lib/acpi/acpigen.c @@ -14,6 +14,7 @@ #include #include #include +#include #include u8 *acpigen_get_current(struct acpi_ctx *ctx) @@ -296,6 +297,76 @@ void acpigen_write_sta(struct acpi_ctx *ctx, uint status) acpigen_pop_len(ctx); } +static void acpigen_write_register(struct acpi_ctx *ctx, + const struct acpi_gen_regaddr *addr) +{ + /* See ACPI v6.3 section 6.4.3.7: Generic Register Descriptor */ + acpigen_emit_byte(ctx, ACPI_DESCRIPTOR_REGISTER); + acpigen_emit_byte(ctx, 0x0c); /* Register Length 7:0 */ + acpigen_emit_byte(ctx, 0x00); /* Register Length 15:8 */ + acpigen_emit_byte(ctx, addr->space_id); + acpigen_emit_byte(ctx, addr->bit_width); + acpigen_emit_byte(ctx, addr->bit_offset); + acpigen_emit_byte(ctx, addr->access_size); + acpigen_emit_dword(ctx, addr->addrl); + acpigen_emit_dword(ctx, addr->addrh); +} + +void acpigen_write_resourcetemplate_header(struct acpi_ctx *ctx) +{ + /* +* A ResourceTemplate() is a Buffer() with a +* (Byte|Word|DWord) containing the length, followed by one or more +* resource items, terminated by the end tag. +* (small item 0xf, len 1) +*/ + acpigen_emit_byte(ctx, BUFFER_OP); + acpigen_write_len_f(ctx); + acpigen_emit_byte(ctx, WORD_PREFIX); + ctx->len_stack[ctx->ltop++] = ctx->current; + + /* +* Add two dummy bytes for the ACPI word (keep aligned with the +* calculation in acpigen_write_resourcetemplate_footer() below) +*/ + acpigen_emit_byte(ctx, 0x00); + acpigen_emit_byte(ctx, 0x00); +} + +void acpigen_write_resourcetemplate_footer(struct acpi_ctx *ctx) +{ + char *p = ctx->len_stack[--ctx->ltop]; + int len; + /* +* See ACPI v6.3 section 6.4.2.9: End Tag +* 0x79 +* 0x00 is treated as a good checksum according to the spec +* and is what iasl generates. +*/ + acpigen_emit_byte(ctx, ACPI_END_TAG); + acpigen_emit_byte(ctx, 0x00); + + /* +* Start counting past the 2-bytes length added in +* acpigen_write_resourcetemplate_header() above +*/ + len = (char *)ctx->current - (p + 2); + + /* patch len word */ + p[0] = len & 0xff; + p[1] = (len >> 8) & 0xff; + + acpigen_pop_len(ctx);
[PATCH v1 07/43] dm: acpi: Add support for the NHLT table
The Intel Non-High-Definition-Audio Link Table (NHLT) table describes the audio codecs and connections in a system. Various devices can contribute information to produce the table. Add core support for this, based on a structure which is built up through calls to the driver. Signed-off-by: Simon Glass --- drivers/core/acpi.c | 15 +++ include/dm/acpi.h | 26 ++ 2 files changed, 41 insertions(+) diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c index ea304a3067..a5053fec6f 100644 --- a/drivers/core/acpi.c +++ b/drivers/core/acpi.c @@ -31,6 +31,7 @@ enum method_t { METHOD_WRITE_TABLES, METHOD_FILL_SSDT, METHOD_INJECT_DSDT, + METHOD_SETUP_NHLT, }; /* Prototype for all methods */ @@ -239,6 +240,8 @@ acpi_method acpi_get_method(struct udevice *dev, enum method_t method) return aops->fill_ssdt; case METHOD_INJECT_DSDT: return aops->inject_dsdt; + case METHOD_SETUP_NHLT: + return aops->setup_nhlt; } } @@ -325,3 +328,15 @@ int acpi_write_dev_tables(struct acpi_ctx *ctx) return ret; } + +int acpi_setup_nhlt(struct acpi_ctx *ctx, struct nhlt *nhlt) +{ + int ret; + + log_debug("Setup NHLT\n"); + ctx->nhlt = nhlt; + ret = acpi_recurse_method(ctx, dm_root(), METHOD_SETUP_NHLT, TYPE_NONE); + log_debug("Setup finished, err=%d\n", ret); + + return ret; +} diff --git a/include/dm/acpi.h b/include/dm/acpi.h index b6308b9fa6..a7f8e10ee2 100644 --- a/include/dm/acpi.h +++ b/include/dm/acpi.h @@ -27,6 +27,8 @@ #if !defined(__ACPI__) +struct nhlt; + /** enum acpi_dump_option - selects what ACPI information to dump */ enum acpi_dump_option { ACPI_DUMP_LIST, /* Just the list of items */ @@ -44,6 +46,9 @@ enum acpi_dump_option { * adding a new table. The RSDP holds pointers to the RSDT and XSDT. * @rsdt: Pointer to the Root System Description Table * @xsdt: Pointer to the Extended System Description Table + * @nhlt: Intel Non-High-Definition-Audio Link Table (NHLT) pointer, used to + * build up information that audio codecs need to provide in the NHLT ACPI + * table * @len_stack: Stack of 'length' words to fix up later * @ltop: Points to current top of stack (0 = empty) */ @@ -53,6 +58,7 @@ struct acpi_ctx { struct acpi_rsdp *rsdp; struct acpi_rsdt *rsdt; struct acpi_xsdt *xsdt; + struct nhlt *nhlt; char *len_stack[ACPIGEN_LENSTACK_SIZE]; int ltop; }; @@ -106,6 +112,15 @@ struct acpi_ops { * @return 0 if OK, -ve on error */ int (*inject_dsdt)(const struct udevice *dev, struct acpi_ctx *ctx); + + /** +* setup_nhlt() - Set up audio information for this device +* +* The method can add information to ctx->nhlt if it likes +* +* @return 0 if OK, -ENODATA if nothing to add, -ve on error +*/ + int (*setup_nhlt)(const struct udevice *dev, struct acpi_ctx *ctx); }; #define device_get_acpi_ops(dev) ((dev)->driver->acpi_ops) @@ -170,6 +185,17 @@ int acpi_fill_ssdt(struct acpi_ctx *ctx); */ int acpi_inject_dsdt(struct acpi_ctx *ctx); +/** + * acpi_setup_nhlt() - Set up audio information + * + * This is called to set up the nhlt information for all devices. + * + * @ctx: ACPI context to use + * @nhlt: Pointer to nhlt information to add to + * @return 0 if OK, -ve on error + */ +int acpi_setup_nhlt(struct acpi_ctx *ctx, struct nhlt *nhlt); + /** * acpi_dump_items() - Dump out the collected ACPI items * -- 2.27.0.290.gba653c62da-goog
[PATCH v1 02/43] binman: Refactor binman_entry_find() to allow other nodes
At present we can only read from a top-level binman node entry. Refactor this function to produce a second local function which supports reading from any node. Signed-off-by: Simon Glass --- lib/binman.c | 18 -- 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/binman.c b/lib/binman.c index dc3a880882..79d01230dd 100644 --- a/lib/binman.c +++ b/lib/binman.c @@ -29,25 +29,31 @@ struct binman_info { static struct binman_info *binman; -int binman_entry_find(const char *name, struct binman_entry *entry) +int binman_entry_find_(ofnode node, const char *name, struct binman_entry *entry) { - ofnode node; int ret; - node = ofnode_find_subnode(binman->image, name); if (!ofnode_valid(node)) - return log_msg_ret("no binman node", -ENOENT); + node = binman->image; + node = ofnode_find_subnode(node, name); + if (!ofnode_valid(node)) + return log_msg_ret("node", -ENOENT); ret = ofnode_read_u32(node, "image-pos", &entry->image_pos); if (ret) - return log_msg_ret("bad binman node1", ret); + return log_msg_ret("import-pos", ret); ret = ofnode_read_u32(node, "size", &entry->size); if (ret) - return log_msg_ret("bad binman node2", ret); + return log_msg_ret("size", ret); return 0; } +int binman_entry_find(const char *name, struct binman_entry *entry) +{ + return binman_entry_find_(binman->image, name, entry); +} + void binman_set_rom_offset(int rom_offset) { binman->rom_offset = rom_offset; -- 2.27.0.290.gba653c62da-goog
[PATCH v1 09/43] acpi: Support generation of a scope
Add a function to write a scope to the generated ACPI code. Signed-off-by: Simon Glass --- include/acpi/acpigen.h | 10 ++ lib/acpi/acpigen.c | 7 +++ test/dm/acpi.c | 3 +-- test/dm/acpigen.c | 33 - 4 files changed, 50 insertions(+), 3 deletions(-) diff --git a/include/acpi/acpigen.h b/include/acpi/acpigen.h index 7c117c1cf6..af66c9828f 100644 --- a/include/acpi/acpigen.h +++ b/include/acpi/acpigen.h @@ -31,6 +31,7 @@ enum { DWORD_PREFIX= 0x0c, STRING_PREFIX = 0x0d, QWORD_PREFIX= 0x0e, + SCOPE_OP= 0x10, BUFFER_OP = 0x11, PACKAGE_OP = 0x12, METHOD_OP = 0x14, @@ -258,6 +259,14 @@ void acpigen_emit_namestring(struct acpi_ctx *ctx, const char *namepath); */ void acpigen_write_name(struct acpi_ctx *ctx, const char *namepath); +/** + * acpigen_write_scope() - Write a scope + * + * @ctx: ACPI context pointer + * @name: Scope to write (e.g. "\\_SB.ABCD") + */ +void acpigen_write_scope(struct acpi_ctx *ctx, const char *name); + /** * acpigen_write_uuid() - Write a UUID * @@ -396,6 +405,7 @@ void acpigen_write_power_res(struct acpi_ctx *ctx, const char *name, uint level, */ int acpigen_set_enable_tx_gpio(struct acpi_ctx *ctx, u32 tx_state_val, const char *dw0_name, struct acpi_gpio *gpio, + bool enable); #endif diff --git a/lib/acpi/acpigen.c b/lib/acpi/acpigen.c index e0af36f775..77d6434806 100644 --- a/lib/acpi/acpigen.c +++ b/lib/acpi/acpigen.c @@ -257,6 +257,13 @@ void acpigen_write_name(struct acpi_ctx *ctx, const char *namepath) acpigen_emit_namestring(ctx, namepath); } +void acpigen_write_scope(struct acpi_ctx *ctx, const char *name) +{ + acpigen_emit_byte(ctx, SCOPE_OP); + acpigen_write_len_f(ctx); + acpigen_emit_namestring(ctx, name); +} + static void acpigen_write_method_(struct acpi_ctx *ctx, const char *name, uint flags) { diff --git a/test/dm/acpi.c b/test/dm/acpi.c index 7768f9514c..b94c4ba4d1 100644 --- a/test/dm/acpi.c +++ b/test/dm/acpi.c @@ -20,9 +20,8 @@ #include #include #include +#include "acpi.h" -#define ACPI_TEST_DEV_NAME "ABCD" -#define ACPI_TEST_CHILD_NAME "EFGH" #define BUF_SIZE 4096 /** diff --git a/test/dm/acpigen.c b/test/dm/acpigen.c index 0322dd4f60..93dfa301d6 100644 --- a/test/dm/acpigen.c +++ b/test/dm/acpigen.c @@ -18,6 +18,7 @@ #include #include #include +#include "acpi.h" #define TEST_STRING"frogmore" #define TEST_STRING2 "ranch" @@ -359,7 +360,7 @@ DM_TEST(dm_test_acpi_spi, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); */ static int get_length(u8 *ptr) { - if (!(*ptr & 0x80)) + if (!(*ptr & ACPI_PKG_LEN_3_BYTES)) return -EINVAL; return (*ptr & 0xf) | ptr[1] << 4 | ptr[2] << 12; @@ -906,3 +907,33 @@ static int dm_test_acpi_write_values(struct unit_test_state *uts) } DM_TEST(dm_test_acpi_write_values, 0); +/* Test writing a scope */ +static int dm_test_acpi_scope(struct unit_test_state *uts) +{ + char buf[ACPI_PATH_MAX]; + struct acpi_ctx *ctx; + struct udevice *dev; + u8 *ptr; + + ut_assertok(alloc_context(&ctx)); + ptr = acpigen_get_current(ctx); + + ut_assertok(uclass_first_device_err(UCLASS_TEST_ACPI, &dev)); + ut_assertok(acpi_device_path(dev, buf, sizeof(buf))); + acpigen_write_scope(ctx, buf); + acpigen_pop_len(ctx); + + ut_asserteq(SCOPE_OP, *ptr++); + ut_asserteq(13, get_length(ptr)); + ptr += 3; + ut_asserteq(ROOT_PREFIX, *ptr++); + ut_asserteq(DUAL_NAME_PREFIX, *ptr++); + ut_asserteq_strn("_SB_" ACPI_TEST_DEV_NAME, (char *)ptr); + ptr += 8; + ut_asserteq_ptr(ptr, ctx->current); + + free_context(&ctx); + + return 0; +} +DM_TEST(dm_test_acpi_scope, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT); -- 2.27.0.290.gba653c62da-goog
[PATCH v1 05/43] dtoc: Support ACPI paths in of-platdata
The start of an ACPI path typically has backslashes in it. These are not preserved during the translation from device tree to C code, since dtc (correctly) uses the first backslash as an escape character, and dtoc therefore leaves it out of the C string. Fix this with special-case handling. Signed-off-by: Simon Glass --- tools/dtoc/dtb_platdata.py | 4 +++- tools/dtoc/dtoc_test_simple.dts | 1 + tools/dtoc/test_dtoc.py | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/dtoc/dtb_platdata.py b/tools/dtoc/dtb_platdata.py index ecfe0624d1..0f903f54e8 100644 --- a/tools/dtoc/dtb_platdata.py +++ b/tools/dtoc/dtb_platdata.py @@ -102,7 +102,9 @@ def get_value(ftype, value): elif ftype == fdt.TYPE_BYTE: return '%#x' % tools.ToByte(value[0]) elif ftype == fdt.TYPE_STRING: -return '"%s"' % value +# Handle evil ACPI backslashes by adding another backslash before them. +# So "\\_SB.GPO0" in the device tree effectively stays like that in C +return '"%s"' % value.replace('\\', '') elif ftype == fdt.TYPE_BOOL: return 'true' elif ftype == fdt.TYPE_INT64: diff --git a/tools/dtoc/dtoc_test_simple.dts b/tools/dtoc/dtoc_test_simple.dts index 165680bd4b..11bfc4c47a 100644 --- a/tools/dtoc/dtoc_test_simple.dts +++ b/tools/dtoc/dtoc_test_simple.dts @@ -34,6 +34,7 @@ longbytearray = [09 0a 0b 0c]; stringval = "message2"; stringarray = "another", "multi-word", "message"; + acpi-name = "\\_SB.GPO0"; }; spl-test3 { diff --git a/tools/dtoc/test_dtoc.py b/tools/dtoc/test_dtoc.py index 8498e8303c..86cb5a7c05 100755 --- a/tools/dtoc/test_dtoc.py +++ b/tools/dtoc/test_dtoc.py @@ -68,6 +68,7 @@ class TestDtoc(unittest.TestCase): @classmethod def setUpClass(cls): tools.PrepareOutputDir(None) +cls.maxDiff = None @classmethod def tearDownClass(cls): @@ -179,6 +180,7 @@ struct dtd_sandbox_pmic_test { \tfdt64_t\t\treg[2]; }; struct dtd_sandbox_spl_test { +\tconst char * acpi_name; \tbool\t\tboolval; \tunsigned char\tbytearray[3]; \tunsigned char\tbyteval; @@ -216,6 +218,7 @@ U_BOOT_DEVICE(spl_test) = { }; static const struct dtd_sandbox_spl_test dtv_spl_test2 = { +\t.acpi_name\t\t= "_SB.GPO0", \t.bytearray\t\t= {0x1, 0x23, 0x34}, \t.byteval\t\t= 0x8, \t.intarray\t\t= {0x5, 0x0, 0x0, 0x0}, -- 2.27.0.290.gba653c62da-goog
[PATCH v1 03/43] binman: Add way to locate an entry in memory
Add support for accessing an entry's contents in memory-mapped SPI flash. Signed-off-by: Simon Glass --- include/binman.h | 22 ++ lib/binman.c | 23 +++ 2 files changed, 45 insertions(+) diff --git a/include/binman.h b/include/binman.h index baf49f7876..e0b92075e2 100644 --- a/include/binman.h +++ b/include/binman.h @@ -9,6 +9,8 @@ #ifndef _BINMAN_H_ #define _BINMAN_H_ +#include + /** *struct binman_entry - information about a binman entry * @@ -20,6 +22,18 @@ struct binman_entry { u32 size; }; +/** + * binman_entry_map() - Look up the address of an entry in memory + * + * @parent: Parent binman node + * @name: Name of entry + * @bufp: Returns a pointer to the entry + * @sizep: Returns the size of the entry + * @return 0 on success, -EPERM if the ROM offset is not set, -ENOENT if the + * entry cannot be found, other error code other error + */ +int binman_entry_map(ofnode parent, const char *name, void **bufp, int *sizep); + /** * binman_set_rom_offset() - Set the ROM memory-map offset * @@ -41,6 +55,14 @@ void binman_set_rom_offset(int rom_offset); */ int binman_entry_find(const char *name, struct binman_entry *entry); +/** + * binman_section_find_node() - Find a binman node + * + * @name: Name of node to look for + * @return Node that was found, ofnode_null() if not found + */ +ofnode binman_section_find_node(const char *name); + /** * binman_init() - Set up the binman symbol information * diff --git a/lib/binman.c b/lib/binman.c index 79d01230dd..ba4d82963d 100644 --- a/lib/binman.c +++ b/lib/binman.c @@ -11,6 +11,7 @@ #include #include #include +#include /** * struct binman_info - Information needed by the binman library @@ -54,6 +55,28 @@ int binman_entry_find(const char *name, struct binman_entry *entry) return binman_entry_find_(binman->image, name, entry); } +int binman_entry_map(ofnode parent, const char *name, void **bufp, int *sizep) +{ + struct binman_entry entry; + int ret; + + if (binman->rom_offset == ROM_OFFSET_NONE) + return -EPERM; + ret = binman_entry_find_(parent, name, &entry); + if (ret) + return log_msg_ret("entry", ret); + if (sizep) + *sizep = entry.size; + *bufp = map_sysmem(entry.image_pos + binman->rom_offset, entry.size); + + return 0; +} + +ofnode binman_section_find_node(const char *name) +{ + return ofnode_find_subnode(binman->image, name); +} + void binman_set_rom_offset(int rom_offset) { binman->rom_offset = rom_offset; -- 2.27.0.290.gba653c62da-goog
[PATCH v1 00/43] x86: Programmatic generation of ACPI tables (Part C)
This series is split off from the original ACPI series and renumbered to version 1. It includes functions for generating more ACPI constructs as well as I2C, GPIO and sound support. There are also quite a few patches related to getting coral to work correctly with ACPI. Changes in v1: - Add a way to set the binman ROM offset - Add linux/err.h header - Capitalise ACPI_OPS_PTR - Use acpi,ddn instead of acpi,desc - Add a check for invalid node - Add NHLT support - Capitalise ACPI_OPS_PTR - Rebase to master - Use acpi,ddn instead of acpi,desc - Drop the unwanted acpi_device_write_gpio_desc() - Rename max97357a to max98357a - Add NHLT support - Capitalise ACPI_OPS_PTR - Rebase to master - Add a new patch to support building up an NHLT structure - Add new patch to add error checking for csrt table generation - Use acpi_get_path() to get device path - Add new patch to improve designware_i2c debugging - Capitalise ACPI_OPS_PTR Simon Glass (43): binman: Allow setting the ROM offset binman: Refactor binman_entry_find() to allow other nodes binman: Add way to locate an entry in memory acpi: Allow creating the GNVS to fail dtoc: Support ACPI paths in of-platdata dm: core: Add a way of overriding the ACPI device path dm: acpi: Add support for the NHLT table acpi: Export functions to write sized values acpi: Support generation of a scope acpi: Support generation of a generic register acpi: mmc: Generate ACPI info for the PCI SD Card x86: Add bindings for NHLT acpi: Support generation of a device acpi: Support writing named values sound: Add an ACPI driver for Dialog Semicondutor da7219 sound: Add an ACPI driver for Maxim MAX98357ac x86: pinctrl: Add a way to get the pinctrl reg address x86: pinctrl: Update comment for intel_pinctrl_get_pad() x86: pinctrl: Add multi-ACPI control x86: pinctrl: Set up itss in the probe() method x86: pinctrl: Drop the acpi_name member x86: Add support for building up an NHLT structure x86: Add error checking for csrt table generation x86: apl: Use memory-mapped access for VBT x86: gpio: Add support for obtaining ACPI info for a GPIO i2c: designware_i2c: Add a little more debugging i2c: Add log_ret() on error i2c: designware_i2c: Support ACPI table generation p2sb: Add a method to hide the bus x86: apl: Support set_hide() in p2sb driver x86: apl: Hide the p2sb on exit from U-Boot pmc: Move common registers to the header file x86: irq: Support flags for acpi_gpe x86: apl: Fix save/restore of ITSS priorities x86: Add debugging to table writing x86: apl: Adjust FSP-M code to avoid hard-coded address x86: Store the coreboot table address in global_data x86: mp: Allow use of mp_run_on_cpus() without MP x86: Update the comment about booting for FSP2 x86: Drop setup_pcat_compatibility() x86: acpi: Correct the version of the MADT x86: Rename board_final_cleanup() to board_final_init() acpi: Enable ACPI table generation by default on x86 arch/Kconfig | 1 + arch/x86/cpu/acpi_gpe.c | 26 + arch/x86/cpu/apollolake/fsp_m.c | 6 +- arch/x86/cpu/apollolake/fsp_s.c | 56 +- arch/x86/cpu/baytrail/acpi.c | 4 +- arch/x86/cpu/coreboot/coreboot.c | 4 +- arch/x86/cpu/coreboot/tables.c| 8 +- arch/x86/cpu/cpu.c| 21 +- arch/x86/cpu/efi/app.c| 2 +- arch/x86/cpu/i386/cpu.c | 7 +- arch/x86/cpu/intel_common/itss.c | 25 +- arch/x86/cpu/intel_common/p2sb.c | 44 ++ arch/x86/cpu/mp_init.c| 12 +- arch/x86/cpu/quark/acpi.c | 4 +- arch/x86/cpu/quark/quark.c| 2 +- arch/x86/cpu/start.S | 1 + arch/x86/cpu/tangier/acpi.c | 4 +- arch/x86/include/asm/acpi_nhlt.h | 314 arch/x86/include/asm/acpi_table.h | 10 +- arch/x86/include/asm/global_data.h| 2 + arch/x86/include/asm/intel_pinctrl.h | 19 +- arch/x86/include/asm/itss.h | 2 +- arch/x86/include/asm/u-boot-x86.h | 2 - arch/x86/lib/Makefile | 1 + arch/x86/lib/acpi_nhlt.c | 482 ++ arch/x86/lib/acpi_table.c | 32 +- arch/x86/lib/fsp/fsp_common.c | 2 +- arch/x86/lib/fsp2/fsp_silicon_init.c | 1 + arch/x86/lib/tables.c | 38 +- configs/sandbox_defconfig | 4 + doc/device-tree-bindings/device.txt | 23 + doc/device-tree-bindings/sound/da7219.txt | 113 doc/device-tree-bindings/sound/max98357a.txt | 22 + drivers/core/acpi.c | 34 ++ drivers/gpio/intel_gpio.c | 49 +- drivers/i2c/designware_i2c.c
[PATCH v1 04/43] acpi: Allow creating the GNVS to fail
In some cases an internal error may prevent this from working. Update the function return value and report the error. At present the API for writing tables does not easily support reporting errors, but once it is fully updated to use a context pointer, this will be easier. Signed-off-by: Simon Glass --- Changes in v1: - Add linux/err.h header arch/x86/cpu/baytrail/acpi.c | 4 +++- arch/x86/cpu/quark/acpi.c | 4 +++- arch/x86/cpu/tangier/acpi.c | 4 +++- arch/x86/include/asm/acpi_table.h | 10 +- arch/x86/lib/acpi_table.c | 11 +-- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/arch/x86/cpu/baytrail/acpi.c b/arch/x86/cpu/baytrail/acpi.c index b17bc62a2d..07757b88a3 100644 --- a/arch/x86/cpu/baytrail/acpi.c +++ b/arch/x86/cpu/baytrail/acpi.c @@ -139,7 +139,7 @@ void acpi_create_fadt(struct acpi_fadt *fadt, struct acpi_facs *facs, header->checksum = table_compute_checksum(fadt, header->length); } -void acpi_create_gnvs(struct acpi_global_nvs *gnvs) +int acpi_create_gnvs(struct acpi_global_nvs *gnvs) { struct udevice *dev; int ret; @@ -159,6 +159,8 @@ void acpi_create_gnvs(struct acpi_global_nvs *gnvs) gnvs->iuart_en = 1; else gnvs->iuart_en = 0; + + return 0; } /* diff --git a/arch/x86/cpu/quark/acpi.c b/arch/x86/cpu/quark/acpi.c index 26cda3b337..b0406a04e9 100644 --- a/arch/x86/cpu/quark/acpi.c +++ b/arch/x86/cpu/quark/acpi.c @@ -133,8 +133,10 @@ void acpi_create_fadt(struct acpi_fadt *fadt, struct acpi_facs *facs, header->checksum = table_compute_checksum(fadt, header->length); } -void acpi_create_gnvs(struct acpi_global_nvs *gnvs) +int acpi_create_gnvs(struct acpi_global_nvs *gnvs) { /* quark is a uni-processor */ gnvs->pcnt = 1; + + return 0; } diff --git a/arch/x86/cpu/tangier/acpi.c b/arch/x86/cpu/tangier/acpi.c index 4ec8fdd6f8..41bd177e09 100644 --- a/arch/x86/cpu/tangier/acpi.c +++ b/arch/x86/cpu/tangier/acpi.c @@ -107,7 +107,7 @@ u32 acpi_fill_csrt(u32 current) return current; } -void acpi_create_gnvs(struct acpi_global_nvs *gnvs) +int acpi_create_gnvs(struct acpi_global_nvs *gnvs) { struct udevice *dev; int ret; @@ -122,4 +122,6 @@ void acpi_create_gnvs(struct acpi_global_nvs *gnvs) if (ret > 0) gnvs->pcnt = ret; } + + return 0; } diff --git a/arch/x86/include/asm/acpi_table.h b/arch/x86/include/asm/acpi_table.h index 928475cef4..733085c178 100644 --- a/arch/x86/include/asm/acpi_table.h +++ b/arch/x86/include/asm/acpi_table.h @@ -35,7 +35,15 @@ int acpi_create_mcfg_mmconfig(struct acpi_mcfg_mmconfig *mmconfig, u32 base, u16 seg_nr, u8 start, u8 end); u32 acpi_fill_mcfg(u32 current); u32 acpi_fill_csrt(u32 current); -void acpi_create_gnvs(struct acpi_global_nvs *gnvs); + +/** + * acpi_create_gnvs() - Create a GNVS (Global Non Volatile Storage) table + * + * @gnvs: Table to fill in + * @return 0 if OK, -ve on error + */ +int acpi_create_gnvs(struct acpi_global_nvs *gnvs); + ulong write_acpi_tables(ulong start); /** diff --git a/arch/x86/lib/acpi_table.c b/arch/x86/lib/acpi_table.c index eeacfe9b06..27869a0e5e 100644 --- a/arch/x86/lib/acpi_table.c +++ b/arch/x86/lib/acpi_table.c @@ -23,6 +23,7 @@ #include #include #include +#include /* * IASL compiles the dsdt entries and writes the hex values @@ -443,8 +444,14 @@ ulong write_acpi_tables(ulong start_addr) dsdt->checksum = 0; dsdt->checksum = table_compute_checksum((void *)dsdt, dsdt->length); - /* Fill in platform-specific global NVS variables */ - acpi_create_gnvs(ctx->current); + /* +* Fill in platform-specific global NVS variables. If this fails we +* cannot return the error but this should only happen while debugging. +*/ + addr = acpi_create_gnvs(ctx->current); + if (IS_ERR_VALUE(addr)) + printf("Error: Gailed to create GNVS\n"); + acpi_inc_align(ctx, sizeof(struct acpi_global_nvs)); debug("ACPI:* FADT\n"); -- 2.27.0.290.gba653c62da-goog
[PATCH v1 06/43] dm: core: Add a way of overriding the ACPI device path
Some devices such as GPIO need to override the normal path that would be generated by driver model. Add a device-tree property for this. Signed-off-by: Simon Glass --- doc/device-tree-bindings/device.txt | 23 +++ drivers/core/acpi.c | 19 +++ include/dm/acpi.h | 13 + 3 files changed, 55 insertions(+) diff --git a/doc/device-tree-bindings/device.txt b/doc/device-tree-bindings/device.txt index 7140339623..2a5736c598 100644 --- a/doc/device-tree-bindings/device.txt +++ b/doc/device-tree-bindings/device.txt @@ -17,6 +17,8 @@ the acpi,compatible property. System) Device Name) - acpi,hid : Contains the string to use as the HID (Hardware ID) identifier _HID + - acpi,path : Specifies the full ACPI path for a device. This overrides the +normal path built from the driver-model hierarchy - acpi,name : Provides the ACPI name for a device, which is a string consisting of four alphanumeric character (upper case) - acpi,uid : _UID value for device @@ -47,3 +49,24 @@ pcie-a0@14,0 { interrupts-extended = <&acpi_gpe 0x3c 0>; }; }; + +p2sb: p2sb@d,0 { + u-boot,dm-pre-reloc; + reg = <0x02006810 0 0 0 0>; + compatible = "intel,apl-p2sb"; + early-regs = ; + pci,no-autoconfig; + + n { + compatible = "intel,apl-pinctrl"; + u-boot,dm-pre-reloc; + intel,p2sb-port-id = ; + acpi,path = "\\_SB.GPO0"; + gpio_n: gpio-n { + compatible = "intel,gpio"; + u-boot,dm-pre-reloc; + gpio-controller; + #gpio-cells = <2>; + linux-name = "INT3452:00"; + }; + }; diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c index fd58c76087..ea304a3067 100644 --- a/drivers/core/acpi.c +++ b/drivers/core/acpi.c @@ -82,6 +82,25 @@ int acpi_get_name(const struct udevice *dev, char *out_name) return 0; } +int acpi_get_path(const struct udevice *dev, char *out_path, int maxlen) +{ + const char *path; + int ret; + + path = dev_read_string(dev, "acpi,path"); + if (path) { + if (strlen(path) >= maxlen) + return -E2BIG; + strcpy(out_path, path); + return 0; + } + ret = acpi_device_path(dev, out_path, maxlen); + if (ret) + return log_msg_ret("dev", ret); + + return 0; +} + /** * acpi_add_item() - Add a new item to the list of data collected * diff --git a/include/dm/acpi.h b/include/dm/acpi.h index 28d9275ccc..b6308b9fa6 100644 --- a/include/dm/acpi.h +++ b/include/dm/acpi.h @@ -180,6 +180,19 @@ int acpi_inject_dsdt(struct acpi_ctx *ctx); */ void acpi_dump_items(enum acpi_dump_option option); +/** + * acpi_get_path() - Get the full ACPI path for a device + * + * This checks for any override in the device tree and calls acpi_device_path() + * if not + * + * @dev: Device to check + * @out_path: Buffer to place the path in (should be ACPI_PATH_MAX long) + * @maxlen: Size of buffer (typically ACPI_PATH_MAX) + * @return 0 if OK, -ve on error + */ +int acpi_get_path(const struct udevice *dev, char *out_path, int maxlen); + #endif /* __ACPI__ */ #endif -- 2.27.0.290.gba653c62da-goog
[PATCH v1 01/43] binman: Allow setting the ROM offset
On x86 the SPI ROM can be memory-mapped, at least most of it. Add a way to tell binman the offset from a ROM address to a RAM address. Signed-off-by: Simon Glass --- Changes in v1: - Add a way to set the binman ROM offset include/binman.h | 8 lib/binman.c | 17 + 2 files changed, 25 insertions(+) diff --git a/include/binman.h b/include/binman.h index b462dc8542..baf49f7876 100644 --- a/include/binman.h +++ b/include/binman.h @@ -20,6 +20,14 @@ struct binman_entry { u32 size; }; +/** + * binman_set_rom_offset() - Set the ROM memory-map offset + * + * @rom_offset: Offset from an image_pos to the memory-mapped address. This + * tells binman that ROM image_pos x can be addressed at rom_offset + x + */ +void binman_set_rom_offset(int rom_offset); + /** * binman_entry_find() - Find a binman symbol * diff --git a/lib/binman.c b/lib/binman.c index fd7de24bd2..dc3a880882 100644 --- a/lib/binman.c +++ b/lib/binman.c @@ -12,10 +12,21 @@ #include #include +/** + * struct binman_info - Information needed by the binman library + * + * @image: Node describing the image we are running from + * @rom_offset: Offset from an image_pos to the memory-mapped address, or + * ROM_OFFSET_NONE if the ROM is not memory-mapped. Can be positive or + * negative + */ struct binman_info { ofnode image; + int rom_offset; }; +#define ROM_OFFSET_NONE(-1) + static struct binman_info *binman; int binman_entry_find(const char *name, struct binman_entry *entry) @@ -37,6 +48,11 @@ int binman_entry_find(const char *name, struct binman_entry *entry) return 0; } +void binman_set_rom_offset(int rom_offset) +{ + binman->rom_offset = rom_offset; +} + int binman_init(void) { binman = malloc(sizeof(struct binman_info)); @@ -45,6 +61,7 @@ int binman_init(void) binman->image = ofnode_path("/binman"); if (!ofnode_valid(binman->image)) return log_msg_ret("binman node", -EINVAL); + binman->rom_offset = ROM_OFFSET_NONE; return 0; } -- 2.27.0.290.gba653c62da-goog
Re: [RESEND PATCH v2 02/11] net: dwc_eth_qos: Add option "snps,reset-gpio" phy-rst gpio for stm32
Hi Patrick, Yes, this is the case, it should be add at PHY node, and I also used the original writing "snps,reset*" at MAC node. Anyway, I will try to put the reset gpio in the PHY node. 在 2020/5/13 下午8:55, Patrick DELAUNAY 写道: Hi David From: David Wu Sent: mardi 12 mai 2020 11:56 It can be seen that most of the Socs using STM mac, "snps,reset-gpio" gpio is used, adding this option makes reset function more general. Signed-off-by: David Wu --- Changes in v2: - Remove the code is not related (Patrice) drivers/net/dwc_eth_qos.c | 32 +++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 66a02aa80b..92dab678c7 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -314,6 +314,7 @@ struct eqos_priv { struct eqos_tegra186_regs *tegra186_regs; struct reset_ctl reset_ctl; struct gpio_desc phy_reset_gpio; + u32 reset_delays[3]; struct clk clk_master_bus; struct clk clk_rx; struct clk clk_ptp_ref; @@ -739,6 +740,15 @@ static int eqos_start_resets_stm32(struct udevice *dev) debug("%s(dev=%p):\n", __func__, dev); if (dm_gpio_is_valid(&eqos->phy_reset_gpio)) { + ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0); + if (ret < 0) { + pr_err("dm_gpio_set_value(phy_reset, deassert) failed: %d", + ret); + return ret; + } + + udelay(eqos->reset_delays[0]); + ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 1); if (ret < 0) { pr_err("dm_gpio_set_value(phy_reset, assert) failed: %d", @@ -746,7 +756,7 @@ static int eqos_start_resets_stm32(struct udevice *dev) return ret; } - udelay(2); + udelay(eqos->reset_delays[1]); ret = dm_gpio_set_value(&eqos->phy_reset_gpio, 0); if (ret < 0) { @@ -754,6 +764,8 @@ static int eqos_start_resets_stm32(struct udevice *dev) ret); return ret; } + + udelay(eqos->reset_delays[2]); } debug("%s: OK\n", __func__); @@ -1864,11 +1876,29 @@ static int eqos_probe_resources_stm32(struct udevice *dev) if (ret) pr_warn("gpio_request_by_name(phy reset) not provided %d", ret); + else + eqos->reset_delays[1] = 2; eqos->phyaddr = ofnode_read_u32_default(phandle_args.node, "reg", -1); } + if (!dm_gpio_is_valid(&eqos->phy_reset_gpio)) { + int reset_flags = GPIOD_IS_OUT; + + if (dev_read_bool(dev, "snps,reset-active-low")) + reset_flags |= GPIOD_ACTIVE_LOW; + + ret = gpio_request_by_name(dev, "snps,reset-gpio", 0, + &eqos->phy_reset_gpio, reset_flags); + if (ret == 0) + ret = dev_read_u32_array(dev, "snps,reset-delays-us", +eqos->reset_delays, 3); + else + pr_warn("gpio_request_by_name(snps,reset-gpio) failed: %d", + ret); + } + debug("%s: OK\n", __func__); return 0; -- 2.19.1 This obsolete binding isn't expected to be supported in stm32 glue for dwmac (and it tis the purpose of eqos_stm32_config) Reference in linux binding ./Documentation/devicetree/bindings/net/stm32-dwmac.txt (the glue) ./Documentation/devicetree/bindings/net/snps,dwmac.yaml snps,reset-gpio: deprecated: true snps,reset-active-low: deprecated: true snps,reset-delays-us: deprecated: true I expected that gpio reset in future device tree should be managed by only by PHY generic binding (upstream in progress on Linux side for STM32MP15x), as described in: Documentation/devicetree/bindings/net/ethernet-phy.yaml reset-gpios: maxItems: 1 description: The GPIO phandle and specifier for the PHY reset signal. reset-assert-us: description: Delay after the reset was asserted in microseconds. If this property is missing the delay will be skipped. reset-deassert-us: description: Delay after the reset was deasserted in microseconds. If this property is missing the delay will be skipped. See alsoU-Boot: doc/device-tree-bindings/net/phy.txt Something as &mac { status = "okay"; pinctrl-0 = <ðernet_mii>; pinctrl-names = "default"; phy-mode= "mii"; phy-handle = <&phy1>; mdio0 { #address-cells = <1>; #size-cells =
Re: [PATCH 6/6] checkpatch.pl: Request if() instead #ifdef
On Thu, Jun 04, 2020 at 07:39:35PM -0400, Tom Rini wrote: > On Fri, May 22, 2020 at 04:32:40PM -0600, Simon Glass wrote: > > > There is a lot of use of #ifdefs in U-Boot. In an effort reduce this, > > suggest using the compile-time construct. > > > > Signed-off-by: Simon Glass > > Applied to u-boot/master, thanks! This check is simple, but IMHO, too simple. It will generate false-positive, or pointless, warnings for some common use cases. Say, In an include header, #ifdef CONFIG_xxx extern int foo_data; int foo(void); #endif Or in a C file (foo_common.c), #ifdef CONFIG_xxx_a int foo_a(void) ... #endif #ifdef CONFIG_xxx_b int foo_b(void) ... #endif Or, struct baa baa_list[] = { #ifdef CONFIG_xxx data_xxx, #endif ... They are harmless and can be ignored, but also annoying. Can you sophisticate this check? In addition, if I want to stick to this rule, there can co-exist an "old" style and "new" style of code in a single file. (particularly tons of examples in UEFI subsystem) How should we deal with this? Thanks, -Takahiro Akashi > -- > Tom
[PATCH v3 10/10] riscv: Add FPIOA and GPIO support for Kendryte K210
This patch adds the necessary configs and docs for FPIOA and GPIO support on the K210. Signed-off-by: Sean Anderson --- Changes in v3: - Document pins 6 and 7 as not set Changes in v2: - Remove SPI flash related Kconfig settings board/sipeed/maix/Kconfig | 9 ++ doc/board/sipeed/maix.rst | 64 +-- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/board/sipeed/maix/Kconfig b/board/sipeed/maix/Kconfig index 0cdcd32adc..4c42dd2087 100644 --- a/board/sipeed/maix/Kconfig +++ b/board/sipeed/maix/Kconfig @@ -44,4 +44,13 @@ config BOARD_SPECIFIC_OPTIONS imply RESET_SYSCON imply SYSRESET imply SYSRESET_SYSCON + imply PINCTRL + imply PINCONF + imply PINCTRL_K210 + imply DM_GPIO + imply DWAPB_GPIO + imply SIFIVE_GPIO + imply CMD_GPIO + imply LED + imply LED_GPIO endif diff --git a/doc/board/sipeed/maix.rst b/doc/board/sipeed/maix.rst index 06e0008b9f..1865e2adfb 100644 --- a/doc/board/sipeed/maix.rst +++ b/doc/board/sipeed/maix.rst @@ -132,7 +132,7 @@ To run legacy images, use the ``bootm`` command: Load Address: 8000 Entry Point: 8000 -$ picocom -b 115200 /dev/ttyUSB0i +$ picocom -b 115200 /dev/ttyUSB0 => loady ## Ready for binary (ymodem) download to 0x8000 at 115200 bps... C @@ -163,6 +163,66 @@ To run legacy images, use the ``bootm`` command: argv[0] = "" Hit any key to exit ... +Pin Assignment +-- + +The K210 contains a Fully Programmable I/O Array (FPIOA), which can remap any of +its 256 input functions to any any of 48 output pins. The following table has +the default pin assignments for the BitM. + += == === +Pin Function Comment += == === +IO_0 JTAG_TCLK +IO_1 JTAG_TDI +IO_2 JTAG_TMS +IO_3 JTAG_TDO +IO_4 UARTHS_RX +IO_5 UARTHS_TX +IO_6 Not set +IO_7 Not set +IO_8 GPIO_0 +IO_9 GPIO_1 +IO_10 GPIO_2 +IO_11 GPIO_3 +IO_12 GPIO_4 Green LED +IO_13 GPIO_5 Red LED +IO_14 GPIO_6 Blue LED +IO_15 GPIO_7 +IO_16 GPIOHS_0 ISP +IO_17 GPIOHS_1 +IO_18 I2S0_SCLK MIC CLK +IO_19 I2S0_WSMIC WS +IO_20 I2S0_IN_D0 MIC SD +IO_21 GPIOHS_5 +IO_22 GPIOHS_6 +IO_23 GPIOHS_7 +IO_24 GPIOHS_8 +IO_25 GPIOHS_9 +IO_26 SPI1_D1MMC MISO +IO_27 SPI1_SCLK MMC CLK +IO_28 SPI1_D0MMC MOSI +IO_29 GPIOHS_13 MMC CS +IO_30 GPIOHS_14 +IO_31 GPIOHS_15 +IO_32 GPIOHS_16 +IO_33 GPIOHS_17 +IO_34 GPIOHS_18 +IO_35 GPIOHS_19 +IO_36 GPIOHS_20 Panel CS +IO_37 GPIOHS_21 Panel RST +IO_38 GPIOHS_22 Panel DC +IO_39 SPI0_SCK Panel WR +IO_40 SCCP_SDA +IO_41 SCCP_SCLK +IO_42 DVP_RST +IO_43 DVP_VSYNC +IO_44 DVP_PWDN +IO_45 DVP_HSYNC +IO_46 DVP_XCLK +IO_47 DVP_PCLK += == === + Over- and Under-clocking @@ -294,5 +354,5 @@ AddressSize Description 0x8801C000 0x1000riscv priv spec 1.9 config 0x8801D000 0x2000flattened device tree (contains only addresses and interrupts) -0x8801f000 0x1000credits +0x8801F000 0x1000credits == = === -- 2.26.2
[PATCH v3 09/10] riscv: Add pinmux and gpio bindings for Kendryte K210
This patch adds the necessary device tree bindings. Signed-off-by: Sean Anderson --- (no changes since v2) Changes in v2: - Convert to use pinmux property - Don't hog ISP on boot - Re-order GPIOs to match the defaults more closely arch/riscv/dts/k210-maix-bit.dts | 104 +++ arch/riscv/dts/k210.dtsi | 12 2 files changed, 116 insertions(+) diff --git a/arch/riscv/dts/k210-maix-bit.dts b/arch/riscv/dts/k210-maix-bit.dts index 5b32c5fd5f..e840e04ada 100644 --- a/arch/riscv/dts/k210-maix-bit.dts +++ b/arch/riscv/dts/k210-maix-bit.dts @@ -17,6 +17,22 @@ stdout-path = "serial0:115200"; }; + gpio-leds { + compatible = "gpio-leds"; + + green { + gpios = <&gpio1_0 4 GPIO_ACTIVE_LOW>; + }; + + red { + gpios = <&gpio1_0 5 GPIO_ACTIVE_LOW>; + }; + + blue { + gpios = <&gpio1_0 6 GPIO_ACTIVE_LOW>; + }; + }; + sound { compatible = "simple-audio-card"; simple-audio-card,format = "i2s"; @@ -39,9 +55,97 @@ }; &uarths0 { + pinctrl-0 = <&fpioa_uarths>; + pinctrl-names = "default"; + status = "okay"; +}; + +&gpio0 { + pinctrl-0 = <&fpioa_gpiohs>; + pinctrl-names = "default"; + status = "okay"; +}; + +&gpio1 { + pinctrl-0 = <&fpioa_gpio>; + pinctrl-names = "default"; status = "okay"; }; &i2s0 { #sound-dai-cells = <1>; + pinctrl-0 = <&fpioa_i2s0>; + pinctrl-names = "default"; +}; + +&fpioa { + status = "okay"; + + fpioa_uarths: uarths { + pinmux = , +; + }; + + fpioa_gpio: gpio { + pinmux = , +, +, +, +, +, +, +; + }; + + fpioa_gpiohs: gpiohs { + pinmux = , +, +, +, +, +, +, +, +, +, +, +, +; + }; + + fpioa_i2s0: i2s0 { + pinmux = , +, +; + }; + + fpioa_dvp: dvp { + pinmux = , +, +, +, +, +, +, +; + }; + + fpioa_spi0: spi0 { + pinmux = , /* cs */ +, /* rst */ +, /* dc */ +; /* wr */ + }; + + fpioa_spi1: spi1 { + pinmux = , +, +, +; + }; +}; + +&dvp0 { + pinctrl-0 = <&fpioa_dvp>; + pinctrl-names = "default"; }; diff --git a/arch/riscv/dts/k210.dtsi b/arch/riscv/dts/k210.dtsi index 2546c7d4e0..fc7986b326 100644 --- a/arch/riscv/dts/k210.dtsi +++ b/arch/riscv/dts/k210.dtsi @@ -5,6 +5,7 @@ #include #include +#include #include / { @@ -367,7 +368,18 @@ reg = <0x502B 0x100>; clocks = <&sysclk K210_CLK_FPIOA>; resets = <&sysrst K210_RST_FPIOA>; + kendryte,sysctl = <&sysctl>; + kendryte,power-offset = ; + pinctrl-0 = <&fpioa_jtag>; + pinctrl-names = "default"; status = "disabled"; + + fpioa_jtag: jtag { + pinmux = , +, +, +; + }; }; sha256: sha256@502C { -- 2.26.2
[PATCH v3 03/10] pinctrl: Add support for Kendryte K210 FPIOA
The Fully-Programmable Input/Output Array (FPIOA) device controls pin multiplexing on the K210. The FPIOA can remap any supported function to any multifunctional IO pin. It can also perform basic GPIO functions, such as reading the current value of a pin. However, GPIO functionality remains largely unimplemented (in favor of the dedicated GPIO peripherals). Signed-off-by: Sean Anderson --- This patch was previously submitted as part of https://patchwork.ozlabs.org/project/uboot/list/?series=161576 Changes from that version include: - Reformat to reduce errors from checkpatch (no changes since v2) Changes in v2: - Don't clear existing pinctrl settings on probe - Rewrite to use pinmux property - Support muxing the output enable signal for each function - Support output and input inversion - Update binding documentation MAINTAINERS | 2 + .../pinctrl/kendryte,k210-fpioa.txt | 102 +++ drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/kendryte/Kconfig | 7 + drivers/pinctrl/kendryte/Makefile | 1 + drivers/pinctrl/kendryte/pinctrl.c| 678 ++ drivers/pinctrl/kendryte/pinctrl.h| 70 ++ include/dt-bindings/pinctrl/k210-pinctrl.h| 277 +++ 9 files changed, 1139 insertions(+) create mode 100644 doc/device-tree-bindings/pinctrl/kendryte,k210-fpioa.txt create mode 100644 drivers/pinctrl/kendryte/Kconfig create mode 100644 drivers/pinctrl/kendryte/Makefile create mode 100644 drivers/pinctrl/kendryte/pinctrl.c create mode 100644 drivers/pinctrl/kendryte/pinctrl.h create mode 100644 include/dt-bindings/pinctrl/k210-pinctrl.h diff --git a/MAINTAINERS b/MAINTAINERS index 2b58cf7d94..e0bae4f199 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -876,7 +876,9 @@ RISC-V KENDRYTE M: Sean Anderson S: Maintained F: doc/device-tree-bindings/mfd/kendryte,k210-sysctl.txt +F: doc/device-tree-bindings/pinctrl/kendryte,k210-fpioa.txt F: drivers/clk/kendryte/ +F: drivers/pinctrl/kendryte/ F: include/kendryte/ RNG diff --git a/doc/device-tree-bindings/pinctrl/kendryte,k210-fpioa.txt b/doc/device-tree-bindings/pinctrl/kendryte,k210-fpioa.txt new file mode 100644 index 00..06a9cc060f --- /dev/null +++ b/doc/device-tree-bindings/pinctrl/kendryte,k210-fpioa.txt @@ -0,0 +1,102 @@ +Kendryte K210 FPIOA + +This binding describes the Fully-Programmable Input/Output Array (FPIOA) found +in Kendryte K210 SoCs. Any of the 256 functions can be mapped to any of the 48 +pins. + +Required properties: +- compatible: should be "kendryte,k210-fpioa" +- reg: address and length of the FPIOA registers +- kendryte,sysctl: phandle to the "sysctl" register map node +- kendryte,power-offset: offset in the register map of the power bank control + register (in bytes) + +Configuration nodes + +Pin configuration nodes are documented in pinctrl-bindings.txt + +Required properties for pin-configuration nodes or sub-nodes are: +- groups: list of power groups to which the configuration applies. Valid groups + are: + A0, A1, A2, B0, B1, B2, C0, C1 + (either this or "pinmux" must be specified) +- pinmux: integer array representing pin multiplexing configuration. In addition + to the 256 standard functions, each pin can also output the direction + indicator (DO) of any function. This signal is high whenever the function + would normally drive the output. Helper macros to ease assembling the "pinmux" + arguments from the pin and function are provided by the FPIOA header file at: + + Integer values in the "pinmux" argument list are assembled as: + ((PIN << 16) | (DO << 8) | (FUNC)) + Valid values for PIN are numbers 0 through 47. + Valid values for DO are 0 or 1. + Valid values for FUNC are numbers 0 through 255. For a complete list of + acceptable functions, consult the FPIOA header file. + (either this or "groups" must be specified) + +Optional properties for "pinmux" nodes are: + bias-disable, bias-pull-down, bias-pull-up, drive-strength, + drive-strength-ua, input-enable, input-disable, input-schmitt-enable, + input-schmitt-disable, output-low, output-high, output-enable, + output-disable, slew-rate, output-polarity-invert, input-polarity-invert + +Optional properties for "groups" nodes are: + power-source + +Notes on specific properties include: +- bias-pull-up, -down, and -pin-default: The pull strength cannot be configured. +- drive-strength: There are 8 drive strength settings between 11 and 50 mA. +- input- and output-polarity-invert: Invert the polarity of either the input or + the output, respectively. +- power-source: Controls the output voltage of a bank of pins. Either + K210_PC_POWER_1V8 or K210_PC_POWER_3V3 may be specified. +- slew-rate: Specifying this property reduces the slew rate. + +Example: +fpioa: pinmux@502B { + compatible = "kendryt
[PATCH v3 05/10] gpio: dw: Fix warnings about casting int to pointer
Change the type of gpio_dwabp_platdata.base from fdt_addr_t to a void pointer, since we pass it to readl. Signed-off-by: Sean Anderson Reviewed-by: Ley Foon Tan Reviewed-by: Bin Meng --- This patch was previously submitted as part of https://patchwork.ozlabs.org/project/uboot/list/?series=161576 (no changes since v1) drivers/gpio/dwapb_gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpio/dwapb_gpio.c b/drivers/gpio/dwapb_gpio.c index e5e3518194..bf324f5239 100644 --- a/drivers/gpio/dwapb_gpio.c +++ b/drivers/gpio/dwapb_gpio.c @@ -40,7 +40,7 @@ struct gpio_dwapb_platdata { const char *name; int bank; int pins; - fdt_addr_t base; + void __iomem*base; }; static int dwapb_gpio_direction_input(struct udevice *dev, unsigned pin) @@ -176,7 +176,7 @@ static int gpio_dwapb_bind(struct udevice *dev) if (!plat) return -ENOMEM; - plat->base = base; + plat->base = (void *)base; plat->bank = bank; plat->pins = ofnode_read_u32_default(node, "snps,nr-gpios", 0); -- 2.26.2
[PATCH v3 06/10] gpio: dw: Add a trailing underscore to generated name
Previously, if there was no bank-name property, it was easy to have confusing gpio names like "gpio1@08", instead of "gpio1@0_8". This patch follows the example of the sifive gpio driver. Signed-off-by: Sean Anderson --- This patch was previously submitted as part of https://patchwork.ozlabs.org/project/uboot/list/?series=161576 (no changes since v1) drivers/gpio/dwapb_gpio.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/gpio/dwapb_gpio.c b/drivers/gpio/dwapb_gpio.c index bf324f5239..a52c9e18e3 100644 --- a/drivers/gpio/dwapb_gpio.c +++ b/drivers/gpio/dwapb_gpio.c @@ -186,7 +186,15 @@ static int gpio_dwapb_bind(struct udevice *dev) * Fall back to node name. This means accessing pins * via bank name won't work. */ - plat->name = ofnode_get_name(node); + char name[32]; + + snprintf(name, sizeof(name), "%s_", +ofnode_get_name(node)); + plat->name = strdup(name); + if (!plat->name) { + kfree(plat); + return -ENOMEM; + } } ret = device_bind_ofnode(dev, dev->driver, plat->name, -- 2.26.2
[PATCH v3 08/10] led: gpio: Default to using node name if label is absent
This more closely mirrors Linux's behaviour, and will make it easier to transition to using function+color in the future. Signed-off-by: Sean Anderson --- This patch was previously submitted as part of https://patchwork.ozlabs.org/project/uboot/list/?series=161576 (no changes since v1) drivers/led/led_gpio.c | 7 ++- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/led/led_gpio.c b/drivers/led/led_gpio.c index ef9b61ee62..2cdb0269f4 100644 --- a/drivers/led/led_gpio.c +++ b/drivers/led/led_gpio.c @@ -99,11 +99,8 @@ static int led_gpio_bind(struct udevice *parent) const char *label; label = ofnode_read_string(node, "label"); - if (!label) { - debug("%s: node %s has no label\n", __func__, - ofnode_get_name(node)); - return -EINVAL; - } + if (!label) + label = ofnode_get_name(node); ret = device_bind_driver_to_node(parent, "gpio_led", ofnode_get_name(node), node, &dev); -- 2.26.2
[PATCH v3 07/10] gpio: dw: Return output value when direction is out
dm_gpio_ops.get_value can be called when the gpio is either input or output. The current dw code always returns the input value, which is invalid if the direction is set to out. Signed-off-by: Sean Anderson Reviewed-by: Ley Foon Tan --- This patch was previously submitted as part of https://patchwork.ozlabs.org/project/uboot/list/?series=161576 Changes in v3: - Undo reorder to prevent use-before-declared error Changes in v2: - Reorder changes to minimize diff drivers/gpio/dwapb_gpio.c | 19 --- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpio/dwapb_gpio.c b/drivers/gpio/dwapb_gpio.c index a52c9e18e3..37916e7771 100644 --- a/drivers/gpio/dwapb_gpio.c +++ b/drivers/gpio/dwapb_gpio.c @@ -66,13 +66,6 @@ static int dwapb_gpio_direction_output(struct udevice *dev, unsigned pin, return 0; } -static int dwapb_gpio_get_value(struct udevice *dev, unsigned pin) -{ - struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); - return !!(readl(plat->base + GPIO_EXT_PORT(plat->bank)) & (1 << pin)); -} - - static int dwapb_gpio_set_value(struct udevice *dev, unsigned pin, int val) { struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); @@ -98,6 +91,18 @@ static int dwapb_gpio_get_function(struct udevice *dev, unsigned offset) return GPIOF_INPUT; } +static int dwapb_gpio_get_value(struct udevice *dev, unsigned pin) +{ + struct gpio_dwapb_platdata *plat = dev_get_platdata(dev); + u32 value; + + if (dwapb_gpio_get_function(dev, pin) == GPIOF_OUTPUT) + value = readl(plat->base + GPIO_SWPORT_DR(plat->bank)); + else + value = readl(plat->base + GPIO_EXT_PORT(plat->bank)); + return !!(value & BIT(pin)); +} + static const struct dm_gpio_ops gpio_dwapb_ops = { .direction_input= dwapb_gpio_direction_input, .direction_output = dwapb_gpio_direction_output, -- 2.26.2
[PATCH v3 02/10] test: pinmux: Add test for pin muxing
This extends the pinctrl-sandbox driver to support pin muxing, and adds a test for that behaviour. The test is done in C and not python (like the existing tests for the pinctrl uclass) because it needs to call pinctrl_select_state. Another option could be to add a command that invokes pinctrl_select_state and then test everything in test/py/tests/test_pinmux.py. The pinctrl-sandbox driver now mimics the way that many pinmux devices work. There are two groups of pins which are muxed together, as well as four pins which are muxed individually. I have tried to test all normal paths. However, very few error cases are explicitly checked for. Signed-off-by: Sean Anderson --- Changes in v3: - Add dt-bindings/pinctrl/sandbox-pinmux.h to patch Changes in v2: - New arch/sandbox/dts/test.dts| 45 +- drivers/pinctrl/pinctrl-sandbox.c| 155 ++- include/dt-bindings/pinctrl/sandbox-pinmux.h | 19 +++ test/dm/Makefile | 3 + test/py/tests/test_pinmux.py | 36 ++--- 5 files changed, 197 insertions(+), 61 deletions(-) create mode 100644 include/dt-bindings/pinctrl/sandbox-pinmux.h diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index f5b685f7fe..36736f374d 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -2,6 +2,7 @@ #include #include +#include / { model = "sandbox"; @@ -967,30 +968,60 @@ pinctrl { compatible = "sandbox,pinctrl"; - pinctrl-names = "default"; - pinctrl-0 = <&gpios>; + pinctrl-names = "default", "alternate"; + pinctrl-0 = <&pinctrl_gpios>, <&pinctrl_i2s>; + pinctrl-1 = <&pinctrl_spi>, <&pinctrl_i2c>; - gpios: gpios { + pinctrl_gpios: gpios { gpio0 { - pins = "GPIO0"; + pins = "P5"; + function = "GPIO"; bias-pull-up; input-disable; }; gpio1 { - pins = "GPIO1"; + pins = "P6"; + function = "GPIO"; output-high; drive-open-drain; }; gpio2 { - pins = "GPIO2"; + pinmux = ; bias-pull-down; input-enable; }; gpio3 { - pins = "GPIO3"; + pinmux = ; bias-disable; }; }; + + pinctrl_i2c: i2c { + groups { + groups = "I2C_UART"; + function = "I2C"; + }; + + pins { + pins = "P0", "P1"; + drive-open-drain; + }; + }; + + pinctrl_i2s: i2s { + groups = "SPI_I2S"; + function = "I2S"; + }; + + pinctrl_spi: spi { + groups = "SPI_I2S"; + function = "SPI"; + + cs { + pinmux = , +; + }; + }; }; hwspinlock@0 { diff --git a/drivers/pinctrl/pinctrl-sandbox.c b/drivers/pinctrl/pinctrl-sandbox.c index ac0119d198..9aa13fbd55 100644 --- a/drivers/pinctrl/pinctrl-sandbox.c +++ b/drivers/pinctrl/pinctrl-sandbox.c @@ -3,55 +3,67 @@ * Copyright (C) 2015 Masahiro Yamada */ -/* #define DEBUG */ - #include #include -#include #include +#include +#include #include +/* + * This driver emulates a pin controller with the following rules: + * - The pinctrl config for each pin must be set individually + * - The first three pins (P0-P2) must be muxed as a group + * - The next two pins (P3-P4) must be muxed as a group + * - The last four pins (P5-P8) must be muxed individually + */ + static const char * const sandbox_pins[] = { - "SCL", - "SDA", - "TX", - "RX", - "W1", - "GPIO0", - "GPIO1", - "GPIO2", - "GPIO3", +#define PIN(x) \ + [x] = "P" #x + PIN(0), + PIN(1), + PIN(2), + PIN(3), + PIN(4), + PIN(5), + PIN(6), + PIN(7), + PIN(8), +#undef PIN }; -static const char * const sandbox_pins_muxing[] = { - "I2C SCL", - "I2C SDA", - "Uart TX", - "Uart RX", - "1-wire gpio", - "gp
[PATCH v3 01/10] pinctrl: Add pinmux property support to pinctrl-generic
The pinmux property allows for smaller and more compact device trees, especially when there are many pins which need to be assigned individually. Instead of specifying an array of strings to be parsed as pins and a function property, the pinmux property contains an array of integers representing pinmux groups. A pinmux group consists of the pin identifier and mux settings represented as a single integer or an array of integers. Each individual pin controller driver specifies the exact format of a pinmux group. As specified in the Linux documentation, a pinmux group may be multiple integers long. However, no existing drivers use multi-integer pinmux groups, so I have chosen to omit this feature. This makes the implementation easier, since there is no need to allocate a buffer to do endian conversions. Support for the pinmux property is done differently than in Linux. As far as I can tell, inversion of control is used when implementing support for the pins and groups properties to avoid allocating. This results in some duplication of effort; every property in a config node is parsed once for each pin in that node. This is not such an overhead with pins and groups properties, since having multiple pins in one config node does not occur especially often. However, the semantics of the pinmux property make such a configuration much more appealing. A future patch could parse all config properties at once and store them in an array. This would make it easier to create drivers which do not function solely as callbacks from pinctrl-generic. This commit increases the size of the sandbox build by approximately 48 bytes. However, it also decreases the size of the K210 device tree by 2 KiB from the previous version of this series. The documentation has been updated from the last Linux commit before it was split off into yaml files. Signed-off-by: Sean Anderson --- (no changes since v2) Changes in v2: - New .../pinctrl/pinctrl-bindings.txt | 65 - drivers/pinctrl/pinctrl-generic.c | 125 ++ include/dm/pinctrl.h | 21 +-- 3 files changed, 168 insertions(+), 43 deletions(-) diff --git a/doc/device-tree-bindings/pinctrl/pinctrl-bindings.txt b/doc/device-tree-bindings/pinctrl/pinctrl-bindings.txt index b73c96d24f..603796f169 100644 --- a/doc/device-tree-bindings/pinctrl/pinctrl-bindings.txt +++ b/doc/device-tree-bindings/pinctrl/pinctrl-bindings.txt @@ -119,7 +119,8 @@ For example: The contents of each of those pin configuration child nodes is defined entirely by the binding for the individual pin controller device. There -exists no common standard for this content. +exists no common standard for this content. The pinctrl framework only +provides generic helper bindings that the pin controller driver can use. The pin configuration nodes need not be direct children of the pin controller device; they may be grandchildren, for example. Whether this is legal, and @@ -156,6 +157,29 @@ state_2_node_a { pins = "mfio29", "mfio30"; }; +For hardware where pin multiplexing configurations have to be specified for +each single pin the number of required sub-nodes containing "pin" and +"function" properties can quickly escalate and become hard to write and +maintain. + +For cases like this, the pin controller driver may use the pinmux helper +property, where the pin identifier is provided with mux configuration settings +in a pinmux group. A pinmux group consists of the pin identifier and mux +settings represented as a single integer or an array of integers. + +The pinmux property accepts an array of pinmux groups, each of them describing +a single pin multiplexing configuration. + +pincontroller { + state_0_node_a { + pinmux = , , ...; + }; +}; + +Each individual pin controller driver bindings documentation shall specify +how pin IDs and pin multiplexing configuration are defined and assembled +together in a pinmux group. + == Generic pin configuration node content == Many data items that are represented in a pin configuration node are common @@ -168,12 +192,15 @@ structure of the DT nodes that contain these properties. Supported generic properties are: pins - the list of pins that properties in the node - apply to (either this or "group" has to be + apply to (either this, "group" or "pinmux" has to be specified) group - the group to apply the properties to, if the driver supports configuration of whole groups rather than - individual pins (either this or "pins" has to be - specified) + individual pins (either this, "pins" or "pinmux" has + to be specified) +pinmux - the list of numeric pin ids and their mux settings + that propert
[PATCH v3 04/10] gpio: sifive: Use generic reg read function
Using an fdt-specific function causes problems with a live tree. Signed-off-by: Sean Anderson Reviewed-by: Bin Meng --- This patch was previously submitted as part of https://patchwork.ozlabs.org/project/uboot/list/?series=161576 (no changes since v1) drivers/gpio/sifive-gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpio/sifive-gpio.c b/drivers/gpio/sifive-gpio.c index 24da3b3c23..bf3537b76b 100644 --- a/drivers/gpio/sifive-gpio.c +++ b/drivers/gpio/sifive-gpio.c @@ -159,7 +159,7 @@ static int sifive_gpio_ofdata_to_platdata(struct udevice *dev) struct sifive_gpio_platdata *plat = dev_get_platdata(dev); fdt_addr_t addr; - addr = devfdt_get_addr(dev); + addr = dev_read_addr(dev); if (addr == FDT_ADDR_T_NONE) return -EINVAL; -- 2.26.2
[PATCH v3 00/10] riscv: Add FPIOA and GPIO support for Kendryte K210
This patch series adds support for pinmuxing, gpios, and leds on the Kendyte K210. This patch series was previously part of https://patchwork.ozlabs.org/project/uboot/list/?series=161576 This patch series depends on https://patchwork.ozlabs.org/project/uboot/list/?series=178480 Changes in v3: - Add dt-bindings/pinctrl/sandbox-pinmux.h to patch Changes in v2: - Add test for pinmuxing - Don't clear existing pinctrl settings on probe - Re-order GPIOs to match the defaults more closely - Rebase onto v13 of "riscv: Add Sipeed Maix support" - Rewrite FPIOA driver to use pinmux property - Support muxing the output enable signal for each function in the FPIOA - Support output and input inversion in the pinmux driver - Support pinmux property in pinctrl-generic Sean Anderson (10): pinctrl: Add pinmux property support to pinctrl-generic test: pinmux: Add test for pin muxing pinctrl: Add support for Kendryte K210 FPIOA gpio: sifive: Use generic reg read function gpio: dw: Fix warnings about casting int to pointer gpio: dw: Add a trailing underscore to generated name gpio: dw: Return output value when direction is out led: gpio: Default to using node name if label is absent riscv: Add pinmux and gpio bindings for Kendryte K210 riscv: Add FPIOA and GPIO support for Kendryte K210 MAINTAINERS | 2 + arch/riscv/dts/k210-maix-bit.dts | 104 +++ arch/riscv/dts/k210.dtsi | 12 + arch/sandbox/dts/test.dts | 45 +- board/sipeed/maix/Kconfig | 9 + doc/board/sipeed/maix.rst | 64 +- .../pinctrl/kendryte,k210-fpioa.txt | 102 +++ .../pinctrl/pinctrl-bindings.txt | 65 +- drivers/gpio/dwapb_gpio.c | 33 +- drivers/gpio/sifive-gpio.c| 2 +- drivers/led/led_gpio.c| 7 +- drivers/pinctrl/Kconfig | 1 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/kendryte/Kconfig | 7 + drivers/pinctrl/kendryte/Makefile | 1 + drivers/pinctrl/kendryte/pinctrl.c| 678 ++ drivers/pinctrl/kendryte/pinctrl.h| 70 ++ drivers/pinctrl/pinctrl-generic.c | 125 +++- drivers/pinctrl/pinctrl-sandbox.c | 155 +++- include/dm/pinctrl.h | 21 +- include/dt-bindings/pinctrl/k210-pinctrl.h| 277 +++ include/dt-bindings/pinctrl/sandbox-pinmux.h | 19 + test/dm/Makefile | 3 + test/py/tests/test_pinmux.py | 36 +- 24 files changed, 1717 insertions(+), 122 deletions(-) create mode 100644 doc/device-tree-bindings/pinctrl/kendryte,k210-fpioa.txt create mode 100644 drivers/pinctrl/kendryte/Kconfig create mode 100644 drivers/pinctrl/kendryte/Makefile create mode 100644 drivers/pinctrl/kendryte/pinctrl.c create mode 100644 drivers/pinctrl/kendryte/pinctrl.h create mode 100644 include/dt-bindings/pinctrl/k210-pinctrl.h create mode 100644 include/dt-bindings/pinctrl/sandbox-pinmux.h -- 2.26.2
Re: [PATCH v2 03/23] am335x: baltos: Enable DM_SPI
On Sat, Jun 13, 2020 at 8:01 PM Jagan Teki wrote: > > On Wed, May 27, 2020 at 6:26 PM Jagan Teki wrote: > > > > Enable DM_SPI for am355x baltos board. > > > > Build is fine, but not tested. > > > > Cc: Yegor Yefremov > > Any comments? Reviewed-by: Yegor Yefremov
Re: [PATCH RESEND v2 1/1] log: don't show function by default
Hi Heinrich, On Sun, 14 Jun 2020 at 08:48, Heinrich Schuchardt wrote: > > The name of the function emitting a log message may be of interest for a > developer but is distracting for normal users. See the example below: > > try_load_entry() Booting: Debian > > Make the default format for log messages customizable. By default show > only the message text. > > Signed-off-by: Heinrich Schuchardt > --- > v2: > adjust logging tests > adjust description of log command > --- > cmd/log.c | 2 +- > common/Kconfig| 18 ++ > include/log.h | 12 +++- > test/log/syslog_test.c| 20 ++-- > test/py/tests/test_log.py | 2 ++ > 5 files changed, 46 insertions(+), 8 deletions(-) > > diff --git a/cmd/log.c b/cmd/log.c > index 78352b2cb9..2c91545c0d 100644 > --- a/cmd/log.c > +++ b/cmd/log.c > @@ -139,7 +139,7 @@ static char log_help_text[] = > "log format - set log output format. is a string where\n" > "\teach letter indicates something that should be displayed:\n" > "\tc=category, l=level, F=file, L=line number, f=function, m=msg\n" > - "\tor 'default', equivalent to 'fm', or 'all' for all\n" > + "\tor 'default', or 'all' for all\n" > "log rec - " > "output a log record" > ; > diff --git a/common/Kconfig b/common/Kconfig > index 7872bc46cd..60cae77f20 100644 > --- a/common/Kconfig > +++ b/common/Kconfig > @@ -792,6 +792,24 @@ config TPL_LOG_CONSOLE > > endif > > +config LOGF_FILE > + bool "Show source file name in log messages by default" > + help > + Show the source file name in log messages by default. This value > + can be overridden using the 'log format' command. > + > +config LOGF_LINE > + bool "Show source line number in log messages by default" > + help > + Show the source line number in log messages by default. This value > + can be overridden using the 'log format' command. > + > +config LOGF_FUNC > + bool "Show function name in log messages by default" > + help > + Show the function name in log messages by default. This value can > + be overridden using the 'log format' command. > + > config LOG_ERROR_RETURN > bool "Log all functions which return an error" > help > diff --git a/include/log.h b/include/log.h > index df65398c04..ec471c3a01 100644 > --- a/include/log.h > +++ b/include/log.h > @@ -411,7 +411,17 @@ enum log_fmt { > LOGF_MSG, > > LOGF_COUNT, > - LOGF_DEFAULT = (1 << LOGF_FUNC) | (1 << LOGF_MSG), > + LOGF_DEFAULT = > +#ifdef CONFIG_LOGF_FILE > + (1 << LOGF_FILE) | > +#endif > +#ifdef CONFIG_LOGF_LINE > + (1 << LOGF_LINE) | > +#endif > +#ifdef CONFIG_LOGF_FUNC > + (1 << LOGF_FUNC) | > +#endif I don't like having these #ifdefs here. Could we instead add a function to common/log.c like log_get_default_format() that uses IS_ENABLED to return the value? > + (1 << LOGF_MSG), > LOGF_ALL = 0x3f, > }; > Regards, Simon
[PATCH v2 23/25] x86: mtrr: Update 'mtrr' to allow setting MTRRs on any CPU
Add a -c option to mtrr to allow any CPU to be updated with this command. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- (no changes since v1) cmd/x86/mtrr.c | 18 -- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/cmd/x86/mtrr.c b/cmd/x86/mtrr.c index b51b1cd7e2..d88a875d92 100644 --- a/cmd/x86/mtrr.c +++ b/cmd/x86/mtrr.c @@ -104,6 +104,17 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc, int ret; cpu_select = MP_SELECT_BSP; + if (argc >= 3 && !strcmp("-c", argv[1])) { + const char *cpustr; + + cpustr = argv[2]; + if (*cpustr == 'a') + cpu_select = MP_SELECT_ALL; + else + cpu_select = simple_strtol(cpustr, NULL, 16); + argc -= 2; + argv += 2; + } argc--; argv++; cmd = argv[0] ? *argv[0] : 0; @@ -145,11 +156,14 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc, } U_BOOT_CMD( - mtrr, 6, 1, do_mtrr, + mtrr, 8, 1, do_mtrr, "Use x86 memory type range registers (32-bit only)", "[list]- list current registers\n" "set - set a register\n" "\t is Uncacheable, Combine, Through, Protect, Back\n" "disable - disable a register\n" - "enable- enable a register" + "enable- enable a register\n" + "\n" + "Precede command with '-c |all' to access a particular CPU, e.g.\n" + " mtrr -c all list; mtrr -c 2e list" ); -- 2.27.0.290.gba653c62da-goog
[PATCH v2 25/25] x86: mtrr: Enhance 'mtrr' command to list MTRRs on any CPU
Update this command so it can list the MTRRs on a selected CPU. If '-c all' is used, then all CPUs are listed. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- (no changes since v1) cmd/x86/mtrr.c | 22 +- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/cmd/x86/mtrr.c b/cmd/x86/mtrr.c index d88a875d92..e688c64052 100644 --- a/cmd/x86/mtrr.c +++ b/cmd/x86/mtrr.c @@ -131,7 +131,27 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc, } } if (cmd == 'l') { - return do_mtrr_list(cpu_select); + bool first; + int i; + + i = mp_first_cpu(cpu_select); + if (i < 0) { + printf("Invalid CPU (err=%d)\n", i); + return CMD_RET_FAILURE; + } + first = true; + for (; i >= 0; i = mp_next_cpu(cpu_select, i)) { + if (!first) + printf("\n"); + printf("CPU %d:\n", i); + ret = do_mtrr_list(i); + if (ret) { + printf("Failed to read CPU %d (err=%d)\n", i, + ret); + return CMD_RET_FAILURE; + } + first = false; + } } else { switch (cmd) { case 'e': -- 2.27.0.290.gba653c62da-goog
[PATCH v2 24/25] x86: mp: Add more comments to the module
Add a description of how this module works and also some missing function comments. Drop struct cpu_map since it is not used. Signed-off-by: Simon Glass --- Changes in v2: - Add a new patch with more comments arch/x86/cpu/mp_init.c| 91 ++- arch/x86/include/asm/mp.h | 14 +- 2 files changed, 102 insertions(+), 3 deletions(-) diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index c708c3e3c0..873b36a81d 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -31,13 +31,99 @@ DECLARE_GLOBAL_DATA_PTR; +/* + * Setting up multiprocessing + * + * See https://www.intel.com/content/www/us/en/intelligent-systems/intel-boot-loader-development-kit/minimal-intel-architecture-boot-loader-paper.html + * + * Note that this file refers to the boot CPU (the one U-Boot is running on) as + * the BSP (BootStrap Processor) and the others as APs (Application Processors). + * + * This module works by loading some setup code into RAM at AP_DEFAULT_BASE and + * telling each AP to execute it. The code that each AP runs is in + * sipi_vector.S (see ap_start16) which includes a struct sipi_params at the + * end of it. Those parameters are set up by the C code. + + * Setting up is handled by load_sipi_vector(). It inits the common block of + * parameters (sipi_params) which tell the APs what to do. This block includes + * microcode and the MTTRs (Memory-Type-Range Registers) from the main CPU. + * There is also an ap_count which each AP increments as it starts up, so the + * BSP can tell how many checked in. + * + * The APs are started with a SIPI (Startup Inter-Processor Interrupt) which + * tells an AP to start executing at a particular address, in this case + * AP_DEFAULT_BASE which contains the code copied from ap_start16. This protocol + * is handled by start_aps(). + * + * After being started, each AP runs the code in ap_start16, switches to 32-bit + * mode, runs the code at ap_start, then jumps to c_handler which is ap_init(). + * This runs a very simple 'flight plan' described in* mp_steps. This sets up + * the CPU and waits for further instructions by looking at its entry in + * ap_callbacks[]. Note that the flight plan is only actually run for each CPU + * in bsp_do_flight_plan(): once the BSP completes each flight record, it sets + * mp_flight_record->barrier to 1 to allow the APs to executed the record one + * by one. + * + * CPUS are numbered sequentially from 0 using the device tree: + * + * cpus { + * u-boot,dm-pre-reloc; + * #address-cells = <1>; + * #size-cells = <0>; + * + * cpu@0 { + * u-boot,dm-pre-reloc; + * device_type = "cpu"; + * compatible = "intel,apl-cpu"; + * reg = <0>; + * intel,apic-id = <0>; + * }; + * + * cpu@1 { + * device_type = "cpu"; + * compatible = "intel,apl-cpu"; + * reg = <1>; + * intel,apic-id = <2>; + * }; + * + * Here the 'reg' property is the CPU number and then is placed in dev->req_seq + * so that we can index into ap_callbacks[] using that. The APIC ID is different + * and may not be sequential (it typically is if hyperthreading is supported). + * + * Once APs are inited they wait in ap_wait_for_instruction() for instructions. + * Instructions come in the form of a function to run. This logic is in + * mp_run_on_cpus() which supports running on any one AP, all APs, just the BSP + * or all CPUs. The BSP logic is handled directly in mp_run_on_cpus(), by + * calling the function. For the APs, callback information is stored in a + * single, common struct mp_callback and a pointer to this is written to each + * AP's slot in ap_callbacks[] by run_ap_work(). All APs get the message even + * if it is only for one of them. When an AP notices a message it checks whether + * it should call the function (see check in ap_wait_for_instruction()) and then + * does so if needed. After that it sets its slot to NULL to indicate it is + * done. + * + * While U-Boot is running it can use mp_run_on_cpus() to run code on the APs. + * An example of this is the 'mtrr' command which allows reading and changing + * the MTRRs on all CPUs. + * + * Before U-Boot exits it calls mp_park_aps() which tells all CPUs to halt by + * executing a 'hlt' instruction. That allows them to be used by Linux when it + * starts up. + */ + /* This also needs to match the sipi.S assembly code for saved MSR encoding */ -struct saved_msr { +struct __packed saved_msr { uint32_t index; uint32_t lo; uint32_t hi; -} __packed; +}; +/** + * struct mp_flight_plan - Holds the flight plan + * + * @num_records: Number of flight records + * @records: Pointer to each record + */ struct mp_flight_plan { int num_records; struct mp_flight_record *records; @@ -58
[PATCH v2 21/25] x86: mtrr: Update the command to use the new mtrr calls
Use the multi-CPU calls to set the MTRR values. This still supports only the boot CPU for now. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- Changes in v2: - Drop the renamed mtrr_set_valid_() instead of mtrr_set_valid() cmd/x86/mtrr.c | 34 -- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/cmd/x86/mtrr.c b/cmd/x86/mtrr.c index 46ef6a2830..b047a9897c 100644 --- a/cmd/x86/mtrr.c +++ b/cmd/x86/mtrr.c @@ -59,14 +59,14 @@ static int do_mtrr_list(int cpu_select) return 0; } -static int do_mtrr_set(uint reg, int argc, char *const argv[]) +static int do_mtrr_set(int cpu_select, uint reg, int argc, char *const argv[]) { const char *typename = argv[0]; - struct mtrr_state state; uint32_t start, size; uint64_t base, mask; int i, type = -1; bool valid; + int ret; if (argc < 3) return CMD_RET_USAGE; @@ -88,27 +88,9 @@ static int do_mtrr_set(uint reg, int argc, char *const argv[]) if (valid) mask |= MTRR_PHYS_MASK_VALID; - mtrr_open(&state, true); - wrmsrl(MTRR_PHYS_BASE_MSR(reg), base); - wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask); - mtrr_close(&state, true); - - return 0; -} - -static int mtrr_set_valid_(int reg, bool valid) -{ - struct mtrr_state state; - uint64_t mask; - - mtrr_open(&state, true); - mask = native_read_msr(MTRR_PHYS_MASK_MSR(reg)); - if (valid) - mask |= MTRR_PHYS_MASK_VALID; - else - mask &= ~MTRR_PHYS_MASK_VALID; - wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask); - mtrr_close(&state, true); + ret = mtrr_set(cpu_select, reg, base, mask); + if (ret) + return CMD_RET_FAILURE; return 0; } @@ -134,11 +116,11 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc, return CMD_RET_USAGE; } if (*cmd == 'e') - return mtrr_set_valid_(reg, true); + return mtrr_set_valid(cpu_select, reg, true); else if (*cmd == 'd') - return mtrr_set_valid_(reg, false); + return mtrr_set_valid(cpu_select, reg, false); else if (*cmd == 's') - return do_mtrr_set(reg, argc - 1, argv + 1); + return do_mtrr_set(cpu_select, reg, argc - 1, argv + 1); else return CMD_RET_USAGE; -- 2.27.0.290.gba653c62da-goog
[PATCH v2 22/25] x86: mtrr: Restructure so command execution is in one place
At present do_mtrr() does the 'list' subcommand at the top and the rest below. Update it to do them all in the same place so we can (in a later patch) add parsing of the CPU number for all subcommands. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- (no changes since v1) cmd/x86/mtrr.c | 55 +- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/cmd/x86/mtrr.c b/cmd/x86/mtrr.c index b047a9897c..b51b1cd7e2 100644 --- a/cmd/x86/mtrr.c +++ b/cmd/x86/mtrr.c @@ -98,31 +98,48 @@ static int do_mtrr_set(int cpu_select, uint reg, int argc, char *const argv[]) static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { - const char *cmd; + int cmd; int cpu_select; uint reg; + int ret; cpu_select = MP_SELECT_BSP; - cmd = argv[1]; - if (argc < 2 || *cmd == 'l') + argc--; + argv++; + cmd = argv[0] ? *argv[0] : 0; + if (argc < 1 || !cmd) { + cmd = 'l'; + reg = 0; + } else { + if (argc < 2) + return CMD_RET_USAGE; + reg = simple_strtoul(argv[1], NULL, 16); + if (reg >= MTRR_COUNT) { + printf("Invalid register number\n"); + return CMD_RET_USAGE; + } + } + if (cmd == 'l') { return do_mtrr_list(cpu_select); - argc -= 2; - argv += 2; - if (argc <= 0) - return CMD_RET_USAGE; - reg = simple_strtoul(argv[0], NULL, 16); - if (reg >= MTRR_COUNT) { - printf("Invalid register number\n"); - return CMD_RET_USAGE; + } else { + switch (cmd) { + case 'e': + ret = mtrr_set_valid(cpu_select, reg, true); + break; + case 'd': + ret = mtrr_set_valid(cpu_select, reg, false); + break; + case 's': + ret = do_mtrr_set(cpu_select, reg, argc - 2, argv + 2); + break; + default: + return CMD_RET_USAGE; + } + if (ret) { + printf("Operation failed (err=%d)\n", ret); + return CMD_RET_FAILURE; + } } - if (*cmd == 'e') - return mtrr_set_valid(cpu_select, reg, true); - else if (*cmd == 'd') - return mtrr_set_valid(cpu_select, reg, false); - else if (*cmd == 's') - return do_mtrr_set(cpu_select, reg, argc - 1, argv + 1); - else - return CMD_RET_USAGE; return 0; } -- 2.27.0.290.gba653c62da-goog
[PATCH v2 20/25] x86: mtrr: Add support for writing to MTRRs on any CPU
To enable support for the 'mtrr' command, add a way to perform MTRR operations on selected CPUs. This works by setting up a little 'operation' structure and sending it around the CPUs for action. Signed-off-by: Simon Glass --- Changes in v2: - Keep things building by temporarily renaming the function in cmd/ arch/x86/cpu/mtrr.c | 81 + arch/x86/include/asm/mtrr.h | 21 ++ cmd/x86/mtrr.c | 6 +-- 3 files changed, 105 insertions(+), 3 deletions(-) diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c index 5c567551e5..2468d88a80 100644 --- a/arch/x86/cpu/mtrr.c +++ b/arch/x86/cpu/mtrr.c @@ -221,3 +221,84 @@ int mtrr_set_next_var(uint type, uint64_t start, uint64_t size) return 0; } + +/** enum mtrr_opcode - supported operations for mtrr_do_oper() */ +enum mtrr_opcode { + MTRR_OP_SET, + MTRR_OP_SET_VALID, +}; + +/** + * struct mtrr_oper - An MTRR operation to perform on a CPU + * + * @opcode: Indicates operation to perform + * @reg: MTRR reg number to select (0-7, -1 = all) + * @valid: Valid value to write for MTRR_OP_SET_VALID + * @base: Base value to write for MTRR_OP_SET + * @mask: Mask value to write for MTRR_OP_SET + */ +struct mtrr_oper { + enum mtrr_opcode opcode; + int reg; + bool valid; + u64 base; + u64 mask; +}; + +static void mtrr_do_oper(void *arg) +{ + struct mtrr_oper *oper = arg; + u64 mask; + + switch (oper->opcode) { + case MTRR_OP_SET_VALID: + mask = native_read_msr(MTRR_PHYS_MASK_MSR(oper->reg)); + if (oper->valid) + mask |= MTRR_PHYS_MASK_VALID; + else + mask &= ~MTRR_PHYS_MASK_VALID; + wrmsrl(MTRR_PHYS_MASK_MSR(oper->reg), mask); + break; + case MTRR_OP_SET: + wrmsrl(MTRR_PHYS_BASE_MSR(oper->reg), oper->base); + wrmsrl(MTRR_PHYS_MASK_MSR(oper->reg), oper->mask); + break; + } +} + +static int mtrr_start_op(int cpu_select, struct mtrr_oper *oper) +{ + struct mtrr_state state; + int ret; + + mtrr_open(&state, true); + ret = mp_run_on_cpus(cpu_select, mtrr_do_oper, oper); + mtrr_close(&state, true); + if (ret) + return log_msg_ret("run", ret); + + return 0; +} + +int mtrr_set_valid(int cpu_select, int reg, bool valid) +{ + struct mtrr_oper oper; + + oper.opcode = MTRR_OP_SET_VALID; + oper.reg = reg; + oper.valid = valid; + + return mtrr_start_op(cpu_select, &oper); +} + +int mtrr_set(int cpu_select, int reg, u64 base, u64 mask) +{ + struct mtrr_oper oper; + + oper.opcode = MTRR_OP_SET; + oper.reg = reg; + oper.base = base; + oper.mask = mask; + + return mtrr_start_op(cpu_select, &oper); +} diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index e1f1a44643..48db1dd82f 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -159,6 +159,27 @@ int mtrr_set_next_var(uint type, uint64_t base, uint64_t size); */ void mtrr_read_all(struct mtrr_info *info); +/** + * mtrr_set_valid() - Set the valid flag for a selected MTRR and CPU(s) + * + * @cpu_select: Selected CPUs (either a CPU number or MP_SELECT_...) + * @reg: MTRR register to write (0-7) + * @valid: Valid flag to write + * @return 0 on success, -ve on error + */ +int mtrr_set_valid(int cpu_select, int reg, bool valid); + +/** + * mtrr_set() - Set the valid flag for a selected MTRR and CPU(s) + * + * @cpu_select: Selected CPUs (either a CPU number or MP_SELECT_...) + * @reg: MTRR register to write (0-7) + * @base: Base address and MTRR_BASE_TYPE_MASK + * @mask: Mask and MTRR_PHYS_MASK_VALID + * @return 0 on success, -ve on error + */ +int mtrr_set(int cpu_select, int reg, u64 base, u64 mask); + #endif #if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0) diff --git a/cmd/x86/mtrr.c b/cmd/x86/mtrr.c index f357f58767..46ef6a2830 100644 --- a/cmd/x86/mtrr.c +++ b/cmd/x86/mtrr.c @@ -96,7 +96,7 @@ static int do_mtrr_set(uint reg, int argc, char *const argv[]) return 0; } -static int mtrr_set_valid(int reg, bool valid) +static int mtrr_set_valid_(int reg, bool valid) { struct mtrr_state state; uint64_t mask; @@ -134,9 +134,9 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc, return CMD_RET_USAGE; } if (*cmd == 'e') - return mtrr_set_valid(reg, true); + return mtrr_set_valid_(reg, true); else if (*cmd == 'd') - return mtrr_set_valid(reg, false); + return mtrr_set_valid_(reg, false); else if (*cmd == 's') return do_mtrr_set(reg, argc - 1, argv + 1); else -- 2.27.0.290.gba653c62da-goog
[PATCH v2 17/25] x86: Don't enable SMP in SPL
SMP should be set up in U-Boot where possible, not SPL. Disable it in SPL. For 64-bit U-Boot we should find a way to allow SMP operations in U-Boot, but this is somewhat more complicated. For now that is disabled too. Signed-off-by: Simon Glass --- Changes in v2: - Add a new patch to avoid enabling SMP in SPL arch/x86/cpu/Makefile | 2 +- arch/x86/include/asm/mp.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index ee0499f5d7..16e67e3da2 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -60,7 +60,7 @@ ifndef CONFIG_SYS_COREBOOT obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += irq.o endif ifndef CONFIG_$(SPL_)X86_64 -obj-$(CONFIG_SMP) += mp_init.o +obj-$(CONFIG_$(SPL_)SMP) += mp_init.o endif obj-y += mtrr.o obj-$(CONFIG_PCI) += pci.o diff --git a/arch/x86/include/asm/mp.h b/arch/x86/include/asm/mp.h index 9f4223ae8c..0fabfca8df 100644 --- a/arch/x86/include/asm/mp.h +++ b/arch/x86/include/asm/mp.h @@ -93,7 +93,7 @@ int x86_mp_init(void); */ typedef void (*mp_run_func)(void *arg); -#if defined(CONFIG_SMP) && !CONFIG_IS_ENABLED(X86_64) +#if CONFIG_IS_ENABLED(SMP) && !CONFIG_IS_ENABLED(X86_64) /** * mp_run_on_cpus() - Run a function on one or all CPUs * -- 2.27.0.290.gba653c62da-goog
[PATCH v2 18/25] x86: coral: Update the memory map
This currently excludes the temporary memory used to start up the APs. Add it. Signed-off-by: Simon Glass --- Changes in v2: - Add new patch to add AP_DEFAULT_BASE to coral's memory map doc/board/google/chromebook_coral.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/board/google/chromebook_coral.rst b/doc/board/google/chromebook_coral.rst index 40bd9397d4..c39f1e310c 100644 --- a/doc/board/google/chromebook_coral.rst +++ b/doc/board/google/chromebook_coral.rst @@ -188,6 +188,7 @@ Partial memory map fef0 1000 CONFIG_BOOTSTAGE_STASH_ADDR fef0 Base of CAR region + 3 AP_DEFAULT_BASE (used to start up additional CPUs) f CONFIG_ROM_TABLE_ADDR 12 BSS (defined in u-boot-spl.lds) 20 FSP-S (which is run after U-Boot is relocated) -- 2.27.0.290.gba653c62da-goog
[PATCH v2 06/25] x86: mtrr: Fix 'ensable' typo
Fix a typo in the command help. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- (no changes since v1) cmd/x86/mtrr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/x86/mtrr.c b/cmd/x86/mtrr.c index 084d7315f4..5d25c5802a 100644 --- a/cmd/x86/mtrr.c +++ b/cmd/x86/mtrr.c @@ -135,5 +135,5 @@ U_BOOT_CMD( "set - set a register\n" "\t is Uncacheable, Combine, Through, Protect, Back\n" "disable - disable a register\n" - "ensable - enable a register" + "enable- enable a register" ); -- 2.27.0.290.gba653c62da-goog
[PATCH v2 19/25] x86: mtrr: Update MTRRs on all CPUs
When the boot CPU MTRRs are updated, perform the same update on all other CPUs so they are kept in sync. This avoids kernel warnings about mismatched MTRRs. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- Changes in v2: - Rename function to mtrr_write_all() arch/x86/cpu/mtrr.c | 57 + 1 file changed, 57 insertions(+) diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c index c9b4e7d06e..5c567551e5 100644 --- a/arch/x86/cpu/mtrr.c +++ b/arch/x86/cpu/mtrr.c @@ -74,10 +74,61 @@ void mtrr_read_all(struct mtrr_info *info) } } +void mtrr_write_all(struct mtrr_info *info) +{ + struct mtrr_state state; + int i; + + for (i = 0; i < MTRR_COUNT; i++) { + mtrr_open(&state, true); + wrmsrl(MTRR_PHYS_BASE_MSR(i), info->mtrr[i].base); + wrmsrl(MTRR_PHYS_MASK_MSR(i), info->mtrr[i].mask); + mtrr_close(&state, true); + } +} + +static void write_mtrrs(void *arg) +{ + struct mtrr_info *info = arg; + + mtrr_write_all(info); +} + +static void read_mtrrs(void *arg) +{ + struct mtrr_info *info = arg; + + mtrr_read_all(info); +} + +/** + * mtrr_copy_to_aps() - Copy the MTRRs from the boot CPU to other CPUs + * + * @return 0 on success, -ve on failure + */ +static int mtrr_copy_to_aps(void) +{ + struct mtrr_info info; + int ret; + + ret = mp_run_on_cpus(MP_SELECT_BSP, read_mtrrs, &info); + if (ret == -ENXIO) + return 0; + else if (ret) + return log_msg_ret("bsp", ret); + + ret = mp_run_on_cpus(MP_SELECT_APS, write_mtrrs, &info); + if (ret) + return log_msg_ret("bsp", ret); + + return 0; +} + int mtrr_commit(bool do_caches) { struct mtrr_request *req = gd->arch.mtrr_req; struct mtrr_state state; + int ret; int i; debug("%s: enabled=%d, count=%d\n", __func__, gd->arch.has_mtrr, @@ -99,6 +150,12 @@ int mtrr_commit(bool do_caches) mtrr_close(&state, do_caches); debug("mtrr done\n"); + if (gd->flags & GD_FLG_RELOC) { + ret = mtrr_copy_to_aps(); + if (ret) + return log_msg_ret("copy", ret); + } + return 0; } -- 2.27.0.290.gba653c62da-goog
[PATCH v2 12/25] x86: Set the SMP flag when MP init is complete
Set this flag so we can track when it is safe to use CPUs other than the main one. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- (no changes since v1) arch/x86/cpu/mp_init.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index 673fdc9628..b0df7a3965 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -643,6 +643,7 @@ int mp_init(void) debug("CPU init failed: err=%d\n", ret); return ret; } + gd->flags |= GD_FLG_SMP_INIT; return 0; } -- 2.27.0.290.gba653c62da-goog
[PATCH v2 14/25] x86: mp: Park CPUs before running the OS
With the new MP features the CPUs are no-longer parked when the OS is run. Fix this by calling a special function to park them, just before the OS is started. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- (no changes since v1) arch/x86/cpu/cpu.c| 5 + arch/x86/cpu/mp_init.c| 18 ++ arch/x86/include/asm/mp.h | 17 + 3 files changed, 40 insertions(+) diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index d0720fb7fb..baa7dae172 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -66,6 +66,11 @@ static const char *const x86_vendor_name[] = { int __weak x86_cleanup_before_linux(void) { + int ret; + + ret = mp_park_aps(); + if (ret) + return log_msg_ret("park", ret); bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR, CONFIG_BOOTSTAGE_STASH_SIZE); diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index e65c82c8fd..9970b51c8d 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -657,6 +657,24 @@ int mp_run_on_cpus(int cpu_select, mp_run_func func, void *arg) return 0; } +static void park_this_cpu(void *unused) +{ + stop_this_cpu(); +} + +int mp_park_aps(void) +{ + unsigned long start; + int ret; + + start = get_timer(0); + ret = mp_run_on_cpus(MP_SELECT_APS, park_this_cpu, NULL); + if (ret) + return ret; + + return get_timer(start); +} + int mp_init(void) { int num_aps, num_cpus; diff --git a/arch/x86/include/asm/mp.h b/arch/x86/include/asm/mp.h index 0272b3c0b6..38961ca44b 100644 --- a/arch/x86/include/asm/mp.h +++ b/arch/x86/include/asm/mp.h @@ -106,6 +106,15 @@ typedef void (*mp_run_func)(void *arg); * @return 0 on success, -ve on error */ int mp_run_on_cpus(int cpu_select, mp_run_func func, void *arg); + +/** + * mp_park_aps() - Park the APs ready for the OS + * + * This halts all CPUs except the main one, ready for the OS to use them + * + * @return 0 on success, -ve on error + */ +int mp_park_aps(void); #else static inline int mp_run_on_cpus(int cpu_select, mp_run_func func, void *arg) { @@ -114,6 +123,14 @@ static inline int mp_run_on_cpus(int cpu_select, mp_run_func func, void *arg) return 0; } + +static inline int mp_park_aps(void) +{ + /* No APs to park */ + + return 0; +} + #endif #endif /* _X86_MP_H_ */ -- 2.27.0.290.gba653c62da-goog
[PATCH v2 16/25] x86: mtrr: Use MP calls to list the MTRRs
Update the mtrr command to use mp_run_on_cpus() to obtain its information. Since the selected CPU is the boot CPU this does not change the result, but it sets the stage for supporting other CPUs. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- Changes in v2: - Rename mtrr_save_all() to mtrr_read_all() arch/x86/cpu/mtrr.c | 11 +++ arch/x86/include/asm/mtrr.h | 30 ++ cmd/x86/mtrr.c | 25 + 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/arch/x86/cpu/mtrr.c b/arch/x86/cpu/mtrr.c index 7ec077..c9b4e7d06e 100644 --- a/arch/x86/cpu/mtrr.c +++ b/arch/x86/cpu/mtrr.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -63,6 +64,16 @@ static void set_var_mtrr(uint reg, uint type, uint64_t start, uint64_t size) wrmsrl(MTRR_PHYS_MASK_MSR(reg), mask | MTRR_PHYS_MASK_VALID); } +void mtrr_read_all(struct mtrr_info *info) +{ + int i; + + for (i = 0; i < MTRR_COUNT; i++) { + info->mtrr[i].base = native_read_msr(MTRR_PHYS_BASE_MSR(i)); + info->mtrr[i].mask = native_read_msr(MTRR_PHYS_MASK_MSR(i)); + } +} + int mtrr_commit(bool do_caches) { struct mtrr_request *req = gd->arch.mtrr_req; diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index 212a699c1b..e1f1a44643 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -70,6 +70,26 @@ struct mtrr_state { bool enable_cache; }; +/** + * struct mtrr - Information about a single MTRR + * + * @base: Base address and MTRR_BASE_TYPE_MASK + * @mask: Mask and MTRR_PHYS_MASK_VALID + */ +struct mtrr { + u64 base; + u64 mask; +}; + +/** + * struct mtrr_info - Information about all MTRRs + * + * @mtrr: Information about each mtrr + */ +struct mtrr_info { + struct mtrr mtrr[MTRR_COUNT]; +}; + /** * mtrr_open() - Prepare to adjust MTRRs * @@ -129,6 +149,16 @@ int mtrr_commit(bool do_caches); */ int mtrr_set_next_var(uint type, uint64_t base, uint64_t size); +/** + * mtrr_read_all() - Save all the MTRRs + * + * This reads all MTRRs from the boot CPU into a struct so they can be loaded + * onto other CPUs + * + * @info: Place to put the MTRR info + */ +void mtrr_read_all(struct mtrr_info *info); + #endif #if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0) diff --git a/cmd/x86/mtrr.c b/cmd/x86/mtrr.c index 5d25c5802a..f357f58767 100644 --- a/cmd/x86/mtrr.c +++ b/cmd/x86/mtrr.c @@ -5,7 +5,9 @@ #include #include +#include #include +#include #include static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = { @@ -18,19 +20,32 @@ static const char *const mtrr_type_name[MTRR_TYPE_COUNT] = { "Back", }; -static int do_mtrr_list(void) +static void read_mtrrs(void *arg) { + struct mtrr_info *info = arg; + + mtrr_read_all(info); +} + +static int do_mtrr_list(int cpu_select) +{ + struct mtrr_info info; + int ret; int i; printf("Reg Valid Write-type %-16s %-16s %-16s\n", "Base ||", "Mask ||", "Size ||"); + memset(&info, '\0', sizeof(info)); + ret = mp_run_on_cpus(cpu_select, read_mtrrs, &info); + if (ret) + return log_msg_ret("run", ret); for (i = 0; i < MTRR_COUNT; i++) { const char *type = "Invalid"; uint64_t base, mask, size; bool valid; - base = native_read_msr(MTRR_PHYS_BASE_MSR(i)); - mask = native_read_msr(MTRR_PHYS_MASK_MSR(i)); + base = info.mtrr[i].base; + mask = info.mtrr[i].mask; size = ~mask & ((1ULL << CONFIG_CPU_ADDR_BITS) - 1); size |= (1 << 12) - 1; size += 1; @@ -102,11 +117,13 @@ static int do_mtrr(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { const char *cmd; + int cpu_select; uint reg; + cpu_select = MP_SELECT_BSP; cmd = argv[1]; if (argc < 2 || *cmd == 'l') - return do_mtrr_list(); + return do_mtrr_list(cpu_select); argc -= 2; argv += 2; if (argc <= 0) -- 2.27.0.290.gba653c62da-goog
[PATCH v2 15/25] x86: mp: Add iterators for CPUs
It is convenient to iterate through the CPUs performing work on each one and processing the result. Add a few iterator functions which handle this. These can be used by any client code. It can call mp_run_on_cpus() on each CPU that is returned, handling them one at a time. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- (no changes since v1) arch/x86/cpu/mp_init.c| 62 +++ arch/x86/include/asm/mp.h | 40 + 2 files changed, 102 insertions(+) diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index 9970b51c8d..c708c3e3c0 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -675,6 +675,68 @@ int mp_park_aps(void) return get_timer(start); } +int mp_first_cpu(int cpu_select) +{ + struct udevice *dev; + int num_cpus; + int ret; + + /* +* This assumes that CPUs are numbered from 0. This function tries to +* avoid assuming the CPU 0 is the boot CPU +*/ + if (cpu_select == MP_SELECT_ALL) + return 0; /* start with the first one */ + + ret = get_bsp(&dev, &num_cpus); + if (ret < 0) + return log_msg_ret("bsp", ret); + + /* Return boot CPU if requested */ + if (cpu_select == MP_SELECT_BSP) + return ret; + + /* Return something other than the boot CPU, if APs requested */ + if (cpu_select == MP_SELECT_APS && num_cpus > 1) + return ret == 0 ? 1 : 0; + + /* Try to check for an invalid value */ + if (cpu_select < 0 || cpu_select >= num_cpus) + return -EINVAL; + + return cpu_select; /* return the only selected one */ +} + +int mp_next_cpu(int cpu_select, int prev_cpu) +{ + struct udevice *dev; + int num_cpus; + int ret; + int bsp; + + /* If we selected the BSP or a particular single CPU, we are done */ + if (cpu_select == MP_SELECT_BSP || cpu_select >= 0) + return -EFBIG; + + /* Must be doing MP_SELECT_ALL or MP_SELECT_APS; return the next CPU */ + ret = get_bsp(&dev, &num_cpus); + if (ret < 0) + return log_msg_ret("bsp", ret); + bsp = ret; + + /* Move to the next CPU */ + assert(prev_cpu >= 0); + ret = prev_cpu + 1; + + /* Skip the BSP if needed */ + if (cpu_select == MP_SELECT_APS && ret == bsp) + ret++; + if (ret >= num_cpus) + return -EFBIG; + + return ret; +} + int mp_init(void) { int num_aps, num_cpus; diff --git a/arch/x86/include/asm/mp.h b/arch/x86/include/asm/mp.h index 38961ca44b..9f4223ae8c 100644 --- a/arch/x86/include/asm/mp.h +++ b/arch/x86/include/asm/mp.h @@ -115,6 +115,31 @@ int mp_run_on_cpus(int cpu_select, mp_run_func func, void *arg); * @return 0 on success, -ve on error */ int mp_park_aps(void); + +/** + * mp_first_cpu() - Get the first CPU to process, from a selection + * + * This is used to iterate through selected CPUs. Call this function first, then + * call mp_next_cpu() repeatedly until it returns -EFBIG. + * + * @cpu_select: Selected CPUs (either a CPU number or MP_SELECT_...) + * @return next CPU number to run on (e.g. 0) + */ +int mp_first_cpu(int cpu_select); + +/** + * mp_next_cpu() - Get the next CPU to process, from a selection + * + * This is used to iterate through selected CPUs. After first calling + * mp_first_cpu() once, call this function repeatedly until it returns -EFBIG. + * + * The value of @cpu_select must be the same for all calls. + * + * @cpu_select: Selected CPUs (either a CPU number or MP_SELECT_...) + * @prev_cpu: Previous value returned by mp_first_cpu()/mp_next_cpu() + * @return next CPU number to run on (e.g. 0) + */ +int mp_next_cpu(int cpu_select, int prev_cpu); #else static inline int mp_run_on_cpus(int cpu_select, mp_run_func func, void *arg) { @@ -131,6 +156,21 @@ static inline int mp_park_aps(void) return 0; } +static inline int mp_first_cpu(int cpu_select) +{ + /* We cannot run on any APs, nor a selected CPU */ + return cpu_select == MP_SELECT_APS ? -EFBIG : MP_SELECT_BSP; +} + +static inline int mp_next_cpu(int cpu_select, int prev_cpu) +{ + /* +* When MP is not enabled, there is only one CPU and we did it in +* mp_first_cpu() +*/ + return -EFBIG; +} + #endif #endif /* _X86_MP_H_ */ -- 2.27.0.290.gba653c62da-goog
[PATCH v2 13/25] x86: mp: Allow running functions on multiple CPUs
Add a way to run a function on a selection of CPUs. This supports either a single CPU, all CPUs, just the main CPU or just the 'APs', in Intel terminology. It works by writing into a mailbox and then waiting for the CPUs to notice it, take action and indicate they are done. When SMP is not yet enabled, this just calls the function on the main CPU. Signed-off-by: Simon Glass --- Changes in v2: - Add a comment to run_ap_work() arch/x86/cpu/mp_init.c| 96 --- arch/x86/include/asm/mp.h | 30 2 files changed, 120 insertions(+), 6 deletions(-) diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index b0df7a3965..e65c82c8fd 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -53,12 +53,7 @@ struct mp_flight_plan { * callback */ struct mp_callback { - /** -* func() - Function to call on the AP -* -* @arg: Argument to pass -*/ - void (*func)(void *arg); + mp_run_func func; void *arg; int logical_cpu_number; }; @@ -517,6 +512,64 @@ static void store_callback(struct mp_callback **slot, struct mp_callback *val) ); } +/** + * run_ap_work() - Run a callback on selected APs + * + * This writes @callback to all APs and waits for them all to acknowledge it, + * Note that whether each AP actually calls the callback depends on the value + * of logical_cpu_number. + * + * @callback: Callback information to pass to all APs + * @bsp: CPU device for the BSP + * @num_cpus: The number of CPUs in the system (= number of APs + 1) + * @expire_ms: Timeout to wait for all APs to finish, in milliseconds, or 0 for + * no timeout + * @return 0 if OK, -ETIMEDOUT if one or more APs failed to respond in time + */ +static int run_ap_work(struct mp_callback *callback, struct udevice *bsp, + int num_cpus, uint expire_ms) +{ + int cur_cpu = bsp->req_seq; + int num_aps = num_cpus - 1; /* number of non-BSPs to get this message */ + int cpus_accepted; + ulong start; + int i; + + /* Signal to all the APs to run the func. */ + for (i = 0; i < num_cpus; i++) { + if (cur_cpu != i) + store_callback(&ap_callbacks[i], callback); + } + mfence(); + + /* Wait for all the APs to signal back that call has been accepted. */ + start = get_timer(0); + + do { + mdelay(1); + cpus_accepted = 0; + + for (i = 0; i < num_cpus; i++) { + if (cur_cpu == i) + continue; + if (!read_callback(&ap_callbacks[i])) + cpus_accepted++; + } + + if (expire_ms && get_timer(start) >= expire_ms) { + log(UCLASS_CPU, LOGL_CRIT, + "AP call expired; %d/%d CPUs accepted\n", + cpus_accepted, num_aps); + return -ETIMEDOUT; + } + } while (cpus_accepted != num_aps); + + /* Make sure we can see any data written by the APs */ + mfence(); + + return 0; +} + /** * ap_wait_for_instruction() - Wait for and process requests from the main CPU * @@ -573,6 +626,37 @@ static struct mp_flight_record mp_steps[] = { MP_FR_BLOCK_APS(ap_wait_for_instruction, NULL, NULL, NULL), }; +int mp_run_on_cpus(int cpu_select, mp_run_func func, void *arg) +{ + struct mp_callback lcb = { + .func = func, + .arg = arg, + .logical_cpu_number = cpu_select, + }; + struct udevice *dev; + int num_cpus; + int ret; + + if (!(gd->flags & GD_FLG_SMP_INIT)) + return -ENXIO; + + ret = get_bsp(&dev, &num_cpus); + if (ret < 0) + return log_msg_ret("bsp", ret); + if (cpu_select == MP_SELECT_ALL || cpu_select == MP_SELECT_BSP || + cpu_select == ret) { + /* Run on BSP first */ + func(arg); + } + + /* Allow up to 1 second for all APs to finish */ + ret = run_ap_work(&lcb, dev, num_cpus, 1000 /* ms */); + if (ret) + return log_msg_ret("aps", ret); + + return 0; +} + int mp_init(void) { int num_aps, num_cpus; diff --git a/arch/x86/include/asm/mp.h b/arch/x86/include/asm/mp.h index 41b1575f4b..0272b3c0b6 100644 --- a/arch/x86/include/asm/mp.h +++ b/arch/x86/include/asm/mp.h @@ -86,4 +86,34 @@ int mp_init(void); /* Set up additional CPUs */ int x86_mp_init(void); +/** + * mp_run_func() - Function to call on the AP + * + * @arg: Argument to pass + */ +typedef void (*mp_run_func)(void *arg); + +#if defined(CONFIG_SMP) && !CONFIG_IS_ENABLED(X86_64) +/** + * mp_run_on_cpus() - Run a function on one or all CPUs + * + * This does not return until all CPUs have completed the work + * + * @cpu_select: CPU to run on, or
[PATCH v2 10/25] x86: mp: Support APs waiting for instructions
At present the APs (non-boot CPUs) are inited once and then parked ready for the OS to use them. However in some cases we want to send new requests through, such as to change MTRRs and keep them consistent across CPUs. Change the last state of the flight plan to go into a wait loop, accepting instructions from the main CPU. Signed-off-by: Simon Glass --- Changes in v2: - Add more comments arch/x86/cpu/mp_init.c| 126 +++--- arch/x86/include/asm/mp.h | 11 2 files changed, 128 insertions(+), 9 deletions(-) diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index cd4cae559d..673fdc9628 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -43,13 +43,38 @@ struct mp_flight_plan { struct mp_flight_record *records; }; +/** + * struct mp_callback - Callback information for APs + * + * @func: Function to run + * @arg: Argument to pass to the function + * @logical_cpu_number: Either a CPU number (i.e. dev->req_seq) or a special + * value like MP_SELECT_BSP. It tells the AP whether it should process this + * callback + */ +struct mp_callback { + /** +* func() - Function to call on the AP +* +* @arg: Argument to pass +*/ + void (*func)(void *arg); + void *arg; + int logical_cpu_number; +}; + static struct mp_flight_plan mp_info; -struct cpu_map { - struct udevice *dev; - int apic_id; - int err_code; -}; +/* + * ap_callbacks - Callback mailbox array + * + * Array of callback, one entry for each available CPU, indexed by the CPU + * number, which is dev->req_seq. The entry for the main CPU is never used. + * When this is NULL, there is no pending work for the CPU to run. When + * non-NULL it points to the mp_callback structure. This is shared between all + * CPUs, so should only be written by the main CPU. + */ +static struct mp_callback **ap_callbacks; static inline void barrier_wait(atomic_t *b) { @@ -147,11 +172,9 @@ static void ap_init(unsigned int cpu_index) debug("AP: slot %d apic_id %x, dev %s\n", cpu_index, apic_id, dev ? dev->name : "(apic_id not found)"); - /* Walk the flight plan */ + /* Walk the flight plan, which never returns */ ap_do_flight_plan(dev); - - /* Park the AP */ - debug("parking\n"); + debug("Unexpected return\n"); done: stop_this_cpu(); } @@ -455,6 +478,86 @@ static int get_bsp(struct udevice **devp, int *cpu_countp) return dev->req_seq; } +/** + * read_callback() - Read the pointer in a callback slot + * + * This is called by APs to read their callback slow to see if there is a + * pointer to new instructions + * + * @slot: Pointer to the AP's callback slot + * @return value of that pointer + */ +static struct mp_callback *read_callback(struct mp_callback **slot) +{ + struct mp_callback *ret; + + asm volatile ("mov %1, %0\n" + : "=r" (ret) + : "m" (*slot) + : "memory" + ); + return ret; +} + +/** + * store_callback() - Store a pointer to the callback slot + * + * This is called by APs to write NULL into the callback slot when they have + * finished the work requested by the BSP. + * + * @slot: Pointer to the AP's callback slot + * @val: Value to write (e.g. NULL) + */ +static void store_callback(struct mp_callback **slot, struct mp_callback *val) +{ + asm volatile ("mov %1, %0\n" + : "=m" (*slot) + : "r" (val) + : "memory" + ); +} + +/** + * ap_wait_for_instruction() - Wait for and process requests from the main CPU + * + * This is called by APs (here, everything other than the main boot CPU) to + * await instructions. They arrive in the form of a function call and argument, + * which is then called. This uses a simple mailbox with atomic read/set + * + * @cpu: CPU that is waiting + * @unused: Optional argument provided by struct mp_flight_record, not used here + * @return Does not return + */ +static int ap_wait_for_instruction(struct udevice *cpu, void *unused) +{ + struct mp_callback lcb; + struct mp_callback **per_cpu_slot; + + per_cpu_slot = &ap_callbacks[cpu->req_seq]; + + while (1) { + struct mp_callback *cb = read_callback(per_cpu_slot); + + if (!cb) { + asm ("pause"); + continue; + } + + /* Copy to local variable before using the value */ + memcpy(&lcb, cb, sizeof(lcb)); + mfence(); + if (lcb.logical_cpu_number == MP_SELECT_ALL || + lcb.logical_cpu_number == MP_SELECT_APS || + cpu->req_seq == lcb.logical_cpu_number) + lcb.func(lcb.arg); + + /* Indicate we are finished */ + store_callback(per_cpu_slot, NULL); + } + + return 0; +} + static int
[PATCH v2 08/25] x86: mp_init: Adjust bsp_init() to return more information
This function is misnamed since it does not actually init the BSP. Also it is convenient to adjust it to return a little more information. Rename and update the function, to allow it to return the BSP CPU device and number, as well as the total number of CPUs. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- Changes in v2: - Drop change to include/dm/uclass.h - Mention error return in get_bsp() arch/x86/cpu/mp_init.c | 35 ++- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index e0270e71db..cd4cae559d 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -421,9 +421,17 @@ static int bsp_do_flight_plan(struct udevice *cpu, struct mp_flight_plan *plan, return ret; } -static int init_bsp(struct udevice **devp) +/** + * get_bsp() - Get information about the bootstrap processor + * + * @devp: If non-NULL, returns CPU device corresponding to the BSP + * @cpu_countp: If non-NULL, returns the total number of CPUs + * @return CPU number of the BSP, or -ve on error + */ +static int get_bsp(struct udevice **devp, int *cpu_countp) { char processor_name[CPU_MAX_NAME_LEN]; + struct udevice *dev; int apic_id; int ret; @@ -431,13 +439,20 @@ static int init_bsp(struct udevice **devp) debug("CPU: %s\n", processor_name); apic_id = lapicid(); - ret = find_cpu_by_apic_id(apic_id, devp); - if (ret) { + ret = find_cpu_by_apic_id(apic_id, &dev); + if (ret < 0) { printf("Cannot find boot CPU, APIC ID %d\n", apic_id); return ret; } + ret = cpu_get_count(dev); + if (ret < 0) + return log_msg_ret("count", ret); + if (devp) + *devp = dev; + if (cpu_countp) + *cpu_countp = ret; - return 0; + return dev->req_seq; } static int mp_init_cpu(struct udevice *cpu, void *unused) @@ -476,24 +491,18 @@ int mp_init(void) uclass_id_foreach_dev(UCLASS_CPU, cpu, uc) cpu->req_seq = dev_read_u32_default(cpu, "reg", -1); - ret = init_bsp(&cpu); - if (ret) { + ret = get_bsp(&cpu, &num_cpus); + if (ret < 0) { debug("Cannot init boot CPU: err=%d\n", ret); return ret; } - num_cpus = cpu_get_count(cpu); - if (num_cpus < 0) { - debug("Cannot get number of CPUs: err=%d\n", num_cpus); - return num_cpus; - } - if (num_cpus < 2) debug("Warning: Only 1 CPU is detected\n"); ret = check_cpu_devices(num_cpus); if (ret) - debug("Warning: Device tree does not describe all CPUs. Extra ones will not be started correctly\n"); + log_warning("Warning: Device tree does not describe all CPUs. Extra ones will not be started correctly\n"); /* Copy needed parameters so that APs have a reference to the plan */ mp_info.num_records = ARRAY_SIZE(mp_steps); -- 2.27.0.290.gba653c62da-goog
[PATCH v2 11/25] global_data: Add a generic global_data flag for SMP state
Allow keeping track of whether all CPUs have been enabled yet. This allows us to know whether other CPUs need to be considered when updating CPU-specific settings such as MTRRs on x86. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- (no changes since v1) include/asm-generic/global_data.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 8c78792cc9..345f365d79 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -167,5 +167,6 @@ typedef struct global_data { #define GD_FLG_LOG_READY 0x08000 /* Log system is ready for use */ #define GD_FLG_WDT_READY 0x1 /* Watchdog is ready for use */ #define GD_FLG_SKIP_LL_INIT0x2 /* Don't perform low-level init*/ +#define GD_FLG_SMP_INIT0x4 /* SMP init is complete */ #endif /* __ASM_GENERIC_GBL_DATA_H */ -- 2.27.0.290.gba653c62da-goog
[PATCH v2 09/25] x86: cpu: Remove unnecessary #ifdefs
Drop some #ifdefs that are not needed or can be converted to compile-time checks. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- (no changes since v1) arch/x86/cpu/cpu.c | 58 - arch/x86/cpu/i386/cpu.c | 2 -- 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 23a4d633d2..d0720fb7fb 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -66,10 +66,8 @@ static const char *const x86_vendor_name[] = { int __weak x86_cleanup_before_linux(void) { -#ifdef CONFIG_BOOTSTAGE_STASH bootstage_stash((void *)CONFIG_BOOTSTAGE_STASH_ADDR, CONFIG_BOOTSTAGE_STASH_SIZE); -#endif return 0; } @@ -200,18 +198,19 @@ int last_stage_init(void) write_tables(); -#ifdef CONFIG_GENERATE_ACPI_TABLE - fadt = acpi_find_fadt(); + if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) { + fadt = acpi_find_fadt(); - /* Don't touch ACPI hardware on HW reduced platforms */ - if (fadt && !(fadt->flags & ACPI_FADT_HW_REDUCED_ACPI)) { - /* -* Other than waiting for OSPM to request us to switch to ACPI -* mode, do it by ourselves, since SMI will not be triggered. -*/ - enter_acpi_mode(fadt->pm1a_cnt_blk); + /* Don't touch ACPI hardware on HW reduced platforms */ + if (fadt && !(fadt->flags & ACPI_FADT_HW_REDUCED_ACPI)) { + /* +* Other than waiting for OSPM to request us to switch +* to ACPI * mode, do it by ourselves, since SMI will +* not be triggered. +*/ + enter_acpi_mode(fadt->pm1a_cnt_blk); + } } -#endif return 0; } @@ -219,19 +218,20 @@ int last_stage_init(void) static int x86_init_cpus(void) { -#ifdef CONFIG_SMP - debug("Init additional CPUs\n"); - x86_mp_init(); -#else - struct udevice *dev; + if (IS_ENABLED(CONFIG_SMP)) { + debug("Init additional CPUs\n"); + x86_mp_init(); + } else { + struct udevice *dev; - /* -* This causes the cpu-x86 driver to be probed. -* We don't check return value here as we want to allow boards -* which have not been converted to use cpu uclass driver to boot. -*/ - uclass_first_device(UCLASS_CPU, &dev); -#endif + /* +* This causes the cpu-x86 driver to be probed. +* We don't check return value here as we want to allow boards +* which have not been converted to use cpu uclass driver to +* boot. +*/ + uclass_first_device(UCLASS_CPU, &dev); + } return 0; } @@ -269,13 +269,11 @@ int cpu_init_r(void) #ifndef CONFIG_EFI_STUB int reserve_arch(void) { -#ifdef CONFIG_ENABLE_MRC_CACHE - mrccache_reserve(); -#endif + if (IS_ENABLED(CONFIG_ENABLE_MRC_CACHE)) + mrccache_reserve(); -#ifdef CONFIG_SEABIOS - high_table_reserve(); -#endif + if (IS_ENABLED(CONFIG_SEABIOS)) + high_table_reserve(); if (IS_ENABLED(CONFIG_HAVE_ACPI_RESUME)) { acpi_s3_reserve(); diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c index 9809ac5111..fca3f79b69 100644 --- a/arch/x86/cpu/i386/cpu.c +++ b/arch/x86/cpu/i386/cpu.c @@ -626,7 +626,6 @@ int cpu_jump_to_64bit_uboot(ulong target) return -EFAULT; } -#ifdef CONFIG_SMP int x86_mp_init(void) { int ret; @@ -639,4 +638,3 @@ int x86_mp_init(void) return 0; } -#endif -- 2.27.0.290.gba653c62da-goog
[PATCH v2 03/25] x86: mp_init: Avoid declarations in header files
The functions used by the flight plan are declared in the header file but are not used in any other file. Move the flight plan steps down to just above where it is used so that we can make these function static. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- (no changes since v1) arch/x86/cpu/mp_init.c| 40 +++ arch/x86/include/asm/mp.h | 3 --- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index 831fd7035d..e77d7f2cd6 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -41,10 +41,6 @@ struct saved_msr { uint32_t hi; } __packed; -static struct mp_flight_record mp_steps[] = { - MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL), -}; - struct mp_flight_plan { int num_records; struct mp_flight_record *records; @@ -423,6 +419,26 @@ static int init_bsp(struct udevice **devp) return 0; } +static int mp_init_cpu(struct udevice *cpu, void *unused) +{ + struct cpu_platdata *plat = dev_get_parent_platdata(cpu); + + /* +* Multiple APs are brought up simultaneously and they may get the same +* seq num in the uclass_resolve_seq() during device_probe(). To avoid +* this, set req_seq to the reg number in the device tree in advance. +*/ + cpu->req_seq = dev_read_u32_default(cpu, "reg", -1); + plat->ucode_version = microcode_read_rev(); + plat->device_id = gd->arch.x86_device; + + return device_probe(cpu); +} + +static struct mp_flight_record mp_steps[] = { + MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL), +}; + int mp_init(void) { int num_aps; @@ -495,19 +511,3 @@ int mp_init(void) return 0; } - -int mp_init_cpu(struct udevice *cpu, void *unused) -{ - struct cpu_platdata *plat = dev_get_parent_platdata(cpu); - - /* -* Multiple APs are brought up simultaneously and they may get the same -* seq num in the uclass_resolve_seq() during device_probe(). To avoid -* this, set req_seq to the reg number in the device tree in advance. -*/ - cpu->req_seq = dev_read_u32_default(cpu, "reg", -1); - plat->ucode_version = microcode_read_rev(); - plat->device_id = gd->arch.x86_device; - - return device_probe(cpu); -} diff --git a/arch/x86/include/asm/mp.h b/arch/x86/include/asm/mp.h index db02904ecb..94af819ad9 100644 --- a/arch/x86/include/asm/mp.h +++ b/arch/x86/include/asm/mp.h @@ -72,9 +72,6 @@ struct mp_flight_record { */ int mp_init(void); -/* Probes the CPU device */ -int mp_init_cpu(struct udevice *cpu, void *unused); - /* Set up additional CPUs */ int x86_mp_init(void); -- 2.27.0.290.gba653c62da-goog
[PATCH v2 07/25] x86: mp_init: Set up the CPU numbers at the start
At present each CPU is given a number when it starts itself up. While this saves a tiny amount of time by doing the device-tree read in parallel, it is confusing that the numbering happens on the fly. Move this code into mp_init() and do it at the start. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- (no changes since v1) arch/x86/cpu/mp_init.c | 21 + 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index aebbca6618..e0270e71db 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -444,12 +444,6 @@ static int mp_init_cpu(struct udevice *cpu, void *unused) { struct cpu_platdata *plat = dev_get_parent_platdata(cpu); - /* -* Multiple APs are brought up simultaneously and they may get the same -* seq num in the uclass_resolve_seq() during device_probe(). To avoid -* this, set req_seq to the reg number in the device tree in advance. -*/ - cpu->req_seq = dev_read_u32_default(cpu, "reg", -1); plat->ucode_version = microcode_read_rev(); plat->device_id = gd->arch.x86_device; @@ -465,13 +459,8 @@ int mp_init(void) int num_aps, num_cpus; atomic_t *ap_count; struct udevice *cpu; - int ret; - - /* This will cause the CPUs devices to be bound */ struct uclass *uc; - ret = uclass_get(UCLASS_CPU, &uc); - if (ret) - return ret; + int ret; if (IS_ENABLED(CONFIG_QFW)) { ret = qemu_cpu_fixup(); @@ -479,6 +468,14 @@ int mp_init(void) return ret; } + /* +* Multiple APs are brought up simultaneously and they may get the same +* seq num in the uclass_resolve_seq() during device_probe(). To avoid +* this, set req_seq to the reg number in the device tree in advance. +*/ + uclass_id_foreach_dev(UCLASS_CPU, cpu, uc) + cpu->req_seq = dev_read_u32_default(cpu, "reg", -1); + ret = init_bsp(&cpu); if (ret) { debug("Cannot init boot CPU: err=%d\n", ret); -- 2.27.0.290.gba653c62da-goog
[PATCH v2 02/25] x86: Move MP code into mp_init
At present the 'flight plan' for CPUs is passed into mp_init. But it is always the same. Move it into the mp_init file so everything is in one place. Also drop the SMI function since it does nothing. If we implement SMIs, more refactoring will be needed anyway. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- (no changes since v1) arch/x86/cpu/i386/cpu.c | 24 +--- arch/x86/cpu/mp_init.c| 22 ++ arch/x86/include/asm/mp.h | 17 + 3 files changed, 16 insertions(+), 47 deletions(-) diff --git a/arch/x86/cpu/i386/cpu.c b/arch/x86/cpu/i386/cpu.c index d27324cb4e..9809ac5111 100644 --- a/arch/x86/cpu/i386/cpu.c +++ b/arch/x86/cpu/i386/cpu.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -626,29 +627,14 @@ int cpu_jump_to_64bit_uboot(ulong target) } #ifdef CONFIG_SMP -static int enable_smis(struct udevice *cpu, void *unused) -{ - return 0; -} - -static struct mp_flight_record mp_steps[] = { - MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL), - /* Wait for APs to finish initialization before proceeding */ - MP_FR_BLOCK_APS(NULL, NULL, enable_smis, NULL), -}; - int x86_mp_init(void) { - struct mp_params mp_params; - - mp_params.parallel_microcode_load = 0, - mp_params.flight_plan = &mp_steps[0]; - mp_params.num_records = ARRAY_SIZE(mp_steps); - mp_params.microcode_pointer = 0; + int ret; - if (mp_init(&mp_params)) { + ret = mp_init(); + if (ret) { printf("Warning: MP init failure\n"); - return -EIO; + return log_ret(ret); } return 0; diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index c25d17c647..831fd7035d 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -41,6 +41,9 @@ struct saved_msr { uint32_t hi; } __packed; +static struct mp_flight_record mp_steps[] = { + MP_FR_BLOCK_APS(mp_init_cpu, NULL, mp_init_cpu, NULL), +}; struct mp_flight_plan { int num_records; @@ -372,7 +375,7 @@ static int start_aps(int ap_count, atomic_t *num_aps) return 0; } -static int bsp_do_flight_plan(struct udevice *cpu, struct mp_params *mp_params) +static int bsp_do_flight_plan(struct udevice *cpu, struct mp_flight_plan *plan) { int i; int ret = 0; @@ -380,8 +383,8 @@ static int bsp_do_flight_plan(struct udevice *cpu, struct mp_params *mp_params) const int step_us = 100; int num_aps = num_cpus - 1; - for (i = 0; i < mp_params->num_records; i++) { - struct mp_flight_record *rec = &mp_params->flight_plan[i]; + for (i = 0; i < plan->num_records; i++) { + struct mp_flight_record *rec = &plan->records[i]; /* Wait for APs if the record is not released */ if (atomic_read(&rec->barrier) == 0) { @@ -420,7 +423,7 @@ static int init_bsp(struct udevice **devp) return 0; } -int mp_init(struct mp_params *p) +int mp_init(void) { int num_aps; atomic_t *ap_count; @@ -445,11 +448,6 @@ int mp_init(struct mp_params *p) return ret; } - if (p == NULL || p->flight_plan == NULL || p->num_records < 1) { - printf("Invalid MP parameters\n"); - return -EINVAL; - } - num_cpus = cpu_get_count(cpu); if (num_cpus < 0) { debug("Cannot get number of CPUs: err=%d\n", num_cpus); @@ -464,8 +462,8 @@ int mp_init(struct mp_params *p) debug("Warning: Device tree does not describe all CPUs. Extra ones will not be started correctly\n"); /* Copy needed parameters so that APs have a reference to the plan */ - mp_info.num_records = p->num_records; - mp_info.records = p->flight_plan; + mp_info.num_records = ARRAY_SIZE(mp_steps); + mp_info.records = mp_steps; /* Load the SIPI vector */ ret = load_sipi_vector(&ap_count, num_cpus); @@ -489,7 +487,7 @@ int mp_init(struct mp_params *p) } /* Walk the flight plan for the BSP */ - ret = bsp_do_flight_plan(cpu, p); + ret = bsp_do_flight_plan(cpu, &mp_info); if (ret) { debug("CPU init failed: err=%d\n", ret); return ret; diff --git a/arch/x86/include/asm/mp.h b/arch/x86/include/asm/mp.h index 9dddf88b5a..db02904ecb 100644 --- a/arch/x86/include/asm/mp.h +++ b/arch/x86/include/asm/mp.h @@ -51,21 +51,6 @@ struct mp_flight_record { #define MP_FR_NOBLOCK_APS(ap_func, ap_arg, bsp_func, bsp_arg) \ MP_FLIGHT_RECORD(1, ap_func, ap_arg, bsp_func, bsp_arg) -/* - * The mp_params structure provides the arguments to the mp subsystem - * for bringing up APs. - * - * At present this is overkill for U-Boot, but it may make it easier to add - * SMM support. - */ -struct mp_params { - int parallel_microcode_load; - const
[PATCH v2 05/25] x86: mp_init: Drop the num_cpus static variable
This does not need to be global across all functions in this file. Pass a parameter instead. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- (no changes since v1) arch/x86/cpu/mp_init.c | 22 +++--- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index 8b00d57c88..aebbca6618 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -31,9 +31,6 @@ DECLARE_GLOBAL_DATA_PTR; -/* Total CPUs include BSP */ -static int num_cpus; - /* This also needs to match the sipi.S assembly code for saved MSR encoding */ struct saved_msr { uint32_t index; @@ -384,13 +381,23 @@ static int start_aps(int num_aps, atomic_t *ap_count) return 0; } -static int bsp_do_flight_plan(struct udevice *cpu, struct mp_flight_plan *plan) +/** + * bsp_do_flight_plan() - Do the flight plan on all CPUs + * + * This runs the flight plan on the main CPU used to boot U-Boot + * + * @cpu: Device for the main CPU + * @plan: Flight plan to run + * @num_aps: Number of APs (CPUs other than the BSP) + * @returns 0 on success, -ETIMEDOUT if an AP failed to come up + */ +static int bsp_do_flight_plan(struct udevice *cpu, struct mp_flight_plan *plan, + int num_aps) { int i; int ret = 0; const int timeout_us = 10; const int step_us = 100; - int num_aps = num_cpus - 1; for (i = 0; i < plan->num_records; i++) { struct mp_flight_record *rec = &plan->records[i]; @@ -410,6 +417,7 @@ static int bsp_do_flight_plan(struct udevice *cpu, struct mp_flight_plan *plan) release_barrier(&rec->barrier); } + return ret; } @@ -454,7 +462,7 @@ static struct mp_flight_record mp_steps[] = { int mp_init(void) { - int num_aps; + int num_aps, num_cpus; atomic_t *ap_count; struct udevice *cpu; int ret; @@ -516,7 +524,7 @@ int mp_init(void) } /* Walk the flight plan for the BSP */ - ret = bsp_do_flight_plan(cpu, &mp_info); + ret = bsp_do_flight_plan(cpu, &mp_info, num_aps); if (ret) { debug("CPU init failed: err=%d\n", ret); return ret; -- 2.27.0.290.gba653c62da-goog
[PATCH v2 01/25] x86: mp_init: Switch to livetree
Update this code to use livetree calls instead of flat-tree. Signed-off-by: Simon Glass Reviewed-by: Wolfgang Wallner --- (no changes since v1) arch/x86/cpu/mp_init.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index 7fde4ff7e1..c25d17c647 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -507,8 +507,7 @@ int mp_init_cpu(struct udevice *cpu, void *unused) * seq num in the uclass_resolve_seq() during device_probe(). To avoid * this, set req_seq to the reg number in the device tree in advance. */ - cpu->req_seq = fdtdec_get_int(gd->fdt_blob, dev_of_offset(cpu), "reg", - -1); + cpu->req_seq = dev_read_u32_default(cpu, "reg", -1); plat->ucode_version = microcode_read_rev(); plat->device_id = gd->arch.x86_device; -- 2.27.0.290.gba653c62da-goog
[PATCH v2 00/25] x86: Enhance MTRR functionality to support multiple CPUs
At present MTRRs are mirrored to the secondary CPUs only once, as those CPUs are started up. But U-Boot may add more MTRRs later, e.g. if it decides that a video console must be set up. This series enhances the x86 multi-processor support to allow MTRRs to be updated at any time. It also updates the 'mtrr' command to support setting the MTRRs on CPUs other than the boot CPU. Changes in v2: - Add comments to explain what start_aps() does - Drop change to include/dm/uclass.h - Mention error return in get_bsp() - Add more comments - Add a comment to run_ap_work() - Rename mtrr_save_all() to mtrr_read_all() - Add a new patch to avoid enabling SMP in SPL - Add new patch to add AP_DEFAULT_BASE to coral's memory map - Rename function to mtrr_write_all() - Keep things building by temporarily renaming the function in cmd/ - Drop the renamed mtrr_set_valid_() instead of mtrr_set_valid() - Add a new patch with more comments Simon Glass (25): x86: mp_init: Switch to livetree x86: Move MP code into mp_init x86: mp_init: Avoid declarations in header files x86: mp_init: Switch parameter names in start_aps() x86: mp_init: Drop the num_cpus static variable x86: mtrr: Fix 'ensable' typo x86: mp_init: Set up the CPU numbers at the start x86: mp_init: Adjust bsp_init() to return more information x86: cpu: Remove unnecessary #ifdefs x86: mp: Support APs waiting for instructions global_data: Add a generic global_data flag for SMP state x86: Set the SMP flag when MP init is complete x86: mp: Allow running functions on multiple CPUs x86: mp: Park CPUs before running the OS x86: mp: Add iterators for CPUs x86: mtrr: Use MP calls to list the MTRRs x86: Don't enable SMP in SPL x86: coral: Update the memory map x86: mtrr: Update MTRRs on all CPUs x86: mtrr: Add support for writing to MTRRs on any CPU x86: mtrr: Update the command to use the new mtrr calls x86: mtrr: Restructure so command execution is in one place x86: mtrr: Update 'mtrr' to allow setting MTRRs on any CPU x86: mp: Add more comments to the module x86: mtrr: Enhance 'mtrr' command to list MTRRs on any CPU arch/x86/cpu/Makefile | 2 +- arch/x86/cpu/cpu.c| 63 ++-- arch/x86/cpu/i386/cpu.c | 26 +- arch/x86/cpu/mp_init.c| 520 ++ arch/x86/cpu/mtrr.c | 149 arch/x86/include/asm/mp.h | 132 ++- arch/x86/include/asm/mtrr.h | 51 +++ cmd/x86/mtrr.c| 148 +--- doc/board/google/chromebook_coral.rst | 1 + include/asm-generic/global_data.h | 1 + 10 files changed, 904 insertions(+), 189 deletions(-) -- 2.27.0.290.gba653c62da-goog
[PATCH v2 04/25] x86: mp_init: Switch parameter names in start_aps()
These parameters are named differently from elsewhere in this file. Switch them to avoid confusion. Also add comments to this function. Signed-off-by: Simon Glass --- Changes in v2: - Add comments to explain what start_aps() does arch/x86/cpu/mp_init.c | 25 +++-- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/arch/x86/cpu/mp_init.c b/arch/x86/cpu/mp_init.c index e77d7f2cd6..8b00d57c88 100644 --- a/arch/x86/cpu/mp_init.c +++ b/arch/x86/cpu/mp_init.c @@ -308,13 +308,26 @@ static int apic_wait_timeout(int total_delay, const char *msg) return 0; } -static int start_aps(int ap_count, atomic_t *num_aps) +/** + * start_aps() - Start up the APs and count how many we find + * + * This is called on the boot processor to start up all the other processors + * (here called APs). + * + * @num_aps: Number of APs we expect to find + * @ap_count: Initially zero. Incremented by this function for each AP found + * @return 0 if all APs were set up correctly or there are none to set up, + * -ENOSPC if the SIPI vector is too high in memory, + * -ETIMEDOUT if the ICR is busy or the second SIPI fails to complete + * -EIO if not all APs check in correctly + */ +static int start_aps(int num_aps, atomic_t *ap_count) { int sipi_vector; /* Max location is 4KiB below 1MiB */ const int max_vector_loc = ((1 << 20) - (1 << 12)) >> 12; - if (ap_count == 0) + if (num_aps == 0) return 0; /* The vector is sent as a 4k aligned address in one byte */ @@ -326,7 +339,7 @@ static int start_aps(int ap_count, atomic_t *num_aps) return -ENOSPC; } - debug("Attempting to start %d APs\n", ap_count); + debug("Attempting to start %d APs\n", num_aps); if (apic_wait_timeout(1000, "ICR not to be busy")) return -ETIMEDOUT; @@ -349,7 +362,7 @@ static int start_aps(int ap_count, atomic_t *num_aps) return -ETIMEDOUT; /* Wait for CPUs to check in up to 200 us */ - wait_for_aps(num_aps, ap_count, 200, 15); + wait_for_aps(ap_count, num_aps, 200, 15); /* Send 2nd SIPI */ if (apic_wait_timeout(1000, "ICR not to be busy")) @@ -362,9 +375,9 @@ static int start_aps(int ap_count, atomic_t *num_aps) return -ETIMEDOUT; /* Wait for CPUs to check in */ - if (wait_for_aps(num_aps, ap_count, 1, 50)) { + if (wait_for_aps(ap_count, num_aps, 1, 50)) { debug("Not all APs checked in: %d/%d\n", - atomic_read(num_aps), ap_count); + atomic_read(ap_count), num_aps); return -EIO; } -- 2.27.0.290.gba653c62da-goog
[PATCH 4/5] patman: Add tests for the rest of the checkpatch checks
Finish off the tests for our small collection of checkpatch checks. Signed-off-by: Simon Glass --- tools/patman/test_checkpatch.py | 47 ++--- 1 file changed, 43 insertions(+), 4 deletions(-) diff --git a/tools/patman/test_checkpatch.py b/tools/patman/test_checkpatch.py index 7f40133b33..710b4a7d88 100644 --- a/tools/patman/test_checkpatch.py +++ b/tools/patman/test_checkpatch.py @@ -348,14 +348,53 @@ index 000..2234c87 self.assertEqual(result.lines, 62) os.remove(inf) +def checkSingleMessage(self, pm, msg, pmtype = 'warning'): +"""Helper function to run checkpatch and check the result + +Args: +pm: PatchMaker object to use +msg" Expected message (e.g. 'LIVETREE') +pmtype: Type of problem ('error', 'warning') +""" +result = pm.run_checkpatch() +if pmtype == 'warning': +self.assertEqual(result.warnings, 1) +elif pmtype == 'error': +self.assertEqual(result.errors, 1) +if len(result.problems) != 1: +print(result.problems) +self.assertEqual(len(result.problems), 1) +self.assertIn(msg, result.problems[0]['cptype']) + def testUclass(self): """Test for possible new uclass""" pm = PatchMaker() pm.add_line('include/dm/uclass-id.h', 'UCLASS_WIBBLE,') -result = pm.run_checkpatch() -self.assertEqual(result.warnings, 1) -self.assertEqual(len(result.problems), 1) -self.assertIn('NEW_UCLASS', result.problems[0]['cptype']) +self.checkSingleMessage(pm, 'NEW_UCLASS') + +def testLivetree(self): +"""Test for Use the livetree API""" +pm = PatchMaker() +pm.add_line('common/main.c', 'fdtdec_do_something()') +self.checkSingleMessage(pm, 'LIVETREE') + +def testNewCommand(self): +"""Test for Use the livetree API""" +pm = PatchMaker() +pm.add_line('common/main.c', 'do_wibble(struct cmd_tbl *cmd_tbl)') +self.checkSingleMessage(pm, 'CMD_TEST') + +def testNewCommand(self): +"""Test for Use the livetree API""" +pm = PatchMaker() +pm.add_line('common/main.c', '#ifdef CONFIG_YELLOW') +self.checkSingleMessage(pm, "PREFER_IF") + +def testCommandUseDefconfig(self): +"""Test for Use the livetree API""" +pm = PatchMaker() +pm.add_line('common/main.c', '#undef CONFIG_CMD_WHICH') +self.checkSingleMessage(pm, 'DEFINE_CONFIG_CMD', 'error') if __name__ == "__main__": -- 2.27.0.290.gba653c62da-goog
[PATCH 3/5] patman: Decode output from the '--show-types' option
Collect the 'checkpatch type' from each error, warning and check. Provide this to patman and update the uclass test to use it. Signed-off-by: Simon Glass --- tools/patman/checkpatch.py | 24 +++- tools/patman/test_checkpatch.py | 4 ++-- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/tools/patman/checkpatch.py b/tools/patman/checkpatch.py index 98c63af1dd..07c3e2739a 100644 --- a/tools/patman/checkpatch.py +++ b/tools/patman/checkpatch.py @@ -38,7 +38,7 @@ def FindCheckPatch(): sys.exit('Cannot find checkpatch.pl - please put it in your ' + '~/bin directory or use --no-check') -def CheckPatch(fname, verbose=False): +def CheckPatch(fname, verbose=False, show_types=False): """Run checkpatch.pl on a file. Returns: @@ -64,8 +64,10 @@ def CheckPatch(fname, verbose=False): result.problems = [] chk = FindCheckPatch() item = {} -result.stdout = command.Output(chk, '--no-tree', fname, - raise_on_error=False) +args = [chk, '--no-tree'] +if show_types: +args.append('--show-types') +result.stdout = command.Output(*args, fname, raise_on_error=False) #pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE) #stdout, stderr = pipe.communicate() @@ -81,9 +83,10 @@ def CheckPatch(fname, verbose=False): ' checks, (\d+)') re_ok = re.compile('.*has no obvious style problems') re_bad = re.compile('.*has style problems, please review') -re_error = re.compile('ERROR: (.*)') -re_warning = re.compile(emacs_prefix + 'WARNING:(?:[A-Z_]+:)? (.*)') -re_check = re.compile('CHECK: (.*)') +type_name = '([A-Z_]+:)?' +re_error = re.compile('ERROR:%s (.*)' % type_name) +re_warning = re.compile(emacs_prefix + 'WARNING:%s (.*)' % type_name) +re_check = re.compile('CHECK:%s (.*)' % type_name) re_file = re.compile('#\d+: FILE: ([^:]*):(\d+):') re_note = re.compile('NOTE: (.*)') indent = ' ' * 6 @@ -129,13 +132,16 @@ def CheckPatch(fname, verbose=False): check_match = re_check.match(line) subject_match = line.startswith('Subject:') if err_match: -item['msg'] = err_match.group(1) +item['cptype'] = err_match.group(1) +item['msg'] = err_match.group(2) item['type'] = 'error' elif warn_match: -item['msg'] = warn_match.group(1) +item['cptype'] = warn_match.group(1) +item['msg'] = warn_match.group(2) item['type'] = 'warning' elif check_match: -item['msg'] = check_match.group(1) +item['cptype'] = check_match.group(1) +item['msg'] = check_match.group(2) item['type'] = 'check' elif file_match: item['file'] = file_match.group(1) diff --git a/tools/patman/test_checkpatch.py b/tools/patman/test_checkpatch.py index e841b9abca..7f40133b33 100644 --- a/tools/patman/test_checkpatch.py +++ b/tools/patman/test_checkpatch.py @@ -82,7 +82,7 @@ Signed-off-by: Simon Glass return inname def run_checkpatch(self): -return checkpatch.CheckPatch(self.get_patch()) +return checkpatch.CheckPatch(self.get_patch(), show_types=True) class TestPatch(unittest.TestCase): @@ -355,7 +355,7 @@ index 000..2234c87 result = pm.run_checkpatch() self.assertEqual(result.warnings, 1) self.assertEqual(len(result.problems), 1) -self.assertIn('Possible new uclass', result.problems[0]['msg']) +self.assertIn('NEW_UCLASS', result.problems[0]['cptype']) if __name__ == "__main__": -- 2.27.0.290.gba653c62da-goog
[PATCH 5/5] checkpatch: Don't warn about PREFER_IF in headers/DT files
This warning should only be displayed for C files. Fix it and update the test. Signed-off-by: Simon Glass --- scripts/checkpatch.pl | 2 +- tools/patman/test_checkpatch.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index edba365651..5731cd221e 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2263,7 +2263,7 @@ sub u_boot_line { } # use if instead of #if - if ($line =~ /^\+#if.*CONFIG.*/) { + if ($realfile =~ /\.c$/ && $line =~ /^\+#if.*CONFIG.*/) { WARN("PREFER_IF", "Use 'if (IS_ENABLED(CONFIG...))' instead of '#if or #ifdef' where possible\n" . $herecurr); } diff --git a/tools/patman/test_checkpatch.py b/tools/patman/test_checkpatch.py index 710b4a7d88..c9580adb54 100644 --- a/tools/patman/test_checkpatch.py +++ b/tools/patman/test_checkpatch.py @@ -388,6 +388,8 @@ index 000..2234c87 """Test for Use the livetree API""" pm = PatchMaker() pm.add_line('common/main.c', '#ifdef CONFIG_YELLOW') +pm.add_line('common/init.h', '#ifdef CONFIG_YELLOW') +pm.add_line('fred.dtsi', '#ifdef CONFIG_YELLOW') self.checkSingleMessage(pm, "PREFER_IF") def testCommandUseDefconfig(self): -- 2.27.0.290.gba653c62da-goog
[PATCH 1/5] patman: Rename test.py to test_checkpatch.py
These tests check checkpatch.pl operation and can server as our tests for the U-Boot-specific updates to that script. Rename the file and update comments to indicate this. Signed-off-by: Simon Glass --- tools/patman/main.py | 4 ++-- tools/patman/{test.py => test_checkpatch.py} | 7 +++ 2 files changed, 5 insertions(+), 6 deletions(-) rename tools/patman/{test.py => test_checkpatch.py} (98%) diff --git a/tools/patman/main.py b/tools/patman/main.py index 0974c84059..4a11f80db5 100755 --- a/tools/patman/main.py +++ b/tools/patman/main.py @@ -25,7 +25,7 @@ from patman import patchstream from patman import project from patman import settings from patman import terminal -from patman import test +from patman import test_checkpatch parser = OptionParser() @@ -93,7 +93,7 @@ elif options.test: sys.argv = [sys.argv[0]] result = unittest.TestResult() -for module in (test.TestPatch, func_test.TestFunctional): +for module in (test_checkpatch.TestPatch, func_test.TestFunctional): suite = unittest.TestLoader().loadTestsFromTestCase(module) suite.run(result) diff --git a/tools/patman/test.py b/tools/patman/test_checkpatch.py similarity index 98% rename from tools/patman/test.py rename to tools/patman/test_checkpatch.py index e7f709e34c..03ff576c9e 100644 --- a/tools/patman/test.py +++ b/tools/patman/test_checkpatch.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- # SPDX-License-Identifier: GPL-2.0+ # +# Tests for U-Boot-specific checkpatch.pl features +# # Copyright (c) 2011 The Chromium OS Authors. # @@ -16,10 +18,7 @@ from patman import commit class TestPatch(unittest.TestCase): -"""Test this program - -TODO: Write tests for the rest of the functionality -""" +"""Test the u_boot_line() function in checkpatch.pl""" def testBasic(self): """Test basic filter operation""" -- 2.27.0.290.gba653c62da-goog
[PATCH 2/5] patman: Add a test for the 'possible new uclass' check
It is quite likely that the number of U-Boot-specific tests in checkpatch.pl will increase over time. We should have tests for these to avoid undefined behaviour and bugs being introduced, which might cause people to ignore the warnings. Add a simple new class that can generate a patch with a single-line addition in it. Use that to add a test for one of the checkpatch checks. Signed-off-by: Simon Glass --- tools/patman/test_checkpatch.py | 77 + 1 file changed, 77 insertions(+) diff --git a/tools/patman/test_checkpatch.py b/tools/patman/test_checkpatch.py index 03ff576c9e..e841b9abca 100644 --- a/tools/patman/test_checkpatch.py +++ b/tools/patman/test_checkpatch.py @@ -17,6 +17,74 @@ from patman import series from patman import commit +class Line: +def __init__(self, fname, text): +self.fname = fname +self.text = text + + +class PatchMaker: +def __init__(self): +self.lines = [] + +def add_line(self, fname, text): +self.lines.append(Line(fname, text)) + +def get_patch_text(self): +base = '''From 125b77450f4c66b8fd9654319520bbe795c9ef31 Mon Sep 17 00:00:00 2001 +From: Simon Glass +Date: Sun, 14 Jun 2020 09:45:14 -0600 +Subject: [PATCH] Test commit + +This is a test commit. + +Signed-off-by: Simon Glass +--- + +''' +lines = base.splitlines() + +# Create the diffstat +change = 0 +insert = 0 +for line in self.lines: +lines.append(' %s | 1 +' % line.fname) +change += 1 +insert += 1 +lines.append(' %d files changed, %d insertions(+)' % (change, insert)) +lines.append('') + +# Create the patch info for each file +for line in self.lines: +lines.append('diff --git a/%s b/%s' % (line.fname, line.fname)) +lines.append('index 7837d459f18..5ba7840f68e 100644') +lines.append('--- a/%s' % line.fname) +lines.append('+++ b/%s' % line.fname) +lines += ('''@@ -121,6 +121,7 @@ enum uclass_id { + UCLASS_W1, /* Dallas 1-Wire bus */ + UCLASS_W1_EEPROM, /* one-wire EEPROMs */ + UCLASS_WDT, /* Watchdog Timer driver */ ++%s + + UCLASS_COUNT, + UCLASS_INVALID = -1, +''' % line.text).splitlines() +lines.append('---') +lines.append('2.17.1') + +return '\n'.join(lines) + +def get_patch(self): +inhandle, inname = tempfile.mkstemp() +infd = os.fdopen(inhandle, 'w') +infd.write(self.get_patch_text()) +infd.close() +return inname + +def run_checkpatch(self): +return checkpatch.CheckPatch(self.get_patch()) + + class TestPatch(unittest.TestCase): """Test the u_boot_line() function in checkpatch.pl""" @@ -280,6 +348,15 @@ index 000..2234c87 self.assertEqual(result.lines, 62) os.remove(inf) +def testUclass(self): +"""Test for possible new uclass""" +pm = PatchMaker() +pm.add_line('include/dm/uclass-id.h', 'UCLASS_WIBBLE,') +result = pm.run_checkpatch() +self.assertEqual(result.warnings, 1) +self.assertEqual(len(result.problems), 1) +self.assertIn('Possible new uclass', result.problems[0]['msg']) + if __name__ == "__main__": unittest.main() -- 2.27.0.290.gba653c62da-goog
[PATCH 0/5] patman: Add tests for U-Boot-specific checkpatch checks
It is quite likely that the number of U-Boot-specific tests in checkpatch.pl will increase over time. We should have tests for these to avoid undefined behaviour and bugs being introduced, which might cause people to ignore the warnings. This series adds the tests and modifies one check to be more specific. Simon Glass (5): patman: Rename test.py to test_checkpatch.py patman: Add a test for the 'possible new uclass' check patman: Decode output from the '--show-types' option patman: Add tests for the rest of the checkpatch checks checkpatch: Don't warn about PREFER_IF in headers/DT files scripts/checkpatch.pl| 2 +- tools/patman/checkpatch.py | 24 ++-- tools/patman/main.py | 4 +- tools/patman/{test.py => test_checkpatch.py} | 125 ++- 4 files changed, 139 insertions(+), 16 deletions(-) rename tools/patman/{test.py => test_checkpatch.py} (69%) -- 2.27.0.290.gba653c62da-goog
Re: Please pull u-boot-dm/next
On Fri, Jun 12, 2020 at 09:17:28PM -0600, Simon Glass wrote: > Hi Tom, > > This is for -next > > But I based it on master to avoid pulling in other people's commits. I hope > that works OK. > > > The following changes since commit be79009f3b9bbdbce283e67a865121e576d790ea: > > Merge tag 'u-boot-imx-20200609' of > https://gitlab.denx.de/u-boot/custodians/u-boot-imx (2020-06-09 09:17:24 > -0400) > > are available in the Git repository at: > > git://git.denx.de/u-boot-dm.git tags/dm-pull-12jun20 > > for you to fetch changes up to cea8f2c995b9d87af6ef42f967402e1c8a3506db: > > doc: driver-model: fix typo in design.rst (2020-06-11 20:52:11 -0600) > Applied to u-boot/master, thanks! -- Tom signature.asc Description: PGP signature
Re: Pull request: u-boot-spi/master
On Thu, Jun 11, 2020 at 11:23:13PM +0530, Jagan Teki wrote: > Hi Tom, > > This PR is for next release. > > I'm sending the PR for migration early hoping it can avoid conflicts > from your series or in general. > > May be applied on next would help keep migrations changes inline. > > Summary: > - Drop davinci, mxs spi nondm code > - Zap nondm soft_spi > - Switch few board to DM_SPI > - Drop omap3_pandora, pcm051 boards > > Travis-CI: > https://travis-ci.org/github/openedev/u-boot-amarula/builds/697164896 > > The following changes since commit be79009f3b9bbdbce283e67a865121e576d790ea: > > Merge tag 'u-boot-imx-20200609' of > https://gitlab.denx.de/u-boot/custodians/u-boot-imx (2020-06-09 09:17:24 > -0400) > > are available in the Git repository at: > > https://gitlab.denx.de/u-boot/custodians/u-boot-spi master > > for you to fetch changes up to b45926fa1d5a1be2a55d0eb208bff8f04f00f875: > > am335x: sl50: Enable DM_SPI (2020-06-11 15:14:04 +0530) > Applied to u-boot/master, thanks! -- Tom signature.asc Description: PGP signature
Re: [PATCH 0/4] arm: fix clang build errors
On Sun, Jun 14, 2020 at 05:51:21PM +0200, Heinrich Schuchardt wrote: > On 5/27/20 8:04 PM, Heinrich Schuchardt wrote: > > With this patch series most ARM boards both 32bit and 64bit can be built > > using Clang 9. > > > > On ARM systems gd is stored in register r9 or x18. When compiling with > > clang gd is defined as a macro calling function gd_ptr(). So we can not > > make assignments to gd. Fixes for the UEFI sub-system and lib/trace.c > > are provided. > > > > Incorrect argument sizes when accessing special registers with inline > > assembly are fixed. > > Hello Tom, > > will you take this series via next? > > https://patchwork.ozlabs.org/project/uboot/list/?series=179688 > > 1/4 is already merged via an EFI pull request. Either -next or the MW when it opens itself. As this doesn't look too tricky overall it's not at the top of my TODO list for -next as I'm focusing on longer outstanding or tricky thingy first. Thanks! -- Tom signature.asc Description: PGP signature
Re: [PATCH 0/4] arm: fix clang build errors
On 5/27/20 8:04 PM, Heinrich Schuchardt wrote: With this patch series most ARM boards both 32bit and 64bit can be built using Clang 9. On ARM systems gd is stored in register r9 or x18. When compiling with clang gd is defined as a macro calling function gd_ptr(). So we can not make assignments to gd. Fixes for the UEFI sub-system and lib/trace.c are provided. Incorrect argument sizes when accessing special registers with inline assembly are fixed. Hello Tom, will you take this series via next? https://patchwork.ozlabs.org/project/uboot/list/?series=179688 1/4 is already merged via an EFI pull request. Best regards Heinrich Heinrich Schuchardt (4): efi_loader: allow compiling with clang trace: clang compatible handling of gd register arm: remove outdated comment concerning -ffixed-x18 arm: use correct argument size of special registers arch/arm/include/asm/global_data.h | 13 + arch/arm/include/asm/system.h | 10 ++ lib/efi_loader/efi_boottime.c | 10 +- lib/trace.c| 8 4 files changed, 24 insertions(+), 17 deletions(-) -- 2.26.2