1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").  
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  *
  26  * Copyright 2017 RackTop Systems.
  27  */
  28 /*
  29  * Silicon Image 3XXX controller specific processing
  30  *
  31  * This file may be expanded to take advantage of Silicon Image
  32  * additional features (if applicable to specific controller model):
  33  * 1. Virtual DMA operation
  34  * 2. Concurrent all-channel DMA
  35  * 3. Large Block Transfers
  36  * 4. Watchdog Timer
  37  * 5. Power Management
  38  * 6. Hot Plug Support
  39  */
  40 
  41 #include "ata_common.h"
  42 #include "sil3xxx.h"
  43 #include <sys/pci.h>
  44 
  45 int fifocntctl[] = {FIFO_CNTCTL_0, FIFO_CNTCTL_1, FIFO_CNTCTL_2, FIFO_CNTCTL_3};
  46 int sfiscfg[] = {SFISCFG_0, SFISCFG_1, SFISCFG_2, SFISCFG_3};
  47 
  48 /*
  49  * Controller specific initialization
  50  */
  51 uint_t
  52 sil3xxx_init_controller(dev_info_t *dip,
  53         /* LINTED */
  54         ushort_t vendor_id, ushort_t device_id)
  55 {
  56         ddi_acc_handle_t  pci_conf_handle; /* pci config space handle */
  57         uint8_t cache_lnsz, frrc = 0;
  58         uint32_t fifo_cnt_ctl;
  59         int ports, i;
  60 
  61 #ifdef  ATA_DEBUG
  62         ushort_t sfiscfg_val;
  63 #endif
  64 
  65         /*
  66          * Sil3114, Sil3512, Sil3112
  67          * We want to perform this initialization only once per entire
  68          * pciide controller (all channels)
  69          */
  70         if (ddi_prop_exists(DDI_DEV_T_ANY, ddi_get_parent(dip),
  71                 DDI_PROP_DONTPASS, "sil3xxx-initialized")) {
  72                 return (TRUE);
  73         }
  74 
  75         if (pci_config_setup(ddi_get_parent(dip), &pci_conf_handle) !=
  76             DDI_SUCCESS) {
  77                 cmn_err(CE_WARN,
  78                     "sil3xxx_init_controller: Can't do pci_config_setup\n");
  79                 return (FALSE);
  80         }
  81 
  82         /*
  83          * Sil3114/3512/3112 incorrectly change between MR and back to
  84          * MRM for same transaction, which violates the PCI spec and can
  85          * lead to incorrect data reads.  The workaround
  86          * is to set bits 2:0 in the FIFO count and control register so
  87          * that its value, a multiple of 32 bytes starting at 32, not 0,
  88          * is greater or equal to the cacheline size, a multiple of 4
  89          * bytes.  This will prevent any reads until the FIFO free space
  90          * is greater than a cacheline size, ensuring only MRM is issued.
  91          */
  92 
  93         cache_lnsz = pci_config_get8(pci_conf_handle, PCI_CONF_CACHE_LINESZ);
  94 
  95         /*
  96          * The cache line is specified in 32-bit words, so multiply by 4
  97          * to get bytes.  Then divide by 32 bytes, the granularity of the
  98          * FIFO control bits 2:0.  Add 1 if there is any remainder to
  99          * account for a partial 32-byte block, then subtract 1 since for
 100          * FIFO controls bits 2:0, 0 corresponds to 32, 1 corresponds to
 101          * 64, and so on.  The calculation is expanded for clarity.
 102          */
 103         if (cache_lnsz != 0) {
 104                 frrc = (cache_lnsz * 4 / 32) +
 105                         (((cache_lnsz * 4) % 32) ? 1 : 0) - 1;
 106         }
 107 
 108         if (device_id == SIL3114_DEVICE_ID) {
 109                 ports = 4;
 110         } else {
 111                 ports = 2;
 112         }
 113 
 114         /*
 115          * The following BAR5 registers are accessed via an indirect register
 116          * in the PCI configuration space rather than mapping BAR5.
 117          */
 118         for (i = 0; i < ports; i++) {
 119                 GET_BAR5_INDIRECT(pci_conf_handle, fifocntctl[i],
 120                     fifo_cnt_ctl);
 121                 fifo_cnt_ctl = (fifo_cnt_ctl & ~0x7) | (frrc & 0x7);
 122                 PUT_BAR5_INDIRECT(pci_conf_handle, fifocntctl[i],
 123                     fifo_cnt_ctl);
 124                 /*
 125                  * Correct default setting for FIS0cfg
 126                  */
 127 #ifdef  ATA_DEBUG
 128                 GET_BAR5_INDIRECT(pci_conf_handle, sfiscfg[i],
 129                         sfiscfg_val);
 130                 ADBG_WARN(("sil3xxx_init_controller: old val SFISCfg "
 131                         "ch%d: %x\n", i, sfiscfg_val));
 132 #endif
 133                 PUT_BAR5_INDIRECT(pci_conf_handle, sfiscfg[i],
 134                         SFISCFG_ERRATA);
 135 #ifdef  ATA_DEBUG
 136                 GET_BAR5_INDIRECT(pci_conf_handle, sfiscfg[i],
 137                         sfiscfg_val);
 138                 ADBG_WARN(("sil3xxx_init_controller: new val SFISCfg "
 139                         "ch%d: %x\n", i, sfiscfg_val));
 140 #endif
 141         }
 142 
 143         /* Now tear down the pci config setup */
 144         pci_config_teardown(&pci_conf_handle);
 145 
 146         /* Create property indicating that initialization was done */
 147         (void) ddi_prop_update_int(DDI_DEV_T_NONE, ddi_get_parent(dip),
 148                 "sil3xxx-initialized", 1);
 149 
 150         return (TRUE);
 151 }