LCOV - code coverage report
Current view: top level - core - pci-quirk.c (source / functions) Hit Total Coverage
Test: skiboot.info Lines: 8 60 13.3 %
Date: 2024-01-02 21:04:04 Functions: 1 5 20.0 %
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
       2                 :            : /*
       3                 :            :  * Deal with PCI device quirks
       4                 :            :  *
       5                 :            :  * Copyright 2017-2018 IBM Corp.
       6                 :            :  */
       7                 :            : 
       8                 :            : #define pr_fmt(fmt)  "PCI-QUIRK: " fmt
       9                 :            : 
      10                 :            : #include <skiboot.h>
      11                 :            : #include <pci.h>
      12                 :            : #include <pci-cfg.h>
      13                 :            : #include <pci-quirk.h>
      14                 :            : #include <platform.h>
      15                 :            : #include <ast.h>
      16                 :            : 
      17                 :          0 : static int64_t cfg_block_filter(void *dev __unused,
      18                 :            :                                 struct pci_cfg_reg_filter *pcrf __unused,
      19                 :            :                                 uint32_t offset __unused, uint32_t len,
      20                 :            :                                 uint32_t *data, bool write)
      21                 :            : {
      22                 :          0 :         if (write)
      23                 :          0 :                 return OPAL_SUCCESS;
      24                 :            : 
      25                 :          0 :         switch (len) {
      26                 :          0 :         case 4:
      27                 :          0 :                 *data = 0x0;
      28                 :          0 :                 return OPAL_SUCCESS;
      29                 :          0 :         case 2:
      30                 :          0 :                 *((uint16_t *)data) = 0x0;
      31                 :          0 :                 return OPAL_SUCCESS;
      32                 :          0 :         case 1:
      33                 :          0 :                 *((uint8_t *)data) = 0x0;
      34                 :          0 :                 return OPAL_SUCCESS;
      35                 :            :         }
      36                 :            : 
      37                 :          0 :         return OPAL_PARAMETER; /* should never happen */
      38                 :            : }
      39                 :            : 
      40                 :            : /* blocks config accesses to registers in the range: [start, end] */
      41                 :            : #define BLOCK_CFG_RANGE(pd, start, end) \
      42                 :            :         pci_add_cfg_reg_filter(pd, start, end - start + 1, \
      43                 :            :                 PCI_REG_FLAG_WRITE | PCI_REG_FLAG_READ, \
      44                 :            :                 cfg_block_filter);
      45                 :            : 
      46                 :          0 : static void quirk_microsemi_gen4_sw(struct phb *phb, struct pci_device *pd)
      47                 :            : {
      48                 :            :         uint8_t data;
      49                 :            :         bool frozen;
      50                 :            :         int offset;
      51                 :            :         int start;
      52                 :            : 
      53                 :          0 :         pci_check_clear_freeze(phb);
      54                 :            : 
      55                 :            :         /*
      56                 :            :          * Reading from 0xff should trigger a UR on the affected switches.
      57                 :            :          * If we don't get a freeze then we don't need the workaround
      58                 :            :          */
      59                 :          0 :         pci_cfg_read8(phb, pd->bdfn, 0xff, &data);
      60                 :          0 :         frozen = pci_check_clear_freeze(phb);
      61                 :          0 :         if (!frozen)
      62                 :          0 :                 return;
      63                 :            : 
      64                 :          0 :         for (start = -1, offset = 0; offset < 4096; offset++) {
      65                 :          0 :                 pci_cfg_read8(phb, pd->bdfn, offset, &data);
      66                 :          0 :                 frozen = pci_check_clear_freeze(phb);
      67                 :            : 
      68                 :          0 :                 if (start < 0 && frozen) { /* new UR range */
      69                 :          0 :                         start = offset;
      70                 :          0 :                 } else if (start >= 0 && !frozen) { /* end of range */
      71                 :          0 :                         BLOCK_CFG_RANGE(pd, start, offset - 1);
      72                 :          0 :                         PCINOTICE(phb, pd->bdfn, "Applied UR workaround to [%03x..%03x]\n", start, offset - 1);
      73                 :            : 
      74                 :          0 :                         start = -1;
      75                 :            :                 }
      76                 :            :         }
      77                 :            : 
      78                 :            :         /* range lasted until the end of config space */
      79                 :          0 :         if (start >= 0) {
      80                 :          0 :                 BLOCK_CFG_RANGE(pd, start, 0xfff);
      81                 :          0 :                 PCINOTICE(phb, pd->bdfn, "Applied UR workaround to [%03x..fff]\n", start);
      82                 :            :         }
      83                 :            : }
      84                 :            : 
      85                 :          0 : static void quirk_astbmc_vga(struct phb *phb __unused,
      86                 :            :                              struct pci_device *pd)
      87                 :            : {
      88                 :          0 :         struct dt_node *np = pd->dn;
      89                 :            :         uint32_t revision, mcr_configuration, mcr_scu_mpll, mcr_scu_strap;
      90                 :            : 
      91                 :          0 :         if (ast_sio_is_enabled()) {
      92                 :          0 :                 revision = ast_ahb_readl(SCU_REVISION_ID);
      93                 :          0 :                 mcr_configuration = ast_ahb_readl(MCR_CONFIGURATION);
      94                 :          0 :                 mcr_scu_mpll = ast_ahb_readl(MCR_SCU_MPLL);
      95                 :          0 :                 mcr_scu_strap = ast_ahb_readl(MCR_SCU_STRAP);
      96                 :            :         } else {
      97                 :            :                 /* Previously we would warn, now SIO disabled by design */
      98                 :          0 :                 prlog(PR_INFO, "Assumed platform default parameters for %s\n",
      99                 :            :                       __func__);
     100                 :          0 :                 revision = bmc_platform->hw->scu_revision_id;
     101                 :          0 :                 mcr_configuration = bmc_platform->hw->mcr_configuration;
     102                 :          0 :                 mcr_scu_mpll = bmc_platform->hw->mcr_scu_mpll;
     103                 :          0 :                 mcr_scu_strap = bmc_platform->hw->mcr_scu_strap;
     104                 :            :         }
     105                 :            : 
     106                 :          0 :         dt_add_property_cells(np, "aspeed,scu-revision-id", revision);
     107                 :          0 :         dt_add_property_cells(np, "aspeed,mcr-configuration", mcr_configuration);
     108                 :          0 :         dt_add_property_cells(np, "aspeed,mcr-scu-mpll", mcr_scu_mpll);
     109                 :          0 :         dt_add_property_cells(np, "aspeed,mcr-scu-strap", mcr_scu_strap);
     110                 :          0 : }
     111                 :            : 
     112                 :            : /* Quirks are: {fixup function, vendor ID, (device ID or PCI_ANY_ID)} */
     113                 :            : static const struct pci_quirk quirk_table[] = {
     114                 :            :         /* ASPEED 2400 VGA device */
     115                 :            :         { 0x1a03, 0x2000, &quirk_astbmc_vga },
     116                 :            :         { 0x11f8, 0x4052, &quirk_microsemi_gen4_sw },
     117                 :            :         { 0, 0, NULL }
     118                 :            : };
     119                 :            : 
     120                 :          4 : static void __pci_handle_quirk(struct phb *phb, struct pci_device *pd,
     121                 :            :                                const struct pci_quirk *quirks)
     122                 :            : {
     123                 :          8 :         while (quirks->vendor_id) {
     124                 :          4 :                 if (quirks->vendor_id == PCI_VENDOR_ID(pd->vdid) &&
     125                 :          2 :                     (quirks->device_id == PCI_ANY_ID ||
     126                 :          2 :                      quirks->device_id == PCI_DEVICE_ID(pd->vdid)))
     127                 :          1 :                         quirks->fixup(phb, pd);
     128                 :          4 :                 quirks++;
     129                 :            :         }
     130                 :          4 : }
     131                 :            : 
     132                 :          0 : void pci_handle_quirk(struct phb *phb, struct pci_device *pd)
     133                 :            : {
     134                 :          0 :         __pci_handle_quirk(phb, pd, quirk_table);
     135                 :          0 : }

Generated by: LCOV version 1.14