[U-Boot] [PATCH v2 0/3] x86: ivybridge: cougarcanyon2: Various enhancements

This adds some enhancements to the Intel Cougar Canyon 2 board.
This series is available at u-boot-x86/cc2-working for testing.
Changes in v2: - drop patches that were applied to u-boot-x86 - drop v1 patches using Kconfig option CONFIG_DISCRETE_PIRQ_ROUT - new patch to "parse number of PIRQ links from device tree" - new patch to "support discrete PIRQ routing registers via device tree" - add the PIRQ register mapping via "intel,pirq-regmap" property
Bin Meng (3): x86: irq: Parse number of PIRQ links from device tree x86: irq: Support discrete PIRQ routing registers via device tree x86: cougarcanyon2: Add missing chipset interrupt information
arch/x86/cpu/irq.c | 116 ++++++++++++++++++--- arch/x86/dts/cougarcanyon2.dts | 46 ++++++++ arch/x86/include/asm/irq.h | 34 ++---- configs/cougarcanyon2_defconfig | 2 + doc/device-tree-bindings/misc/intel,irq-router.txt | 6 ++ 5 files changed, 167 insertions(+), 37 deletions(-)

The "intel,pirq-link" property in Intel IRQ router's dt bindings has two cells, where the second one represents the number of PIRQ links on the platform. However current driver does not parse this information from device tree. This adds the codes to do the parse and save it for future use.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
---
Changes in v2: - drop patches that were applied to u-boot-x86 - drop v1 patches using Kconfig option CONFIG_DISCRETE_PIRQ_ROUT - new patch to "parse number of PIRQ links from device tree"
arch/x86/cpu/irq.c | 14 ++++++++++---- arch/x86/include/asm/irq.h | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c index ec556d3..096c34f 100644 --- a/arch/x86/cpu/irq.c +++ b/arch/x86/cpu/irq.c @@ -116,10 +116,16 @@ static int create_pirq_routing_table(struct udevice *dev) return -EINVAL; }
- ret = fdtdec_get_int(blob, node, "intel,pirq-link", -1); - if (ret == -1) - return ret; - priv->link_base = ret; + cell = fdt_getprop(blob, node, "intel,pirq-link", &len); + if (!cell || len != 8) + return -EINVAL; + priv->link_base = fdt_addr_to_cpu(cell[0]); + priv->link_num = fdt_addr_to_cpu(cell[1]); + if (priv->link_num > CONFIG_MAX_PIRQ_LINKS) { + debug("Limiting supported PIRQ link number from %d to %d\n", + priv->link_num, CONFIG_MAX_PIRQ_LINKS); + priv->link_num = CONFIG_MAX_PIRQ_LINKS; + }
priv->irq_mask = fdtdec_get_int(blob, node, "intel,pirq-mask", PIRQ_BITMAP); diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index bfa58cf..9ac91f2 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -29,6 +29,7 @@ enum pirq_config { * * @config: PIRQ_VIA_PCI or PIRQ_VIA_IBASE * @link_base: link value base number + * @link_num: number of PIRQ links supported * @irq_mask: IRQ mask reprenting the 16 IRQs in 8259, bit N is 1 means * IRQ N is available to be routed * @lb_bdf: irq router's PCI bus/device/function number encoding @@ -39,6 +40,7 @@ enum pirq_config { struct irq_router { int config; u32 link_base; + int link_num; u16 irq_mask; u32 bdf; u32 ibase;

Hi Bin,
On 12 June 2018 at 02:26, Bin Meng bmeng.cn@gmail.com wrote:
The "intel,pirq-link" property in Intel IRQ router's dt bindings has two cells, where the second one represents the number of PIRQ links on the platform. However current driver does not parse this information from device tree. This adds the codes to do the parse and save it for future use.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- drop patches that were applied to u-boot-x86
- drop v1 patches using Kconfig option CONFIG_DISCRETE_PIRQ_ROUT
- new patch to "parse number of PIRQ links from device tree"
arch/x86/cpu/irq.c | 14 ++++++++++---- arch/x86/include/asm/irq.h | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
At some point this driver should be converted to livetree.

On Wed, Jun 13, 2018 at 9:29 AM, Simon Glass sjg@chromium.org wrote:
Hi Bin,
On 12 June 2018 at 02:26, Bin Meng bmeng.cn@gmail.com wrote:
The "intel,pirq-link" property in Intel IRQ router's dt bindings has two cells, where the second one represents the number of PIRQ links on the platform. However current driver does not parse this information from device tree. This adds the codes to do the parse and save it for future use.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- drop patches that were applied to u-boot-x86
- drop v1 patches using Kconfig option CONFIG_DISCRETE_PIRQ_ROUT
- new patch to "parse number of PIRQ links from device tree"
arch/x86/cpu/irq.c | 14 ++++++++++---- arch/x86/include/asm/irq.h | 2 ++ 2 files changed, 12 insertions(+), 4 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
At some point this driver should be converted to livetree.
applied to u-boot-x86, thanks!

Currently both pirq_reg_to_linkno() and pirq_linkno_to_reg() assume consecutive PIRQ routing control registers. But this is not always the case on some platforms. Introduce a new device tree property intel,pirq-regmap to describe how the PIRQ routing register offset is mapped to the link number and adjust the irq router driver to utilize the mapping.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
---
Changes in v2: - new patch to "support discrete PIRQ routing registers via device tree"
arch/x86/cpu/irq.c | 102 +++++++++++++++++++-- arch/x86/include/asm/irq.h | 32 ++----- doc/device-tree-bindings/misc/intel,irq-router.txt | 6 ++ 3 files changed, 107 insertions(+), 33 deletions(-)
diff --git a/arch/x86/cpu/irq.c b/arch/x86/cpu/irq.c index 096c34f..3adc155 100644 --- a/arch/x86/cpu/irq.c +++ b/arch/x86/cpu/irq.c @@ -16,18 +16,75 @@
DECLARE_GLOBAL_DATA_PTR;
+/** + * pirq_reg_to_linkno() - Convert a PIRQ routing register offset to link number + * + * @priv: IRQ router driver's priv data + * @reg: PIRQ routing register offset from the base address + * @return: PIRQ link number (0 for PIRQA, 1 for PIRQB, etc) + */ +static inline int pirq_reg_to_linkno(struct irq_router *priv, int reg) +{ + int linkno = 0; + + if (priv->has_regmap) { + struct pirq_regmap *map = priv->regmap; + int i; + + for (i = 0; i < priv->link_num; i++) { + if (reg - priv->link_base == map->offset) { + linkno = map->link; + break; + } + map++; + } + } else { + linkno = reg - priv->link_base; + } + + return linkno; +} + +/** + * pirq_linkno_to_reg() - Convert a PIRQ link number to routing register offset + * + * @priv: IRQ router driver's priv data + * @linkno: PIRQ link number (0 for PIRQA, 1 for PIRQB, etc) + * @return: PIRQ routing register offset from the base address + */ +static inline int pirq_linkno_to_reg(struct irq_router *priv, int linkno) +{ + int reg = 0; + + if (priv->has_regmap) { + struct pirq_regmap *map = priv->regmap; + int i; + + for (i = 0; i < priv->link_num; i++) { + if (linkno == map->link) { + reg = map->offset + priv->link_base; + break; + } + map++; + } + } else { + reg = linkno + priv->link_base; + } + + return reg; +} + bool pirq_check_irq_routed(struct udevice *dev, int link, u8 irq) { struct irq_router *priv = dev_get_priv(dev); u8 pirq; - int base = priv->link_base;
if (priv->config == PIRQ_VIA_PCI) dm_pci_read_config8(dev->parent, - pirq_linkno_to_reg(link, base), &pirq); + pirq_linkno_to_reg(priv, link), &pirq); else pirq = readb((uintptr_t)priv->ibase + - pirq_linkno_to_reg(link, base)); + pirq_linkno_to_reg(priv, link));
pirq &= 0xf;
@@ -42,13 +99,12 @@ int pirq_translate_link(struct udevice *dev, int link) { struct irq_router *priv = dev_get_priv(dev);
- return pirq_reg_to_linkno(link, priv->link_base); + return pirq_reg_to_linkno(priv, link); }
void pirq_assign_irq(struct udevice *dev, int link, u8 irq) { struct irq_router *priv = dev_get_priv(dev); - int base = priv->link_base;
/* IRQ# 0/1/2/8/13 are reserved */ if (irq < 3 || irq == 8 || irq == 13) @@ -56,10 +112,10 @@ void pirq_assign_irq(struct udevice *dev, int link, u8 irq)
if (priv->config == PIRQ_VIA_PCI) dm_pci_write_config8(dev->parent, - pirq_linkno_to_reg(link, base), irq); + pirq_linkno_to_reg(priv, link), irq); else writeb(irq, (uintptr_t)priv->ibase + - pirq_linkno_to_reg(link, base)); + pirq_linkno_to_reg(priv, link)); }
static struct irq_info *check_dup_entry(struct irq_info *slot_base, @@ -82,7 +138,7 @@ static inline void fill_irq_info(struct irq_router *priv, struct irq_info *slot, { slot->bus = bus; slot->devfn = (device << 3) | 0; - slot->irq[pin - 1].link = pirq_linkno_to_reg(pirq, priv->link_base); + slot->irq[pin - 1].link = pirq_linkno_to_reg(priv, pirq); slot->irq[pin - 1].bitmap = priv->irq_mask; }
@@ -93,6 +149,7 @@ static int create_pirq_routing_table(struct udevice *dev) int node; int len, count; const u32 *cell; + struct pirq_regmap *map; struct irq_routing_table *rt; struct irq_info *slot, *slot_base; int irq_entries = 0; @@ -127,6 +184,33 @@ static int create_pirq_routing_table(struct udevice *dev) priv->link_num = CONFIG_MAX_PIRQ_LINKS; }
+ cell = fdt_getprop(blob, node, "intel,pirq-regmap", &len); + if (cell) { + if (len % sizeof(struct pirq_regmap)) + return -EINVAL; + + count = len / sizeof(struct pirq_regmap); + if (count < priv->link_num) { + printf("Number of pirq-regmap entires is wrong\n"); + return -EINVAL; + } + + count = priv->link_num; + priv->regmap = calloc(count, sizeof(struct pirq_regmap)); + if (!priv->regmap) + return -ENOMEM; + + priv->has_regmap = true; + map = priv->regmap; + for (i = 0; i < count; i++) { + map->link = fdt_addr_to_cpu(cell[0]); + map->offset = fdt_addr_to_cpu(cell[1]); + + cell += sizeof(struct pirq_regmap) / sizeof(u32); + map++; + } + } + priv->irq_mask = fdtdec_get_int(blob, node, "intel,pirq-mask", PIRQ_BITMAP);
@@ -209,7 +293,7 @@ static int create_pirq_routing_table(struct udevice *dev) * routing information in the device tree. */ if (slot->irq[pr.pin - 1].link != - pirq_linkno_to_reg(pr.pirq, priv->link_base)) + pirq_linkno_to_reg(priv, pr.pirq)) debug("WARNING: Inconsistent PIRQ routing information\n"); continue; } diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index 9ac91f2..e5c9160 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -22,6 +22,11 @@ enum pirq_config { PIRQ_VIA_IBASE };
+struct pirq_regmap { + int link; + int offset; +}; + /** * Intel interrupt router control block * @@ -30,6 +35,7 @@ enum pirq_config { * @config: PIRQ_VIA_PCI or PIRQ_VIA_IBASE * @link_base: link value base number * @link_num: number of PIRQ links supported + * @has_regmap: has mapping table between PIRQ link and routing register offset * @irq_mask: IRQ mask reprenting the 16 IRQs in 8259, bit N is 1 means * IRQ N is available to be routed * @lb_bdf: irq router's PCI bus/device/function number encoding @@ -41,6 +47,8 @@ struct irq_router { int config; u32 link_base; int link_num; + bool has_regmap; + struct pirq_regmap *regmap; u16 irq_mask; u32 bdf; u32 ibase; @@ -54,30 +62,6 @@ struct pirq_routing { int pirq; };
-/** - * pirq_reg_to_linkno() - Convert a PIRQ routing register offset to link number - * - * @reg: PIRQ routing register offset from the base address - * @base: PIRQ routing register block base address - * @return: PIRQ link number (0 for PIRQA, 1 for PIRQB, etc) - */ -static inline int pirq_reg_to_linkno(int reg, int base) -{ - return reg - base; -} - -/** - * pirq_linkno_to_reg() - Convert a PIRQ link number to routing register offset - * - * @linkno: PIRQ link number (0 for PIRQA, 1 for PIRQB, etc) - * @base: PIRQ routing register block base address - * @return: PIRQ routing register offset from the base address - */ -static inline int pirq_linkno_to_reg(int linkno, int base) -{ - return linkno + base; -} - #define PIRQ_BITMAP 0xdef8
#endif /* _ARCH_IRQ_H_ */ diff --git a/doc/device-tree-bindings/misc/intel,irq-router.txt b/doc/device-tree-bindings/misc/intel,irq-router.txt index 04ad346..9fb575c 100644 --- a/doc/device-tree-bindings/misc/intel,irq-router.txt +++ b/doc/device-tree-bindings/misc/intel,irq-router.txt @@ -22,6 +22,12 @@ Required properties : - intel,pirq-link : Specifies the PIRQ link information with two cells. The first cell is the register offset that controls the first PIRQ link routing. The second cell is the total number of PIRQ links the router supports. +- intel,pirq-reg : Specifies PIRQ routing register offset of all PIRQ links, + encoded as 2 cells a group for each link. The first cell is the PIRQ link + number (0 for PIRQA, 1 for PIRQB, etc). The second cell is the PIRQ routing + register offset from the interrupt router's base address. If this property + is omitted, it indicates a consecutive register offset from the first PIRQ + link, as specified by the first cell of intel,pirq-link. - intel,pirq-mask : Specifies the IRQ mask representing the 16 IRQs in the 8259 PIC. Bit N is 1 means IRQ N is available to be routed. - intel,pirq-routing : Specifies all PCI devices' IRQ routing information,

On 12 June 2018 at 02:26, Bin Meng bmeng.cn@gmail.com wrote:
Currently both pirq_reg_to_linkno() and pirq_linkno_to_reg() assume consecutive PIRQ routing control registers. But this is not always the case on some platforms. Introduce a new device tree property intel,pirq-regmap to describe how the PIRQ routing register offset is mapped to the link number and adjust the irq router driver to utilize the mapping.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- new patch to "support discrete PIRQ routing registers via device tree"
arch/x86/cpu/irq.c | 102 +++++++++++++++++++-- arch/x86/include/asm/irq.h | 32 ++----- doc/device-tree-bindings/misc/intel,irq-router.txt | 6 ++ 3 files changed, 107 insertions(+), 33 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

On Wed, Jun 13, 2018 at 9:29 AM, Simon Glass sjg@chromium.org wrote:
On 12 June 2018 at 02:26, Bin Meng bmeng.cn@gmail.com wrote:
Currently both pirq_reg_to_linkno() and pirq_linkno_to_reg() assume consecutive PIRQ routing control registers. But this is not always the case on some platforms. Introduce a new device tree property intel,pirq-regmap to describe how the PIRQ routing register offset is mapped to the link number and adjust the irq router driver to utilize the mapping.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- new patch to "support discrete PIRQ routing registers via device tree"
arch/x86/cpu/irq.c | 102 +++++++++++++++++++-- arch/x86/include/asm/irq.h | 32 ++----- doc/device-tree-bindings/misc/intel,irq-router.txt | 6 ++ 3 files changed, 107 insertions(+), 33 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org
applied to u-boot-x86, thanks!

Add Panther Point chipset interrupt pin/PIRQ information, and enable the generation of PIRQ routing table and MP table.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
---
Changes in v2: - add the PIRQ register mapping via "intel,pirq-regmap" property
arch/x86/dts/cougarcanyon2.dts | 46 +++++++++++++++++++++++++++++++++++++++++ configs/cougarcanyon2_defconfig | 2 ++ 2 files changed, 48 insertions(+)
diff --git a/arch/x86/dts/cougarcanyon2.dts b/arch/x86/dts/cougarcanyon2.dts index 946ba06..c1cda73 100644 --- a/arch/x86/dts/cougarcanyon2.dts +++ b/arch/x86/dts/cougarcanyon2.dts @@ -5,6 +5,8 @@
/dts-v1/;
+#include <dt-bindings/interrupt-router/intel-irq.h> + /include/ "skeleton.dtsi" /include/ "serial.dtsi" /include/ "keyboard.dtsi" @@ -99,6 +101,50 @@ #address-cells = <1>; #size-cells = <1>;
+ irq-router { + compatible = "intel,irq-router"; + intel,pirq-config = "pci"; + intel,actl-8bit; + intel,actl-addr = <0x44>; + intel,pirq-link = <0x60 8>; + intel,pirq-regmap = < + PIRQA 0 + PIRQB 1 + PIRQC 2 + PIRQD 3 + PIRQE 8 + PIRQF 9 + PIRQG 10 + PIRQH 11 + >; + intel,pirq-mask = <0xcee0>; + intel,pirq-routing = < + /* Panther Point PCI devices */ + PCI_BDF(0, 2, 0) INTA PIRQA + PCI_BDF(0, 20, 0) INTA PIRQA + PCI_BDF(0, 22, 0) INTA PIRQA + PCI_BDF(0, 22, 1) INTB PIRQB + PCI_BDF(0, 22, 2) INTC PIRQC + PCI_BDF(0, 22, 3) INTD PIRQD + PCI_BDF(0, 25, 0) INTA PIRQA + PCI_BDF(0, 26, 0) INTA PIRQA + PCI_BDF(0, 27, 0) INTB PIRQA + PCI_BDF(0, 28, 0) INTA PIRQA + PCI_BDF(0, 28, 1) INTB PIRQB + PCI_BDF(0, 28, 2) INTC PIRQC + PCI_BDF(0, 28, 3) INTD PIRQD + PCI_BDF(0, 28, 4) INTA PIRQA + PCI_BDF(0, 28, 5) INTB PIRQB + PCI_BDF(0, 28, 6) INTC PIRQC + PCI_BDF(0, 28, 7) INTD PIRQD + PCI_BDF(0, 29, 0) INTA PIRQA + PCI_BDF(0, 31, 2) INTB PIRQB + PCI_BDF(0, 31, 3) INTC PIRQC + PCI_BDF(0, 31, 5) INTB PIRQB + PCI_BDF(0, 31, 6) INTC PIRQC + >; + }; + spi0: spi { #address-cells = <1>; #size-cells = <0>; diff --git a/configs/cougarcanyon2_defconfig b/configs/cougarcanyon2_defconfig index 98d9aa0..eeee252 100644 --- a/configs/cougarcanyon2_defconfig +++ b/configs/cougarcanyon2_defconfig @@ -6,6 +6,8 @@ CONFIG_TARGET_COUGARCANYON2=y # CONFIG_HAVE_INTEL_ME is not set # CONFIG_ENABLE_MRC_CACHE is not set CONFIG_SMP=y +CONFIG_GENERATE_PIRQ_TABLE=y +CONFIG_GENERATE_MP_TABLE=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro" CONFIG_SYS_CONSOLE_INFO_QUIET=y

On 12 June 2018 at 02:26, Bin Meng bmeng.cn@gmail.com wrote:
Add Panther Point chipset interrupt pin/PIRQ information, and enable the generation of PIRQ routing table and MP table.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- add the PIRQ register mapping via "intel,pirq-regmap" property
arch/x86/dts/cougarcanyon2.dts | 46 +++++++++++++++++++++++++++++++++++++++++ configs/cougarcanyon2_defconfig | 2 ++ 2 files changed, 48 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

On Wed, Jun 13, 2018 at 9:29 AM, Simon Glass sjg@chromium.org wrote:
On 12 June 2018 at 02:26, Bin Meng bmeng.cn@gmail.com wrote:
Add Panther Point chipset interrupt pin/PIRQ information, and enable the generation of PIRQ routing table and MP table.
Signed-off-by: Bin Meng bmeng.cn@gmail.com
Changes in v2:
- add the PIRQ register mapping via "intel,pirq-regmap" property
arch/x86/dts/cougarcanyon2.dts | 46 +++++++++++++++++++++++++++++++++++++++++ configs/cougarcanyon2_defconfig | 2 ++ 2 files changed, 48 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org
applied to u-boot-x86, thanks!
participants (2)
-
Bin Meng
-
Simon Glass