0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/kernel.h>
0011 #include <linux/smp.h>
0012 #include <linux/platform_device.h>
0013 #include <linux/platform_data/sgi-w1.h>
0014 #include <linux/platform_data/xtalk-bridge.h>
0015 #include <asm/sn/addrs.h>
0016 #include <asm/sn/types.h>
0017 #include <asm/sn/klconfig.h>
0018 #include <asm/pci/bridge.h>
0019 #include <asm/xtalk/xtalk.h>
0020
0021
0022 #define XBOW_WIDGET_PART_NUM 0x0
0023 #define XXBOW_WIDGET_PART_NUM 0xd000
0024 #define BASE_XBOW_PORT 8
0025
0026 static void bridge_platform_create(nasid_t nasid, int widget, int masterwid)
0027 {
0028 struct xtalk_bridge_platform_data *bd;
0029 struct sgi_w1_platform_data *wd;
0030 struct platform_device *pdev;
0031 struct resource w1_res;
0032 unsigned long offset;
0033
0034 offset = NODE_OFFSET(nasid);
0035
0036 wd = kzalloc(sizeof(*wd), GFP_KERNEL);
0037 if (!wd)
0038 goto no_mem;
0039
0040 snprintf(wd->dev_id, sizeof(wd->dev_id), "bridge-%012lx",
0041 offset + (widget << SWIN_SIZE_BITS));
0042
0043 memset(&w1_res, 0, sizeof(w1_res));
0044 w1_res.start = offset + (widget << SWIN_SIZE_BITS) +
0045 offsetof(struct bridge_regs, b_nic);
0046 w1_res.end = w1_res.start + 3;
0047 w1_res.flags = IORESOURCE_MEM;
0048
0049 pdev = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO);
0050 if (!pdev) {
0051 kfree(wd);
0052 goto no_mem;
0053 }
0054 platform_device_add_resources(pdev, &w1_res, 1);
0055 platform_device_add_data(pdev, wd, sizeof(*wd));
0056
0057 kfree(wd);
0058 platform_device_add(pdev);
0059
0060 bd = kzalloc(sizeof(*bd), GFP_KERNEL);
0061 if (!bd)
0062 goto no_mem;
0063 pdev = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO);
0064 if (!pdev) {
0065 kfree(bd);
0066 goto no_mem;
0067 }
0068
0069
0070 bd->bridge_addr = RAW_NODE_SWIN_BASE(nasid, widget);
0071 bd->intr_addr = BIT_ULL(47) + 0x01800000 + PI_INT_PEND_MOD;
0072 bd->nasid = nasid;
0073 bd->masterwid = masterwid;
0074
0075 bd->mem.name = "Bridge PCI MEM";
0076 bd->mem.start = offset + (widget << SWIN_SIZE_BITS) + BRIDGE_DEVIO0;
0077 bd->mem.end = offset + (widget << SWIN_SIZE_BITS) + SWIN_SIZE - 1;
0078 bd->mem.flags = IORESOURCE_MEM;
0079 bd->mem_offset = offset;
0080
0081 bd->io.name = "Bridge PCI IO";
0082 bd->io.start = offset + (widget << SWIN_SIZE_BITS) + BRIDGE_DEVIO0;
0083 bd->io.end = offset + (widget << SWIN_SIZE_BITS) + SWIN_SIZE - 1;
0084 bd->io.flags = IORESOURCE_IO;
0085 bd->io_offset = offset;
0086
0087 platform_device_add_data(pdev, bd, sizeof(*bd));
0088
0089 kfree(bd);
0090 platform_device_add(pdev);
0091 pr_info("xtalk:n%d/%x bridge widget\n", nasid, widget);
0092 return;
0093
0094 no_mem:
0095 pr_warn("xtalk:n%d/%x bridge create out of memory\n", nasid, widget);
0096 }
0097
0098 static int probe_one_port(nasid_t nasid, int widget, int masterwid)
0099 {
0100 widgetreg_t widget_id;
0101 xwidget_part_num_t partnum;
0102
0103 widget_id = *(volatile widgetreg_t *)
0104 (RAW_NODE_SWIN_BASE(nasid, widget) + WIDGET_ID);
0105 partnum = XWIDGET_PART_NUM(widget_id);
0106
0107 switch (partnum) {
0108 case BRIDGE_WIDGET_PART_NUM:
0109 case XBRIDGE_WIDGET_PART_NUM:
0110 bridge_platform_create(nasid, widget, masterwid);
0111 break;
0112 default:
0113 pr_info("xtalk:n%d/%d unknown widget (0x%x)\n",
0114 nasid, widget, partnum);
0115 break;
0116 }
0117
0118 return 0;
0119 }
0120
0121 static int xbow_probe(nasid_t nasid)
0122 {
0123 lboard_t *brd;
0124 klxbow_t *xbow_p;
0125 unsigned masterwid, i;
0126
0127
0128
0129
0130
0131 brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_MIDPLANE8);
0132 if (!brd)
0133 return -ENODEV;
0134
0135 xbow_p = (klxbow_t *)find_component(brd, NULL, KLSTRUCT_XBOW);
0136 if (!xbow_p)
0137 return -ENODEV;
0138
0139
0140
0141
0142
0143
0144
0145 #ifdef WIDGET_A
0146 i = HUB_WIDGET_ID_MAX + 1;
0147 do {
0148 i--;
0149 } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) ||
0150 (!XBOW_PORT_IS_ENABLED(xbow_p, i)));
0151 #else
0152 i = HUB_WIDGET_ID_MIN - 1;
0153 do {
0154 i++;
0155 } while ((!XBOW_PORT_TYPE_HUB(xbow_p, i)) ||
0156 (!XBOW_PORT_IS_ENABLED(xbow_p, i)));
0157 #endif
0158
0159 masterwid = i;
0160 if (nasid != XBOW_PORT_NASID(xbow_p, i))
0161 return 1;
0162
0163 for (i = HUB_WIDGET_ID_MIN; i <= HUB_WIDGET_ID_MAX; i++) {
0164 if (XBOW_PORT_IS_ENABLED(xbow_p, i) &&
0165 XBOW_PORT_TYPE_IO(xbow_p, i))
0166 probe_one_port(nasid, i, masterwid);
0167 }
0168
0169 return 0;
0170 }
0171
0172 static void xtalk_probe_node(nasid_t nasid)
0173 {
0174 volatile u64 hubreg;
0175 xwidget_part_num_t partnum;
0176 widgetreg_t widget_id;
0177
0178 hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
0179
0180
0181 if (!(hubreg & IIO_LLP_CSR_IS_UP))
0182 return;
0183
0184 widget_id = *(volatile widgetreg_t *)
0185 (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID);
0186 partnum = XWIDGET_PART_NUM(widget_id);
0187
0188 switch (partnum) {
0189 case BRIDGE_WIDGET_PART_NUM:
0190 bridge_platform_create(nasid, 0x8, 0xa);
0191 break;
0192 case XBOW_WIDGET_PART_NUM:
0193 case XXBOW_WIDGET_PART_NUM:
0194 pr_info("xtalk:n%d/0 xbow widget\n", nasid);
0195 xbow_probe(nasid);
0196 break;
0197 default:
0198 pr_info("xtalk:n%d/0 unknown widget (0x%x)\n", nasid, partnum);
0199 break;
0200 }
0201 }
0202
0203 static int __init xtalk_init(void)
0204 {
0205 nasid_t nasid;
0206
0207 for_each_online_node(nasid)
0208 xtalk_probe_node(nasid);
0209
0210 return 0;
0211 }
0212 arch_initcall(xtalk_init);