Skip to content

Commit e039053

Browse files
Charles E. Youseandrewboie
authored andcommitted
uart/ns16550, drivers/pcie: add PCI(e) support
A parallel PCI implementation ("pcie") is added with features for PCIe. In particular, message-signaled interrupts (MSI) are supported, which are essential to the use of any non-trivial PCIe device. The NS16550 UART driver is modified to use pcie. pcie is a complete replacement for the old PCI support ("pci"). It is smaller, by an order of magnitude, and cleaner. Both pci and pcie can (and do) coexist in the same builds, but the intent is to rework any existing drivers that depend on pci and ultimately remove pci entirely. This patch is large, but things in mirror are smaller than they appear. Most of the modified files are configuration-related, and are changed only slightly to accommodate the modified UART driver. Deficiencies: 64-bit support is minimal. The code works fine with 64-bit capable devices, but will not cooperate with MMIO regions (or MSI targets) that have high bits set. This is not needed on any current boards, and is unlikely to be needed in the future. Only superficial changes would be required if we change our minds. The method specifying PCI endpoints in devicetree is somewhat kludgey. The "right" way would be to hang PCI devices off a topological tree; while this would be more aesthetically pleasing, I don't think it's worth the effort, given our non-standard use of devicetree. Signed-off-by: Charles E. Youse <[email protected]>
1 parent 4cf4040 commit e039053

File tree

32 files changed

+971
-436
lines changed

32 files changed

+971
-436
lines changed

CODEOWNERS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
/arch/x86/ @andrewboie @ramakrishnapallala
3030
/arch/x86/core/ @andrewboie
3131
/arch/x86/core/crt0.S @ramakrishnapallala @nashif
32+
/arch/x86/core/pcie.c @gnuless
3233
/soc/x86/ @andrewboie @ramakrishnapallala
3334
/soc/x86/intel_quark/quark_d2000/ @nashif
3435
/soc/x86/intel_quark/quark_se/ @nashif
@@ -119,13 +120,15 @@
119120
/drivers/led_strip/ @mbolivar
120121
/drivers/modem/ @mike-scott
121122
/drivers/pci/ @gnuless
123+
/drivers/pcie/ @gnuless
122124
/drivers/pinmux/stm32/ @rsalveti @idlethread
123125
/drivers/sensor/ @bogdan-davidoaia @MaureenHelm
124126
/drivers/sensor/hts*/ @avisconti
125127
/drivers/sensor/lis*/ @avisconti
126128
/drivers/sensor/lps*/ @avisconti
127129
/drivers/sensor/lsm*/ @avisconti
128130
/drivers/serial/uart_altera_jtag_hal.c @ramakrishnapallala
131+
/drivers/serial/*ns16550* @gnuless
129132
/drivers/net/slip.c @jukkar @tbursztyka
130133
/drivers/spi/ @tbursztyka
131134
/drivers/spi/spi_ll_stm32.* @superna9999
@@ -142,6 +145,7 @@
142145
/dts/arm/nxp/ @MaureenHelm
143146
/dts/bindings/ @galak
144147
/dts/bindings/can/ @alexanderwachter
148+
/dts/bindings/serial/ns16550.yaml @gnuless
145149
/dts/bindings/*/nordic* @anangl
146150
/dts/bindings/*/nxp* @MaureenHelm
147151
/ext/fs/ @nashif @ramakrishnapallala
@@ -181,6 +185,9 @@
181185
/include/drivers/ioapic.h @andrewboie
182186
/include/drivers/loapic.h @andrewboie
183187
/include/drivers/mvic.h @andrewboie
188+
/include/drivers/pcie/ @gnuless
189+
/include/drivers/serial/uart_ns16550.h @gnuless
190+
/include/dt-bindings/pcie/ @gnuless
184191
/include/fs.h @nashif @ramakrishnapallala
185192
/include/fs/ @nashif @ramakrishnapallala
186193
/include/hwinfo.h @alexanderwachter

arch/x86/core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ zephyr_library_sources(
3232
zephyr_library_sources_if_kconfig( irq_offload.c)
3333
zephyr_library_sources_if_kconfig( x86_mmu.c)
3434
zephyr_library_sources_if_kconfig( reboot_rst_cnt.c)
35+
zephyr_library_sources_if_kconfig( pcie.c)
3536
zephyr_library_sources_ifdef(CONFIG_LAZY_FP_SHARING float.c)
3637
zephyr_library_sources_ifdef(CONFIG_X86_USERSPACE userspace.S)
3738

arch/x86/core/pcie.c

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* Copyright (c) 2019 Intel Corporation
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <kernel.h>
8+
#include <drivers/pcie/pcie.h>
9+
#include <arch/x86/arch.h>
10+
11+
#ifdef CONFIG_PCIE_MSI
12+
#include <drivers/pcie/msi.h>
13+
#endif
14+
15+
/*
16+
* The Configuration Mechanism (previously, Configuration Mechanism #1)
17+
* uses two 32-bit ports in the I/O space, here called CAP and CDP.
18+
*
19+
* N.B.: this code relies on the fact that the PCIE_BDF() format (as
20+
* defined in dt-bindings/pcie/pcie.h) and the CAP agree on the bus/dev/func
21+
* bitfield positions and sizes.
22+
*/
23+
24+
#define PCIE_X86_CAP 0xCF8U /* Configuration Address Port */
25+
#define PCIE_X86_CAP_BDF_MASK 0x00FFFF00U /* b/d/f bits */
26+
#define PCIE_X86_CAP_EN 0x80000000U /* enable bit */
27+
#define PCIE_X86_CAP_WORD_MASK 0x3FU /* 6-bit word index .. */
28+
#define PCIE_X86_CAP_WORD_SHIFT 2U /* .. is in CAP[7:2] */
29+
30+
#define PCIE_X86_CDP 0xCFCU /* Configuration Data Port */
31+
32+
/*
33+
* Helper function for exported configuration functions. Configuration access
34+
* ain't atomic, so spinlock to keep drivers from clobbering each other.
35+
*/
36+
static void pcie_conf(pcie_bdf_t bdf, unsigned int reg, bool write, u32_t *data)
37+
{
38+
static struct k_spinlock lock;
39+
k_spinlock_key_t k;
40+
41+
bdf &= PCIE_X86_CAP_BDF_MASK;
42+
bdf |= PCIE_X86_CAP_EN;
43+
bdf |= (reg & PCIE_X86_CAP_WORD_MASK) << PCIE_X86_CAP_WORD_SHIFT;
44+
45+
k = k_spin_lock(&lock);
46+
sys_out32(bdf, PCIE_X86_CAP);
47+
48+
if (write) {
49+
sys_out32(*data, PCIE_X86_CDP);
50+
} else {
51+
*data = sys_in32(PCIE_X86_CDP);
52+
}
53+
54+
sys_out32(0U, PCIE_X86_CAP);
55+
k_spin_unlock(&lock, k);
56+
}
57+
58+
/* these functions are explained in include/drivers/pcie/pcie.h */
59+
60+
u32_t pcie_conf_read(pcie_bdf_t bdf, unsigned int reg)
61+
{
62+
u32_t data;
63+
64+
pcie_conf(bdf, reg, false, &data);
65+
return data;
66+
}
67+
68+
void pcie_conf_write(pcie_bdf_t bdf, unsigned int reg, u32_t data)
69+
{
70+
pcie_conf(bdf, reg, true, &data);
71+
}
72+
73+
#ifdef CONFIG_PCIE_MSI
74+
75+
/* these functions are explained in include/drivers/pcie/msi.h */
76+
77+
u32_t pcie_msi_map(unsigned int irq)
78+
{
79+
ARG_UNUSED(irq);
80+
return 0xFEE00000U; /* standard delivery to BSP local APIC */
81+
}
82+
83+
u16_t pcie_msi_mdr(unsigned int irq)
84+
{
85+
unsigned char vector = _irq_to_interrupt_vector[irq];
86+
87+
return 0x4000U | vector; /* edge triggered */
88+
}
89+
90+
#endif

boards/x86/galileo/galileo_defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# SPDX-License-Identifier: Apache-2.0
22

33
CONFIG_X86=y
4+
CONFIG_PCIE=y
45
CONFIG_SOC_QUARK_X1000=y
56
CONFIG_SOC_SERIES_QUARK_X1000=y
67
CONFIG_BOARD_GALILEO=y

boards/x86/up_squared/dts_fixup.h

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -6,42 +6,32 @@
66

77
/* Board level DTS fixup file */
88

9-
#ifdef CONFIG_SBL_FIXUP
10-
11-
#define DT_UART_NS16550_PORT_0_BASE_ADDR DT_NS16550_81434000_BASE_ADDRESS
12-
#define DT_UART_NS16550_PORT_0_BAUD_RATE DT_NS16550_81434000_CURRENT_SPEED
13-
#define DT_UART_NS16550_PORT_0_NAME DT_NS16550_81434000_LABEL
14-
#define DT_UART_NS16550_PORT_0_IRQ DT_NS16550_81434000_IRQ_0
15-
#define DT_UART_NS16550_PORT_0_IRQ_PRI DT_NS16550_81434000_IRQ_0_PRIORITY
16-
#define DT_UART_NS16550_PORT_0_IRQ_FLAGS DT_NS16550_81434000_IRQ_0_SENSE
17-
#define DT_UART_NS16550_PORT_0_CLK_FREQ DT_NS16550_81434000_CLOCK_FREQUENCY
18-
19-
#define DT_UART_NS16550_PORT_1_BASE_ADDR DT_NS16550_81432000_BASE_ADDRESS
20-
#define DT_UART_NS16550_PORT_1_BAUD_RATE DT_NS16550_81432000_CURRENT_SPEED
21-
#define DT_UART_NS16550_PORT_1_NAME DT_NS16550_81432000_LABEL
22-
#define DT_UART_NS16550_PORT_1_IRQ DT_NS16550_81432000_IRQ_0
23-
#define DT_UART_NS16550_PORT_1_IRQ_PRI DT_NS16550_81432000_IRQ_0_PRIORITY
24-
#define DT_UART_NS16550_PORT_1_IRQ_FLAGS DT_NS16550_81432000_IRQ_0_SENSE
25-
#define DT_UART_NS16550_PORT_1_CLK_FREQ DT_NS16550_81432000_CLOCK_FREQUENCY
26-
27-
#else
28-
29-
#define DT_UART_NS16550_PORT_0_BASE_ADDR DT_NS16550_91524000_BASE_ADDRESS
30-
#define DT_UART_NS16550_PORT_0_BAUD_RATE DT_NS16550_91524000_CURRENT_SPEED
31-
#define DT_UART_NS16550_PORT_0_NAME DT_NS16550_91524000_LABEL
32-
#define DT_UART_NS16550_PORT_0_IRQ DT_NS16550_91524000_IRQ_0
33-
#define DT_UART_NS16550_PORT_0_IRQ_PRI DT_NS16550_91524000_IRQ_0_PRIORITY
34-
#define DT_UART_NS16550_PORT_0_IRQ_FLAGS DT_NS16550_91524000_IRQ_0_SENSE
35-
#define DT_UART_NS16550_PORT_0_CLK_FREQ DT_NS16550_91524000_CLOCK_FREQUENCY
36-
37-
#define DT_UART_NS16550_PORT_1_BASE_ADDR DT_NS16550_91522000_BASE_ADDRESS
38-
#define DT_UART_NS16550_PORT_1_BAUD_RATE DT_NS16550_91522000_CURRENT_SPEED
39-
#define DT_UART_NS16550_PORT_1_NAME DT_NS16550_91522000_LABEL
40-
#define DT_UART_NS16550_PORT_1_IRQ DT_NS16550_91522000_IRQ_0
41-
#define DT_UART_NS16550_PORT_1_IRQ_PRI DT_NS16550_91522000_IRQ_0_PRIORITY
42-
#define DT_UART_NS16550_PORT_1_IRQ_FLAGS DT_NS16550_91522000_IRQ_0_SENSE
43-
#define DT_UART_NS16550_PORT_1_CLK_FREQ DT_NS16550_91522000_CLOCK_FREQUENCY
9+
#define DT_UART_NS16550_PORT_0_BASE_ADDR DT_NS16550_0_BASE_ADDRESS
10+
#define DT_UART_NS16550_PORT_0_SIZE DT_NS16550_0_SIZE
11+
#define DT_UART_NS16550_PORT_0_BAUD_RATE DT_NS16550_0_CURRENT_SPEED
12+
#define DT_UART_NS16550_PORT_0_NAME DT_NS16550_0_LABEL
13+
#define DT_UART_NS16550_PORT_0_IRQ DT_NS16550_0_IRQ_0
14+
#define DT_UART_NS16550_PORT_0_IRQ_PRI DT_NS16550_0_IRQ_0_PRIORITY
15+
#define DT_UART_NS16550_PORT_0_IRQ_FLAGS DT_NS16550_0_IRQ_0_SENSE
16+
#define DT_UART_NS16550_PORT_0_CLK_FREQ DT_NS16550_0_CLOCK_FREQUENCY
17+
#define DT_UART_NS16550_PORT_0_PCIE DT_NS16550_0_PCIE
18+
19+
#ifdef DT_NS16550_0_PCP
20+
#define DT_UART_NS16550_PORT_0_PCP DT_NS16550_0_PCP
21+
#endif
4422

23+
#define DT_UART_NS16550_PORT_1_BASE_ADDR DT_NS16550_1_BASE_ADDRESS
24+
#define DT_UART_NS16550_PORT_1_SIZE DT_NS16550_1_SIZE
25+
#define DT_UART_NS16550_PORT_1_BAUD_RATE DT_NS16550_1_CURRENT_SPEED
26+
#define DT_UART_NS16550_PORT_1_NAME DT_NS16550_1_LABEL
27+
#define DT_UART_NS16550_PORT_1_IRQ DT_NS16550_1_IRQ_0
28+
#define DT_UART_NS16550_PORT_1_IRQ_PRI DT_NS16550_1_IRQ_0_PRIORITY
29+
#define DT_UART_NS16550_PORT_1_IRQ_FLAGS DT_NS16550_1_IRQ_0_SENSE
30+
#define DT_UART_NS16550_PORT_1_CLK_FREQ DT_NS16550_1_CLOCK_FREQUENCY
31+
#define DT_UART_NS16550_PORT_1_PCIE DT_NS16550_1_PCIE
32+
33+
#ifdef DT_NS16550_1_PCP
34+
#define DT_UART_NS16550_PORT_1_PCP DT_NS16550_1_PCP
4535
#endif
4636

4737
/* End of Board Level DTS fixup file */

boards/x86/up_squared/up_squared.dts

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include <apollo_lake.dtsi>
1515
#include <dt-bindings/i2c/i2c.h>
16+
#include <dt-bindings/pcie/pcie.h>
1617

1718
/ {
1819
model = "up_squared";
@@ -29,24 +30,29 @@
2930
};
3031

3132
soc {
32-
uart0: uart@91524000 {
33+
uart0: uart@0 {
3334
compatible = "ns16550";
34-
reg = <0x91524000 0x1000>;
35+
36+
pcie;
37+
reg = <PCIE_BDF(0,0x18,0) PCIE_ID(0x8086,0x5abc)>;
38+
3539
label = "UART_0";
3640
clock-frequency = <1843200>;
3741
interrupts = <4 IRQ_TYPE_LEVEL_LOW 3>;
3842
interrupt-parent = <&intc>;
39-
4043
status = "ok";
4144
current-speed = <115200>;
4245
};
4346

44-
uart1: uart@91522000 {
47+
uart1: uart@1 {
4548
compatible = "ns16550";
46-
reg = <0x91522000 0x1000>;
49+
50+
pcie;
51+
reg = <PCIE_BDF(0,0x18,1) PCIE_ID(0x8086,0x5abe)>;
52+
4753
label = "UART_1";
4854
clock-frequency = <1843200>;
49-
interrupts = <5 IRQ_TYPE_LEVEL_LOW 3>;
55+
interrupts = <3 IRQ_TYPE_LEVEL_LOW 3>;
5056
interrupt-parent = <&intc>;
5157

5258
status = "ok";

boards/x86/up_squared/up_squared_defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ CONFIG_UART_NS16550=y
1313
CONFIG_UART_CONSOLE=y
1414
CONFIG_I2C=y
1515
CONFIG_PCI=y
16+
CONFIG_PCIE=y
1617
CONFIG_PCI_ENUMERATION=y

drivers/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ add_subdirectory_if_kconfig(led)
2121
add_subdirectory_if_kconfig(led_strip)
2222
add_subdirectory_if_kconfig(modem)
2323
add_subdirectory_if_kconfig(pci)
24+
add_subdirectory_if_kconfig(pcie)
2425
add_subdirectory_if_kconfig(pinmux)
2526
add_subdirectory_if_kconfig(pwm)
2627
add_subdirectory_if_kconfig(rtc)

drivers/Kconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ source "drivers/entropy/Kconfig"
2929

3030
source "drivers/pci/Kconfig"
3131

32+
source "drivers/pcie/Kconfig"
33+
3234
source "drivers/gpio/Kconfig"
3335

3436
source "drivers/interrupt_controller/Kconfig.shared_irq"

drivers/pcie/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
zephyr_sources(pcie.c)
2+
zephyr_sources_ifdef(CONFIG_PCIE_MSI msi.c)
3+
zephyr_sources_ifdef(CONFIG_PCIE_SHELL shell.c)

0 commit comments

Comments
 (0)