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

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

DEFINITIONS

This source file includes following definitions.
  1. bridge_platform_create
  2. probe_one_port
  3. xbow_probe
  4. xtalk_probe_node
  5. xtalk_init

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
   4  * Copyright (C) 1999, 2000 Silcon Graphics, Inc.
   5  * Copyright (C) 2004 Christoph Hellwig.
   6  *
   7  * Generic XTALK initialization code
   8  */
   9 
  10 #include <linux/kernel.h>
  11 #include <linux/smp.h>
  12 #include <linux/platform_device.h>
  13 #include <linux/platform_data/xtalk-bridge.h>
  14 #include <asm/sn/addrs.h>
  15 #include <asm/sn/types.h>
  16 #include <asm/sn/klconfig.h>
  17 #include <asm/sn/hub.h>
  18 #include <asm/pci/bridge.h>
  19 #include <asm/xtalk/xtalk.h>
  20 
  21 
  22 #define XBOW_WIDGET_PART_NUM    0x0
  23 #define XXBOW_WIDGET_PART_NUM   0xd000  /* Xbow in Xbridge */
  24 #define BASE_XBOW_PORT          8     /* Lowest external port */
  25 
  26 static void bridge_platform_create(nasid_t nasid, int widget, int masterwid)
  27 {
  28         struct xtalk_bridge_platform_data *bd;
  29         struct platform_device *pdev;
  30         unsigned long offset;
  31 
  32         bd = kzalloc(sizeof(*bd), GFP_KERNEL);
  33         if (!bd)
  34                 goto no_mem;
  35         pdev = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO);
  36         if (!pdev) {
  37                 kfree(bd);
  38                 goto no_mem;
  39         }
  40 
  41         offset = NODE_OFFSET(nasid);
  42 
  43         bd->bridge_addr = RAW_NODE_SWIN_BASE(nasid, widget);
  44         bd->intr_addr   = BIT_ULL(47) + 0x01800000 + PI_INT_PEND_MOD;
  45         bd->nasid       = nasid;
  46         bd->masterwid   = masterwid;
  47 
  48         bd->mem.name    = "Bridge PCI MEM";
  49         bd->mem.start   = offset + (widget << SWIN_SIZE_BITS);
  50         bd->mem.end     = bd->mem.start + SWIN_SIZE - 1;
  51         bd->mem.flags   = IORESOURCE_MEM;
  52         bd->mem_offset  = offset;
  53 
  54         bd->io.name     = "Bridge PCI IO";
  55         bd->io.start    = offset + (widget << SWIN_SIZE_BITS);
  56         bd->io.end      = bd->io.start + SWIN_SIZE - 1;
  57         bd->io.flags    = IORESOURCE_IO;
  58         bd->io_offset   = offset;
  59 
  60         platform_device_add_data(pdev, bd, sizeof(*bd));
  61         platform_device_add(pdev);
  62         pr_info("xtalk:n%d/%x bridge widget\n", nasid, widget);
  63         return;
  64 
  65 no_mem:
  66         pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget);
  67 }
  68 
  69 static int probe_one_port(nasid_t nasid, int widget, int masterwid)
  70 {
  71         widgetreg_t             widget_id;
  72         xwidget_part_num_t      partnum;
  73 
  74         widget_id = *(volatile widgetreg_t *)
  75                 (RAW_NODE_SWIN_BASE(nasid, widget) + WIDGET_ID);
  76         partnum = XWIDGET_PART_NUM(widget_id);
  77 
  78         switch (partnum) {
  79         case BRIDGE_WIDGET_PART_NUM:
  80         case XBRIDGE_WIDGET_PART_NUM:
  81                 bridge_platform_create(nasid, widget, masterwid);
  82                 break;
  83         default:
  84                 break;
  85         }
  86 
  87         return 0;
  88 }
  89 
  90 static int xbow_probe(nasid_t nasid)
  91 {
  92         lboard_t *brd;
  93         klxbow_t *xbow_p;
  94         unsigned masterwid, i;
  95 
  96         /*
  97          * found xbow, so may have multiple bridges
  98          * need to probe xbow
  99          */
 100         brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_MIDPLANE8);
 101         if (!brd)
 102                 return -ENODEV;
 103 
 104         xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW);
 105         if (!xbow_p)
 106                 return -ENODEV;
 107 
 108         /*
 109          * Okay, here's a xbow. Let's arbitrate and find
 110          * out if we should initialize it. Set enabled
 111          * hub connected at highest or lowest widget as
 112          * master.
 113          */
 114 #ifdef WIDGET_A
 115         i = HUB_WIDGET_ID_MAX + 1;
 116         do {
 117                 i--;
 118         } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) ||
 119                  (!XBOW_PORT_IS_ENABLED(xbow_p, i)));
 120 #else
 121         i = HUB_WIDGET_ID_MIN - 1;
 122         do {
 123                 i++;
 124         } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) ||
 125                  (!XBOW_PORT_IS_ENABLED(xbow_p, i)));
 126 #endif
 127 
 128         masterwid = i;
 129         if (nasid != XBOW_PORT_NASID(xbow_p, i))
 130                 return 1;
 131 
 132         for (i = HUB_WIDGET_ID_MIN; i <= HUB_WIDGET_ID_MAX; i++) {
 133                 if (XBOW_PORT_IS_ENABLED(xbow_p, i) &&
 134                     XBOW_PORT_TYPE_IO(xbow_p, i))
 135                         probe_one_port(nasid, i, masterwid);
 136         }
 137 
 138         return 0;
 139 }
 140 
 141 static void xtalk_probe_node(cnodeid_t nid)
 142 {
 143         volatile u64            hubreg;
 144         nasid_t                 nasid;
 145         xwidget_part_num_t      partnum;
 146         widgetreg_t             widget_id;
 147 
 148         nasid = COMPACT_TO_NASID_NODEID(nid);
 149         hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
 150 
 151         /* check whether the link is up */
 152         if (!(hubreg & IIO_LLP_CSR_IS_UP))
 153                 return;
 154 
 155         widget_id = *(volatile widgetreg_t *)
 156                        (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID);
 157         partnum = XWIDGET_PART_NUM(widget_id);
 158 
 159         switch (partnum) {
 160         case BRIDGE_WIDGET_PART_NUM:
 161                 bridge_platform_create(nasid, 0x8, 0xa);
 162                 break;
 163         case XBOW_WIDGET_PART_NUM:
 164         case XXBOW_WIDGET_PART_NUM:
 165                 pr_info("xtalk:n%d/0 xbow widget\n", nasid);
 166                 xbow_probe(nasid);
 167                 break;
 168         default:
 169                 pr_info("xtalk:n%d/0 unknown widget (0x%x)\n", nasid, partnum);
 170                 break;
 171         }
 172 }
 173 
 174 static int __init xtalk_init(void)
 175 {
 176         cnodeid_t cnode;
 177 
 178         for_each_online_node(cnode)
 179                 xtalk_probe_node(cnode);
 180 
 181         return 0;
 182 }
 183 arch_initcall(xtalk_init);

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