Merge branch 'master' of git://git.denx.de/u-boot-nios
[kernel/u-boot.git] / common / cmd_pci.c
index 22e4b9a..d3e7c08 100644 (file)
@@ -6,23 +6,7 @@
  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  * Wolfgang Grandegger, DENX Software Engineering, wg@denx.de.
  *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 /*
  */
 
 #include <common.h>
-
-#ifdef CONFIG_PCI
-
 #include <command.h>
-#include <cmd_boot.h>
 #include <asm/processor.h>
 #include <asm/io.h>
-#include <cmd_pci.h>
 #include <pci.h>
 
-#if (CONFIG_COMMANDS & CFG_CMD_PCI)
-
-extern int cmd_get_data_size(char* arg, int default_size);
-
-unsigned char  ShortPCIListing = 1;
-
 /*
  * Follows routines for the output of infos about devices on PCI bus.
  */
@@ -57,7 +30,7 @@ void pci_header_show_brief(pci_dev_t dev);
  * Subroutine:  pciinfo
  *
  * Description: Show information about devices on PCI bus.
- *                             Depending on the define CFG_SHORT_PCI_LISTING
+ *                             Depending on the define CONFIG_SYS_SHORT_PCI_LISTING
  *                             the output will be more or less exhaustive.
  *
  * Inputs:     bus_no          the number of the bus to be scanned.
@@ -96,7 +69,7 @@ void pciinfo(int BusNum, int ShortPCIListing)
                        if ((VendorID == 0xFFFF) || (VendorID == 0x0000))
                                continue;
 
-                       pci_read_config_byte(dev, PCI_HEADER_TYPE, &HeaderType);
+                       if (!Function) pci_read_config_byte(dev, PCI_HEADER_TYPE, &HeaderType);
 
                        if (ShortPCIListing)
                        {
@@ -113,37 +86,12 @@ void pciinfo(int BusNum, int ShortPCIListing)
     }
 }
 
-char* pci_classes_str(u8 class)
-{
-       static char *pci_classes[] = {
-               "Build before PCI Rev2.0",
-               "Mass storage controller",
-               "Network controller     ",
-               "Display controller     ",
-               "Multimedia device      ",
-               "Memory controller      ",
-               "Bridge device          ",
-               "Simple comm. controller",
-               "Base system peripheral ",
-               "Input device           ",
-               "Docking station        ",
-               "Processor              ",
-               "Serial bus controller  ",
-               "Reserved entry         ",
-               "Does not fit any class "
-       };
-
-       if (class < (sizeof pci_classes / sizeof *pci_classes))
-               return pci_classes[(int) class];
-
-       return  "???                    ";
-}
 
 /*
  * Subroutine:  pci_header_show_brief
  *
  * Description: Reads and prints the header of the
- *             specified PCI device in short form.
+ *             specified PCI device in short form.
  *
  * Inputs:     dev      Bus+Device+Function number
  *
@@ -160,9 +108,9 @@ void pci_header_show_brief(pci_dev_t dev)
        pci_read_config_byte(dev, PCI_CLASS_CODE, &class);
        pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &subclass);
 
-       printf("0x%.4x     0x%.4x     %s 0x%.2x\n",
+       printf("0x%.4x     0x%.4x     %-23s 0x%.2x\n",
               vendor, device,
-              pci_classes_str(class), subclass);
+              pci_class_str(class), subclass);
 }
 
 /*
@@ -197,7 +145,7 @@ void pci_header_show(pci_dev_t dev)
        PRINT ("  status register =             0x%.4x\n", word, PCI_STATUS);
        PRINT ("  revision ID =                 0x%.2x\n", byte, PCI_REVISION_ID);
        PRINT2("  class code =                  0x%.2x (%s)\n", byte, PCI_CLASS_CODE,
-                                                               pci_classes_str);
+                                                               pci_class_str);
        PRINT ("  sub class code =              0x%.2x\n", byte, PCI_CLASS_SUB_CODE);
        PRINT ("  programming interface =       0x%.2x\n", byte, PCI_CLASS_PROG);
        PRINT ("  cache line =                  0x%.2x\n", byte, PCI_CACHE_LINE_SIZE);
@@ -205,9 +153,27 @@ void pci_header_show(pci_dev_t dev)
        PRINT ("  header type =                 0x%.2x\n", byte, PCI_HEADER_TYPE);
        PRINT ("  BIST =                        0x%.2x\n", byte, PCI_BIST);
        PRINT ("  base address 0 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_0);
-       PRINT ("  base address 1 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_1);
 
-       if (header_type & 0x01) {               /* PCI-to-PCI bridge */
+       switch (header_type & 0x03) {
+       case PCI_HEADER_TYPE_NORMAL:    /* "normal" PCI device */
+               PRINT ("  base address 1 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_1);
+               PRINT ("  base address 2 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_2);
+               PRINT ("  base address 3 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_3);
+               PRINT ("  base address 4 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_4);
+               PRINT ("  base address 5 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_5);
+               PRINT ("  cardBus CIS pointer =         0x%.8x\n", dword, PCI_CARDBUS_CIS);
+               PRINT ("  sub system vendor ID =        0x%.4x\n", word, PCI_SUBSYSTEM_VENDOR_ID);
+               PRINT ("  sub system ID =               0x%.4x\n", word, PCI_SUBSYSTEM_ID);
+               PRINT ("  expansion ROM base address =  0x%.8x\n", dword, PCI_ROM_ADDRESS);
+               PRINT ("  interrupt line =              0x%.2x\n", byte, PCI_INTERRUPT_LINE);
+               PRINT ("  interrupt pin =               0x%.2x\n", byte, PCI_INTERRUPT_PIN);
+               PRINT ("  min Grant =                   0x%.2x\n", byte, PCI_MIN_GNT);
+               PRINT ("  max Latency =                 0x%.2x\n", byte, PCI_MAX_LAT);
+               break;
+
+       case PCI_HEADER_TYPE_BRIDGE:    /* PCI-to-PCI bridge */
+
+               PRINT ("  base address 1 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_1);
                PRINT ("  primary bus number =          0x%.2x\n", byte, PCI_PRIMARY_BUS);
                PRINT ("  secondary bus number =        0x%.2x\n", byte, PCI_SECONDARY_BUS);
                PRINT ("  subordinate bus number =      0x%.2x\n", byte, PCI_SUBORDINATE_BUS);
@@ -227,19 +193,39 @@ void pci_header_show(pci_dev_t dev)
                PRINT ("  interrupt line =              0x%.2x\n", byte, PCI_INTERRUPT_LINE);
                PRINT ("  interrupt pin =               0x%.2x\n", byte, PCI_INTERRUPT_PIN);
                PRINT ("  bridge control =              0x%.4x\n", word, PCI_BRIDGE_CONTROL);
-    } else {                                   /* PCI device */
-               PRINT("  base address 2 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_2);
-               PRINT("  base address 3 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_3);
-               PRINT("  base address 4 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_4);
-               PRINT("  base address 5 =              0x%.8x\n", dword, PCI_BASE_ADDRESS_5);
-               PRINT("  cardBus CIS pointer =         0x%.8x\n", dword, PCI_CARDBUS_CIS);
-               PRINT("  sub system vendor ID =        0x%.4x\n", word, PCI_SUBSYSTEM_VENDOR_ID);
-               PRINT("  sub system ID =               0x%.4x\n", word, PCI_SUBSYSTEM_ID);
-               PRINT("  expansion ROM base address =  0x%.8x\n", dword, PCI_ROM_ADDRESS);
-               PRINT("  interrupt line =              0x%.2x\n", byte, PCI_INTERRUPT_LINE);
-               PRINT("  interrupt pin =               0x%.2x\n", byte, PCI_INTERRUPT_PIN);
-               PRINT("  min Grant =                   0x%.2x\n", byte, PCI_MIN_GNT);
-               PRINT("  max Latency =                 0x%.2x\n", byte, PCI_MAX_LAT);
+               break;
+
+       case PCI_HEADER_TYPE_CARDBUS:   /* PCI-to-CardBus bridge */
+
+               PRINT ("  capabilities =                0x%.2x\n", byte, PCI_CB_CAPABILITY_LIST);
+               PRINT ("  secondary status =            0x%.4x\n", word, PCI_CB_SEC_STATUS);
+               PRINT ("  primary bus number =          0x%.2x\n", byte, PCI_CB_PRIMARY_BUS);
+               PRINT ("  CardBus number =              0x%.2x\n", byte, PCI_CB_CARD_BUS);
+               PRINT ("  subordinate bus number =      0x%.2x\n", byte, PCI_CB_SUBORDINATE_BUS);
+               PRINT ("  CardBus latency timer =       0x%.2x\n", byte, PCI_CB_LATENCY_TIMER);
+               PRINT ("  CardBus memory base 0 =       0x%.8x\n", dword, PCI_CB_MEMORY_BASE_0);
+               PRINT ("  CardBus memory limit 0 =      0x%.8x\n", dword, PCI_CB_MEMORY_LIMIT_0);
+               PRINT ("  CardBus memory base 1 =       0x%.8x\n", dword, PCI_CB_MEMORY_BASE_1);
+               PRINT ("  CardBus memory limit 1 =      0x%.8x\n", dword, PCI_CB_MEMORY_LIMIT_1);
+               PRINT ("  CardBus IO base 0 =           0x%.4x\n", word, PCI_CB_IO_BASE_0);
+               PRINT ("  CardBus IO base high 0 =      0x%.4x\n", word, PCI_CB_IO_BASE_0_HI);
+               PRINT ("  CardBus IO limit 0 =          0x%.4x\n", word, PCI_CB_IO_LIMIT_0);
+               PRINT ("  CardBus IO limit high 0 =     0x%.4x\n", word, PCI_CB_IO_LIMIT_0_HI);
+               PRINT ("  CardBus IO base 1 =           0x%.4x\n", word, PCI_CB_IO_BASE_1);
+               PRINT ("  CardBus IO base high 1 =      0x%.4x\n", word, PCI_CB_IO_BASE_1_HI);
+               PRINT ("  CardBus IO limit 1 =          0x%.4x\n", word, PCI_CB_IO_LIMIT_1);
+               PRINT ("  CardBus IO limit high 1 =     0x%.4x\n", word, PCI_CB_IO_LIMIT_1_HI);
+               PRINT ("  interrupt line =              0x%.2x\n", byte, PCI_INTERRUPT_LINE);
+               PRINT ("  interrupt pin =               0x%.2x\n", byte, PCI_INTERRUPT_PIN);
+               PRINT ("  bridge control =              0x%.4x\n", word, PCI_CB_BRIDGE_CONTROL);
+               PRINT ("  subvendor ID =                0x%.4x\n", word, PCI_CB_SUBSYSTEM_VENDOR_ID);
+               PRINT ("  subdevice ID =                0x%.4x\n", word, PCI_CB_SUBSYSTEM_ID);
+               PRINT ("  PC Card 16bit base address =  0x%.8x\n", dword, PCI_CB_LEGACY_MODE_BASE);
+               break;
+
+       default:
+               printf("unknown header\n");
+               break;
     }
 
 #undef PRINT
@@ -337,7 +323,6 @@ pci_cfg_modify (pci_dev_t bdf, ulong addr, ulong size, ulong value, int incrflag
 {
        ulong   i;
        int     nbytes;
-       extern char console_buffer[];
        uint    val4;
        ushort  val2;
        u_char  val1;
@@ -405,7 +390,7 @@ pci_cfg_modify (pci_dev_t bdf, ulong addr, ulong size, ulong value, int incrflag
  *      pci modify[.b, .w, .l] bus.device.function [addr]
  *      pci write[.b, .w, .l] bus.device.function addr value
  */
-int do_pci (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+static int do_pci(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
        ulong addr = 0, value = 0, size = 0;
        pci_dev_t bdf = 0;
@@ -431,6 +416,10 @@ int do_pci (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                if ((bdf = get_pci_dev(argv[2])) == -1)
                        return 1;
                break;
+#ifdef CONFIG_CMD_PCI_ENUM
+       case 'e':
+               break;
+#endif
        default:                /* scan bus */
                value = 1; /* short listing */
                bdf = 0;   /* bus number  */
@@ -452,6 +441,11 @@ int do_pci (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
                return 0;
        case 'd':               /* display */
                return pci_cfg_display(bdf, addr, size, value);
+#ifdef CONFIG_CMD_PCI_ENUM
+       case 'e':
+               pci_init();
+               return 0;
+#endif
        case 'n':               /* next */
                if (argc < 4)
                        goto usage;
@@ -468,10 +462,32 @@ int do_pci (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
 
        return 1;
  usage:
-       printf ("Usage:\n%s\n", cmdtp->usage);
-       return 1;
+       return CMD_RET_USAGE;
 }
 
-#endif /* (CONFIG_COMMANDS & CFG_CMD_PCI) */
+/***************************************************/
+
+#ifdef CONFIG_SYS_LONGHELP
+static char pci_help_text[] =
+       "[bus] [long]\n"
+       "    - short or long list of PCI devices on bus 'bus'\n"
+#ifdef CONFIG_CMD_PCI_ENUM
+       "pci enum\n"
+       "    - re-enumerate PCI buses\n"
+#endif
+       "pci header b.d.f\n"
+       "    - show header of PCI device 'bus.device.function'\n"
+       "pci display[.b, .w, .l] b.d.f [address] [# of objects]\n"
+       "    - display PCI configuration space (CFG)\n"
+       "pci next[.b, .w, .l] b.d.f address\n"
+       "    - modify, read and keep CFG address\n"
+       "pci modify[.b, .w, .l] b.d.f address\n"
+       "    -  modify, auto increment CFG address\n"
+       "pci write[.b, .w, .l] b.d.f address value\n"
+       "    - write to CFG address";
+#endif
 
-#endif /* CONFIG_PCI */
+U_BOOT_CMD(
+       pci,    5,      1,      do_pci,
+       "list and access PCI Configuration Space", pci_help_text
+);