Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:20

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /*  PCI (Static) Configuration Library
0004  *
0005  *  COPYRIGHT (c) 2010 Cobham Gaisler AB.
0006  *
0007  * Redistribution and use in source and binary forms, with or without
0008  * modification, are permitted provided that the following conditions
0009  * are met:
0010  * 1. Redistributions of source code must retain the above copyright
0011  *    notice, this list of conditions and the following disclaimer.
0012  * 2. Redistributions in binary form must reproduce the above copyright
0013  *    notice, this list of conditions and the following disclaimer in the
0014  *    documentation and/or other materials provided with the distribution.
0015  *
0016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0017  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0018  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0019  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0020  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0021  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0022  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0023  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0024  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0025  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0026  * POSSIBILITY OF SUCH DAMAGE.
0027  */
0028  
0029 /*
0030  * The Host Bridge bus must be declared by user. It contains the static
0031  * configuration used to setup the devices/functions.
0032  */
0033 
0034 /* Configure headers */
0035 #define PCI_CFG_STATIC_LIB
0036 
0037 #include <stdlib.h>
0038 #include <pci.h>
0039 #include <pci/access.h>
0040 #include <pci/cfg.h>
0041 
0042 #include "pci_internal.h"
0043 
0044 #define PCI_CFG_R8(dev, args...) pci_cfg_r8(dev, args)
0045 #define PCI_CFG_R16(dev, args...) pci_cfg_r16(dev, args)
0046 #define PCI_CFG_R32(dev, args...) pci_cfg_r32(dev, args)
0047 #define PCI_CFG_W8(dev, args...) pci_cfg_w8(dev, args)
0048 #define PCI_CFG_W16(dev, args...) pci_cfg_w16(dev, args)
0049 #define PCI_CFG_W32(dev, args...) pci_cfg_w32(dev, args)
0050 
0051 /* Enumrate one bus if device is a bridge, and all it's subordinate buses */
0052 static int pci_init_dev(struct pci_dev *dev, void *unused)
0053 {
0054     uint32_t tmp;
0055     uint16_t tmp16, cmd;
0056     struct pci_bus *bridge;
0057     int maxbars, i, romofs;
0058     pci_dev_t pcidev = dev->busdevfun;
0059     struct pci_res *res;
0060 
0061     /* Init Device */
0062 
0063     /* Set command to reset values, it disables bus
0064      * mastering and address responses.
0065      */
0066     PCI_CFG_W16(pcidev, PCIR_COMMAND, 0);
0067 
0068     /* Clear any already set status bits */
0069     PCI_CFG_W16(pcidev, PCIR_STATUS, 0xf900);
0070 
0071     /* Set latency timer to 64 */
0072     PCI_CFG_W8(pcidev, PCIR_LATTIMER, 64);
0073 
0074     /* Set System IRQ of PIN */
0075     PCI_CFG_W8(pcidev, PCIR_INTLINE, dev->sysirq);
0076 
0077     cmd = dev->command;
0078 
0079     if ((dev->flags & PCI_DEV_BRIDGE) == 0) {
0080         /* Disable Cardbus CIS Pointer */
0081         PCI_CFG_W32(pcidev, PCIR_CIS, 0);
0082 
0083         romofs = PCIR_BIOS;
0084         maxbars = 6;
0085     } else {
0086         /* Init Bridge */
0087 
0088         /* Configure bridge (no support for 64-bit) */
0089         PCI_CFG_W32(pcidev, PCIR_PMBASEH_1, 0);
0090         PCI_CFG_W32(pcidev, PCIR_PMLIMITH_1, 0);
0091 
0092         bridge = (struct pci_bus *)dev;
0093         tmp = (64 << 24) | (bridge->sord << 16) |
0094             (bridge->num << 8) | bridge->pri;
0095         PCI_CFG_W32(pcidev, PCIR_PRIBUS_1, tmp);
0096 
0097         /*** Setup I/O Bridge Window ***/
0098         res = &dev->resources[BRIDGE_RES_IO];
0099         if (res->size > 0) {
0100             tmp16 = ((res->end-1) & 0x0000f000) |
0101                 ((res->start & 0x0000f000) >> 8);
0102             tmp = ((res->end-1) & 0xffff0000) | (res->start >> 16);
0103             cmd |= PCIM_CMD_PORTEN;
0104         } else {
0105             tmp16 = 0x00ff;
0106             tmp = 0;
0107         }
0108         /* I/O Limit and Base */
0109         PCI_CFG_W16(pcidev, PCIR_IOBASEL_1, tmp16);
0110         PCI_CFG_W32(pcidev, PCIR_IOBASEH_1, tmp);
0111 
0112         /*** Setup MEMIO Bridge Window ***/
0113         res = &dev->resources[BRIDGE_RES_MEMIO];
0114         if (res->size > 0) {
0115             tmp = ((res->end-1) & 0xffff0000) |
0116                 (res->start >> 16);
0117             cmd |= PCIM_CMD_MEMEN;
0118         } else {
0119             tmp = 0x0000ffff;
0120         }
0121         /* MEMIO Limit and Base */
0122         PCI_CFG_W32(pcidev, PCIR_MEMBASE_1, tmp);
0123 
0124         /*** Setup MEM Bridge Window ***/
0125         res = &dev->resources[BRIDGE_RES_MEM];
0126         if (res->size > 0) {
0127             tmp = ((res->end-1) & 0xffff0000) |
0128                 (res->start >> 16);
0129             cmd |= PCIM_CMD_MEMEN;
0130         } else {
0131             tmp = 0x0000ffff;
0132         }
0133         /* MEM Limit and Base */
0134         PCI_CFG_W32(pcidev, PCIR_PMBASEL_1, tmp);
0135         /* 64-bit space not supported */
0136         PCI_CFG_W32(pcidev, PCIR_PMBASEH_1, 0);
0137         PCI_CFG_W32(pcidev, PCIR_PMLIMITH_1, 0);
0138 
0139         cmd |= PCIM_CMD_BUSMASTEREN;
0140         romofs = PCIR_BIOS_1;
0141         maxbars = 2;
0142     }
0143 
0144     /* Init BARs */
0145     for (i = 0; i < maxbars; i++) {
0146         res = &dev->resources[i];
0147         if (res->flags & PCI_RES_TYPE_MASK) {
0148             PCI_CFG_W32(pcidev, PCIR_BAR(0) + 4*i,
0149                                 res->start);
0150             if ((res->flags & PCI_RES_TYPE_MASK) == PCI_RES_IO)
0151                 cmd |= PCIM_CMD_PORTEN;
0152             else
0153                 cmd |= PCIM_CMD_MEMEN;
0154         }
0155     }
0156     res = &dev->resources[DEV_RES_ROM];
0157     if (res->flags & PCI_RES_TYPE_MASK) {
0158         PCI_CFG_W32(pcidev, romofs, res->start|PCIM_BIOS_ENABLE);
0159         cmd |= PCIM_CMD_MEMEN;
0160     }
0161     PCI_CFG_W16(pcidev, PCIR_COMMAND, cmd);
0162 
0163     return 0;
0164 }
0165 
0166 /* Assume that user has defined static setup array in pci_hb */
0167 int pci_config_static(void)
0168 {
0169     pci_bus_cnt = pci_hb.sord + 1;
0170     pci_system_type = PCI_SYSTEM_HOST;
0171 
0172     /* Init all PCI devices according to depth-first search algorithm */
0173     return pci_for_each_dev(pci_init_dev, NULL);
0174 }