[PATCH 5/6] MIPS: malta: add support for PCI driver model

Simon Glass sjg at chromium.org
Sun Jul 11 02:00:56 CEST 2021


() Hi Daniel,

On Tue, 6 Jul 2021 at 08:22, Daniel Schwierzeck
<daniel.schwierzeck at gmail.com> wrote:
>
> As almost all peripherals are connected via PCI dependent on the
> used core card, PCI setup is always required. Thus run pci_init()
> including PCI scanning and probing and core card specific setups
> in board_early_init_r().
>
> Also prepare support for dynamically managing the status of the
> different PCI DT nodes dependent on used core card via option
> CONFIG_OF_BOARD_FIXUP. Before this feature can be enabled,
> the call order of the fix_fdt() init hook in board_init_f
> needs to be changed. Otherwise rw_fdt_blob points to a read-only
> NOR flash address. Thus this options needs to stay disabled
> until the board_init_f problem could be solved. This breaks
> running the default U-Boot image on real HW using the FPGA core
> card but Qemu emulation still works. Currently Qemu is more
> important as MIPS CI tests depend on Malta and the deadline
> for PCI DM conversion will be enforced soon.
>
> Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck at gmail.com>
> ---
>
>  board/imgtec/malta/malta.c | 84 +++++++++++++++++++++++++++++++++++++-
>  1 file changed, 83 insertions(+), 1 deletion(-)
>
> diff --git a/board/imgtec/malta/malta.c b/board/imgtec/malta/malta.c
> index c04f727961..e78d5a7fbc 100644
> --- a/board/imgtec/malta/malta.c
> +++ b/board/imgtec/malta/malta.c
> @@ -4,7 +4,8 @@
>   * Copyright (C) 2013 Imagination Technologies
>   */
>
> -#include <common.h>
> +#include <config.h>
> +#include <fdt_support.h>
>  #include <ide.h>
>  #include <init.h>
>  #include <net.h>
> @@ -24,6 +25,9 @@
>
>  DECLARE_GLOBAL_DATA_PTR;
>
> +#define MALTA_GT_PATH   "/pci0 at 1be00000"
> +#define MALTA_MSC_PATH  "/pci0 at 1bd00000"
> +
>  enum core_card {
>         CORE_UNKNOWN,
>         CORE_LV,
> @@ -120,10 +124,12 @@ int checkboard(void)
>         return 0;
>  }
>
> +#if !IS_ENABLED(CONFIG_DM_ETH)
>  int board_eth_init(struct bd_info *bis)
>  {
>         return pci_eth_init(bis);
>  }
> +#endif
>
>  void _machine_restart(void)
>  {
> @@ -167,6 +173,81 @@ int misc_init_r(void)
>         return 0;
>  }
>
> +#if IS_ENABLED(CONFIG_OF_BOARD_FIXUP)
> +/*
> + * TODO: currently doesn't work because rw_fdt_blob points to a
> + * NOR flash address. This needs some changes in board_init_f.
> + */
> +int board_fix_fdt(void *rw_fdt_blob)
> +{
> +       int node = -1;
> +
> +       switch (malta_sys_con()) {
> +       case SYSCON_GT64120:
> +               node =  fdt_path_offset(rw_fdt_blob, MALTA_GT_PATH);
> +               break;
> +       default:
> +       case SYSCON_MSC01:
> +               node =  fdt_path_offset(rw_fdt_blob,
);
> +               break;
> +       }
> +
> +       return fdt_status_okay(rw_fdt_blob, node);
> +}
> +#endif
> +
> +#if IS_ENABLED(CONFIG_DM_PCI)
> +int board_early_init_r(void)
> +{
> +       struct udevice *dev;
> +       u32 val32;
> +       u8 val8;
> +       int ret;
> +
> +       pci_init();
> +
> +       ret = dm_pci_find_device(PCI_VENDOR_ID_INTEL,
> +                                PCI_DEVICE_ID_INTEL_82371AB_0, 0, &dev);

This feels a bit wonky to me. How about a sysinfo driver for your
board which does this init? Then you could just probe it.

As to finding PCI devices, your sysinfo driver could have a few
phandle properties to point to the two devices you need.

But if these are really SYSCON devices, why not use the SYSCON
devices, give them a unique ID (perhaps you already have with
SYSCON_MSC01) and then call syscon_get_regmap_by_driver_data() ?


> +       if (ret)
> +               panic("Failed to find PIIX4 PCI bridge\n");
> +
> +       /* setup PCI interrupt routing */
> +       dm_pci_write_config8(dev, PCI_CFG_PIIX4_PIRQRCA, 10);
> +       dm_pci_write_config8(dev, PCI_CFG_PIIX4_PIRQRCB, 10);
> +       dm_pci_write_config8(dev, PCI_CFG_PIIX4_PIRQRCC, 11);
> +       dm_pci_write_config8(dev, PCI_CFG_PIIX4_PIRQRCD, 11);

This feels like it should be in DT.

I don't know if this is at all similar to x86, but see
create_pirq_routing_table()  and intel,irq-router.txt for some ideas.

> +
> +       /* mux SERIRQ onto SERIRQ pin */
> +       dm_pci_read_config32(dev, PCI_CFG_PIIX4_GENCFG, &val32);
> +       val32 |= PCI_CFG_PIIX4_GENCFG_SERIRQ;
> +       dm_pci_write_config32(dev, PCI_CFG_PIIX4_GENCFG, val32);
> +

dm_pci_clrset_config32() can do these three in one line, similar below.


> +       /* enable SERIRQ - Linux currently depends upon this */
> +       dm_pci_read_config8(dev, PCI_CFG_PIIX4_SERIRQC, &val8);
> +       val8 |= PCI_CFG_PIIX4_SERIRQC_EN | PCI_CFG_PIIX4_SERIRQC_CONT;
> +       dm_pci_write_config8(dev, PCI_CFG_PIIX4_SERIRQC, val8);
> +
> +       ret = dm_pci_find_device(PCI_VENDOR_ID_INTEL,
> +                                PCI_DEVICE_ID_INTEL_82371AB, 0, &dev);
> +       if (ret)
> +               panic("Failed to find PIIX4 IDE controller\n");
> +
> +       /* enable bus master & IO access */
> +       val32 |= PCI_COMMAND_MASTER | PCI_COMMAND_IO;
> +       dm_pci_write_config32(dev, PCI_COMMAND, val32);
> +
> +       /* set latency */
> +       dm_pci_write_config8(dev, PCI_LATENCY_TIMER, 0x40);
> +
> +       /* enable IDE/ATA */
> +       dm_pci_write_config32(dev, PCI_CFG_PIIX4_IDETIM_PRI,
> +                             PCI_CFG_PIIX4_IDETIM_IDE);
> +       dm_pci_write_config32(dev, PCI_CFG_PIIX4_IDETIM_SEC,
> +                             PCI_CFG_PIIX4_IDETIM_IDE);
> +
> +       return 0;
> +}
> +#else
>  void pci_init_board(void)
>  {
>         pci_dev_t bdf;
> @@ -231,3 +312,4 @@ void pci_init_board(void)
>         pci_write_config_dword(bdf, PCI_CFG_PIIX4_IDETIM_SEC,
>                                PCI_CFG_PIIX4_IDETIM_IDE);
>  }
> +#endif
> --
> 2.32.0
>

Regards,
Simon
-------------- next part --------------
Intel Interrupt Router Device Binding
=====================================

The device tree node which describes the operation of the Intel Interrupt Router
device is as follows:

Required properties :
- reg : Specifies the interrupt router's PCI configuration space address as
    defined by the Open Firmware spec.
- compatible = "intel,irq-router"
- intel,pirq-config : Specifies the IRQ routing register programming mechanism.
    Valid values are:
      "pci": IRQ routing is controlled by PCI configuration registers
      "ibase": IRQ routing is in the memory-mapped IBASE register block
- intel,ibase-offset : IBASE register offset in the interrupt router's PCI
    configuration space, required only if intel,pirq-config = "ibase".
- intel,actl-8bit : If ACTL (ACPI control) register width is 8-bit, this must
    be specified. The 8-bit ACTL register is seen on ICH series chipset, like
    ICH9/Panther Point/etc. On Atom chipset it is a 32-bit register.
- intel,actl-addr : ACTL (ACPI control) register offset. ACTL can be either
    in the interrupt router's PCI configuration space, or IBASE.
- 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-regmap : 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,
   encoded as 3 cells a group for a device. The first cell is the device's PCI
   bus number, device number and function number encoding with PCI_BDF() macro.
   The second cell is the PCI interrupt pin used by this device. The last cell
   is which PIRQ line the PCI interrupt pin is routed to.


Example
-------

#include <dt-bindings/interrupt-router/intel-irq.h>

	irq-router at 1f,0 {
		reg = <0x0000f800 0 0 0 0>;
		compatible = "intel,irq-router";
		intel,pirq-config = "pci";
		intel,pirq-link = <0x60 8>;
		intel,pirq-mask = <0xdef8>;
		intel,pirq-routing = <
			PCI_BDF(0, 2, 0) INTA PIRQA
			PCI_BDF(0, 3, 0) INTA PIRQB
			PCI_BDF(0, 8, 0) INTA PIRQC
			PCI_BDF(0, 8, 1) INTB PIRQD
			PCI_BDF(1, 6, 0) INTA PIRQE
			PCI_BDF(1, 6, 1) INTB PIRQF
			PCI_BDF(1, 6, 2) INTC PIRQG
			PCI_BDF(1, 6, 3) INTD PIRQH
		>;
	};


More information about the U-Boot mailing list