dm: pci: Move common PCI functions into their own file
authorSimon Glass <sjg@chromium.org>
Thu, 5 Mar 2015 19:25:24 +0000 (12:25 -0700)
committerSimon Glass <sjg@chromium.org>
Fri, 17 Apr 2015 01:27:42 +0000 (19:27 -0600)
Driver model will share many functions with the existing PCI implementation.
Move these into their own file to avoid duplication and confusion.

Signed-off-by: Simon Glass <sjg@chromium.org>
drivers/pci/Makefile
drivers/pci/pci.c
drivers/pci/pci_common.c [new file with mode: 0644]
include/pci.h

index 50b7be53cae82268bb561d1f8fcbba059d29831a..856a5f5b538fc1d39484e930a2097136f7ac011a 100644 (file)
@@ -6,7 +6,7 @@
 #
 
 obj-$(CONFIG_FSL_PCI_INIT) += fsl_pci_init.o
-obj-$(CONFIG_PCI) += pci.o pci_auto.o pci_rom.o
+obj-$(CONFIG_PCI) += pci.o  pci_common.o pci_auto.o pci_rom.o
 obj-$(CONFIG_PCI_INDIRECT_BRIDGE) += pci_indirect.o
 obj-$(CONFIG_PCI_GT64120) += pci_gt64120.o
 obj-$(CONFIG_PCI_MSC01) += pci_msc01.o
index e1296cab9ecc8ea93ed617f5c8417ba23761f7a1..3babd948056da4a25d58a8d593b0cc36761fcfc1 100644 (file)
@@ -101,25 +101,6 @@ PCI_READ_VIA_DWORD_OP(word, u16 *, 0x02)
 PCI_WRITE_VIA_DWORD_OP(byte, u8, 0x03, 0x000000ff)
 PCI_WRITE_VIA_DWORD_OP(word, u16, 0x02, 0x0000ffff)
 
-/* Get a virtual address associated with a BAR region */
-void *pci_map_bar(pci_dev_t pdev, int bar, int flags)
-{
-       pci_addr_t pci_bus_addr;
-       u32 bar_response;
-
-       /* read BAR address */
-       pci_read_config_dword(pdev, bar, &bar_response);
-       pci_bus_addr = (pci_addr_t)(bar_response & ~0xf);
-
-       /*
-        * Pass "0" as the length argument to pci_bus_to_virt.  The arg
-        * isn't actualy used on any platform because u-boot assumes a static
-        * linear mapping.  In the future, this could read the BAR size
-        * and pass that as the size if needed.
-        */
-       return pci_bus_to_virt(pdev, pci_bus_addr, flags, 0, MAP_NOCACHE);
-}
-
 /*
  *
  */
@@ -187,106 +168,22 @@ int pci_last_busno(void)
 pci_dev_t pci_find_devices(struct pci_device_id *ids, int index)
 {
        struct pci_controller * hose;
-       u16 vendor, device;
-       u8 header_type;
        pci_dev_t bdf;
-       int i, bus, found_multi = 0;
+       int bus;
 
        for (hose = pci_get_hose_head(); hose; hose = hose->next) {
 #ifdef CONFIG_SYS_SCSI_SCAN_BUS_REVERSE
-               for (bus = hose->last_busno; bus >= hose->first_busno; bus--)
+               for (bus = hose->last_busno; bus >= hose->first_busno; bus--) {
 #else
-               for (bus = hose->first_busno; bus <= hose->last_busno; bus++)
+               for (bus = hose->first_busno; bus <= hose->last_busno; bus++) {
 #endif
-                       for (bdf = PCI_BDF(bus, 0, 0);
-                            bdf < PCI_BDF(bus + 1, 0, 0);
-                            bdf += PCI_BDF(0, 0, 1)) {
-                               if (pci_skip_dev(hose, bdf))
-                                       continue;
-
-                               if (!PCI_FUNC(bdf)) {
-                                       pci_read_config_byte(bdf,
-                                                            PCI_HEADER_TYPE,
-                                                            &header_type);
-
-                                       found_multi = header_type & 0x80;
-                               } else {
-                                       if (!found_multi)
-                                               continue;
-                               }
-
-                               pci_read_config_word(bdf,
-                                                    PCI_VENDOR_ID,
-                                                    &vendor);
-                               pci_read_config_word(bdf,
-                                                    PCI_DEVICE_ID,
-                                                    &device);
-
-                               for (i = 0; ids[i].vendor != 0; i++) {
-                                       if (vendor == ids[i].vendor &&
-                                           device == ids[i].device) {
-                                               if (index <= 0)
-                                                       return bdf;
-
-                                               index--;
-                                       }
-                               }
-                       }
-       }
-
-       return -1;
-}
-
-pci_dev_t pci_find_class(uint find_class, int index)
-{
-       int bus;
-       int devnum;
-       pci_dev_t bdf;
-       uint32_t class;
-
-       for (bus = 0; bus <= pci_last_busno(); bus++) {
-               for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES - 1; devnum++) {
-                       pci_read_config_dword(PCI_BDF(bus, devnum, 0),
-                                             PCI_CLASS_REVISION, &class);
-                       if (class >> 16 == 0xffff)
-                               continue;
-
-                       for (bdf = PCI_BDF(bus, devnum, 0);
-                                       bdf <= PCI_BDF(bus, devnum,
-                                               PCI_MAX_PCI_FUNCTIONS - 1);
-                                       bdf += PCI_BDF(0, 0, 1)) {
-                               pci_read_config_dword(bdf, PCI_CLASS_REVISION,
-                                                     &class);
-                               class >>= 8;
-
-                               if (class != find_class)
-                                       continue;
-                               /*
-                                * Decrement the index. We want to return the
-                                * correct device, so index is 0 for the first
-                                * matching device, 1 for the second, etc.
-                                */
-                               if (index) {
-                                       index--;
-                                       continue;
-                               }
-                               /* Return index'th controller. */
+                       bdf = pci_hose_find_devices(hose, bus, ids, &index);
+                       if (bdf != -1)
                                return bdf;
-                       }
                }
        }
 
-       return -ENODEV;
-}
-
-pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
-{
-       struct pci_device_id ids[2] = { {}, {0, 0} };
-
-       ids[0].vendor = vendor;
-       ids[0].device = device;
-
-       return pci_find_devices(ids, index);
+       return -1;
 }
 
 /*
@@ -355,87 +252,6 @@ pci_addr_t pci_hose_phys_to_bus (struct pci_controller *hose,
        return bus_addr;
 }
 
-int __pci_hose_bus_to_phys(struct pci_controller *hose,
-                               pci_addr_t bus_addr,
-                               unsigned long flags,
-                               unsigned long skip_mask,
-                               phys_addr_t *pa)
-{
-       struct pci_region *res;
-       int i;
-
-       for (i = 0; i < hose->region_count; i++) {
-               res = &hose->regions[i];
-
-               if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
-                       continue;
-
-               if (res->flags & skip_mask)
-                       continue;
-
-               if (bus_addr >= res->bus_start &&
-                       (bus_addr - res->bus_start) < res->size) {
-                       *pa = (bus_addr - res->bus_start + res->phys_start);
-                       return 0;
-               }
-       }
-
-       return 1;
-}
-
-phys_addr_t pci_hose_bus_to_phys(struct pci_controller* hose,
-                                pci_addr_t bus_addr,
-                                unsigned long flags)
-{
-       phys_addr_t phys_addr = 0;
-       int ret;
-
-       if (!hose) {
-               puts("pci_hose_bus_to_phys: invalid hose\n");
-               return phys_addr;
-       }
-
-       /*
-        * if PCI_REGION_MEM is set we do a two pass search with preference
-        * on matches that don't have PCI_REGION_SYS_MEMORY set
-        */
-       if ((flags & PCI_REGION_MEM) == PCI_REGION_MEM) {
-               ret = __pci_hose_bus_to_phys(hose, bus_addr,
-                               flags, PCI_REGION_SYS_MEMORY, &phys_addr);
-               if (!ret)
-                       return phys_addr;
-       }
-
-       ret = __pci_hose_bus_to_phys(hose, bus_addr, flags, 0, &phys_addr);
-
-       if (ret)
-               puts("pci_hose_bus_to_phys: invalid physical address\n");
-
-       return phys_addr;
-}
-
-void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum,
-                    u32 addr_and_ctrl)
-{
-       int bar;
-
-       bar = PCI_BASE_ADDRESS_0 + barnum * 4;
-       pci_hose_write_config_dword(hose, dev, bar, addr_and_ctrl);
-}
-
-u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum)
-{
-       u32 addr;
-       int bar;
-
-       bar = PCI_BASE_ADDRESS_0 + barnum * 4;
-       pci_hose_read_config_dword(hose, dev, bar, &addr);
-       if (addr & PCI_BASE_ADDRESS_SPACE_IO)
-               return addr & PCI_BASE_ADDRESS_IO_MASK;
-       else
-               return addr & PCI_BASE_ADDRESS_MEM_MASK;
-}
-
 int pci_hose_config_device(struct pci_controller *hose,
                           pci_dev_t dev,
                           unsigned long io,
@@ -576,91 +392,6 @@ void pci_cfgfunc_do_nothing(struct pci_controller *hose,
  */
 extern int pciauto_config_device(struct pci_controller *hose, pci_dev_t dev);
 
-#if defined(CONFIG_CMD_PCI) || defined(CONFIG_PCI_SCAN_SHOW)
-const char * pci_class_str(u8 class)
-{
-       switch (class) {
-       case PCI_CLASS_NOT_DEFINED:
-               return "Build before PCI Rev2.0";
-               break;
-       case PCI_BASE_CLASS_STORAGE:
-               return "Mass storage controller";
-               break;
-       case PCI_BASE_CLASS_NETWORK:
-               return "Network controller";
-               break;
-       case PCI_BASE_CLASS_DISPLAY:
-               return "Display controller";
-               break;
-       case PCI_BASE_CLASS_MULTIMEDIA:
-               return "Multimedia device";
-               break;
-       case PCI_BASE_CLASS_MEMORY:
-               return "Memory controller";
-               break;
-       case PCI_BASE_CLASS_BRIDGE:
-               return "Bridge device";
-               break;
-       case PCI_BASE_CLASS_COMMUNICATION:
-               return "Simple comm. controller";
-               break;
-       case PCI_BASE_CLASS_SYSTEM:
-               return "Base system peripheral";
-               break;
-       case PCI_BASE_CLASS_INPUT:
-               return "Input device";
-               break;
-       case PCI_BASE_CLASS_DOCKING:
-               return "Docking station";
-               break;
-       case PCI_BASE_CLASS_PROCESSOR:
-               return "Processor";
-               break;
-       case PCI_BASE_CLASS_SERIAL:
-               return "Serial bus controller";
-               break;
-       case PCI_BASE_CLASS_INTELLIGENT:
-               return "Intelligent controller";
-               break;
-       case PCI_BASE_CLASS_SATELLITE:
-               return "Satellite controller";
-               break;
-       case PCI_BASE_CLASS_CRYPT:
-               return "Cryptographic device";
-               break;
-       case PCI_BASE_CLASS_SIGNAL_PROCESSING:
-               return "DSP";
-               break;
-       case PCI_CLASS_OTHERS:
-               return "Does not fit any class";
-               break;
-       default:
-       return  "???";
-               break;
-       };
-}
-#endif /* CONFIG_CMD_PCI || CONFIG_PCI_SCAN_SHOW */
-
-__weak int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
-{
-       /*
-        * Check if pci device should be skipped in configuration
-        */
-       if (dev == PCI_BDF(hose->first_busno, 0, 0)) {
-#if defined(CONFIG_PCI_CONFIG_HOST_BRIDGE) /* don't skip host bridge */
-               /*
-                * Only skip configuration if "pciconfighost" is not set
-                */
-               if (getenv("pciconfighost") == NULL)
-                       return 1;
-#else
-               return 1;
-#endif
-       }
-
-       return 0;
-}
-
 #ifdef CONFIG_PCI_SCAN_SHOW
 __weak int pci_print_dev(struct pci_controller *hose, pci_dev_t dev)
 {
diff --git a/drivers/pci/pci_common.c b/drivers/pci/pci_common.c
new file mode 100644 (file)
index 0000000..24c66bb
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2014 Google, Inc
+ *
+ * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Andreas Heppel <aheppel@sysgo.de>
+ *
+ * (C) Copyright 2002, 2003
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <pci.h>
+#include <asm/io.h>
+
+const char *pci_class_str(u8 class)
+{
+       switch (class) {
+       case PCI_CLASS_NOT_DEFINED:
+               return "Build before PCI Rev2.0";
+               break;
+       case PCI_BASE_CLASS_STORAGE:
+               return "Mass storage controller";
+               break;
+       case PCI_BASE_CLASS_NETWORK:
+               return "Network controller";
+               break;
+       case PCI_BASE_CLASS_DISPLAY:
+               return "Display controller";
+               break;
+       case PCI_BASE_CLASS_MULTIMEDIA:
+               return "Multimedia device";
+               break;
+       case PCI_BASE_CLASS_MEMORY:
+               return "Memory controller";
+               break;
+       case PCI_BASE_CLASS_BRIDGE:
+               return "Bridge device";
+               break;
+       case PCI_BASE_CLASS_COMMUNICATION:
+               return "Simple comm. controller";
+               break;
+       case PCI_BASE_CLASS_SYSTEM:
+               return "Base system peripheral";
+               break;
+       case PCI_BASE_CLASS_INPUT:
+               return "Input device";
+               break;
+       case PCI_BASE_CLASS_DOCKING:
+               return "Docking station";
+               break;
+       case PCI_BASE_CLASS_PROCESSOR:
+               return "Processor";
+               break;
+       case PCI_BASE_CLASS_SERIAL:
+               return "Serial bus controller";
+               break;
+       case PCI_BASE_CLASS_INTELLIGENT:
+               return "Intelligent controller";
+               break;
+       case PCI_BASE_CLASS_SATELLITE:
+               return "Satellite controller";
+               break;
+       case PCI_BASE_CLASS_CRYPT:
+               return "Cryptographic device";
+               break;
+       case PCI_BASE_CLASS_SIGNAL_PROCESSING:
+               return "DSP";
+               break;
+       case PCI_CLASS_OTHERS:
+               return "Does not fit any class";
+               break;
+       default:
+       return  "???";
+               break;
+       };
+}
+
+pci_dev_t pci_find_class(uint find_class, int index)
+{
+       int bus;
+       int devnum;
+       pci_dev_t bdf;
+       uint32_t class;
+
+       for (bus = 0; bus <= pci_last_busno(); bus++) {
+               for (devnum = 0; devnum < PCI_MAX_PCI_DEVICES - 1; devnum++) {
+                       pci_read_config_dword(PCI_BDF(bus, devnum, 0),
+                                             PCI_CLASS_REVISION, &class);
+                       if (class >> 16 == 0xffff)
+                               continue;
+
+                       for (bdf = PCI_BDF(bus, devnum, 0);
+                                       bdf <= PCI_BDF(bus, devnum,
+                                               PCI_MAX_PCI_FUNCTIONS - 1);
+                                       bdf += PCI_BDF(0, 0, 1)) {
+                               pci_read_config_dword(bdf, PCI_CLASS_REVISION,
+                                                     &class);
+                               class >>= 8;
+
+                               if (class != find_class)
+                                       continue;
+                               /*
+                                * Decrement the index. We want to return the
+                                * correct device, so index is 0 for the first
+                                * matching device, 1 for the second, etc.
+                                */
+                               if (index) {
+                                       index--;
+                                       continue;
+                               }
+                               /* Return index'th controller. */
+                               return bdf;
+                       }
+               }
+       }
+
+       return -ENODEV;
+}
+
+__weak int pci_skip_dev(struct pci_controller *hose, pci_dev_t dev)
+{
+       /*
+        * Check if pci device should be skipped in configuration
+        */
+       if (dev == PCI_BDF(hose->first_busno, 0, 0)) {
+#if defined(CONFIG_PCI_CONFIG_HOST_BRIDGE) /* don't skip host bridge */
+               /*
+                * Only skip configuration if "pciconfighost" is not set
+                */
+               if (getenv("pciconfighost") == NULL)
+                       return 1;
+#else
+               return 1;
+#endif
+       }
+
+       return 0;
+}
+
+/* Get a virtual address associated with a BAR region */
+void *pci_map_bar(pci_dev_t pdev, int bar, int flags)
+{
+       pci_addr_t pci_bus_addr;
+       u32 bar_response;
+
+       /* read BAR address */
+       pci_read_config_dword(pdev, bar, &bar_response);
+       pci_bus_addr = (pci_addr_t)(bar_response & ~0xf);
+
+       /*
+        * Pass "0" as the length argument to pci_bus_to_virt.  The arg
+        * isn't actualy used on any platform because u-boot assumes a static
+        * linear mapping.  In the future, this could read the BAR size
+        * and pass that as the size if needed.
+        */
+       return pci_bus_to_virt(pdev, pci_bus_addr, flags, 0, MAP_NOCACHE);
+}
+
+void pci_write_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum,
+                    u32 addr_and_ctrl)
+{
+       int bar;
+
+       bar = PCI_BASE_ADDRESS_0 + barnum * 4;
+       pci_hose_write_config_dword(hose, dev, bar, addr_and_ctrl);
+}
+
+u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum)
+{
+       u32 addr;
+       int bar;
+
+       bar = PCI_BASE_ADDRESS_0 + barnum * 4;
+       pci_hose_read_config_dword(hose, dev, bar, &addr);
+       if (addr & PCI_BASE_ADDRESS_SPACE_IO)
+               return addr & PCI_BASE_ADDRESS_IO_MASK;
+       else
+               return addr & PCI_BASE_ADDRESS_MEM_MASK;
+}
+
+int __pci_hose_bus_to_phys(struct pci_controller *hose,
+                               pci_addr_t bus_addr,
+                               unsigned long flags,
+                               unsigned long skip_mask,
+                               phys_addr_t *pa)
+{
+       struct pci_region *res;
+       int i;
+
+       for (i = 0; i < hose->region_count; i++) {
+               res = &hose->regions[i];
+
+               if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0)
+                       continue;
+
+               if (res->flags & skip_mask)
+                       continue;
+
+               if (bus_addr >= res->bus_start &&
+                   (bus_addr - res->bus_start) < res->size) {
+                       *pa = (bus_addr - res->bus_start + res->phys_start);
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+
+phys_addr_t pci_hose_bus_to_phys(struct pci_controller *hose,
+                                pci_addr_t bus_addr,
+                                unsigned long flags)
+{
+       phys_addr_t phys_addr = 0;
+       int ret;
+
+       if (!hose) {
+               puts("pci_hose_bus_to_phys: invalid hose\n");
+               return phys_addr;
+       }
+
+       /*
+        * if PCI_REGION_MEM is set we do a two pass search with preference
+        * on matches that don't have PCI_REGION_SYS_MEMORY set
+        */
+       if ((flags & PCI_REGION_MEM) == PCI_REGION_MEM) {
+               ret = __pci_hose_bus_to_phys(hose, bus_addr,
+                               flags, PCI_REGION_SYS_MEMORY, &phys_addr);
+               if (!ret)
+                       return phys_addr;
+       }
+
+       ret = __pci_hose_bus_to_phys(hose, bus_addr, flags, 0, &phys_addr);
+
+       if (ret)
+               puts("pci_hose_bus_to_phys: invalid physical address\n");
+
+       return phys_addr;
+}
+
+pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index)
+{
+       struct pci_device_id ids[2] = { {}, {0, 0} };
+
+       ids[0].vendor = vendor;
+       ids[0].device = device;
+
+       return pci_find_devices(ids, index);
+}
+
+pci_dev_t pci_hose_find_devices(struct pci_controller *hose, int busnum,
+                               struct pci_device_id *ids, int *indexp)
+{
+       int found_multi = 0;
+       u16 vendor, device;
+       u8 header_type;
+       pci_dev_t bdf;
+       int i;
+
+       for (bdf = PCI_BDF(busnum, 0, 0);
+            bdf < PCI_BDF(busnum + 1, 0, 0);
+            bdf += PCI_BDF(0, 0, 1)) {
+               if (pci_skip_dev(hose, bdf))
+                       continue;
+
+               if (!PCI_FUNC(bdf)) {
+                       pci_read_config_byte(bdf, PCI_HEADER_TYPE,
+                                            &header_type);
+                       found_multi = header_type & 0x80;
+               } else {
+                       if (!found_multi)
+                               continue;
+               }
+
+               pci_read_config_word(bdf, PCI_VENDOR_ID, &vendor);
+               pci_read_config_word(bdf, PCI_DEVICE_ID, &device);
+
+               for (i = 0; ids[i].vendor != 0; i++) {
+                       if (vendor == ids[i].vendor &&
+                           device == ids[i].device) {
+                               if ((*indexp) <= 0)
+                                       return bdf;
+
+                               (*indexp)--;
+                       }
+               }
+       }
+
+       return -1;
+}
index 004a048d2f872a946caf9875372353f6a47ef3eb..4e8826a03a8ccc9d6ac08246a26d77cdbd79eddc 100644 (file)
@@ -705,5 +705,19 @@ u32 pci_read_bar32(struct pci_controller *hose, pci_dev_t dev, int barnum);
  */
 int pciauto_setup_rom(struct pci_controller *hose, pci_dev_t dev);
 
+/**
+ * pci_hose_find_devices() - Find devices by vendor/device ID
+ *
+ * @hose:      PCI hose to search
+ * @busnum:    Bus number to search
+ * @ids:       PCI vendor/device IDs to look for, terminated by 0, 0 record
+ * @indexp:    Pointer to device index to find. To find the first matching
+ *             device, pass 0; to find the second, pass 1, etc. This
+ *             parameter is decremented for each non-matching device so
+ *             can be called repeatedly.
+ */
+pci_dev_t pci_hose_find_devices(struct pci_controller *hose, int busnum,
+                               struct pci_device_id *ids, int *indexp);
+
 #endif /* __ASSEMBLY__ */
 #endif /* _PCI_H */