Commit d4827fcd4c1b04c338e4019e412f495aa4231d24
Exists in
smarc_8mq_lf_v2020.04
and in
9 other branches
Merge https://gitlab.denx.de/u-boot/custodians/u-boot-x86
- Various minor fixes for x86 - Switch to ACPI mode on Intel edison - Support run-time configuration for NS16550 driver - Update coreboot and slimbootloader serial drivers to use NS16550 run-time configuration - ICH SPI driver fixes to hardware sequencing erase case - Move ITSS from Apollo Lake to a more generic location - Intel GPIO driver bug fixes - Move to vs2017-win2016 platform build host for Azure pipelines
Showing 28 changed files Side-by-side Diff
- .azure-pipelines.yml
- arch/x86/Kconfig
- arch/x86/cpu/apollolake/Kconfig
- arch/x86/cpu/apollolake/Makefile
- arch/x86/cpu/apollolake/itss.c
- arch/x86/cpu/i386/cpu.c
- arch/x86/cpu/intel_common/Makefile
- arch/x86/cpu/intel_common/itss.c
- arch/x86/cpu/slimbootloader/serial.c
- arch/x86/cpu/start.S
- arch/x86/cpu/start16.S
- arch/x86/dts/chromebook_coral.dts
- arch/x86/dts/coreboot.dts
- arch/x86/include/asm/arch-apollolake/itss.h
- arch/x86/include/asm/coreboot_tables.h
- arch/x86/include/asm/itss.h
- configs/edison_defconfig
- doc/board/google/chromebook_coral.rst
- doc/board/intel/slimbootloader.rst
- drivers/gpio/intel_gpio.c
- drivers/pinctrl/intel/pinctrl.c
- drivers/serial/Kconfig
- drivers/serial/Makefile
- drivers/serial/ns16550.c
- drivers/serial/serial_coreboot.c
- drivers/spi/ich.c
- include/configs/slimbootloader.h
- include/ns16550.h
.azure-pipelines.yml
arch/x86/Kconfig
... | ... | @@ -709,6 +709,12 @@ |
709 | 709 | hex |
710 | 710 | default 0x10000 |
711 | 711 | |
712 | +config HAVE_ITSS | |
713 | + bool "Enable ITSS" | |
714 | + help | |
715 | + Select this to include the driver for the Interrupt Timer | |
716 | + Subsystem (ITSS) which is found on several Intel devices. | |
717 | + | |
712 | 718 | menu "System tables" |
713 | 719 | depends on !EFI && !SYS_COREBOOT |
714 | 720 |
arch/x86/cpu/apollolake/Kconfig
arch/x86/cpu/apollolake/Makefile
arch/x86/cpu/apollolake/itss.c
1 | -// SPDX-License-Identifier: GPL-2.0 | |
2 | -/* | |
3 | - * Something to do with Interrupts, but I don't know what ITSS stands for | |
4 | - * | |
5 | - * Copyright (C) 2017 Intel Corporation. | |
6 | - * Copyright (C) 2017 Siemens AG | |
7 | - * Copyright 2019 Google LLC | |
8 | - * | |
9 | - * Taken from coreboot itss.c | |
10 | - */ | |
11 | - | |
12 | -#include <common.h> | |
13 | -#include <dm.h> | |
14 | -#include <dt-structs.h> | |
15 | -#include <irq.h> | |
16 | -#include <p2sb.h> | |
17 | -#include <spl.h> | |
18 | -#include <asm/arch/itss.h> | |
19 | - | |
20 | -struct apl_itss_platdata { | |
21 | -#if CONFIG_IS_ENABLED(OF_PLATDATA) | |
22 | - /* Put this first since driver model will copy the data here */ | |
23 | - struct dtd_intel_apl_itss dtplat; | |
24 | -#endif | |
25 | -}; | |
26 | - | |
27 | -/* struct pmc_route - Routing for PMC to GPIO */ | |
28 | -struct pmc_route { | |
29 | - u32 pmc; | |
30 | - u32 gpio; | |
31 | -}; | |
32 | - | |
33 | -struct apl_itss_priv { | |
34 | - struct pmc_route *route; | |
35 | - uint route_count; | |
36 | - u32 irq_snapshot[NUM_IPC_REGS]; | |
37 | -}; | |
38 | - | |
39 | -static int apl_set_polarity(struct udevice *dev, uint irq, bool active_low) | |
40 | -{ | |
41 | - u32 mask; | |
42 | - uint reg; | |
43 | - | |
44 | - if (irq > ITSS_MAX_IRQ) | |
45 | - return -EINVAL; | |
46 | - | |
47 | - reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * (irq / IRQS_PER_IPC); | |
48 | - mask = 1 << (irq % IRQS_PER_IPC); | |
49 | - | |
50 | - pcr_clrsetbits32(dev, reg, mask, active_low ? mask : 0); | |
51 | - | |
52 | - return 0; | |
53 | -} | |
54 | - | |
55 | -#ifndef CONFIG_TPL_BUILD | |
56 | -static int apl_snapshot_polarities(struct udevice *dev) | |
57 | -{ | |
58 | - struct apl_itss_priv *priv = dev_get_priv(dev); | |
59 | - const int start = GPIO_IRQ_START; | |
60 | - const int end = GPIO_IRQ_END; | |
61 | - int reg_start; | |
62 | - int reg_end; | |
63 | - int i; | |
64 | - | |
65 | - reg_start = start / IRQS_PER_IPC; | |
66 | - reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC; | |
67 | - | |
68 | - for (i = reg_start; i < reg_end; i++) { | |
69 | - uint reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i; | |
70 | - | |
71 | - priv->irq_snapshot[i] = pcr_read32(dev, reg); | |
72 | - } | |
73 | - | |
74 | - return 0; | |
75 | -} | |
76 | - | |
77 | -static void show_polarities(struct udevice *dev, const char *msg) | |
78 | -{ | |
79 | - int i; | |
80 | - | |
81 | - log_info("ITSS IRQ Polarities %s:\n", msg); | |
82 | - for (i = 0; i < NUM_IPC_REGS; i++) { | |
83 | - uint reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i; | |
84 | - | |
85 | - log_info("IPC%d: 0x%08x\n", i, pcr_read32(dev, reg)); | |
86 | - } | |
87 | -} | |
88 | - | |
89 | -static int apl_restore_polarities(struct udevice *dev) | |
90 | -{ | |
91 | - struct apl_itss_priv *priv = dev_get_priv(dev); | |
92 | - const int start = GPIO_IRQ_START; | |
93 | - const int end = GPIO_IRQ_END; | |
94 | - int reg_start; | |
95 | - int reg_end; | |
96 | - int i; | |
97 | - | |
98 | - show_polarities(dev, "Before"); | |
99 | - | |
100 | - reg_start = start / IRQS_PER_IPC; | |
101 | - reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC; | |
102 | - | |
103 | - for (i = reg_start; i < reg_end; i++) { | |
104 | - u32 mask; | |
105 | - u16 reg; | |
106 | - int irq_start; | |
107 | - int irq_end; | |
108 | - | |
109 | - irq_start = i * IRQS_PER_IPC; | |
110 | - irq_end = min(irq_start + IRQS_PER_IPC - 1, ITSS_MAX_IRQ); | |
111 | - | |
112 | - if (start > irq_end) | |
113 | - continue; | |
114 | - if (end < irq_start) | |
115 | - break; | |
116 | - | |
117 | - /* Track bits within the bounds of of the register */ | |
118 | - irq_start = max(start, irq_start) % IRQS_PER_IPC; | |
119 | - irq_end = min(end, irq_end) % IRQS_PER_IPC; | |
120 | - | |
121 | - /* Create bitmask of the inclusive range of start and end */ | |
122 | - mask = (((1U << irq_end) - 1) | (1U << irq_end)); | |
123 | - mask &= ~((1U << irq_start) - 1); | |
124 | - | |
125 | - reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i; | |
126 | - pcr_clrsetbits32(dev, reg, mask, mask & priv->irq_snapshot[i]); | |
127 | - } | |
128 | - | |
129 | - show_polarities(dev, "After"); | |
130 | - | |
131 | - return 0; | |
132 | -} | |
133 | -#endif | |
134 | - | |
135 | -static int apl_route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num) | |
136 | -{ | |
137 | - struct apl_itss_priv *priv = dev_get_priv(dev); | |
138 | - struct pmc_route *route; | |
139 | - int i; | |
140 | - | |
141 | - for (i = 0, route = priv->route; i < priv->route_count; i++, route++) { | |
142 | - if (pmc_gpe_num == route->pmc) | |
143 | - return route->gpio; | |
144 | - } | |
145 | - | |
146 | - return -ENOENT; | |
147 | -} | |
148 | - | |
149 | -static int apl_itss_ofdata_to_platdata(struct udevice *dev) | |
150 | -{ | |
151 | - struct apl_itss_priv *priv = dev_get_priv(dev); | |
152 | - int ret; | |
153 | - | |
154 | -#if CONFIG_IS_ENABLED(OF_PLATDATA) | |
155 | - struct apl_itss_platdata *plat = dev_get_platdata(dev); | |
156 | - struct dtd_intel_apl_itss *dtplat = &plat->dtplat; | |
157 | - | |
158 | - /* | |
159 | - * It would be nice to do this in the bind() method, but with | |
160 | - * of-platdata binding happens in the order that DM finds things in the | |
161 | - * linker list (i.e. alphabetical order by driver name). So the GPIO | |
162 | - * device may well be bound before its parent (p2sb), and this call | |
163 | - * will fail if p2sb is not bound yet. | |
164 | - * | |
165 | - * TODO(sjg@chromium.org): Add a parent pointer to child devices in dtoc | |
166 | - */ | |
167 | - ret = p2sb_set_port_id(dev, dtplat->intel_p2sb_port_id); | |
168 | - if (ret) | |
169 | - return log_msg_ret("Could not set port id", ret); | |
170 | - priv->route = (struct pmc_route *)dtplat->intel_pmc_routes; | |
171 | - priv->route_count = ARRAY_SIZE(dtplat->intel_pmc_routes) / | |
172 | - sizeof(struct pmc_route); | |
173 | -#else | |
174 | - int size; | |
175 | - | |
176 | - size = dev_read_size(dev, "intel,pmc-routes"); | |
177 | - if (size < 0) | |
178 | - return size; | |
179 | - priv->route = malloc(size); | |
180 | - if (!priv->route) | |
181 | - return -ENOMEM; | |
182 | - ret = dev_read_u32_array(dev, "intel,pmc-routes", (u32 *)priv->route, | |
183 | - size / sizeof(fdt32_t)); | |
184 | - if (ret) | |
185 | - return log_msg_ret("Cannot read pmc-routes", ret); | |
186 | - priv->route_count = size / sizeof(struct pmc_route); | |
187 | -#endif | |
188 | - | |
189 | - return 0; | |
190 | -} | |
191 | - | |
192 | -static const struct irq_ops apl_itss_ops = { | |
193 | - .route_pmc_gpio_gpe = apl_route_pmc_gpio_gpe, | |
194 | - .set_polarity = apl_set_polarity, | |
195 | -#ifndef CONFIG_TPL_BUILD | |
196 | - .snapshot_polarities = apl_snapshot_polarities, | |
197 | - .restore_polarities = apl_restore_polarities, | |
198 | -#endif | |
199 | -}; | |
200 | - | |
201 | -static const struct udevice_id apl_itss_ids[] = { | |
202 | - { .compatible = "intel,apl-itss"}, | |
203 | - { } | |
204 | -}; | |
205 | - | |
206 | -U_BOOT_DRIVER(apl_itss_drv) = { | |
207 | - .name = "intel_apl_itss", | |
208 | - .id = UCLASS_IRQ, | |
209 | - .of_match = apl_itss_ids, | |
210 | - .ops = &apl_itss_ops, | |
211 | - .ofdata_to_platdata = apl_itss_ofdata_to_platdata, | |
212 | - .platdata_auto_alloc_size = sizeof(struct apl_itss_platdata), | |
213 | - .priv_auto_alloc_size = sizeof(struct apl_itss_priv), | |
214 | -}; |
arch/x86/cpu/i386/cpu.c
... | ... | @@ -136,10 +136,14 @@ |
136 | 136 | /* DS: data, read/write, 4 GB, base 0 */ |
137 | 137 | gdt_addr[X86_GDT_ENTRY_32BIT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff); |
138 | 138 | |
139 | - /* FS: data, read/write, 4 GB, base (Global Data Pointer) */ | |
139 | + /* | |
140 | + * FS: data, read/write, sizeof (Global Data Pointer), | |
141 | + * base (Global Data Pointer) | |
142 | + */ | |
140 | 143 | new_gd->arch.gd_addr = new_gd; |
141 | - gdt_addr[X86_GDT_ENTRY_32BIT_FS] = GDT_ENTRY(0xc093, | |
142 | - (ulong)&new_gd->arch.gd_addr, 0xfffff); | |
144 | + gdt_addr[X86_GDT_ENTRY_32BIT_FS] = GDT_ENTRY(0x8093, | |
145 | + (ulong)&new_gd->arch.gd_addr, | |
146 | + sizeof(new_gd->arch.gd_addr) - 1); | |
143 | 147 | |
144 | 148 | /* 16-bit CS: code, read/execute, 64 kB, base 0 */ |
145 | 149 | gdt_addr[X86_GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x009b, 0, 0x0ffff); |
arch/x86/cpu/intel_common/Makefile
arch/x86/cpu/intel_common/itss.c
1 | +// SPDX-License-Identifier: GPL-2.0 | |
2 | +/* | |
3 | + * Interrupt Timer Subsystem | |
4 | + * | |
5 | + * Copyright (C) 2017 Intel Corporation. | |
6 | + * Copyright (C) 2017 Siemens AG | |
7 | + * Copyright 2019 Google LLC | |
8 | + * | |
9 | + * Taken from coreboot itss.c | |
10 | + */ | |
11 | + | |
12 | +#include <common.h> | |
13 | +#include <dm.h> | |
14 | +#include <dt-structs.h> | |
15 | +#include <irq.h> | |
16 | +#include <p2sb.h> | |
17 | +#include <spl.h> | |
18 | +#include <asm/itss.h> | |
19 | + | |
20 | +struct itss_platdata { | |
21 | +#if CONFIG_IS_ENABLED(OF_PLATDATA) | |
22 | + /* Put this first since driver model will copy the data here */ | |
23 | + struct dtd_intel_itss dtplat; | |
24 | +#endif | |
25 | +}; | |
26 | + | |
27 | +/* struct pmc_route - Routing for PMC to GPIO */ | |
28 | +struct pmc_route { | |
29 | + u32 pmc; | |
30 | + u32 gpio; | |
31 | +}; | |
32 | + | |
33 | +struct itss_priv { | |
34 | + struct pmc_route *route; | |
35 | + uint route_count; | |
36 | + u32 irq_snapshot[NUM_IPC_REGS]; | |
37 | +}; | |
38 | + | |
39 | +static int set_polarity(struct udevice *dev, uint irq, bool active_low) | |
40 | +{ | |
41 | + u32 mask; | |
42 | + uint reg; | |
43 | + | |
44 | + if (irq > ITSS_MAX_IRQ) | |
45 | + return -EINVAL; | |
46 | + | |
47 | + reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * (irq / IRQS_PER_IPC); | |
48 | + mask = 1 << (irq % IRQS_PER_IPC); | |
49 | + | |
50 | + pcr_clrsetbits32(dev, reg, mask, active_low ? mask : 0); | |
51 | + | |
52 | + return 0; | |
53 | +} | |
54 | + | |
55 | +#ifndef CONFIG_TPL_BUILD | |
56 | +static int snapshot_polarities(struct udevice *dev) | |
57 | +{ | |
58 | + struct itss_priv *priv = dev_get_priv(dev); | |
59 | + const int start = GPIO_IRQ_START; | |
60 | + const int end = GPIO_IRQ_END; | |
61 | + int reg_start; | |
62 | + int reg_end; | |
63 | + int i; | |
64 | + | |
65 | + reg_start = start / IRQS_PER_IPC; | |
66 | + reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC; | |
67 | + | |
68 | + for (i = reg_start; i < reg_end; i++) { | |
69 | + uint reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i; | |
70 | + | |
71 | + priv->irq_snapshot[i] = pcr_read32(dev, reg); | |
72 | + } | |
73 | + | |
74 | + return 0; | |
75 | +} | |
76 | + | |
77 | +static void show_polarities(struct udevice *dev, const char *msg) | |
78 | +{ | |
79 | + int i; | |
80 | + | |
81 | + log_info("ITSS IRQ Polarities %s:\n", msg); | |
82 | + for (i = 0; i < NUM_IPC_REGS; i++) { | |
83 | + uint reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i; | |
84 | + | |
85 | + log_info("IPC%d: 0x%08x\n", i, pcr_read32(dev, reg)); | |
86 | + } | |
87 | +} | |
88 | + | |
89 | +static int restore_polarities(struct udevice *dev) | |
90 | +{ | |
91 | + struct itss_priv *priv = dev_get_priv(dev); | |
92 | + const int start = GPIO_IRQ_START; | |
93 | + const int end = GPIO_IRQ_END; | |
94 | + int reg_start; | |
95 | + int reg_end; | |
96 | + int i; | |
97 | + | |
98 | + show_polarities(dev, "Before"); | |
99 | + | |
100 | + reg_start = start / IRQS_PER_IPC; | |
101 | + reg_end = (end + IRQS_PER_IPC - 1) / IRQS_PER_IPC; | |
102 | + | |
103 | + for (i = reg_start; i < reg_end; i++) { | |
104 | + u32 mask; | |
105 | + u16 reg; | |
106 | + int irq_start; | |
107 | + int irq_end; | |
108 | + | |
109 | + irq_start = i * IRQS_PER_IPC; | |
110 | + irq_end = min(irq_start + IRQS_PER_IPC - 1, ITSS_MAX_IRQ); | |
111 | + | |
112 | + if (start > irq_end) | |
113 | + continue; | |
114 | + if (end < irq_start) | |
115 | + break; | |
116 | + | |
117 | + /* Track bits within the bounds of of the register */ | |
118 | + irq_start = max(start, irq_start) % IRQS_PER_IPC; | |
119 | + irq_end = min(end, irq_end) % IRQS_PER_IPC; | |
120 | + | |
121 | + /* Create bitmask of the inclusive range of start and end */ | |
122 | + mask = (((1U << irq_end) - 1) | (1U << irq_end)); | |
123 | + mask &= ~((1U << irq_start) - 1); | |
124 | + | |
125 | + reg = PCR_ITSS_IPC0_CONF + sizeof(u32) * i; | |
126 | + pcr_clrsetbits32(dev, reg, mask, mask & priv->irq_snapshot[i]); | |
127 | + } | |
128 | + | |
129 | + show_polarities(dev, "After"); | |
130 | + | |
131 | + return 0; | |
132 | +} | |
133 | +#endif | |
134 | + | |
135 | +static int route_pmc_gpio_gpe(struct udevice *dev, uint pmc_gpe_num) | |
136 | +{ | |
137 | + struct itss_priv *priv = dev_get_priv(dev); | |
138 | + struct pmc_route *route; | |
139 | + int i; | |
140 | + | |
141 | + for (i = 0, route = priv->route; i < priv->route_count; i++, route++) { | |
142 | + if (pmc_gpe_num == route->pmc) | |
143 | + return route->gpio; | |
144 | + } | |
145 | + | |
146 | + return -ENOENT; | |
147 | +} | |
148 | + | |
149 | +static int itss_ofdata_to_platdata(struct udevice *dev) | |
150 | +{ | |
151 | + struct itss_priv *priv = dev_get_priv(dev); | |
152 | + int ret; | |
153 | + | |
154 | +#if CONFIG_IS_ENABLED(OF_PLATDATA) | |
155 | + struct itss_platdata *plat = dev_get_platdata(dev); | |
156 | + struct dtd_intel_itss *dtplat = &plat->dtplat; | |
157 | + | |
158 | + /* | |
159 | + * It would be nice to do this in the bind() method, but with | |
160 | + * of-platdata binding happens in the order that DM finds things in the | |
161 | + * linker list (i.e. alphabetical order by driver name). So the GPIO | |
162 | + * device may well be bound before its parent (p2sb), and this call | |
163 | + * will fail if p2sb is not bound yet. | |
164 | + * | |
165 | + * TODO(sjg@chromium.org): Add a parent pointer to child devices in dtoc | |
166 | + */ | |
167 | + ret = p2sb_set_port_id(dev, dtplat->intel_p2sb_port_id); | |
168 | + if (ret) | |
169 | + return log_msg_ret("Could not set port id", ret); | |
170 | + priv->route = (struct pmc_route *)dtplat->intel_pmc_routes; | |
171 | + priv->route_count = ARRAY_SIZE(dtplat->intel_pmc_routes) / | |
172 | + sizeof(struct pmc_route); | |
173 | +#else | |
174 | + int size; | |
175 | + | |
176 | + size = dev_read_size(dev, "intel,pmc-routes"); | |
177 | + if (size < 0) | |
178 | + return size; | |
179 | + priv->route = malloc(size); | |
180 | + if (!priv->route) | |
181 | + return -ENOMEM; | |
182 | + ret = dev_read_u32_array(dev, "intel,pmc-routes", (u32 *)priv->route, | |
183 | + size / sizeof(fdt32_t)); | |
184 | + if (ret) | |
185 | + return log_msg_ret("Cannot read pmc-routes", ret); | |
186 | + priv->route_count = size / sizeof(struct pmc_route); | |
187 | +#endif | |
188 | + | |
189 | + return 0; | |
190 | +} | |
191 | + | |
192 | +static const struct irq_ops itss_ops = { | |
193 | + .route_pmc_gpio_gpe = route_pmc_gpio_gpe, | |
194 | + .set_polarity = set_polarity, | |
195 | +#ifndef CONFIG_TPL_BUILD | |
196 | + .snapshot_polarities = snapshot_polarities, | |
197 | + .restore_polarities = restore_polarities, | |
198 | +#endif | |
199 | +}; | |
200 | + | |
201 | +static const struct udevice_id itss_ids[] = { | |
202 | + { .compatible = "intel,itss"}, | |
203 | + { } | |
204 | +}; | |
205 | + | |
206 | +U_BOOT_DRIVER(itss_drv) = { | |
207 | + .name = "intel_itss", | |
208 | + .id = UCLASS_IRQ, | |
209 | + .of_match = itss_ids, | |
210 | + .ops = &itss_ops, | |
211 | + .ofdata_to_platdata = itss_ofdata_to_platdata, | |
212 | + .platdata_auto_alloc_size = sizeof(struct itss_platdata), | |
213 | + .priv_auto_alloc_size = sizeof(struct itss_priv), | |
214 | +}; |
arch/x86/cpu/slimbootloader/serial.c
... | ... | @@ -34,18 +34,15 @@ |
34 | 34 | data->stride, |
35 | 35 | data->clk); |
36 | 36 | |
37 | - /* | |
38 | - * The data->type provides port io or mmio access type info, | |
39 | - * but the access type will be controlled by | |
40 | - * CONFIG_SYS_NS16550_PORT_MAPPED or CONFIG_SYS_NS16550_MEM32. | |
41 | - * | |
42 | - * TBD: ns16550 access type configuration in runtime. | |
43 | - * ex) plat->access_type = data->type | |
44 | - */ | |
45 | 37 | plat->base = data->base; |
46 | 38 | /* ns16550 uses reg_shift, then covert stride to shift */ |
47 | 39 | plat->reg_shift = data->stride >> 1; |
40 | + plat->reg_width = data->stride; | |
48 | 41 | plat->clock = data->clk; |
42 | + plat->fcr = UART_FCR_DEFVAL; | |
43 | + plat->flags = 0; | |
44 | + if (data->type == 1) | |
45 | + plat->flags |= NS16550_FLAG_IO; | |
49 | 46 | |
50 | 47 | return 0; |
51 | 48 | } |
arch/x86/cpu/start.S
arch/x86/cpu/start16.S
arch/x86/dts/chromebook_coral.dts
arch/x86/dts/coreboot.dts
... | ... | @@ -8,7 +8,6 @@ |
8 | 8 | /dts-v1/; |
9 | 9 | |
10 | 10 | /include/ "skeleton.dtsi" |
11 | -/include/ "serial.dtsi" | |
12 | 11 | /include/ "keyboard.dtsi" |
13 | 12 | /include/ "pcspkr.dtsi" |
14 | 13 | /include/ "reset.dtsi" |
... | ... | @@ -38,6 +37,11 @@ |
38 | 37 | pci { |
39 | 38 | compatible = "pci-x86"; |
40 | 39 | u-boot,dm-pre-reloc; |
40 | + }; | |
41 | + | |
42 | + serial: serial { | |
43 | + u-boot,dm-pre-reloc; | |
44 | + compatible = "coreboot-serial"; | |
41 | 45 | }; |
42 | 46 | |
43 | 47 | coreboot-fb { |
arch/x86/include/asm/arch-apollolake/itss.h
1 | -/* SPDX-License-Identifier: GPL-2.0 */ | |
2 | -/* | |
3 | - * Copyright (C) 2017 Intel Corporation. | |
4 | - * Copyright 2019 Google LLC | |
5 | - * | |
6 | - * Modified from coreboot itss.h | |
7 | - */ | |
8 | - | |
9 | -#ifndef _ASM_ARCH_ITSS_H | |
10 | -#define _ASM_ARCH_ITSS_H | |
11 | - | |
12 | -#define GPIO_IRQ_START 50 | |
13 | -#define GPIO_IRQ_END ITSS_MAX_IRQ | |
14 | - | |
15 | -#define ITSS_MAX_IRQ 119 | |
16 | -#define IRQS_PER_IPC 32 | |
17 | -#define NUM_IPC_REGS ((ITSS_MAX_IRQ + IRQS_PER_IPC - 1) / IRQS_PER_IPC) | |
18 | - | |
19 | -/* Max PXRC registers in ITSS */ | |
20 | -#define MAX_PXRC_CONFIG (PCR_ITSS_PIRQH_ROUT - PCR_ITSS_PIRQA_ROUT + 1) | |
21 | - | |
22 | -/* PIRQA Routing Control Register */ | |
23 | -#define PCR_ITSS_PIRQA_ROUT 0x3100 | |
24 | -/* PIRQB Routing Control Register */ | |
25 | -#define PCR_ITSS_PIRQB_ROUT 0x3101 | |
26 | -/* PIRQC Routing Control Register */ | |
27 | -#define PCR_ITSS_PIRQC_ROUT 0x3102 | |
28 | -/* PIRQD Routing Control Register */ | |
29 | -#define PCR_ITSS_PIRQD_ROUT 0x3103 | |
30 | -/* PIRQE Routing Control Register */ | |
31 | -#define PCR_ITSS_PIRQE_ROUT 0x3104 | |
32 | -/* PIRQF Routing Control Register */ | |
33 | -#define PCR_ITSS_PIRQF_ROUT 0x3105 | |
34 | -/* PIRQG Routing Control Register */ | |
35 | -#define PCR_ITSS_PIRQG_ROUT 0x3106 | |
36 | -/* PIRQH Routing Control Register */ | |
37 | -#define PCR_ITSS_PIRQH_ROUT 0x3107 | |
38 | -/* ITSS Interrupt polarity control */ | |
39 | -#define PCR_ITSS_IPC0_CONF 0x3200 | |
40 | -/* ITSS Power reduction control */ | |
41 | -#define PCR_ITSS_ITSSPRC 0x3300 | |
42 | - | |
43 | -#endif /* _ASM_ARCH_ITSS_H */ |
arch/x86/include/asm/coreboot_tables.h
... | ... | @@ -97,6 +97,25 @@ |
97 | 97 | u32 type; |
98 | 98 | u32 baseaddr; |
99 | 99 | u32 baud; |
100 | + u32 regwidth; | |
101 | + | |
102 | + /* | |
103 | + * Crystal or input frequency to the chip containing the UART. | |
104 | + * Provide the board specific details to allow the payload to | |
105 | + * initialize the chip containing the UART and make independent | |
106 | + * decisions as to which dividers to select and their values | |
107 | + * to eventually arrive at the desired console baud-rate. | |
108 | + */ | |
109 | + u32 input_hertz; | |
110 | + | |
111 | + /* | |
112 | + * UART PCI address: bus, device, function | |
113 | + * 1 << 31 - Valid bit, PCI UART in use | |
114 | + * Bus << 20 | |
115 | + * Device << 15 | |
116 | + * Function << 12 | |
117 | + */ | |
118 | + u32 uart_pci_addr; | |
100 | 119 | }; |
101 | 120 | |
102 | 121 | #define CB_TAG_CONSOLE 0x0010 |
arch/x86/include/asm/itss.h
1 | +/* SPDX-License-Identifier: GPL-2.0 */ | |
2 | +/* | |
3 | + * Interrupt Timer Subsystem | |
4 | + * | |
5 | + * Copyright (C) 2017 Intel Corporation. | |
6 | + * Copyright 2019 Google LLC | |
7 | + * | |
8 | + * Modified from coreboot itss.h | |
9 | + */ | |
10 | + | |
11 | +#ifndef _ASM_ARCH_ITSS_H | |
12 | +#define _ASM_ARCH_ITSS_H | |
13 | + | |
14 | +#define GPIO_IRQ_START 50 | |
15 | +#define GPIO_IRQ_END ITSS_MAX_IRQ | |
16 | + | |
17 | +#define ITSS_MAX_IRQ 119 | |
18 | +#define IRQS_PER_IPC 32 | |
19 | +#define NUM_IPC_REGS ((ITSS_MAX_IRQ + IRQS_PER_IPC - 1) / IRQS_PER_IPC) | |
20 | + | |
21 | +/* Max PXRC registers in ITSS */ | |
22 | +#define MAX_PXRC_CONFIG (PCR_ITSS_PIRQH_ROUT - PCR_ITSS_PIRQA_ROUT + 1) | |
23 | + | |
24 | +/* PIRQA Routing Control Register */ | |
25 | +#define PCR_ITSS_PIRQA_ROUT 0x3100 | |
26 | +/* PIRQB Routing Control Register */ | |
27 | +#define PCR_ITSS_PIRQB_ROUT 0x3101 | |
28 | +/* PIRQC Routing Control Register */ | |
29 | +#define PCR_ITSS_PIRQC_ROUT 0x3102 | |
30 | +/* PIRQD Routing Control Register */ | |
31 | +#define PCR_ITSS_PIRQD_ROUT 0x3103 | |
32 | +/* PIRQE Routing Control Register */ | |
33 | +#define PCR_ITSS_PIRQE_ROUT 0x3104 | |
34 | +/* PIRQF Routing Control Register */ | |
35 | +#define PCR_ITSS_PIRQF_ROUT 0x3105 | |
36 | +/* PIRQG Routing Control Register */ | |
37 | +#define PCR_ITSS_PIRQG_ROUT 0x3106 | |
38 | +/* PIRQH Routing Control Register */ | |
39 | +#define PCR_ITSS_PIRQH_ROUT 0x3107 | |
40 | +/* ITSS Interrupt polarity control */ | |
41 | +#define PCR_ITSS_IPC0_CONF 0x3200 | |
42 | +/* ITSS Power reduction control */ | |
43 | +#define PCR_ITSS_ITSSPRC 0x3300 | |
44 | + | |
45 | +#endif /* _ASM_ARCH_ITSS_H */ |
configs/edison_defconfig
... | ... | @@ -6,10 +6,10 @@ |
6 | 6 | CONFIG_VENDOR_INTEL=y |
7 | 7 | CONFIG_TARGET_EDISON=y |
8 | 8 | CONFIG_SMP=y |
9 | +CONFIG_GENERATE_ACPI_TABLE=y | |
9 | 10 | CONFIG_BOARD_EARLY_INIT_R=y |
10 | 11 | CONFIG_LAST_STAGE_INIT=y |
11 | 12 | CONFIG_HUSH_PARSER=y |
12 | -# CONFIG_CMDLINE_EDITING is not set | |
13 | 13 | CONFIG_CMD_CPU=y |
14 | 14 | CONFIG_CMD_ASKENV=y |
15 | 15 | CONFIG_CMD_GREPENV=y |
doc/board/google/chromebook_coral.rst
... | ... | @@ -112,7 +112,7 @@ |
112 | 112 | |
113 | 113 | |
114 | 114 | Boot flow - U-Boot post-relocation |
115 | ---------------------------------- | |
115 | +---------------------------------- | |
116 | 116 | |
117 | 117 | U-Boot starts up normally, running near the top of RAM. After driver model is |
118 | 118 | running, arch_fsp_init_r() is called which loads and runs the FSP-S binary. |
119 | 119 | |
120 | 120 | |
121 | 121 | |
122 | 122 | |
123 | 123 | |
124 | 124 | |
... | ... | @@ -142,54 +142,56 @@ |
142 | 142 | ----------- |
143 | 143 | |
144 | 144 | Bootstage is used through all phases of U-Boot to keep accurate timimgs for |
145 | -boot. Use 'bootstage report' in U-Boot to see the report, e.g.: | |
145 | +boot. Use 'bootstage report' in U-Boot to see the report, e.g.:: | |
146 | 146 | |
147 | -Timer summary in microseconds (16 records): | |
148 | - Mark Elapsed Stage | |
149 | - 0 0 reset | |
150 | - 155,325 155,325 TPL | |
151 | - 204,014 48,689 end TPL | |
152 | - 204,385 371 SPL | |
153 | - 738,633 534,248 end SPL | |
154 | - 739,161 528 board_init_f | |
155 | - 842,764 103,603 board_init_r | |
156 | - 1,166,233 323,469 main_loop | |
157 | - 1,166,283 50 id=175 | |
147 | + Timer summary in microseconds (16 records): | |
148 | + Mark Elapsed Stage | |
149 | + 0 0 reset | |
150 | + 155,325 155,325 TPL | |
151 | + 204,014 48,689 end TPL | |
152 | + 204,385 371 SPL | |
153 | + 738,633 534,248 end SPL | |
154 | + 739,161 528 board_init_f | |
155 | + 842,764 103,603 board_init_r | |
156 | + 1,166,233 323,469 main_loop | |
157 | + 1,166,283 50 id=175 | |
158 | 158 | |
159 | -Accumulated time: | |
160 | - 62 fast_spi | |
161 | - 202 dm_r | |
162 | - 7,779 dm_spl | |
163 | - 15,555 dm_f | |
164 | - 208,357 fsp-m | |
165 | - 239,847 fsp-s | |
166 | - 292,143 mmap_spi | |
159 | + Accumulated time: | |
160 | + 62 fast_spi | |
161 | + 202 dm_r | |
162 | + 7,779 dm_spl | |
163 | + 15,555 dm_f | |
164 | + 208,357 fsp-m | |
165 | + 239,847 fsp-s | |
166 | + 292,143 mmap_spi | |
167 | 167 | |
168 | -CPU performance is about 3500 DMIPS: | |
168 | +CPU performance is about 3500 DMIPS:: | |
169 | 169 | |
170 | -=> dhry | |
171 | -1000000 iterations in 161 ms: 6211180/s, 3535 DMIPS | |
170 | + => dhry | |
171 | + 1000000 iterations in 161 ms: 6211180/s, 3535 DMIPS | |
172 | 172 | |
173 | 173 | |
174 | 174 | Partial memory map |
175 | 175 | ------------------ |
176 | 176 | |
177 | -ffffffff Top of ROM (and last byte of 32-bit address space) | |
178 | -ffff8000 TPL loaded here (from IFWI) | |
179 | -ff000000 Bottom of ROM | |
180 | -fefc000 Top of CAR region | |
181 | -fef96000 Stack for FSP-M | |
182 | -fef40000 59000 FSP-M | |
183 | -fef11000 SPL loaded here | |
184 | -fef10000 CONFIG_BLOBLIST_ADDR | |
185 | -fef10000 Stack top in TPL, SPL and U-Boot before relocation | |
186 | -fef00000 1000 CONFIG_BOOTSTAGE_STASH_ADDR | |
187 | -fef00000 Base of CAR region | |
177 | +:: | |
188 | 178 | |
189 | - f0000 CONFIG_ROM_TABLE_ADDR | |
190 | - 120000 BSS (defined in u-boot-spl.lds) | |
191 | - 200000 FSP-S (which is run after U-Boot is relocated) | |
192 | - 1110000 CONFIG_SYS_TEXT_BASE | |
179 | + ffffffff Top of ROM (and last byte of 32-bit address space) | |
180 | + ffff8000 TPL loaded here (from IFWI) | |
181 | + ff000000 Bottom of ROM | |
182 | + fefc000 Top of CAR region | |
183 | + fef96000 Stack for FSP-M | |
184 | + fef40000 59000 FSP-M | |
185 | + fef11000 SPL loaded here | |
186 | + fef10000 CONFIG_BLOBLIST_ADDR | |
187 | + fef10000 Stack top in TPL, SPL and U-Boot before relocation | |
188 | + fef00000 1000 CONFIG_BOOTSTAGE_STASH_ADDR | |
189 | + fef00000 Base of CAR region | |
190 | + | |
191 | + f0000 CONFIG_ROM_TABLE_ADDR | |
192 | + 120000 BSS (defined in u-boot-spl.lds) | |
193 | + 200000 FSP-S (which is run after U-Boot is relocated) | |
194 | + 1110000 CONFIG_SYS_TEXT_BASE | |
193 | 195 | |
194 | 196 | |
195 | 197 | Supported peripherals |
doc/board/intel/slimbootloader.rst
... | ... | @@ -111,35 +111,16 @@ |
111 | 111 | Build Instruction for Slim Bootloader for LeafHill (APL) target |
112 | 112 | --------------------------------------------------------------- |
113 | 113 | |
114 | -LeafHill is using PCI UART2 device as a serial port. | |
115 | -For MEM32 serial port, CONFIG_SYS_NS16550_MEM32 needs to be enabled in U-Boot. | |
114 | +Prepare U-Boot and Slim Bootloader as described at the beginning of this page. | |
115 | +Also, the PayloadId needs to be set for APL board. | |
116 | 116 | |
117 | -1. Enable CONFIG_SYS_NS16550_MEM32 in U-Boot:: | |
117 | +1. Update PayloadId. Let's use 'U-BT' as an example:: | |
118 | 118 | |
119 | - $ vi include/configs/slimbootloader.h | |
120 | - +#define CONFIG_SYS_NS16550_MEM32 | |
121 | - #ifdef CONFIG_SYS_NS16550_MEM3 | |
122 | - | |
123 | -2. Build U-Boot:: | |
124 | - | |
125 | - $ make disclean | |
126 | - $ make slimbootloader_defconfig | |
127 | - $ make all | |
128 | - | |
129 | -3. Copy u-boot-dtb.bin to Slim Bootloader. | |
130 | - Slim Bootloader looks for a payload from the specific location. | |
131 | - Copy the build u-boot-dtb.bin to the expected location:: | |
132 | - | |
133 | - $ mkdir -p <Slim Bootloader Dir>/PayloadPkg/PayloadBins/ | |
134 | - $ cp <U-Boot Dir>/u-boot-dtb.bin <Slim Bootloader Dir>/PayloadPkg/PayloadBins/u-boot-dtb.bin | |
135 | - | |
136 | -4. Update PayloadId. Let's use 'U-BT' as an example:: | |
137 | - | |
138 | 119 | $ vi Platform/ApollolakeBoardPkg/CfgData/CfgData_Int_LeafHill.dlt |
139 | 120 | -GEN_CFG_DATA.PayloadId | 'AUTO |
140 | 121 | +GEN_CFG_DATA.PayloadId | 'U-BT' |
141 | 122 | |
142 | -5. Update payload text base. | |
123 | +2. Update payload text base. | |
143 | 124 | |
144 | 125 | * PAYLOAD_EXE_BASE must be the same as U-Boot CONFIG_SYS_TEXT_BASE |
145 | 126 | in board/intel/slimbootloader/Kconfig. |
146 | 127 | |
147 | 128 | |
... | ... | @@ -149,18 +130,18 @@ |
149 | 130 | + self.PAYLOAD_LOAD_HIGH = 0 |
150 | 131 | + self.PAYLOAD_EXE_BASE = 0x00100000 |
151 | 132 | |
152 | -6. Build APL target. Make sure u-boot-dtb.bin and U-BT PayloadId | |
133 | +3. Build APL target. Make sure u-boot-dtb.bin and U-BT PayloadId | |
153 | 134 | in build command. The output is Outputs/apl/Stitch_Components.zip:: |
154 | 135 | |
155 | 136 | $ python BuildLoader.py build apl -p "OsLoader.efi:LLDR:Lz4;u-boot-dtb.bin:U-BT:Lzma" |
156 | 137 | |
157 | -7. Stitch IFWI. | |
138 | +4. Stitch IFWI. | |
158 | 139 | |
159 | 140 | Refer to Apollolake_ page in Slim Bootloader document site:: |
160 | 141 | |
161 | 142 | $ python Platform/ApollolakeBoardPkg/Script/StitchLoader.py -i <Existing IFWI> -s Outputs/apl/Stitch_Components.zip -o <Output IFWI> |
162 | 143 | |
163 | -8. Flash IFWI. | |
144 | +5. Flash IFWI. | |
164 | 145 | |
165 | 146 | Use DediProg to flash IFWI. You should reach at U-Boot serial console. |
166 | 147 | |
... | ... | @@ -175,7 +156,7 @@ |
175 | 156 | |
176 | 157 | 2. Build U-Boot:: |
177 | 158 | |
178 | - $ make disclean | |
159 | + $ make distclean | |
179 | 160 | $ make slimbootloader_defconfig |
180 | 161 | $ make all |
181 | 162 | $ strip u-boot (removing symbol for reduced size) |
drivers/gpio/intel_gpio.c
... | ... | @@ -39,9 +39,9 @@ |
39 | 39 | struct udevice *pinctrl = dev_get_parent(dev); |
40 | 40 | uint config_offset = intel_pinctrl_get_config_reg_addr(pinctrl, offset); |
41 | 41 | |
42 | - pcr_clrsetbits32(dev, config_offset, | |
42 | + pcr_clrsetbits32(pinctrl, config_offset, | |
43 | 43 | PAD_CFG0_MODE_MASK | PAD_CFG0_RX_STATE | |
44 | - PAD_CFG0_TX_DISABLE, | |
44 | + PAD_CFG0_TX_DISABLE | PAD_CFG0_TX_STATE, | |
45 | 45 | PAD_CFG0_MODE_GPIO | PAD_CFG0_RX_DISABLE | |
46 | 46 | (value ? PAD_CFG0_TX_STATE : 0)); |
47 | 47 | |
48 | 48 | |
... | ... | @@ -59,9 +59,9 @@ |
59 | 59 | if (!mode) { |
60 | 60 | rx_tx = reg & (PAD_CFG0_TX_DISABLE | PAD_CFG0_RX_DISABLE); |
61 | 61 | if (rx_tx == PAD_CFG0_TX_DISABLE) |
62 | - return mode & PAD_CFG0_RX_STATE_BIT ? 1 : 0; | |
62 | + return reg & PAD_CFG0_RX_STATE ? 1 : 0; | |
63 | 63 | else if (rx_tx == PAD_CFG0_RX_DISABLE) |
64 | - return mode & PAD_CFG0_TX_STATE_BIT ? 1 : 0; | |
64 | + return reg & PAD_CFG0_TX_STATE ? 1 : 0; | |
65 | 65 | } |
66 | 66 | |
67 | 67 | return 0; |
... | ... | @@ -72,7 +72,7 @@ |
72 | 72 | struct udevice *pinctrl = dev_get_parent(dev); |
73 | 73 | uint config_offset = intel_pinctrl_get_config_reg_addr(pinctrl, offset); |
74 | 74 | |
75 | - pcr_clrsetbits32(dev, config_offset, PAD_CFG0_TX_STATE, | |
75 | + pcr_clrsetbits32(pinctrl, config_offset, PAD_CFG0_TX_STATE, | |
76 | 76 | value ? PAD_CFG0_TX_STATE : 0); |
77 | 77 | |
78 | 78 | return 0; |
drivers/pinctrl/intel/pinctrl.c
drivers/serial/Kconfig
... | ... | @@ -542,6 +542,17 @@ |
542 | 542 | help |
543 | 543 | Select this to enable UART on BCM6345 SoCs. |
544 | 544 | |
545 | +config COREBOOT_SERIAL | |
546 | + bool "Coreboot UART support" | |
547 | + depends on DM_SERIAL | |
548 | + default y if SYS_COREBOOT | |
549 | + select SYS_NS16550 | |
550 | + help | |
551 | + Select this to enable a ns16550-style UART where the platform data | |
552 | + comes from the coreboot 'sysinfo' tables. This allows U-Boot to have | |
553 | + a serial console on any platform without needing to change the | |
554 | + device tree, etc. | |
555 | + | |
545 | 556 | config FSL_LINFLEXUART |
546 | 557 | bool "Freescale Linflex UART support" |
547 | 558 | depends on DM_SERIAL |
... | ... | @@ -600,6 +611,27 @@ |
600 | 611 | CONFIG_SYS_NS16550_CLK defined in a legacy board header file will |
601 | 612 | be used. It can be a constant or a function to get clock, eg, |
602 | 613 | get_serial_clock(). |
614 | + | |
615 | +config NS16550_DYNAMIC | |
616 | + bool "Allow NS16550 to be configured at runtime" | |
617 | + default y if SYS_COREBOOT || SYS_SLIMBOOTLOADER | |
618 | + help | |
619 | + Enable this option to allow device-tree control of the driver. | |
620 | + | |
621 | + Normally this driver is controlled by the following options: | |
622 | + | |
623 | + CONFIG_SYS_NS16550_PORT_MAPPED - indicates that port I/O is used for | |
624 | + access. If not enabled, then the UART is memory-mapped. | |
625 | + CONFIG_SYS_NS16550_MEM32 - if memory-mapped, indicates that 32-bit | |
626 | + access should be used (instead of 8-bit) | |
627 | + CONFIG_SYS_NS16550_REG_SIZE - indicates register width and also | |
628 | + endianness. If positive, big-endian access is used. If negative, | |
629 | + little-endian is used. | |
630 | + | |
631 | + It is not a good practice for a driver to be statically configured, | |
632 | + since it prevents the same driver being used for different types of | |
633 | + UARTs in a system. This option avoids this problem at the cost of a | |
634 | + slightly increased code size. | |
603 | 635 | |
604 | 636 | config INTEL_MID_SERIAL |
605 | 637 | bool "Intel MID platform UART support" |
drivers/serial/Makefile
... | ... | @@ -35,6 +35,7 @@ |
35 | 35 | obj-$(CONFIG_ARM_DCC) += arm_dcc.o |
36 | 36 | obj-$(CONFIG_ATMEL_USART) += atmel_usart.o |
37 | 37 | obj-$(CONFIG_BCM6345_SERIAL) += serial_bcm6345.o |
38 | +obj-$(CONFIG_COREBOOT_SERIAL) += serial_coreboot.o | |
38 | 39 | obj-$(CONFIG_EFI_APP) += serial_efi.o |
39 | 40 | obj-$(CONFIG_LPC32XX_HSUART) += lpc32xx_hsuart.o |
40 | 41 | obj-$(CONFIG_MCFUART) += mcfuart.o |
drivers/serial/ns16550.c
... | ... | @@ -93,19 +93,79 @@ |
93 | 93 | #define CONFIG_SYS_NS16550_CLK 0 |
94 | 94 | #endif |
95 | 95 | |
96 | +/* | |
97 | + * Use this #ifdef for now since many platforms don't define in(), out(), | |
98 | + * out_le32(), etc. but we don't have #defines to indicate this. | |
99 | + * | |
100 | + * TODO(sjg@chromium.org): Add CONFIG options to indicate what I/O is available | |
101 | + * on a platform | |
102 | + */ | |
103 | +#ifdef CONFIG_NS16550_DYNAMIC | |
104 | +static void serial_out_dynamic(struct ns16550_platdata *plat, u8 *addr, | |
105 | + int value) | |
106 | +{ | |
107 | + if (plat->flags & NS16550_FLAG_IO) { | |
108 | + outb(value, addr); | |
109 | + } else if (plat->reg_width == 4) { | |
110 | + if (plat->flags & NS16550_FLAG_ENDIAN) { | |
111 | + if (plat->flags & NS16550_FLAG_BE) | |
112 | + out_be32(addr, value); | |
113 | + else | |
114 | + out_le32(addr, value); | |
115 | + } else { | |
116 | + writel(value, addr); | |
117 | + } | |
118 | + } else if (plat->flags & NS16550_FLAG_BE) { | |
119 | + writeb(value, addr + (1 << plat->reg_shift) - 1); | |
120 | + } else { | |
121 | + writeb(value, addr); | |
122 | + } | |
123 | +} | |
124 | + | |
125 | +static int serial_in_dynamic(struct ns16550_platdata *plat, u8 *addr) | |
126 | +{ | |
127 | + if (plat->flags & NS16550_FLAG_IO) { | |
128 | + return inb(addr); | |
129 | + } else if (plat->reg_width == 4) { | |
130 | + if (plat->flags & NS16550_FLAG_ENDIAN) { | |
131 | + if (plat->flags & NS16550_FLAG_BE) | |
132 | + return in_be32(addr); | |
133 | + else | |
134 | + return in_le32(addr); | |
135 | + } else { | |
136 | + return readl(addr); | |
137 | + } | |
138 | + } else if (plat->flags & NS16550_FLAG_BE) { | |
139 | + return readb(addr + (1 << plat->reg_shift) - 1); | |
140 | + } else { | |
141 | + return readb(addr); | |
142 | + } | |
143 | +} | |
144 | +#else | |
145 | +static inline void serial_out_dynamic(struct ns16550_platdata *plat, u8 *addr, | |
146 | + int value) | |
147 | +{ | |
148 | +} | |
149 | + | |
150 | +static inline int serial_in_dynamic(struct ns16550_platdata *plat, u8 *addr) | |
151 | +{ | |
152 | + return 0; | |
153 | +} | |
154 | + | |
155 | +#endif /* CONFIG_NS16550_DYNAMIC */ | |
156 | + | |
96 | 157 | static void ns16550_writeb(NS16550_t port, int offset, int value) |
97 | 158 | { |
98 | 159 | struct ns16550_platdata *plat = port->plat; |
99 | 160 | unsigned char *addr; |
100 | 161 | |
101 | 162 | offset *= 1 << plat->reg_shift; |
102 | - addr = (unsigned char *)plat->base + offset; | |
163 | + addr = (unsigned char *)plat->base + offset + plat->reg_offset; | |
103 | 164 | |
104 | - /* | |
105 | - * As far as we know it doesn't make sense to support selection of | |
106 | - * these options at run-time, so use the existing CONFIG options. | |
107 | - */ | |
108 | - serial_out_shift(addr + plat->reg_offset, plat->reg_shift, value); | |
165 | + if (IS_ENABLED(CONFIG_NS16550_DYNAMIC)) | |
166 | + serial_out_dynamic(plat, addr, value); | |
167 | + else | |
168 | + serial_out_shift(addr, plat->reg_shift, value); | |
109 | 169 | } |
110 | 170 | |
111 | 171 | static int ns16550_readb(NS16550_t port, int offset) |
112 | 172 | |
... | ... | @@ -114,9 +174,12 @@ |
114 | 174 | unsigned char *addr; |
115 | 175 | |
116 | 176 | offset *= 1 << plat->reg_shift; |
117 | - addr = (unsigned char *)plat->base + offset; | |
177 | + addr = (unsigned char *)plat->base + offset + plat->reg_offset; | |
118 | 178 | |
119 | - return serial_in_shift(addr + plat->reg_offset, plat->reg_shift); | |
179 | + if (IS_ENABLED(CONFIG_NS16550_DYNAMIC)) | |
180 | + return serial_in_dynamic(plat, addr); | |
181 | + else | |
182 | + return serial_in_shift(addr, plat->reg_shift); | |
120 | 183 | } |
121 | 184 | |
122 | 185 | static u32 ns16550_getfcr(NS16550_t port) |
drivers/serial/serial_coreboot.c
1 | +// SPDX-License-Identifier: GPL-2.0+ | |
2 | +/* | |
3 | + * UART support for U-Boot when launched from Coreboot | |
4 | + * | |
5 | + * Copyright 2019 Google LLC | |
6 | + */ | |
7 | + | |
8 | +#include <common.h> | |
9 | +#include <dm.h> | |
10 | +#include <ns16550.h> | |
11 | +#include <serial.h> | |
12 | +#include <asm/arch/sysinfo.h> | |
13 | + | |
14 | +static int coreboot_ofdata_to_platdata(struct udevice *dev) | |
15 | +{ | |
16 | + struct ns16550_platdata *plat = dev_get_platdata(dev); | |
17 | + struct cb_serial *cb_info = lib_sysinfo.serial; | |
18 | + | |
19 | + plat->base = cb_info->baseaddr; | |
20 | + plat->reg_shift = cb_info->regwidth == 4 ? 2 : 0; | |
21 | + plat->reg_width = cb_info->regwidth; | |
22 | + plat->clock = cb_info->input_hertz; | |
23 | + plat->fcr = UART_FCR_DEFVAL; | |
24 | + plat->flags = 0; | |
25 | + if (cb_info->type == CB_SERIAL_TYPE_IO_MAPPED) | |
26 | + plat->flags |= NS16550_FLAG_IO; | |
27 | + | |
28 | + return 0; | |
29 | +} | |
30 | + | |
31 | +static const struct udevice_id coreboot_serial_ids[] = { | |
32 | + { .compatible = "coreboot-serial" }, | |
33 | + { }, | |
34 | +}; | |
35 | + | |
36 | +U_BOOT_DRIVER(coreboot_uart) = { | |
37 | + .name = "coreboot_uart", | |
38 | + .id = UCLASS_SERIAL, | |
39 | + .of_match = coreboot_serial_ids, | |
40 | + .priv_auto_alloc_size = sizeof(struct NS16550), | |
41 | + .platdata_auto_alloc_size = sizeof(struct ns16550_platdata), | |
42 | + .ofdata_to_platdata = coreboot_ofdata_to_platdata, | |
43 | + .probe = ns16550_serial_probe, | |
44 | + .ops = &ns16550_serial_ops, | |
45 | + .flags = DM_FLAG_PRE_RELOC, | |
46 | +}; |
drivers/spi/ich.c
... | ... | @@ -562,16 +562,8 @@ |
562 | 562 | return 0; /* ignore */ |
563 | 563 | case SPINOR_OP_BE_4K: |
564 | 564 | cycle = HSFSTS_CYCLE_4K_ERASE; |
565 | - while (len) { | |
566 | - uint xfer_len = 0x1000; | |
567 | - | |
568 | - ret = exec_sync_hwseq_xfer(regs, cycle, offset, 0); | |
569 | - if (ret) | |
570 | - return ret; | |
571 | - offset += xfer_len; | |
572 | - len -= xfer_len; | |
573 | - } | |
574 | - return 0; | |
565 | + ret = exec_sync_hwseq_xfer(regs, cycle, offset, 0); | |
566 | + return ret; | |
575 | 567 | default: |
576 | 568 | debug("Unknown cycle %x\n", op->cmd.opcode); |
577 | 569 | return -EINVAL; |
include/configs/slimbootloader.h
... | ... | @@ -8,19 +8,6 @@ |
8 | 8 | |
9 | 9 | #include <configs/x86-common.h> |
10 | 10 | |
11 | -/* | |
12 | - * By default, CONFIG_SYS_NS16550_PORT_MAPPED is enabled for port io serial. | |
13 | - * To use mmio base serial, enable CONFIG_SYS_NS16550_MEM32 and disable | |
14 | - * CONFIG_SYS_NS16550_PORT_MAPPED until ns16550 driver supports serial port | |
15 | - * configuration in run-time. | |
16 | - * | |
17 | - * #define CONFIG_SYS_NS16550_MEM32 | |
18 | - * #undef CONFIG_SYS_NS16550_PORT_MAPPED | |
19 | - */ | |
20 | -#ifdef CONFIG_SYS_NS16550_MEM32 | |
21 | -#undef CONFIG_SYS_NS16550_PORT_MAPPED | |
22 | -#endif | |
23 | - | |
24 | 11 | #define CONFIG_STD_DEVICES_SETTINGS \ |
25 | 12 | "stdin=serial,i8042-kbd,usbkbd\0" \ |
26 | 13 | "stdout=serial\0" \ |
include/ns16550.h
... | ... | @@ -31,6 +31,9 @@ |
31 | 31 | #define CONFIG_SYS_NS16550_REG_SIZE (-1) |
32 | 32 | #endif |
33 | 33 | |
34 | +#ifdef CONFIG_NS16550_DYNAMIC | |
35 | +#define UART_REG(x) unsigned char x | |
36 | +#else | |
34 | 37 | #if !defined(CONFIG_SYS_NS16550_REG_SIZE) || (CONFIG_SYS_NS16550_REG_SIZE == 0) |
35 | 38 | #error "Please define NS16550 registers size." |
36 | 39 | #elif defined(CONFIG_SYS_NS16550_MEM32) && !defined(CONFIG_DM_SERIAL) |
37 | 40 | |
38 | 41 | |
39 | 42 | |
40 | 43 | |
... | ... | @@ -44,14 +47,24 @@ |
44 | 47 | unsigned char x; \ |
45 | 48 | unsigned char postpad_##x[-CONFIG_SYS_NS16550_REG_SIZE - 1]; |
46 | 49 | #endif |
50 | +#endif /* CONFIG_NS16550_DYNAMIC */ | |
47 | 51 | |
52 | +enum ns16550_flags { | |
53 | + NS16550_FLAG_IO = 1 << 0, /* Use I/O access (else mem-mapped) */ | |
54 | + NS16550_FLAG_ENDIAN = 1 << 1, /* Use out_le/be_32() */ | |
55 | + NS16550_FLAG_BE = 1 << 2, /* Big-endian access (else little) */ | |
56 | +}; | |
57 | + | |
48 | 58 | /** |
49 | 59 | * struct ns16550_platdata - information about a NS16550 port |
50 | 60 | * |
51 | 61 | * @base: Base register address |
52 | - * @reg_width: IO accesses size of registers (in bytes) | |
62 | + * @reg_width: IO accesses size of registers (in bytes, 1 or 4) | |
53 | 63 | * @reg_shift: Shift size of registers (0=byte, 1=16bit, 2=32bit...) |
64 | + * @reg_offset: Offset to start of registers (normally 0) | |
54 | 65 | * @clock: UART base clock speed in Hz |
66 | + * @fcr: Offset of FCR register (normally UART_FCR_DEFVAL) | |
67 | + * @flags: A few flags (enum ns16550_flags) | |
55 | 68 | * @bdf: PCI slot/function (pci_dev_t) |
56 | 69 | */ |
57 | 70 | struct ns16550_platdata { |
... | ... | @@ -61,6 +74,7 @@ |
61 | 74 | int reg_offset; |
62 | 75 | int clock; |
63 | 76 | u32 fcr; |
77 | + int flags; | |
64 | 78 | #if defined(CONFIG_PCI) && defined(CONFIG_SPL) |
65 | 79 | int bdf; |
66 | 80 | #endif |