| The U-Boot Driver Model Project |
| =============================== |
| PCI subsystem analysis |
| ====================== |
| |
| Pavel Herrmann <morpheus.ibis@gmail.com> |
| 2012-03-17 |
| |
| I) Overview |
| ----------- |
| |
| U-Boot already supports multiple PCI busses, stored in a linked-list of |
| pci_controller structures. This structure contains generic driver data, bus |
| interface operations and private data for the driver. |
| |
| Bus interface operations for PCI are (names are self-explanatory): |
| |
| read_byte() |
| read_word() |
| read_dword() |
| write_byte() |
| write_word() |
| write_dword() |
| |
| Each driver has to implement dword operations, and either implement word and |
| byte operations, or use shared $operation_config_$type_via_dword (eg. |
| read_config_byte_via_dword and similar) function. These functions are used |
| for config space I/O (read_config_dword and similar functions of the PCI |
| subsystem), which is used to configure the connected devices for standard MMIO |
| operations. All data transfers by respective device drivers are then done by |
| MMIO |
| |
| Each driver also defines a separate init function, which has unique symbol |
| name, and thus more drivers can be compiled in without colliding. This init |
| function is typically called from pci_init_board(), different for each |
| particular board. |
| |
| Some boards also define a function called fixup_irq, which gets called after |
| scanning the PCI bus for devices, and should dismiss any interrupts. |
| |
| Several drivers are also located in arch/ and should be moved to drivers/pci. |
| |
| II) Approach |
| ------------ |
| |
| The pci_controller structure needs to be broken down to fit the new driver |
| model. Due to a large number of members, this will be done through three |
| distinct accessors, one for memory regions, one for config table and one for |
| everything else. That will make the pci_ops structure look like this: |
| |
| struct pci_ops { |
| int (*read_byte)(struct instance *bus, pci_dev_t *dev, int addr, |
| u8 *buf); |
| int (*read_word)(struct instance *bus, pci_dev_t *dev, int addr, |
| u16 *buf); |
| int (*read_dword)(struct instance *bus, pci_dev_t *dev, int addr, |
| u32 *buf); |
| int (*write_byte)(struct instance *bus, pci_dev_t *dev, int addr, |
| u8 val); |
| int (*write_byte)(struct instance *bus, pci_dev_t *dev, int addr, |
| u8 val); |
| int (*write_dword)(struct instance *bus, pci_dev_t *dev, int addr, |
| u32 val); |
| void (*fixup_irq)(struct instance *bus, pci_dev_t *dev); |
| struct pci_region* (*get_region)(struct instance *, uint num); |
| struct pci_config_table* (*get_cfg_table)(struct instance *bus); |
| uint (*get_option)(struct instance * bus, enum pci_option_code op); |
| } |
| |
| enum pci_option_code { |
| PCI_OPT_BUS_NUMBER=0, |
| PCI_OPT_REGION_COUNT, |
| PCI_OPT_INDIRECT_TYPE, |
| PCI_OPT_AUTO_MEM, |
| PCI_OPT_AUTO_IO, |
| PCI_OPT_AUTO_PREFETCH, |
| PCI_OPT_AUTO_FB, |
| PCI_OPT_CURRENT_BUS, |
| PCI_OPT_CFG_ADDR, |
| } |
| |
| The return value for get_option will be an unsigned integer value for any |
| option code. If the option currently is a pointer to pci_region, it will |
| return an index for get_region function. Special case has to be made for |
| PCI_OPT_CFG_ADDR, which should be interpreted as a pointer, but it is only |
| used for equality in find_hose_by_cfg_addr, and thus can be returned as an |
| uint. Other function using cfg_addr value are read/write functions for |
| specific drivers (especially ops for indirect bridges), and thus have access |
| to private_data of the driver instance. |
| |
| The config table accessor will return a pointer to a NULL-terminated array of |
| pci_config_table, which is supplied by the board in platform_data, or NULL if |
| the board didn't specify one. This table is used to override PnP |
| auto-initialization, or to specific initialization functions for non-PNP |
| devices. |
| |
| Transparent PCI-PCI bridges will get their own driver, and will forward all |
| operations to operations of their parent bus. This however makes it |
| impossible to use instances to identify devices, as not all devices will be |
| directly visible to the respective bus driver. |
| |
| Init functions of controller drivers will be moved to their respective |
| probe() functions, in accordance to the driver model. |
| |
| The PCI core will handle all mapping functions currently found in pci.c, as |
| well as proxy functions for read/write operations of the drivers. The PCI |
| core will also handle bus scanning and device configuration. |
| |
| The PnP helper functions currently in pci_auto.c will also be a part of PCI |
| core, but they will be exposed only to PCI controller drivers, not to other |
| device drivers. |
| |
| The PCI API for device drivers will remain largely unchanged, most drivers |
| will require no changes at all, and all modifications will be limited to |
| changing the pci_controlle into instance*. |
| |
| III) Analysis of in-tree drivers |
| -------------------------------- |
| |
| A) drivers in drivers/pci/ |
| -------------------------- |
| |
| pci_indirect.c |
| -------------- |
| Shared driver for indirect PCI bridges, several CONFIG macros - will |
| require significant cleanup. |
| |
| pci_ixp.c |
| --------- |
| Standard driver, specifies all read/write functions separately. |
| |
| pci_sh4.c |
| --------- |
| Shared init function for SH4 drivers, uses dword for read/write ops. |
| |
| pci_sh7751.c |
| ------------ |
| Standard driver, uses SH4 shared init. |
| |
| pci_sh7780.c |
| ------------ |
| Standard driver, uses SH4 shared init. |
| |
| tsi108_pci.c |
| ------------ |
| Standard driver, uses dword for read/write ops. |
| |
| fsl_pci_init.c |
| -------------- |
| Driver for PCI and PCI-e, uses indirect functions. |
| |
| pci_ftpci100.c |
| -------------- |
| Standard driver, uses indirect functions, has separate scan/setup |
| functions. |
| |
| B) driver in arch/ |
| ------------------ |
| |
| x86/lib/pci_type1.c |
| ------------------- |
| Standard driver, specifies all read/write functions separately. |
| |
| m68k/cpu/mcf5445x/pci.c |
| ----------------------- |
| Standard driver, specifies all read/write functions separately. |
| |
| m68k/cpu/mcf547x_8x/pci.c |
| ------------------------- |
| Standard driver, specifies all read/write functions separately. |
| |
| powerpc/cpu/mpc824x/pci.c |
| ------------------------- |
| Standard driver, uses indirect functions, does not setup HW. |
| |
| powerpc/cpu/mpc8260/pci.c |
| ------------------------- |
| Standard driver, uses indirect functions. |
| |
| powerpc/cpu/ppc4xx/4xx_pci.c |
| ---------------------------- |
| Standard driver, uses indirect functions. |
| |
| powerpc/cpu/ppc4xx/4xx_pcie.c |
| ----------------------------- |
| PCI-e driver, specifies all read/write functions separately. |
| |
| powerpc/cpu/mpc83xx/pci.c |
| ------------------------- |
| Standard driver, uses indirect functions. |
| |
| powerpc/cpu/mpc83xx/pcie.c |
| -------------------------- |
| PCI-e driver, specifies all read/write functions separately. |
| |
| powerpc/cpu/mpc5xxx/pci_mpc5200.c |
| --------------------------------- |
| Standard driver, uses dword for read/write ops. |
| |
| powerpc/cpu/mpc512x/pci.c |
| ------------------------- |
| Standard driver, uses indirect functions. |
| |
| powerpc/cpu/mpc85xx/pci.c |
| ------------------------- |
| Standard driver, uses indirect functions, has two busses. |
| |
| C) drivers in board/ |
| -------------------- |
| |
| eltec/elppc/pci.c |
| ----------------- |
| Standard driver, uses indirect functions. |
| |
| amirix/ap1000/pci.c |
| ------------------- |
| Standard driver, specifies all read/write functions separately. |
| |
| prodrive/p3mx/pci.c |
| ------------------- |
| Standard driver, uses dword for read/write ops, has two busses. |
| |
| esd/cpci750/pci.c |
| ----------------- |
| Standard driver, uses dword for read/write ops, has two busses. |
| |
| esd/common/pci.c |
| ---------------- |
| Standard driver, uses dword for read/write ops. |
| |
| dave/common/pci.c |
| ----------------- |
| Standard driver, uses dword for read/write ops. |
| |
| ppmc7xx/pci.c |
| ------------- |
| Standard driver, uses indirect functions. |
| |
| Marvell/db64360/pci.c |
| --------------------- |
| Standard driver, uses dword for read/write ops, has two busses. |
| |
| Marvell/db64460/pci.c |
| --------------------- |
| Standard driver, uses dword for read/write ops, has two busses. |
| |
| evb64260/pci.c |
| -------------- |
| Standard driver, uses dword for read/write ops, has two busses. |
| |
| armltd/integrator/pci.c |
| ----------------------- |
| Standard driver, specifies all read/write functions separately. |
| |
| All drivers will be moved to drivers/pci. Several drivers seem |
| similar/identical, especially those located under board, and may be merged |
| into one. |