root/arch/mips/sgi-ip27/ip27-hubio.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hub_pio_map
  2. hub_setup_prb
  3. hub_set_piomode
  4. hub_pio_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc.
   4  * Copyright (C) 2004 Christoph Hellwig.
   5  *
   6  * Support functions for the HUB ASIC - mostly PIO mapping related.
   7  */
   8 
   9 #include <linux/bitops.h>
  10 #include <linux/string.h>
  11 #include <linux/mmzone.h>
  12 #include <asm/sn/addrs.h>
  13 #include <asm/sn/arch.h>
  14 #include <asm/sn/hub.h>
  15 
  16 
  17 static int force_fire_and_forget = 1;
  18 
  19 /**
  20  * hub_pio_map  -  establish a HUB PIO mapping
  21  *
  22  * @hub:        hub to perform PIO mapping on
  23  * @widget:     widget ID to perform PIO mapping for
  24  * @xtalk_addr: xtalk_address that needs to be mapped
  25  * @size:       size of the PIO mapping
  26  *
  27  **/
  28 unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget,
  29                           unsigned long xtalk_addr, size_t size)
  30 {
  31         nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
  32         unsigned i;
  33 
  34         /* use small-window mapping if possible */
  35         if ((xtalk_addr % SWIN_SIZE) + size <= SWIN_SIZE)
  36                 return NODE_SWIN_BASE(nasid, widget) + (xtalk_addr % SWIN_SIZE);
  37 
  38         if ((xtalk_addr % BWIN_SIZE) + size > BWIN_SIZE) {
  39                 printk(KERN_WARNING "PIO mapping at hub %d widget %d addr 0x%lx"
  40                                 " too big (%ld)\n",
  41                                 nasid, widget, xtalk_addr, size);
  42                 return 0;
  43         }
  44 
  45         xtalk_addr &= ~(BWIN_SIZE-1);
  46         for (i = 0; i < HUB_NUM_BIG_WINDOW; i++) {
  47                 if (test_and_set_bit(i, hub_data(cnode)->h_bigwin_used))
  48                         continue;
  49 
  50                 /*
  51                  * The code below does a PIO write to setup an ITTE entry.
  52                  *
  53                  * We need to prevent other CPUs from seeing our updated
  54                  * memory shadow of the ITTE (in the piomap) until the ITTE
  55                  * entry is actually set up; otherwise, another CPU might
  56                  * attempt a PIO prematurely.
  57                  *
  58                  * Also, the only way we can know that an entry has been
  59                  * received  by the hub and can be used by future PIO reads/
  60                  * writes is by reading back the ITTE entry after writing it.
  61                  *
  62                  * For these two reasons, we PIO read back the ITTE entry
  63                  * after we write it.
  64                  */
  65                 IIO_ITTE_PUT(nasid, i, HUB_PIO_MAP_TO_MEM, widget, xtalk_addr);
  66                 __raw_readq(IIO_ITTE_GET(nasid, i));
  67 
  68                 return NODE_BWIN_BASE(nasid, widget) + (xtalk_addr % BWIN_SIZE);
  69         }
  70 
  71         printk(KERN_WARNING "unable to establish PIO mapping for at"
  72                         " hub %d widget %d addr 0x%lx\n",
  73                         nasid, widget, xtalk_addr);
  74         return 0;
  75 }
  76 
  77 
  78 /*
  79  * hub_setup_prb(nasid, prbnum, credits, conveyor)
  80  *
  81  *      Put a PRB into fire-and-forget mode if conveyor isn't set.  Otherwise,
  82  *      put it into conveyor belt mode with the specified number of credits.
  83  */
  84 static void hub_setup_prb(nasid_t nasid, int prbnum, int credits)
  85 {
  86         iprb_t prb;
  87         int prb_offset;
  88 
  89         /*
  90          * Get the current register value.
  91          */
  92         prb_offset = IIO_IOPRB(prbnum);
  93         prb.iprb_regval = REMOTE_HUB_L(nasid, prb_offset);
  94 
  95         /*
  96          * Clear out some fields.
  97          */
  98         prb.iprb_ovflow = 1;
  99         prb.iprb_bnakctr = 0;
 100         prb.iprb_anakctr = 0;
 101 
 102         /*
 103          * Enable or disable fire-and-forget mode.
 104          */
 105         prb.iprb_ff = force_fire_and_forget ? 1 : 0;
 106 
 107         /*
 108          * Set the appropriate number of PIO credits for the widget.
 109          */
 110         prb.iprb_xtalkctr = credits;
 111 
 112         /*
 113          * Store the new value to the register.
 114          */
 115         REMOTE_HUB_S(nasid, prb_offset, prb.iprb_regval);
 116 }
 117 
 118 /**
 119  * hub_set_piomode  -  set pio mode for a given hub
 120  *
 121  * @nasid:      physical node ID for the hub in question
 122  *
 123  * Put the hub into either "PIO conveyor belt" mode or "fire-and-forget" mode.
 124  * To do this, we have to make absolutely sure that no PIOs are in progress
 125  * so we turn off access to all widgets for the duration of the function.
 126  *
 127  * XXX - This code should really check what kind of widget we're talking
 128  * to.  Bridges can only handle three requests, but XG will do more.
 129  * How many can crossbow handle to widget 0?  We're assuming 1.
 130  *
 131  * XXX - There is a bug in the crossbow that link reset PIOs do not
 132  * return write responses.  The easiest solution to this problem is to
 133  * leave widget 0 (xbow) in fire-and-forget mode at all times.  This
 134  * only affects pio's to xbow registers, which should be rare.
 135  **/
 136 static void hub_set_piomode(nasid_t nasid)
 137 {
 138         u64 ii_iowa;
 139         hubii_wcr_t ii_wcr;
 140         unsigned i;
 141 
 142         ii_iowa = REMOTE_HUB_L(nasid, IIO_OUTWIDGET_ACCESS);
 143         REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, 0);
 144 
 145         ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid, IIO_WCR);
 146 
 147         if (ii_wcr.iwcr_dir_con) {
 148                 /*
 149                  * Assume a bridge here.
 150                  */
 151                 hub_setup_prb(nasid, 0, 3);
 152         } else {
 153                 /*
 154                  * Assume a crossbow here.
 155                  */
 156                 hub_setup_prb(nasid, 0, 1);
 157         }
 158 
 159         /*
 160          * XXX - Here's where we should take the widget type into
 161          * when account assigning credits.
 162          */
 163         for (i = HUB_WIDGET_ID_MIN; i <= HUB_WIDGET_ID_MAX; i++)
 164                 hub_setup_prb(nasid, i, 3);
 165 
 166         REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa);
 167 }
 168 
 169 /*
 170  * hub_pio_init  -  PIO-related hub initialization
 171  *
 172  * @hub:        hubinfo structure for our hub
 173  */
 174 void hub_pio_init(cnodeid_t cnode)
 175 {
 176         nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
 177         unsigned i;
 178 
 179         /* initialize big window piomaps for this hub */
 180         bitmap_zero(hub_data(cnode)->h_bigwin_used, HUB_NUM_BIG_WINDOW);
 181         for (i = 0; i < HUB_NUM_BIG_WINDOW; i++)
 182                 IIO_ITTE_DISABLE(nasid, i);
 183 
 184         hub_set_piomode(nasid);
 185 }

/* [<][>][^][v][top][bottom][index][help] */