Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Low-level PCI config space access for OLPC systems who lack the VSA
0004  * PCI virtualization software.
0005  *
0006  * Copyright © 2006  Advanced Micro Devices, Inc.
0007  *
0008  * The AMD Geode chipset (ie: GX2 processor, cs5536 I/O companion device)
0009  * has some I/O functions (display, southbridge, sound, USB HCIs, etc)
0010  * that more or less behave like PCI devices, but the hardware doesn't
0011  * directly implement the PCI configuration space headers.  AMD provides
0012  * "VSA" (Virtual System Architecture) software that emulates PCI config
0013  * space for these devices, by trapping I/O accesses to PCI config register
0014  * (CF8/CFC) and running some code in System Management Mode interrupt state.
0015  * On the OLPC platform, we don't want to use that VSA code because
0016  * (a) it slows down suspend/resume, and (b) recompiling it requires special
0017  * compilers that are hard to get.  So instead of letting the complex VSA
0018  * code simulate the PCI config registers for the on-chip devices, we
0019  * just simulate them the easy way, by inserting the code into the
0020  * pci_write_config and pci_read_config path.  Most of the config registers
0021  * are read-only anyway, so the bulk of the simulation is just table lookup.
0022  */
0023 
0024 #include <linux/pci.h>
0025 #include <linux/init.h>
0026 #include <asm/olpc.h>
0027 #include <asm/geode.h>
0028 #include <asm/pci_x86.h>
0029 
0030 /*
0031  * In the tables below, the first two line (8 longwords) are the
0032  * size masks that are used when the higher level PCI code determines
0033  * the size of the region by writing ~0 to a base address register
0034  * and reading back the result.
0035  *
0036  * The following lines are the values that are read during normal
0037  * PCI config access cycles, i.e. not after just having written
0038  * ~0 to a base address register.
0039  */
0040 
0041 static const uint32_t lxnb_hdr[] = {  /* dev 1 function 0 - devfn = 8 */
0042     0x0,    0x0,    0x0,    0x0,
0043     0x0,    0x0,    0x0,    0x0,
0044 
0045     0x281022, 0x2200005, 0x6000021, 0x80f808,   /* AMD Vendor ID */
0046     0x0,    0x0,    0x0,    0x0,   /* No virtual registers, hence no BAR */
0047     0x0,    0x0,    0x0,    0x28100b,
0048     0x0,    0x0,    0x0,    0x0,
0049     0x0,    0x0,    0x0,    0x0,
0050     0x0,    0x0,    0x0,    0x0,
0051     0x0,    0x0,    0x0,    0x0,
0052 };
0053 
0054 static const uint32_t gxnb_hdr[] = {  /* dev 1 function 0 - devfn = 8 */
0055     0xfffffffd, 0x0, 0x0,   0x0,
0056     0x0,    0x0,    0x0,    0x0,
0057 
0058     0x28100b, 0x2200005, 0x6000021, 0x80f808,   /* NSC Vendor ID */
0059     0xac1d, 0x0,    0x0,    0x0,  /* I/O BAR - base of virtual registers */
0060     0x0,    0x0,    0x0,    0x28100b,
0061     0x0,    0x0,    0x0,    0x0,
0062     0x0,    0x0,    0x0,    0x0,
0063     0x0,    0x0,    0x0,    0x0,
0064     0x0,    0x0,    0x0,    0x0,
0065 };
0066 
0067 static const uint32_t lxfb_hdr[] = {  /* dev 1 function 1 - devfn = 9 */
0068     0xff000008, 0xffffc000, 0xffffc000, 0xffffc000,
0069     0xffffc000, 0x0,    0x0,    0x0,
0070 
0071     0x20811022, 0x2200003, 0x3000000, 0x0,      /* AMD Vendor ID */
0072     0xfd000000, 0xfe000000, 0xfe004000, 0xfe008000, /* FB, GP, VG, DF */
0073     0xfe00c000, 0x0, 0x0,   0x30100b,       /* VIP */
0074     0x0,    0x0,    0x0,    0x10e,     /* INTA, IRQ14 for graphics accel */
0075     0x0,    0x0,    0x0,    0x0,
0076     0x3d0,  0x3c0,  0xa0000, 0x0,       /* VG IO, VG IO, EGA FB, MONO FB */
0077     0x0,    0x0,    0x0,    0x0,
0078 };
0079 
0080 static const uint32_t gxfb_hdr[] = {  /* dev 1 function 1 - devfn = 9 */
0081     0xff800008, 0xffffc000, 0xffffc000, 0xffffc000,
0082     0x0,    0x0,    0x0,    0x0,
0083 
0084     0x30100b, 0x2200003, 0x3000000, 0x0,        /* NSC Vendor ID */
0085     0xfd000000, 0xfe000000, 0xfe004000, 0xfe008000, /* FB, GP, VG, DF */
0086     0x0,    0x0,    0x0,    0x30100b,
0087     0x0,    0x0,    0x0,    0x0,
0088     0x0,    0x0,    0x0,    0x0,
0089     0x3d0,  0x3c0,  0xa0000, 0x0,       /* VG IO, VG IO, EGA FB, MONO FB */
0090     0x0,    0x0,    0x0,    0x0,
0091 };
0092 
0093 static const uint32_t aes_hdr[] = { /* dev 1 function 2 - devfn = 0xa */
0094     0xffffc000, 0x0, 0x0,   0x0,
0095     0x0,    0x0,    0x0,    0x0,
0096 
0097     0x20821022, 0x2a00006, 0x10100000, 0x8,     /* NSC Vendor ID */
0098     0xfe010000, 0x0, 0x0,   0x0,            /* AES registers */
0099     0x0,    0x0,    0x0,    0x20821022,
0100     0x0,    0x0,    0x0,    0x0,
0101     0x0,    0x0,    0x0,    0x0,
0102     0x0,    0x0,    0x0,    0x0,
0103     0x0,    0x0,    0x0,    0x0,
0104 };
0105 
0106 
0107 static const uint32_t isa_hdr[] = {  /* dev f function 0 - devfn = 78 */
0108     0xfffffff9, 0xffffff01, 0xffffffc1, 0xffffffe1,
0109     0xffffff81, 0xffffffc1, 0x0, 0x0,
0110 
0111     0x20901022, 0x2a00049, 0x6010003, 0x802000,
0112     0x18b1, 0x1001, 0x1801, 0x1881, /* SMB-8   GPIO-256 MFGPT-64  IRQ-32 */
0113     0x1401, 0x1841, 0x0,    0x20901022,     /* PMS-128 ACPI-64 */
0114     0x0,    0x0,    0x0,    0x0,
0115     0x0,    0x0,    0x0,    0x0,
0116     0x0,    0x0,    0x0,    0xaa5b,         /* IRQ steering */
0117     0x0,    0x0,    0x0,    0x0,
0118 };
0119 
0120 static const uint32_t ac97_hdr[] = {  /* dev f function 3 - devfn = 7b */
0121     0xffffff81, 0x0, 0x0,   0x0,
0122     0x0,    0x0,    0x0,    0x0,
0123 
0124     0x20931022, 0x2a00041, 0x4010001, 0x0,
0125     0x1481, 0x0,    0x0,    0x0,            /* I/O BAR-128 */
0126     0x0,    0x0,    0x0,    0x20931022,
0127     0x0,    0x0,    0x0,    0x205,          /* IntB, IRQ5 */
0128     0x0,    0x0,    0x0,    0x0,
0129     0x0,    0x0,    0x0,    0x0,
0130     0x0,    0x0,    0x0,    0x0,
0131 };
0132 
0133 static const uint32_t ohci_hdr[] = {  /* dev f function 4 - devfn = 7c */
0134     0xfffff000, 0x0, 0x0,   0x0,
0135     0x0,    0x0,    0x0,    0x0,
0136 
0137     0x20941022, 0x2300006, 0xc031002, 0x0,
0138     0xfe01a000, 0x0, 0x0,   0x0,            /* MEMBAR-1000 */
0139     0x0,    0x0,    0x0,    0x20941022,
0140     0x0,    0x40,   0x0,    0x40a,          /* CapPtr INT-D, IRQA */
0141     0xc8020001, 0x0, 0x0,   0x0,    /* Capabilities - 40 is R/O,
0142                        44 is mask 8103 (power control) */
0143     0x0,    0x0,    0x0,    0x0,
0144     0x0,    0x0,    0x0,    0x0,
0145 };
0146 
0147 static const uint32_t ehci_hdr[] = {  /* dev f function 4 - devfn = 7d */
0148     0xfffff000, 0x0, 0x0,   0x0,
0149     0x0,    0x0,    0x0,    0x0,
0150 
0151     0x20951022, 0x2300006, 0xc032002, 0x0,
0152     0xfe01b000, 0x0, 0x0,   0x0,            /* MEMBAR-1000 */
0153     0x0,    0x0,    0x0,    0x20951022,
0154     0x0,    0x40,   0x0,    0x40a,          /* CapPtr INT-D, IRQA */
0155     0xc8020001, 0x0, 0x0,   0x0,    /* Capabilities - 40 is R/O, 44 is
0156                        mask 8103 (power control) */
0157 #if 0
0158     0x1,    0x40080000, 0x0, 0x0,   /* EECP - see EHCI spec section 2.1.7 */
0159 #endif
0160     0x01000001, 0x0, 0x0,   0x0,    /* EECP - see EHCI spec section 2.1.7 */
0161     0x2020, 0x0,    0x0,    0x0,    /* (EHCI page 8) 60 SBRN (R/O),
0162                        61 FLADJ (R/W), PORTWAKECAP  */
0163 };
0164 
0165 static uint32_t ff_loc = ~0;
0166 static uint32_t zero_loc;
0167 static int bar_probing;     /* Set after a write of ~0 to a BAR */
0168 static int is_lx;
0169 
0170 #define NB_SLOT 0x1 /* Northbridge - GX chip - Device 1 */
0171 #define SB_SLOT 0xf /* Southbridge - CS5536 chip - Device F */
0172 
0173 static int is_simulated(unsigned int bus, unsigned int devfn)
0174 {
0175     return (!bus && ((PCI_SLOT(devfn) == NB_SLOT) ||
0176             (PCI_SLOT(devfn) == SB_SLOT)));
0177 }
0178 
0179 static uint32_t *hdr_addr(const uint32_t *hdr, int reg)
0180 {
0181     uint32_t addr;
0182 
0183     /*
0184      * This is a little bit tricky.  The header maps consist of
0185      * 0x20 bytes of size masks, followed by 0x70 bytes of header data.
0186      * In the normal case, when not probing a BAR's size, we want
0187      * to access the header data, so we add 0x20 to the reg offset,
0188      * thus skipping the size mask area.
0189      * In the BAR probing case, we want to access the size mask for
0190      * the BAR, so we subtract 0x10 (the config header offset for
0191      * BAR0), and don't skip the size mask area.
0192      */
0193 
0194     addr = (uint32_t)hdr + reg + (bar_probing ? -0x10 : 0x20);
0195 
0196     bar_probing = 0;
0197     return (uint32_t *)addr;
0198 }
0199 
0200 static int pci_olpc_read(unsigned int seg, unsigned int bus,
0201         unsigned int devfn, int reg, int len, uint32_t *value)
0202 {
0203     uint32_t *addr;
0204 
0205     WARN_ON(seg);
0206 
0207     /* Use the hardware mechanism for non-simulated devices */
0208     if (!is_simulated(bus, devfn))
0209         return pci_direct_conf1.read(seg, bus, devfn, reg, len, value);
0210 
0211     /*
0212      * No device has config registers past 0x70, so we save table space
0213      * by not storing entries for the nonexistent registers
0214      */
0215     if (reg >= 0x70)
0216         addr = &zero_loc;
0217     else {
0218         switch (devfn) {
0219         case  0x8:
0220             addr = hdr_addr(is_lx ? lxnb_hdr : gxnb_hdr, reg);
0221             break;
0222         case  0x9:
0223             addr = hdr_addr(is_lx ? lxfb_hdr : gxfb_hdr, reg);
0224             break;
0225         case  0xa:
0226             addr = is_lx ? hdr_addr(aes_hdr, reg) : &ff_loc;
0227             break;
0228         case 0x78:
0229             addr = hdr_addr(isa_hdr, reg);
0230             break;
0231         case 0x7b:
0232             addr = hdr_addr(ac97_hdr, reg);
0233             break;
0234         case 0x7c:
0235             addr = hdr_addr(ohci_hdr, reg);
0236             break;
0237         case 0x7d:
0238             addr = hdr_addr(ehci_hdr, reg);
0239             break;
0240         default:
0241             addr = &ff_loc;
0242             break;
0243         }
0244     }
0245     switch (len) {
0246     case 1:
0247         *value = *(uint8_t *)addr;
0248         break;
0249     case 2:
0250         *value = *(uint16_t *)addr;
0251         break;
0252     case 4:
0253         *value = *addr;
0254         break;
0255     default:
0256         BUG();
0257     }
0258 
0259     return 0;
0260 }
0261 
0262 static int pci_olpc_write(unsigned int seg, unsigned int bus,
0263         unsigned int devfn, int reg, int len, uint32_t value)
0264 {
0265     WARN_ON(seg);
0266 
0267     /* Use the hardware mechanism for non-simulated devices */
0268     if (!is_simulated(bus, devfn))
0269         return pci_direct_conf1.write(seg, bus, devfn, reg, len, value);
0270 
0271     /* XXX we may want to extend this to simulate EHCI power management */
0272 
0273     /*
0274      * Mostly we just discard writes, but if the write is a size probe
0275      * (i.e. writing ~0 to a BAR), we remember it and arrange to return
0276      * the appropriate size mask on the next read.  This is cheating
0277      * to some extent, because it depends on the fact that the next
0278      * access after such a write will always be a read to the same BAR.
0279      */
0280 
0281     if ((reg >= 0x10) && (reg < 0x2c)) {
0282         /* write is to a BAR */
0283         if (value == ~0)
0284             bar_probing = 1;
0285     } else {
0286         /*
0287          * No warning on writes to ROM BAR, CMD, LATENCY_TIMER,
0288          * CACHE_LINE_SIZE, or PM registers.
0289          */
0290         if ((reg != PCI_ROM_ADDRESS) && (reg != PCI_COMMAND_MASTER) &&
0291                 (reg != PCI_LATENCY_TIMER) &&
0292                 (reg != PCI_CACHE_LINE_SIZE) && (reg != 0x44))
0293             printk(KERN_WARNING "OLPC PCI: Config write to devfn"
0294                 " %x reg %x value %x\n", devfn, reg, value);
0295     }
0296 
0297     return 0;
0298 }
0299 
0300 static const struct pci_raw_ops pci_olpc_conf = {
0301     .read = pci_olpc_read,
0302     .write = pci_olpc_write,
0303 };
0304 
0305 int __init pci_olpc_init(void)
0306 {
0307     printk(KERN_INFO "PCI: Using configuration type OLPC XO-1\n");
0308     raw_pci_ops = &pci_olpc_conf;
0309     is_lx = is_geode_lx();
0310     return 0;
0311 }