x86: Add a function to assign IRQ numbers to PCI device
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/4 x86: Add a function to assign IRQ numbers to PCI device
Add a function to assign an IRQ number to PCI device's interrupt line register in its configuration space, so that the PCI device can have its interrupt working under PIC mode after OS boots up.
---
arch/x86/cpu/pci.c | 21 +++++++++++++++++++++ arch/x86/include/asm/pci.h | 14 ++++++++++++++ 2 files changed, 35 insertions(+)
arch/x86/cpu/pci.c +21 -0
@@ -151,3 +151,24 @@ int pci_x86_write_config(struct udevice *bus, pci_dev_t bdf, uint offset,return 0 ; } + +void pci_assign_irqs (int bus,int device,int func,u8 irq[4 ]) +{ +pci_dev_t bdf; +u8 pin, line; + + bdf =PCI_BDF (bus, device, func); + + pin =x86_pci_read_config8 (bdf,PCI_INTERRUPT_PIN ); + +/* PCI spec says all values except 1..4 are reserved */ +if ((pin <1 ) || (pin >4 )) +return ; + + line = irq[pin -1 ]; + +debug ("Assigning IRQ %d to PCI device %d.%x.%d (INT%c)\n" , + line, bus, device, func,'A' + pin -1 ); + +x86_pci_write_config8 (bdf,PCI_INTERRUPT_LINE , line); +}
arch/x86/include/asm/pci.h +14 -0
@@ -64,6 +64,20 @@ int pci_x86_read_config(struct udevice *bus, pci_dev_t bdf, uint offset,int pci_x86_write_config (struct udevice *bus,pci_dev_t bdf,uint offset,ulong value,enum pci_size_t size); +/** +* Assign IRQ number to a PCI device +* +* This function assigns IRQ for a PCI device. If the device does not exist +* or does not require interrupts then this function has no effect. +* +* @bus: PCI bus number +* @device: PCI device number +* @func: PCI function number +* @irq: An array of IRQ numbers that are assigned to INTA through +* INTD of this PCI device. +*/ +void pci_assign_irqs (int bus,int device,int func,u8 irq[4 ]); +#endif /* __ASSEMBLY__ */ #endif /* _PCI_I386_H_ */
Signature · 1 line
1.8.2.1
PATCH 1/4 x86: Add a function to assign IRQ numbers to PCI device
Quoted 10 lines · Bin Meng
Add a function to assign an IRQ number to PCI device's interrupt line register in its configuration space, so that the PCI device can have its interrupt working under PIC mode after OS boots up.
Signed-off-by Bin Meng <[email protected]>---
arch/x86/cpu/pci.c | 21 +++++++++++++++++++++ arch/x86/include/asm/pci.h | 14 ++++++++++++++ 2 files changed, 35 insertions(+)
PATCH 2/4 x86: Write configuration tables in last_stage_init()
In reply to a message not in the archiveWe can write the configuration table in last_stage_init() for all x86 boards, but not with coreboot since coreboot already has them.
---
arch/x86/cpu/cpu.c | 10 +++++++++ arch/x86/include/asm/tables.h | 49 +++++++++++++++++++++++++++++++++++++++++++ arch/x86/lib/Makefile | 1 + arch/x86/lib/tables.c | 30 ++++++++++++++++++++++++++ include/configs/x86-common.h | 1 + 5 files changed, 91 insertions(+) create mode 100644 arch/x86/include/asm/tables.h create mode 100644 arch/x86/lib/tables.c
arch/x86/cpu/cpu.c +10 -0
@@ -29,6 +29,7 @@#include <asm/processor.h> #include <asm/processor-flags.h> #include <asm/interrupt.h> +#include <asm/tables.h> #include <linux/compiler.h> DECLARE_GLOBAL_DATA_PTR ;
@@ -593,3 +594,12 @@ void show_boot_progress(int val)#endif outb (val,POST_PORT ); } + +#ifndef CONFIG_SYS_COREBOOT +int last_stage_init (void ) +{ +write_tables (); + +return 0 ; +} +#endif
arch/x86/include/asm/tables.h new file +49 -0
49 lines not on this page · raw message
arch/x86/lib/Makefile +1 -0
@@ -26,6 +26,7 @@ obj-y += relocate.o obj-y += physmem.o obj-$(CONFIG_X86_RAMTEST) += ramtest.o obj-y += string.o +obj-y += tables.o obj-$(CONFIG_SYS_X86_TSC_TIMER) += tsc_timer.o obj-$(CONFIG_CMD_ZBOOT) += zimage.o obj-$(CONFIG_HAVE_FSP) += fsp/
arch/x86/lib/tables.c new file +30 -0
@@ -0,0 +1,30 @@ +/* +* Copyright (C) 2015, Bin Meng <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <common.h> +#include <asm/tables.h> + +u8 table_compute_checksum (void *v,int len) +{ +u8 *bytes = v; +u8 checksum =0 ; +int i; + +for (i =0 ; i < len; i++) + checksum -= bytes[i]; + +return checksum; +} + +void write_tables (void ) +{ +u32 __maybe_unused rom_table_end =ROM_TABLE_ADDR ; + +#if CONFIG_GENERATE_PIRQ_TABLE + rom_table_end =write_pirq_routing_table (rom_table_end); + rom_table_end =ALIGN (rom_table_end,1024 ); +#endif +}
include/configs/x86-common.h +1 -0
@@ -20,6 +20,7 @@#define CONFIG_PHYSMEM #define CONFIG_DISPLAY_BOARDINFO_LATE #define CONFIG_DISPLAY_CPUINFO +#define CONFIG_LAST_STAGE_INIT #define CONFIG_LMB #define CONFIG_OF_LIBFDT
Signature · 1 line
1.8.2.1
PATCH 2/4 x86: Write configuration tables in last_stage_init()
Quoted 6 lines · Bin Meng
We can write the configuration table in
last_stage_init()for all x86 boards, but not with coreboot since coreboot already has them.Signed-off-by Bin Meng <[email protected]>---
Quoted 8 lines
arch/x86/cpu/cpu.c | 10 +++++++++ arch/x86/include/asm/tables.h | 49 +++++++++++++++++++++++++++++++++++++++++++ arch/x86/lib/Makefile | 1 + arch/x86/lib/tables.c | 30 ++++++++++++++++++++++++++ include/configs/x86-common.h | 1 + 5 files changed, 91 insertions(+) create mode 100644 arch/x86/include/asm/tables.h create mode 100644 arch/x86/lib/tables.c
PATCH 3/4 x86: Support platform PIRQ routing
In reply to a message not in the archiveOn x86 boards, platform chipset receives up to four different interrupt signals from PCI devices (INTA/B/C/D), which in turn will be routed to chipset internal PIRQ lines then routed to 8259 PIC finally if configuring the whole system to work under the so-called PIC mode (in contrast to symmetric IO mode which uses IOAPIC).
We add two major APIs to aid this, one for routing PIRQ and the other one for generating a PIRQ routing table.
---
arch/x86/Kconfig | 31 ++++++++ arch/x86/include/asm/pirq_routing.h | 139 ++++++++++++++++++++++++++++++++++++ arch/x86/lib/Makefile | 1 + arch/x86/lib/pirq_routing.c | 129 +++++++++++++++++++++++++++++++++ 4 files changed, 300 insertions(+) create mode 100644 arch/x86/include/asm/pirq_routing.h create mode 100644 arch/x86/lib/pirq_routing.c
arch/x86/Kconfig +31 -0
@@ -442,6 +442,37 @@ config TSC_FREQ_IN_MHZ help The running frequency in MHz of Time-Stamp Counter (TSC). +menu "System tables" + +config GENERATE_PIRQ_TABLE + bool "Generate a PIRQ table" + default n + help + Generate a PIRQ routing table for this board. The PIRQ routing table + is generated by U-Boot in the system memory from 0xf0000 to 0xfffff + at every 16-byte boundary with a PCI IRQ routing signature ("$PIR"). + It specifies the interrupt router information as well how all the PCI + devices' interrupt pins are wired to PIRQs. + +endmenu + +config MAX_PIRQ_LINKS + int + default 8 + help + This variable specifies the number of PIRQ interrupt links which are + routable. On most older chipsets, this is 4, PIRQA through PIRQD. + Some newer chipsets offer more than four links, commonly up to PIRQH. + +config IRQ_SLOT_COUNT + int + default 128 + help + U-Boot can support up to 254 IRQ slot info in the PIRQ routing table + which in turns forms a table of exact 4KiB. The default value 128 + should be enough for most boards. If this does not fit your board, + change it according to your needs. + source "board/coreboot/coreboot/Kconfig" source "board/google/chromebook_link/Kconfig"
arch/x86/include/asm/pirq_routing.h new file +139 -0
139 lines not on this page · raw message
arch/x86/lib/Makefile +1 -0
@@ -22,6 +22,7 @@ ifndef CONFIG_DM_PCI obj-$(CONFIG_PCI) += pci_type1.o endif obj-y += pch-uclass.o +obj-y += pirq_routing.o obj-y += relocate.o obj-y += physmem.o obj-$(CONFIG_X86_RAMTEST) += ramtest.o
arch/x86/lib/pirq_routing.c new file +129 -0
129 lines not on this page · raw message
Signature · 1 line
1.8.2.1
PATCH 3/4 x86: Support platform PIRQ routing
Quoted 13 lines · Bin Meng
On x86 boards, platform chipset receives up to four different interrupt signals from PCI devices (INTA/B/C/D), which in turn will be routed to chipset internal PIRQ lines then routed to 8259 PIC finally if configuring the whole system to work under the so-called PIC mode (in contrast to symmetric IO mode which uses IOAPIC).
We add two major APIs to aid this, one for routing PIRQ and the other one for generating a PIRQ routing table.
Signed-off-by Bin Meng <[email protected]>---
Quoted 7 lines
arch/x86/Kconfig | 31 ++++++++ arch/x86/include/asm/pirq_routing.h | 139 ++++++++++++++++++++++++++++++++++++ arch/x86/lib/Makefile | 1 + arch/x86/lib/pirq_routing.c | 129 +++++++++++++++++++++++++++++++++ 4 files changed, 300 insertions(+) create mode 100644 arch/x86/include/asm/pirq_routing.h create mode 100644 arch/x86/lib/pirq_routing.c
PATCH 4/4 x86: queensbay: Implement PIRQ routing
In reply to a message not in the archiveImplement Intel Queensbay platform-specific PIRQ routing support. The chipset PIRQ routing setup is called in the arch_mist_init().
---
arch/x86/cpu/queensbay/Makefile | 2 +- arch/x86/cpu/queensbay/irq.c | 236 +++++++++++++++++++++++++++ arch/x86/cpu/queensbay/tnc.c | 10 +- arch/x86/include/asm/arch-queensbay/device.h | 94 +++++++++++ arch/x86/include/asm/arch-queensbay/irq.h | 55 +++++++ arch/x86/include/asm/arch-queensbay/tnc.h | 26 ++- arch/x86/include/asm/u-boot-x86.h | 2 + configs/crownbay_defconfig | 1 + include/configs/crownbay.h | 1 + 9 files changed, 423 insertions(+), 4 deletions(-) create mode 100644 arch/x86/cpu/queensbay/irq.c create mode 100644 arch/x86/include/asm/arch-queensbay/device.h create mode 100644 arch/x86/include/asm/arch-queensbay/irq.h
arch/x86/cpu/queensbay/Makefile +1 -1
@@ -5,5 +5,5 @@ # obj-y += fsp_configs.o -obj-y += tnc.o topcliff.o +obj-y += irq.o tnc.o topcliff.o obj-$(CONFIG_PCI) += tnc_pci.o
arch/x86/cpu/queensbay/irq.c new file +236 -0
236 lines not on this page · raw message
arch/x86/cpu/queensbay/tnc.c +9 -1
@@ -8,7 +8,8 @@#include <asm/io.h> #include <asm/pci.h> #include <asm/post.h> -#include <asm/arch/tnc.h> +#include <asm/arch/device.h> +#include <asm/arch/irq.h> #include <asm/fsp/fsp_support.h> #include <asm/processor.h>
@@ -43,3 +44,10 @@ int arch_cpu_init(void)return 0 ; } + +int arch_misc_init (void ) +{ +pirq_init (); + +return 0 ; +}
arch/x86/include/asm/arch-queensbay/device.h new file +94 -0
94 lines not on this page · raw message
arch/x86/include/asm/arch-queensbay/irq.h new file +55 -0
55 lines not on this page · raw message
arch/x86/include/asm/arch-queensbay/tnc.h +24 -2
@@ -7,8 +7,30 @@#ifndef _X86_ARCH_TNC_H_#define _X86_ARCH_TNC_H_ -#include <pci.h> +/* Memory BAR Enable */ +#define MEM_BAR_EN 0x00000001 -#define TNC_LPC PCI_BDF(0, 31, 0) +/* LPC PCI Configuration Registers */ +#define LPC_RCBA 0xf0 + +/* Interupt Pin Configuration (in RCBA) */ +#define D02IP 0x3118 +#define D03IP 0x3130 +#define D23IP 0x312c +#define D24IP 0x3128 +#define D25IP 0x3124 +#define D26IP 0x3120 +#define D27IP 0x3110 +#define D31IP 0x3100 + +/* Interupt Route Configuration (in RCBA) */ +#define D02IR 0x3160 +#define D03IR 0x3162 +#define D23IR 0x3150 +#define D24IR 0x314e +#define D25IR 0x314c +#define D26IR 0x314a +#define D27IR 0x3148 +#define D31IR 0x3140#endif /* _X86_ARCH_TNC_H_ */
arch/x86/include/asm/u-boot-x86.h +2 -0
@@ -53,6 +53,8 @@ int video_bios_init(void);void board_init_f_r_trampoline (ulong ) __attribute__ ((noreturn));void board_init_f_r (void ) __attribute__ ((noreturn)); +int arch_misc_init (void ); +/* Read the time stamp counter */ static inline __attribute__((no_instrument_function))uint64_t rdtsc (void ) {
configs/crownbay_defconfig +1 -0
@@ -4,3 +4,4 @@ CONFIG_TARGET_CROWNBAY=y CONFIG_OF_CONTROL=y CONFIG_OF_SEPARATE=y CONFIG_DEFAULT_DEVICE_TREE="crownbay" +CONFIG_GENERATE_PIRQ_TABLE=y
include/configs/crownbay.h +1 -0
@@ -15,6 +15,7 @@#define CONFIG_SYS_MONITOR_LEN (1 << 20)#define CONFIG_BOARD_EARLY_INIT_F +#define CONFIG_ARCH_MISC_INIT #define CONFIG_NR_DRAM_BANKS 1
Signature · 1 line
1.8.2.1
PATCH 4/4 x86: queensbay: Implement PIRQ routing
Hi Bin,
Quoted 2 lines · Bin Meng
Implement Intel Queensbay platform-specific PIRQ routing support. The chipset PIRQ routing setup is called in the
arch_mist_init().
arch_misc_init()?
Also how can this be used on other boards? Should part of this code be moved to a generic place?
Quoted 77 lines
Signed-off-by Bin Meng <[email protected]>---
arch/x86/cpu/queensbay/Makefile | 2 +- arch/x86/cpu/queensbay/irq.c | 236 +++++++++++++++++++++++++++ arch/x86/cpu/queensbay/tnc.c | 10 +- arch/x86/include/asm/arch-queensbay/device.h | 94 +++++++++++ arch/x86/include/asm/arch-queensbay/irq.h | 55 +++++++ arch/x86/include/asm/arch-queensbay/tnc.h | 26 ++- arch/x86/include/asm/u-boot-x86.h | 2 + configs/crownbay_defconfig | 1 + include/configs/crownbay.h | 1 + 9 files changed, 423 insertions(+), 4 deletions(-) create mode 100644 arch/x86/cpu/queensbay/irq.c create mode 100644 arch/x86/include/asm/arch-queensbay/device.h create mode 100644 arch/x86/include/asm/arch-queensbay/irq.harch/x86/cpu/queensbay/Makefile +1
-1@@ -5,5 +5,5 @@ # obj-y += fsp_configs.o -obj-y += tnc.o topcliff.o +obj-y += irq.o tnc.o topcliff.o obj-$(CONFIG_PCI) += tnc_pci.oarch/x86/cpu/queensbay/irq.c new file +41
-0@@ -0,0 +1,236 @@ +/* +* Copyright (C) 2015, Bin Meng <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <common.h> +#include <errno.h> +#include <malloc.h> +#include <asm/io.h> +#include <asm/pci.h> +#include <asm/post.h> +#include <asm/processor.h> +#include <asm/pirq_routing.h> +#include <asm/arch/device.h> +#include <asm/arch/tnc.h> +#include <asm/arch/irq.h> + +static struct irq_routing_table *pirq_routing_table; + +bool pirq_check_irq_routed (int link,u8 irq) +{ +u8 pirq; + + pirq =x86_pci_read_config8 (TNC_LPC ,LINK_N2V (link)); + pirq &=0xf ; + +/* IRQ# 0/1/2/8/13 are reserved */ +if (pirq <3 || pirq ==8 || pirq ==13 ) +return false; + +return pirq == irq ? true : false; +} + +int pirq_translate_link (int link) +{ +return LINK_V2N (link); +} + +void pirq_assign_irq (int link,u8 irq) +{
arch/x86/cpu/queensbay/irq.c line 51
Quoted 10 lines
arch/x86/cpu/queensbay/irq.c new file +10
-0+/* IRQ# 0/1/2/8/13 are reserved */ +if (irq <3 || irq ==8 || irq ==13 ) +return ; + +x86_pci_write_config8 (TNC_LPC ,LINK_N2V (link), irq); +} + +static inline void fill_irq_info (struct irq_info **slot,int *entries,u8 bus, +u8 device,u8 func,u8 pin,u8 pirq) +{
Please declare a local variable
struct irq_info *slot = *slotp;
and rename the param to slotp, to avoid the first four (*slot).
Quoted 123 lines
arch/x86/cpu/queensbay/irq.c new file +123
-0+ (*slot)->bus = bus; + (*slot)->devfn = (device <<3 ) | func; + (*slot)->irq[pin -1 ].link =LINK_N2V (pirq); + (*slot)->irq[pin -1 ].bitmap =PIRQ_BITMAP ; + (*entries)++; + (*slot)++; +} + +/* PCIe port downstream INTx swizzle */ +static inline u8 pin_swizzle (u8 pin,int port) +{ +return (pin + port) %4 ; +} + +__weak int board_fill_irq_info (struct irq_info *slot) +{ +return 0 ; +} + +static int create_pirq_routing_table (void ) +{ +struct irq_routing_table *rt; +struct irq_info *slot; +int irq_entries =0 ; +pci_dev_t tcf_bdf; +u8 tcf_bus, bus; +int i; + + rt =malloc (sizeof (struct irq_routing_table )); +if (!rt) +return -ENOMEM ; +memset ((char *)rt,0 ,sizeof (struct irq_routing_table )); + +/* Populate the PIRQ table fields */ + rt->signature =PIRQ_SIGNATURE ; + rt->version =PIRQ_VERSION ; + rt->rtr_bus =0 ; + rt->rtr_devfn = (TNC_LPC_DEV <<3 ) |TNC_LPC_FUNC ; + rt->rtr_vendor =PCI_VENDOR_ID_INTEL ; + rt->rtr_device =PCI_DEVICE_ID_INTEL_ICH7_31 ; + + slot = rt->slots; + +/* +* Now fill in the irq_info entries in the PIRQ table +* +* We start from internal TunnelCreek PCI devices first, then +* followed by all the 4 PCIe ports downstream devices, including +* the Queensbay platform Topcliff chipset devices. +*/ +fill_irq_info (&slot, &irq_entries,0 ,TNC_IGD_DEV , +TNC_IGD_FUNC ,INTA ,PIRQE ); +fill_irq_info (&slot, &irq_entries,0 ,TNC_SDVO_DEV , +TNC_SDVO_FUNC ,INTA ,PIRQF ); +fill_irq_info (&slot, &irq_entries,0 ,TNC_HDA_DEV , +TNC_HDA_FUNC ,INTA ,PIRQG ); +fill_irq_info (&slot, &irq_entries,0 ,TNC_PCIE0_DEV , +TNC_PCIE0_FUNC ,INTA ,PIRQE ); +fill_irq_info (&slot, &irq_entries,0 ,TNC_PCIE1_DEV , +TNC_PCIE1_FUNC ,INTA ,PIRQF ); +fill_irq_info (&slot, &irq_entries,0 ,TNC_PCIE2_DEV , +TNC_PCIE2_FUNC ,INTA ,PIRQG ); +fill_irq_info (&slot, &irq_entries,0 ,TNC_PCIE3_DEV , +TNC_PCIE3_FUNC ,INTA ,PIRQH ); + +/* Check which PCIe port the Topcliff chipset is connected to */ + tcf_bdf =pci_find_device (PCI_VENDOR_ID_INTEL ,0x8800 ,0 ); + tcf_bus =PCI_BUS (tcf_bdf); +for (i =0 ; i <4 ; i++) { + bus =x86_pci_read_config8 (PCI_BDF (0 ,TNC_PCIE0_DEV + i,0 ), +PCI_SECONDARY_BUS ); +if (bus == tcf_bus) +break ; + } + +/* Fill in the Topcliff chipset devices' irq info */ +if (i <4 ) { +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_PCIE_PORT_DEV , +TCF_PCIE_PORT_FUNC ,INTA ,pin_swizzle (PIRQA , i)); + + tcf_bus++; +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_0 , +TCF_GBE_FUNC ,INTA ,pin_swizzle (PIRQA , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_0 , +TCF_GPIO_FUNC ,INTA ,pin_swizzle (PIRQA , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_2 , +TCF_USB1_OHCI0_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_2 , +TCF_USB1_OHCI1_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_2 , +TCF_USB1_OHCI2_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_2 , +TCF_USB1_EHCI_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_2 , +TCF_USB_DEVICE_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_4 , +TCF_SDIO0_FUNC ,INTC ,pin_swizzle (PIRQC , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_4 , +TCF_SDIO1_FUNC ,INTC ,pin_swizzle (PIRQC , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_6 , +TCF_SATA_FUNC ,INTD ,pin_swizzle (PIRQD , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_8 , +TCF_USB2_OHCI0_FUNC ,INTA ,pin_swizzle (PIRQA , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_8 , +TCF_USB2_OHCI1_FUNC ,INTA ,pin_swizzle (PIRQA , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_8 , +TCF_USB2_OHCI2_FUNC ,INTA ,pin_swizzle (PIRQA , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_8 , +TCF_USB2_EHCI_FUNC ,INTA ,pin_swizzle (PIRQA , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_10 , +TCF_DMA1_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_10 , +TCF_UART0_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_10 , +TCF_UART1_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_10 , +TCF_UART2_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_10 , +TCF_UART3_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_12 , +TCF_DMA2_FUNC ,INTC ,pin_swizzle (PIRQC , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_12 , +TCF_SPI_FUNC ,INTC ,pin_swizzle (PIRQC , i));
arch/x86/cpu/queensbay/irq.c line 184
Quoted 10 lines
arch/x86/cpu/queensbay/irq.c new file +10
-0+fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_12 , +TCF_I2C_FUNC ,INTC ,pin_swizzle (PIRQC , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_12 , +TCF_CAN_FUNC ,INTC ,pin_swizzle (PIRQC , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_12 , +TCF_1588_FUNC ,INTC ,pin_swizzle (PIRQC , i)); + } + +/* Call board-specific routine to fill in add-in card's irq info */ + irq_entries +=board_fill_irq_info (slot);
But isn't this already board-specific code?
Quoted 32 lines
arch/x86/cpu/queensbay/irq.c new file +32
-0+ + rt->size = irq_entries *sizeof (struct irq_info ) +32 ; + + pirq_routing_table = rt; + +return 0 ; +} + +void pirq_init (void ) +{ +u32 rcba; + + rcba =x86_pci_read_config32 (TNC_LPC ,LPC_RCBA ); + rcba &= ~MEM_BAR_EN ; + +/* Make sure all internal PCI devices are using INTA */ +writel (INTA , rcba +D02IP ); +writel (INTA , rcba +D03IP ); +writel (INTA , rcba +D27IP ); +writel (INTA , rcba +D31IP ); +writel (INTA , rcba +D23IP ); +writel (INTA , rcba +D24IP ); +writel (INTA , rcba +D25IP ); +writel (INTA , rcba +D26IP ); + +/* +* Route TunnelCreek PCI device interrupt pin to PIRQ +* +* Since PCIe downstream ports received INTx are routed to PIRQ +* A/B/C/D directly and not configurable, we route internal PCI +* device's INTx to PIRQ E/F/G/H. +*/
arch/x86/cpu/queensbay/irq.c line 226
Quoted 10 lines
arch/x86/cpu/queensbay/irq.c new file +10
-0+writew (PIRQE , rcba +D02IR ); +writew (PIRQF , rcba +D03IR ); +writew (PIRQG , rcba +D27IR ); +writew (PIRQH , rcba +D31IR ); +writew (PIRQE , rcba +D23IR ); +writew (PIRQF , rcba +D24IR ); +writew (PIRQG , rcba +D25IR ); +writew (PIRQH , rcba +D26IR ); + +if (!create_pirq_routing_table ()) {
Can you add a comment here as to why you do this next bit if create_pirq_routing_table() fails?
Quoted 221 lines
arch/x86/cpu/queensbay/irq.c new file +10
-0+/* Route PIRQ */ +pirq_route_irqs (pirq_routing_table->slots, +get_irq_slot_count (pirq_routing_table)); + } +} + +u32 write_pirq_routing_table (u32 addr) +{ +return copy_pirq_routing_table (addr, pirq_routing_table); +}arch/x86/cpu/queensbay/tnc.c +9
-1@@ -8,7 +8,8 @@#include <asm/io.h> #include <asm/pci.h> #include <asm/post.h> -#include <asm/arch/tnc.h> +#include <asm/arch/device.h> +#include <asm/arch/irq.h> #include <asm/fsp/fsp_support.h> #include <asm/processor.h> @@ -43,3 +44,10 @@ int arch_cpu_init(void)return 0 ; } + +int arch_misc_init (void ) +{ +pirq_init (); + +return 0 ; +}arch/x86/include/asm/arch-queensbay/device.h new file +94
-0@@ -0,0 +1,94 @@ +/* +* Copyright (C) 2015, Bin Meng <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#ifndef _QUEENSBAY_DEVICE_H_ +#define _QUEENSBAY_DEVICE_H_ + +#include <pci.h> + +/* TunnelCreek PCI Devices */ +#define TNC_HOST_BRIDGE_DEV 0 +#define TNC_HOST_BRIDGE_FUNC 0 +#define TNC_IGD_DEV 2 +#define TNC_IGD_FUNC 0 +#define TNC_SDVO_DEV 3 +#define TNC_SDVO_FUNC 0 +#define TNC_PCIE0_DEV 23 +#define TNC_PCIE0_FUNC 0 +#define TNC_PCIE1_DEV 24 +#define TNC_PCIE1_FUNC 0 +#define TNC_PCIE2_DEV 25 +#define TNC_PCIE2_FUNC 0 +#define TNC_PCIE3_DEV 26 +#define TNC_PCIE3_FUNC 0 +#define TNC_HDA_DEV 27 +#define TNC_HDA_FUNC 0 +#define TNC_LPC_DEV 31 +#define TNC_LPC_FUNC 0 + +#define TNC_HOST_BRIDGE \ + PCI_BDF(0, TNC_HOST_BRIDGE_DEV, TNC_HOST_BRIDGE_FUNC) +#define TNC_IGD \ + PCI_BDF(0, TNC_IGD_DEV, TNC_IGD_FUNC) +#define TNC_SDVO \ + PCI_BDF(0, TNC_SDVO_DEV, TNC_SDVO_FUNC) +#define TNC_PCIE0 \ + PCI_BDF(0, TNC_PCIE0_DEV, TNC_PCIE0_FUNC) +#define TNC_PCIE1 \ + PCI_BDF(0, TNC_PCIE1_DEV, TNC_PCIE1_FUNC) +#define TNC_PCIE2 \ + PCI_BDF(0, TNC_PCIE2_DEV, TNC_PCIE2_FUNC) +#define TNC_PCIE3 \ + PCI_BDF(0, TNC_PCIE3_DEV, TNC_PCIE3_FUNC) +#define TNC_HDA \ + PCI_BDF(0, TNC_HDA_DEV, TNC_HDA_FUNC) +#define TNC_LPC \ + PCI_BDF(0, TNC_LPC_DEV, TNC_LPC_FUNC) + +/* Topcliff IOH PCI Devices */ +#define TCF_PCIE_PORT_DEV 0 +#define TCF_PCIE_PORT_FUNC 0 + +#define TCF_DEV_0 0 +#define TCF_PKT_HUB_FUNC 0 +#define TCF_GBE_FUNC 1 +#define TCF_GPIO_FUNC 2 + +#define TCF_DEV_2 2 +#define TCF_USB1_OHCI0_FUNC 0 +#define TCF_USB1_OHCI1_FUNC 1 +#define TCF_USB1_OHCI2_FUNC 2 +#define TCF_USB1_EHCI_FUNC 3 +#define TCF_USB_DEVICE_FUNC 4 + +#define TCF_DEV_4 4 +#define TCF_SDIO0_FUNC 0 +#define TCF_SDIO1_FUNC 1 + +#define TCF_DEV_6 6 +#define TCF_SATA_FUNC 0 + +#define TCF_DEV_8 8 +#define TCF_USB2_OHCI0_FUNC 0 +#define TCF_USB2_OHCI1_FUNC 1 +#define TCF_USB2_OHCI2_FUNC 2 +#define TCF_USB2_EHCI_FUNC 3 + +#define TCF_DEV_10 10 +#define TCF_DMA1_FUNC 0 +#define TCF_UART0_FUNC 1 +#define TCF_UART1_FUNC 2 +#define TCF_UART2_FUNC 3 +#define TCF_UART3_FUNC 4 + +#define TCF_DEV_12 12 +#define TCF_DMA2_FUNC 0 +#define TCF_SPI_FUNC 1 +#define TCF_I2C_FUNC 2 +#define TCF_CAN_FUNC 3 +#define TCF_1588_FUNC 4 + +#endif /* _QUEENSBAY_DEVICE_H_ */ arch/x86/include/asm/arch-queensbay/irq.h new file +55
-0@@ -0,0 +1,55 @@ +/* +* Copyright (C) 2015, Bin Meng <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#ifndef _ARCH_IRQ_H_ +#define _ARCH_IRQ_H_ + +enum pci_int_pin { +INTX , +INTA , +INTB , +INTC , +INTD +}; + +enum pirq_pin { +PIRQA , +PIRQB , +PIRQC , +PIRQD , +PIRQE , +PIRQF , +PIRQG , +PIRQH +}; + +/* PIRQ link number and value conversion */ +#define LINK_V2N (link) (link - 0x60) +#define LINK_N2V (link) (link + 0x60) + +#define PIRQ_BITMAP 0xdee0 + +struct irq_info ; + +/** +* board_fill_irq_info() - Board-specific irq_info fill routine +* +* This fills the irq_info table for any board-specific add-in cards. +* +* @slot: pointer to the struct irq_info that is to be filled in +* @return: number of entries were written to the struct irq_info +*/ +int board_fill_irq_info (struct irq_info *slot); + +/** +* pirq_init() - Initialize platform PIRQ routing +* +* This initializes the PIRQ routing on the platform and configures all PCI +* devices' interrupt line register to a working IRQ number on the 8259 PIC. +*/ +void pirq_init (void ); + +#endif /* _ARCH_IRQ_H_ */ arch/x86/include/asm/arch-queensbay/tnc.h +14
-2@@ -7,8 +7,30 @@#ifndef _X86_ARCH_TNC_H_#define _X86_ARCH_TNC_H_ -#include <pci.h> +/* Memory BAR Enable */ +#define MEM_BAR_EN 0x00000001 -#define TNC_LPC PCI_BDF(0, 31, 0) +/* LPC PCI Configuration Registers */ +#define LPC_RCBA 0xf0 + +/* Interupt Pin Configuration (in RCBA) */ +#define D02IP 0x3118 +#define D03IP 0x3130 +#define D23IP 0x312c +#define D24IP 0x3128 +#define D25IP 0x3124 +#define D26IP 0x3120 +#define D27IP 0x3110 +#define D31IP 0x3100
arch/x86/include/asm/arch-queensbay/tnc.h line 34
Quoted 10 lines
arch/x86/include/asm/arch-queensbay/tnc.h +10
-0+ +/* Interupt Route Configuration (in RCBA) */ +#define D02IR 0x3160 +#define D03IR 0x3162 +#define D23IR 0x3150 +#define D24IR 0x314e +#define D25IR 0x314c +#define D26IR 0x314a +#define D27IR 0x3148 +#define D31IR 0x3140
Can we use a C structure for the RCBA, or part of it?
Quoted 37 lines
arch/x86/include/asm/arch-queensbay/tnc.h +0
-0#endif /* _X86_ARCH_TNC_H_ */ arch/x86/include/asm/u-boot-x86.h +2
-0@@ -53,6 +53,8 @@ int video_bios_init(void);void board_init_f_r_trampoline (ulong ) __attribute__ ((noreturn));void board_init_f_r (void ) __attribute__ ((noreturn)); +int arch_misc_init (void ); +/* Read the time stamp counter */ static inline __attribute__((no_instrument_function))uint64_t rdtsc (void ) {configs/crownbay_defconfig +1
-0@@ -4,3 +4,4 @@ CONFIG_TARGET_CROWNBAY=y CONFIG_OF_CONTROL=y CONFIG_OF_SEPARATE=y CONFIG_DEFAULT_DEVICE_TREE="crownbay" +CONFIG_GENERATE_PIRQ_TABLE=yinclude/configs/crownbay.h +1
-1@@ -15,6 +15,7 @@#define CONFIG_SYS_MONITOR_LEN (1 << 20)#define CONFIG_BOARD_EARLY_INIT_F +#define CONFIG_ARCH_MISC_INIT #define CONFIG_NR_DRAM_BANKS 1 --
Quoted 2 lines
1.8.2.1
Regards,
Simon
PATCH 4/4 x86: queensbay: Implement PIRQ routing
Hi Simon,
Quoted 7 lines · Simon Glass
Hi Bin,
Quoted 2 lines · Bin Meng
Implement Intel Queensbay platform-specific PIRQ routing support. The chipset PIRQ routing setup is called in the
arch_mist_init().
arch_misc_init()?
Will fix.
Quoted 2 lines
Also how can this be used on other boards? Should part of this code be moved to a generic place?
Generally Intel interrupt router should be compatible, but the offsets of these interrupt routing registers might be different from platform to platform. The platform-specific part is the internal PCI devices' interrupt pin to PIRQ map.
Quoted 90 lines
Quoted 77 lines
Signed-off-by Bin Meng <[email protected]>---
arch/x86/cpu/queensbay/Makefile | 2 +- arch/x86/cpu/queensbay/irq.c | 236 +++++++++++++++++++++++++++ arch/x86/cpu/queensbay/tnc.c | 10 +- arch/x86/include/asm/arch-queensbay/device.h | 94 +++++++++++ arch/x86/include/asm/arch-queensbay/irq.h | 55 +++++++ arch/x86/include/asm/arch-queensbay/tnc.h | 26 ++- arch/x86/include/asm/u-boot-x86.h | 2 + configs/crownbay_defconfig | 1 + include/configs/crownbay.h | 1 + 9 files changed, 423 insertions(+), 4 deletions(-) create mode 100644 arch/x86/cpu/queensbay/irq.c create mode 100644 arch/x86/include/asm/arch-queensbay/device.h create mode 100644 arch/x86/include/asm/arch-queensbay/irq.harch/x86/cpu/queensbay/Makefile +1
-1@@ -5,5 +5,5 @@ # obj-y += fsp_configs.o -obj-y += tnc.o topcliff.o +obj-y += irq.o tnc.o topcliff.o obj-$(CONFIG_PCI) += tnc_pci.oarch/x86/cpu/queensbay/irq.c new file +41
-0@@ -0,0 +1,236 @@ +/* +* Copyright (C) 2015, Bin Meng <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#include <common.h> +#include <errno.h> +#include <malloc.h> +#include <asm/io.h> +#include <asm/pci.h> +#include <asm/post.h> +#include <asm/processor.h> +#include <asm/pirq_routing.h> +#include <asm/arch/device.h> +#include <asm/arch/tnc.h> +#include <asm/arch/irq.h> + +static struct irq_routing_table *pirq_routing_table; + +bool pirq_check_irq_routed (int link,u8 irq) +{ +u8 pirq; + + pirq =x86_pci_read_config8 (TNC_LPC ,LINK_N2V (link)); + pirq &=0xf ; + +/* IRQ# 0/1/2/8/13 are reserved */ +if (pirq <3 || pirq ==8 || pirq ==13 ) +return false; + +return pirq == irq ? true : false; +} + +int pirq_translate_link (int link) +{ +return LINK_V2N (link); +} + +void pirq_assign_irq (int link,u8 irq) +{arch/x86/cpu/queensbay/irq.c line 51
Quoted 10 lines
arch/x86/cpu/queensbay/irq.c new file +10
-0+/* IRQ# 0/1/2/8/13 are reserved */ +if (irq <3 || irq ==8 || irq ==13 ) +return ; + +x86_pci_write_config8 (TNC_LPC ,LINK_N2V (link), irq); +} + +static inline void fill_irq_info (struct irq_info **slot,int *entries,u8 bus, +u8 device,u8 func,u8 pin,u8 pirq) +{Please declare a local variable
Quoted 3 lines
struct
irq_info*slot = *slotp;and rename the param to slotp, to avoid the first four (*slot).
Will fix.
Quoted 127 lines
Quoted 127 lines
arch/x86/cpu/queensbay/irq.c new file +127
-0+ (*slot)->bus = bus; + (*slot)->devfn = (device <<3 ) | func; + (*slot)->irq[pin -1 ].link =LINK_N2V (pirq); + (*slot)->irq[pin -1 ].bitmap =PIRQ_BITMAP ; + (*entries)++; + (*slot)++; +} + +/* PCIe port downstream INTx swizzle */ +static inline u8 pin_swizzle (u8 pin,int port) +{ +return (pin + port) %4 ; +} + +__weak int board_fill_irq_info (struct irq_info *slot) +{ +return 0 ; +} + +static int create_pirq_routing_table (void ) +{ +struct irq_routing_table *rt; +struct irq_info *slot; +int irq_entries =0 ; +pci_dev_t tcf_bdf; +u8 tcf_bus, bus; +int i; + + rt =malloc (sizeof (struct irq_routing_table )); +if (!rt) +return -ENOMEM ; +memset ((char *)rt,0 ,sizeof (struct irq_routing_table )); + +/* Populate the PIRQ table fields */ + rt->signature =PIRQ_SIGNATURE ; + rt->version =PIRQ_VERSION ; + rt->rtr_bus =0 ; + rt->rtr_devfn = (TNC_LPC_DEV <<3 ) |TNC_LPC_FUNC ; + rt->rtr_vendor =PCI_VENDOR_ID_INTEL ; + rt->rtr_device =PCI_DEVICE_ID_INTEL_ICH7_31 ; + + slot = rt->slots; + +/* +* Now fill in the irq_info entries in the PIRQ table +* +* We start from internal TunnelCreek PCI devices first, then +* followed by all the 4 PCIe ports downstream devices, including +* the Queensbay platform Topcliff chipset devices. +*/ +fill_irq_info (&slot, &irq_entries,0 ,TNC_IGD_DEV , +TNC_IGD_FUNC ,INTA ,PIRQE ); +fill_irq_info (&slot, &irq_entries,0 ,TNC_SDVO_DEV , +TNC_SDVO_FUNC ,INTA ,PIRQF ); +fill_irq_info (&slot, &irq_entries,0 ,TNC_HDA_DEV , +TNC_HDA_FUNC ,INTA ,PIRQG ); +fill_irq_info (&slot, &irq_entries,0 ,TNC_PCIE0_DEV , +TNC_PCIE0_FUNC ,INTA ,PIRQE ); +fill_irq_info (&slot, &irq_entries,0 ,TNC_PCIE1_DEV , +TNC_PCIE1_FUNC ,INTA ,PIRQF ); +fill_irq_info (&slot, &irq_entries,0 ,TNC_PCIE2_DEV , +TNC_PCIE2_FUNC ,INTA ,PIRQG ); +fill_irq_info (&slot, &irq_entries,0 ,TNC_PCIE3_DEV , +TNC_PCIE3_FUNC ,INTA ,PIRQH ); + +/* Check which PCIe port the Topcliff chipset is connected to */ + tcf_bdf =pci_find_device (PCI_VENDOR_ID_INTEL ,0x8800 ,0 ); + tcf_bus =PCI_BUS (tcf_bdf); +for (i =0 ; i <4 ; i++) { + bus =x86_pci_read_config8 (PCI_BDF (0 ,TNC_PCIE0_DEV + i,0 ), +PCI_SECONDARY_BUS ); +if (bus == tcf_bus) +break ; + } + +/* Fill in the Topcliff chipset devices' irq info */ +if (i <4 ) { +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_PCIE_PORT_DEV , +TCF_PCIE_PORT_FUNC ,INTA ,pin_swizzle (PIRQA , i)); + + tcf_bus++; +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_0 , +TCF_GBE_FUNC ,INTA ,pin_swizzle (PIRQA , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_0 , +TCF_GPIO_FUNC ,INTA ,pin_swizzle (PIRQA , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_2 , +TCF_USB1_OHCI0_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_2 , +TCF_USB1_OHCI1_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_2 , +TCF_USB1_OHCI2_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_2 , +TCF_USB1_EHCI_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_2 , +TCF_USB_DEVICE_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_4 , +TCF_SDIO0_FUNC ,INTC ,pin_swizzle (PIRQC , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_4 , +TCF_SDIO1_FUNC ,INTC ,pin_swizzle (PIRQC , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_6 , +TCF_SATA_FUNC ,INTD ,pin_swizzle (PIRQD , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_8 , +TCF_USB2_OHCI0_FUNC ,INTA ,pin_swizzle (PIRQA , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_8 , +TCF_USB2_OHCI1_FUNC ,INTA ,pin_swizzle (PIRQA , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_8 , +TCF_USB2_OHCI2_FUNC ,INTA ,pin_swizzle (PIRQA , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_8 , +TCF_USB2_EHCI_FUNC ,INTA ,pin_swizzle (PIRQA , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_10 , +TCF_DMA1_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_10 , +TCF_UART0_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_10 , +TCF_UART1_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_10 , +TCF_UART2_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_10 , +TCF_UART3_FUNC ,INTB ,pin_swizzle (PIRQB , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_12 , +TCF_DMA2_FUNC ,INTC ,pin_swizzle (PIRQC , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_12 , +TCF_SPI_FUNC ,INTC ,pin_swizzle (PIRQC , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_12 , +TCF_I2C_FUNC ,INTC ,pin_swizzle (PIRQC , i)); +fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_12 , +TCF_CAN_FUNC ,INTC ,pin_swizzle (PIRQC , i));
Quoted 8 lines
arch/x86/cpu/queensbay/irq.c line 184
Quoted 6 lines
arch/x86/cpu/queensbay/irq.c new file +6
-0+fill_irq_info (&slot, &irq_entries, tcf_bus,TCF_DEV_12 , +TCF_1588_FUNC ,INTC ,pin_swizzle (PIRQC , i)); + } + +/* Call board-specific routine to fill in add-in card's irq info */ + irq_entries +=board_fill_irq_info (slot);But isn't this already board-specific code?
This codes are put in the platform directory (arch/cpu/queensbay). We should implement board_fill_irq_info() in board directory (board/intel/crownbay) for any add-in cards.
Quoted 37 lines
Quoted 37 lines
arch/x86/cpu/queensbay/irq.c new file +37
-0+ + rt->size = irq_entries *sizeof (struct irq_info ) +32 ; + + pirq_routing_table = rt; + +return 0 ; +} + +void pirq_init (void ) +{ +u32 rcba; + + rcba =x86_pci_read_config32 (TNC_LPC ,LPC_RCBA ); + rcba &= ~MEM_BAR_EN ; + +/* Make sure all internal PCI devices are using INTA */ +writel (INTA , rcba +D02IP ); +writel (INTA , rcba +D03IP ); +writel (INTA , rcba +D27IP ); +writel (INTA , rcba +D31IP ); +writel (INTA , rcba +D23IP ); +writel (INTA , rcba +D24IP ); +writel (INTA , rcba +D25IP ); +writel (INTA , rcba +D26IP ); + +/* +* Route TunnelCreek PCI device interrupt pin to PIRQ +* +* Since PCIe downstream ports received INTx are routed to PIRQ +* A/B/C/D directly and not configurable, we route internal PCI +* device's INTx to PIRQ E/F/G/H. +*/ +writew (PIRQE , rcba +D02IR ); +writew (PIRQF , rcba +D03IR ); +writew (PIRQG , rcba +D27IR ); +writew (PIRQH , rcba +D31IR ); +writew (PIRQE , rcba +D23IR );
Quoted 8 lines
arch/x86/cpu/queensbay/irq.c line 226
Quoted 5 lines
arch/x86/cpu/queensbay/irq.c new file +5
-0+writew (PIRQF , rcba +D24IR ); +writew (PIRQG , rcba +D25IR ); +writew (PIRQH , rcba +D26IR ); + +if (!create_pirq_routing_table ()) {Can you add a comment here as to why you do this next bit if
create_pirq_routing_table()fails?
I am not sure if you misread the codes? If create_pirq_routing_table() fails, it returns non-zero value and the following pirq_route_irqs() will not be called.
Quoted 225 lines
Quoted 225 lines
arch/x86/cpu/queensbay/irq.c new file +10
-0+/* Route PIRQ */ +pirq_route_irqs (pirq_routing_table->slots, +get_irq_slot_count (pirq_routing_table)); + } +} + +u32 write_pirq_routing_table (u32 addr) +{ +return copy_pirq_routing_table (addr, pirq_routing_table); +}arch/x86/cpu/queensbay/tnc.c +9
-1@@ -8,7 +8,8 @@#include <asm/io.h> #include <asm/pci.h> #include <asm/post.h> -#include <asm/arch/tnc.h> +#include <asm/arch/device.h> +#include <asm/arch/irq.h> #include <asm/fsp/fsp_support.h> #include <asm/processor.h> @@ -43,3 +44,10 @@ int arch_cpu_init(void)return 0 ; } + +int arch_misc_init (void ) +{ +pirq_init (); + +return 0 ; +}arch/x86/include/asm/arch-queensbay/device.h new file +94
-0@@ -0,0 +1,94 @@ +/* +* Copyright (C) 2015, Bin Meng <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#ifndef _QUEENSBAY_DEVICE_H_ +#define _QUEENSBAY_DEVICE_H_ + +#include <pci.h> + +/* TunnelCreek PCI Devices */ +#define TNC_HOST_BRIDGE_DEV 0 +#define TNC_HOST_BRIDGE_FUNC 0 +#define TNC_IGD_DEV 2 +#define TNC_IGD_FUNC 0 +#define TNC_SDVO_DEV 3 +#define TNC_SDVO_FUNC 0 +#define TNC_PCIE0_DEV 23 +#define TNC_PCIE0_FUNC 0 +#define TNC_PCIE1_DEV 24 +#define TNC_PCIE1_FUNC 0 +#define TNC_PCIE2_DEV 25 +#define TNC_PCIE2_FUNC 0 +#define TNC_PCIE3_DEV 26 +#define TNC_PCIE3_FUNC 0 +#define TNC_HDA_DEV 27 +#define TNC_HDA_FUNC 0 +#define TNC_LPC_DEV 31 +#define TNC_LPC_FUNC 0 + +#define TNC_HOST_BRIDGE \ + PCI_BDF(0, TNC_HOST_BRIDGE_DEV, TNC_HOST_BRIDGE_FUNC) +#define TNC_IGD \ + PCI_BDF(0, TNC_IGD_DEV, TNC_IGD_FUNC) +#define TNC_SDVO \ + PCI_BDF(0, TNC_SDVO_DEV, TNC_SDVO_FUNC) +#define TNC_PCIE0 \ + PCI_BDF(0, TNC_PCIE0_DEV, TNC_PCIE0_FUNC) +#define TNC_PCIE1 \ + PCI_BDF(0, TNC_PCIE1_DEV, TNC_PCIE1_FUNC) +#define TNC_PCIE2 \ + PCI_BDF(0, TNC_PCIE2_DEV, TNC_PCIE2_FUNC) +#define TNC_PCIE3 \ + PCI_BDF(0, TNC_PCIE3_DEV, TNC_PCIE3_FUNC) +#define TNC_HDA \ + PCI_BDF(0, TNC_HDA_DEV, TNC_HDA_FUNC) +#define TNC_LPC \ + PCI_BDF(0, TNC_LPC_DEV, TNC_LPC_FUNC) + +/* Topcliff IOH PCI Devices */ +#define TCF_PCIE_PORT_DEV 0 +#define TCF_PCIE_PORT_FUNC 0 + +#define TCF_DEV_0 0 +#define TCF_PKT_HUB_FUNC 0 +#define TCF_GBE_FUNC 1 +#define TCF_GPIO_FUNC 2 + +#define TCF_DEV_2 2 +#define TCF_USB1_OHCI0_FUNC 0 +#define TCF_USB1_OHCI1_FUNC 1 +#define TCF_USB1_OHCI2_FUNC 2 +#define TCF_USB1_EHCI_FUNC 3 +#define TCF_USB_DEVICE_FUNC 4 + +#define TCF_DEV_4 4 +#define TCF_SDIO0_FUNC 0 +#define TCF_SDIO1_FUNC 1 + +#define TCF_DEV_6 6 +#define TCF_SATA_FUNC 0 + +#define TCF_DEV_8 8 +#define TCF_USB2_OHCI0_FUNC 0 +#define TCF_USB2_OHCI1_FUNC 1 +#define TCF_USB2_OHCI2_FUNC 2 +#define TCF_USB2_EHCI_FUNC 3 + +#define TCF_DEV_10 10 +#define TCF_DMA1_FUNC 0 +#define TCF_UART0_FUNC 1 +#define TCF_UART1_FUNC 2 +#define TCF_UART2_FUNC 3 +#define TCF_UART3_FUNC 4 + +#define TCF_DEV_12 12 +#define TCF_DMA2_FUNC 0 +#define TCF_SPI_FUNC 1 +#define TCF_I2C_FUNC 2 +#define TCF_CAN_FUNC 3 +#define TCF_1588_FUNC 4 + +#endif /* _QUEENSBAY_DEVICE_H_ */ arch/x86/include/asm/arch-queensbay/irq.h new file +55
-0@@ -0,0 +1,55 @@ +/* +* Copyright (C) 2015, Bin Meng <[email protected]> +* +* SPDX-License-Identifier: GPL-2.0+ +*/ + +#ifndef _ARCH_IRQ_H_ +#define _ARCH_IRQ_H_ + +enum pci_int_pin { +INTX , +INTA , +INTB , +INTC , +INTD +}; + +enum pirq_pin { +PIRQA , +PIRQB , +PIRQC , +PIRQD , +PIRQE , +PIRQF , +PIRQG , +PIRQH +}; + +/* PIRQ link number and value conversion */ +#define LINK_V2N (link) (link - 0x60) +#define LINK_N2V (link) (link + 0x60) + +#define PIRQ_BITMAP 0xdee0 + +struct irq_info ; + +/** +* board_fill_irq_info() - Board-specific irq_info fill routine +* +* This fills the irq_info table for any board-specific add-in cards. +* +* @slot: pointer to the struct irq_info that is to be filled in +* @return: number of entries were written to the struct irq_info +*/ +int board_fill_irq_info (struct irq_info *slot); + +/** +* pirq_init() - Initialize platform PIRQ routing +* +* This initializes the PIRQ routing on the platform and configures all PCI +* devices' interrupt line register to a working IRQ number on the 8259 PIC. +*/ +void pirq_init (void ); + +#endif /* _ARCH_IRQ_H_ */ arch/x86/include/asm/arch-queensbay/tnc.h +18
-2@@ -7,8 +7,30 @@#ifndef _X86_ARCH_TNC_H_#define _X86_ARCH_TNC_H_ -#include <pci.h> +/* Memory BAR Enable */ +#define MEM_BAR_EN 0x00000001 -#define TNC_LPC PCI_BDF(0, 31, 0) +/* LPC PCI Configuration Registers */ +#define LPC_RCBA 0xf0 + +/* Interupt Pin Configuration (in RCBA) */ +#define D02IP 0x3118 +#define D03IP 0x3130 +#define D23IP 0x312c +#define D24IP 0x3128 +#define D25IP 0x3124 +#define D26IP 0x3120 +#define D27IP 0x3110 +#define D31IP 0x3100 + +/* Interupt Route Configuration (in RCBA) */ +#define D02IR 0x3160 +#define D03IR 0x3162
Quoted 8 lines
arch/x86/include/asm/arch-queensbay/tnc.h line 34
Quoted 6 lines
arch/x86/include/asm/arch-queensbay/tnc.h +6
-0+#define D23IR 0x3150 +#define D24IR 0x314e +#define D25IR 0x314c +#define D26IR 0x314a +#define D27IR 0x3148 +#define D31IR 0x3140Can we use a C structure for the RCBA, or part of it?
Yes, we can.
Quoted 30 lines
Quoted 30 lines
arch/x86/include/asm/arch-queensbay/tnc.h +0
-0#endif /* _X86_ARCH_TNC_H_ */ arch/x86/include/asm/u-boot-x86.h +2
-0@@ -53,6 +53,8 @@ int video_bios_init(void);void board_init_f_r_trampoline (ulong ) __attribute__ ((noreturn));void board_init_f_r (void ) __attribute__ ((noreturn)); +int arch_misc_init (void ); +/* Read the time stamp counter */ static inline __attribute__((no_instrument_function))uint64_t rdtsc (void ) {configs/crownbay_defconfig +1
-0@@ -4,3 +4,4 @@ CONFIG_TARGET_CROWNBAY=y CONFIG_OF_CONTROL=y CONFIG_OF_SEPARATE=y CONFIG_DEFAULT_DEVICE_TREE="crownbay" +CONFIG_GENERATE_PIRQ_TABLE=yinclude/configs/crownbay.h +0
-0@@ -15,6 +15,7 @@
Quoted 7 lines
include/configs/crownbay.h
Quoted 7 lines
include/configs/crownbay.h +1
-1#define CONFIG_SYS_MONITOR_LEN (1 << 20)#define CONFIG_BOARD_EARLY_INIT_F +#define CONFIG_ARCH_MISC_INIT #define CONFIG_NR_DRAM_BANKS 1 --
Regards,
Bin
PATCH 4/4 x86: queensbay: Implement PIRQ routing
Hi Bin,
Quoted 40 lines · Bin Meng
Hi Simon,
Quoted 7 lines · Simon Glass
Hi Bin,
Quoted 2 lines · Bin Meng
Implement Intel Queensbay platform-specific PIRQ routing support. The chipset PIRQ routing setup is called in the
arch_mist_init().
arch_misc_init()?Will fix.
Quoted 2 lines
Also how can this be used on other boards? Should part of this code be moved to a generic place?
Generally Intel interrupt router should be compatible, but the offsets of these interrupt routing registers might be different from platform to platform. The platform-specific part is the internal PCI devices' interrupt pin to PIRQ map.
Quoted 19 lines
Quoted 19 lines
Signed-off-by Bin Meng <[email protected]>---
arch/x86/cpu/queensbay/Makefile | 2 +- arch/x86/cpu/queensbay/irq.c | 236 +++++++++++++++++++++++++++ arch/x86/cpu/queensbay/tnc.c | 10 +- arch/x86/include/asm/arch-queensbay/device.h | 94 +++++++++++ arch/x86/include/asm/arch-queensbay/irq.h | 55 +++++++ arch/x86/include/asm/arch-queensbay/tnc.h | 26 ++- arch/x86/include/asm/u-boot-x86.h | 2 + configs/crownbay_defconfig | 1 + include/configs/crownbay.h | 1 + 9 files changed, 423 insertions(+), 4 deletions(-) create mode 100644 arch/x86/cpu/queensbay/irq.c create mode 100644 arch/x86/include/asm/arch-queensbay/device.h create mode 100644 arch/x86/include/asm/arch-queensbay/irq.h
[snip]
Quoted 11 lines
Quoted 11 lines
Quoted 10 lines
arch/x86/cpu/queensbay/irq.c new file +10
-0+writew (PIRQE , rcba +D02IR ); +writew (PIRQF , rcba +D03IR ); +writew (PIRQG , rcba +D27IR ); +writew (PIRQH , rcba +D31IR ); +writew (PIRQE , rcba +D23IR ); +writew (PIRQF , rcba +D24IR ); +writew (PIRQG , rcba +D25IR ); +writew (PIRQH , rcba +D26IR ); + +if (!create_pirq_routing_table ()) {
Quoted 6 lines
Quoted 2 lines
Can you add a comment here as to why you do this next bit if
create_pirq_routing_table()fails?I am not sure if you misread the codes? If
create_pirq_routing_table()fails, it returns non-zero value and the followingpirq_route_irqs()will not be called.
Yes I misread it. So should this function return the error code it gets? Or maybe add debug()?
Quoted 7 lines
Quoted 7 lines
arch/x86/cpu/queensbay/irq.c line 232
Quoted 7 lines
arch/x86/cpu/queensbay/irq.c new file +6
-0+/* Route PIRQ */ +pirq_route_irqs (pirq_routing_table->slots, +get_irq_slot_count (pirq_routing_table)); + } +} +
Regards,
Simon
PATCH 4/4 x86: queensbay: Implement PIRQ routing
Hi Simon,
Quoted 59 lines · Simon Glass
Hi Bin,
Quoted 40 lines · Bin Meng
Hi Simon,
Quoted 7 lines · Simon Glass
Hi Bin,
Quoted 2 lines · Bin Meng
Implement Intel Queensbay platform-specific PIRQ routing support. The chipset PIRQ routing setup is called in the
arch_mist_init().
arch_misc_init()?Will fix.
Quoted 2 lines
Also how can this be used on other boards? Should part of this code be moved to a generic place?
Generally Intel interrupt router should be compatible, but the offsets of these interrupt routing registers might be different from platform to platform. The platform-specific part is the internal PCI devices' interrupt pin to PIRQ map.
Quoted 19 lines
Quoted 19 lines
Signed-off-by Bin Meng <[email protected]>---
arch/x86/cpu/queensbay/Makefile | 2 +- arch/x86/cpu/queensbay/irq.c | 236 +++++++++++++++++++++++++++ arch/x86/cpu/queensbay/tnc.c | 10 +- arch/x86/include/asm/arch-queensbay/device.h | 94 +++++++++++ arch/x86/include/asm/arch-queensbay/irq.h | 55 +++++++ arch/x86/include/asm/arch-queensbay/tnc.h | 26 ++- arch/x86/include/asm/u-boot-x86.h | 2 + configs/crownbay_defconfig | 1 + include/configs/crownbay.h | 1 + 9 files changed, 423 insertions(+), 4 deletions(-) create mode 100644 arch/x86/cpu/queensbay/irq.c create mode 100644 arch/x86/include/asm/arch-queensbay/device.h create mode 100644 arch/x86/include/asm/arch-queensbay/irq.h[snip]
Quoted 14 lines
Quoted 13 lines
arch/x86/cpu/queensbay/irq.c line 226
Quoted 10 lines
arch/x86/cpu/queensbay/irq.c new file +10
-0+writew (PIRQE , rcba +D02IR ); +writew (PIRQF , rcba +D03IR ); +writew (PIRQG , rcba +D27IR ); +writew (PIRQH , rcba +D31IR ); +writew (PIRQE , rcba +D23IR ); +writew (PIRQF , rcba +D24IR ); +writew (PIRQG , rcba +D25IR ); +writew (PIRQH , rcba +D26IR ); + +if (!create_pirq_routing_table ()) {Can you add a comment here as to why you do this next bit if
create_pirq_routing_table()fails?
Quoted 6 lines
Quoted 3 lines
I am not sure if you misread the codes? If
create_pirq_routing_table()fails, it returns non-zero value and the followingpirq_route_irqs()will not be called.Yes I misread it. So should this function return the error code it gets? Or maybe add
debug()?
Yep, adding one debug() is nice. Will do that in v2.
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
arch/x86/cpu/queensbay/irq.c line 232
Quoted 7 lines
arch/x86/cpu/queensbay/irq.c new file +6
-0+/* Route PIRQ */ +pirq_route_irqs (pirq_routing_table->slots, +get_irq_slot_count (pirq_routing_table)); + } +} +
Regards,
Bin