ip30-xtalk.c (4164B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * ip30-xtalk.c - Very basic Crosstalk (XIO) detection support. 4 * Copyright (C) 2004-2007 Stanislaw Skowronek <skylark@unaligned.org> 5 * Copyright (C) 2009 Johannes Dickgreber <tanzy@gmx.de> 6 * Copyright (C) 2007, 2014-2016 Joshua Kinard <kumba@gentoo.org> 7 */ 8 9#include <linux/init.h> 10#include <linux/kernel.h> 11#include <linux/platform_device.h> 12#include <linux/platform_data/sgi-w1.h> 13#include <linux/platform_data/xtalk-bridge.h> 14 15#include <asm/xtalk/xwidget.h> 16#include <asm/pci/bridge.h> 17 18#define IP30_SWIN_BASE(widget) \ 19 (0x0000000010000000 | (((unsigned long)(widget)) << 24)) 20 21#define IP30_RAW_SWIN_BASE(widget) (IO_BASE + IP30_SWIN_BASE(widget)) 22 23#define IP30_SWIN_SIZE (1 << 24) 24 25#define IP30_WIDGET_XBOW _AC(0x0, UL) /* XBow is always 0 */ 26#define IP30_WIDGET_HEART _AC(0x8, UL) /* HEART is always 8 */ 27#define IP30_WIDGET_PCI_BASE _AC(0xf, UL) /* BaseIO PCI is always 15 */ 28 29#define XTALK_NODEV 0xffffffff 30 31#define XBOW_REG_LINK_STAT_0 0x114 32#define XBOW_REG_LINK_BLK_SIZE 0x40 33#define XBOW_REG_LINK_ALIVE 0x80000000 34 35#define HEART_INTR_ADDR 0x00000080 36 37#define xtalk_read __raw_readl 38 39static void bridge_platform_create(int widget, int masterwid) 40{ 41 struct xtalk_bridge_platform_data *bd; 42 struct sgi_w1_platform_data *wd; 43 struct platform_device *pdev; 44 struct resource w1_res; 45 46 wd = kzalloc(sizeof(*wd), GFP_KERNEL); 47 if (!wd) 48 goto no_mem; 49 50 snprintf(wd->dev_id, sizeof(wd->dev_id), "bridge-%012lx", 51 IP30_SWIN_BASE(widget)); 52 53 memset(&w1_res, 0, sizeof(w1_res)); 54 w1_res.start = IP30_SWIN_BASE(widget) + 55 offsetof(struct bridge_regs, b_nic); 56 w1_res.end = w1_res.start + 3; 57 w1_res.flags = IORESOURCE_MEM; 58 59 pdev = platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO); 60 if (!pdev) { 61 kfree(wd); 62 goto no_mem; 63 } 64 platform_device_add_resources(pdev, &w1_res, 1); 65 platform_device_add_data(pdev, wd, sizeof(*wd)); 66 /* platform_device_add_data() duplicates the data */ 67 kfree(wd); 68 platform_device_add(pdev); 69 70 bd = kzalloc(sizeof(*bd), GFP_KERNEL); 71 if (!bd) 72 goto no_mem; 73 pdev = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO); 74 if (!pdev) { 75 kfree(bd); 76 goto no_mem; 77 } 78 79 bd->bridge_addr = IP30_RAW_SWIN_BASE(widget); 80 bd->intr_addr = HEART_INTR_ADDR; 81 bd->nasid = 0; 82 bd->masterwid = masterwid; 83 84 bd->mem.name = "Bridge PCI MEM"; 85 bd->mem.start = IP30_SWIN_BASE(widget) + BRIDGE_DEVIO0; 86 bd->mem.end = IP30_SWIN_BASE(widget) + IP30_SWIN_SIZE - 1; 87 bd->mem.flags = IORESOURCE_MEM; 88 bd->mem_offset = IP30_SWIN_BASE(widget); 89 90 bd->io.name = "Bridge PCI IO"; 91 bd->io.start = IP30_SWIN_BASE(widget) + BRIDGE_DEVIO0; 92 bd->io.end = IP30_SWIN_BASE(widget) + IP30_SWIN_SIZE - 1; 93 bd->io.flags = IORESOURCE_IO; 94 bd->io_offset = IP30_SWIN_BASE(widget); 95 96 platform_device_add_data(pdev, bd, sizeof(*bd)); 97 /* platform_device_add_data() duplicates the data */ 98 kfree(bd); 99 platform_device_add(pdev); 100 pr_info("xtalk:%x bridge widget\n", widget); 101 return; 102 103no_mem: 104 pr_warn("xtalk:%x bridge create out of memory\n", widget); 105} 106 107static unsigned int __init xbow_widget_active(s8 wid) 108{ 109 unsigned int link_stat; 110 111 link_stat = xtalk_read((void *)(IP30_RAW_SWIN_BASE(IP30_WIDGET_XBOW) + 112 XBOW_REG_LINK_STAT_0 + 113 XBOW_REG_LINK_BLK_SIZE * 114 (wid - 8))); 115 116 return (link_stat & XBOW_REG_LINK_ALIVE) ? 1 : 0; 117} 118 119static void __init xtalk_init_widget(s8 wid, s8 masterwid) 120{ 121 xwidget_part_num_t partnum; 122 widgetreg_t widget_id; 123 124 if (!xbow_widget_active(wid)) 125 return; 126 127 widget_id = xtalk_read((void *)(IP30_RAW_SWIN_BASE(wid) + WIDGET_ID)); 128 129 partnum = XWIDGET_PART_NUM(widget_id); 130 131 switch (partnum) { 132 case BRIDGE_WIDGET_PART_NUM: 133 case XBRIDGE_WIDGET_PART_NUM: 134 bridge_platform_create(wid, masterwid); 135 break; 136 default: 137 pr_info("xtalk:%x unknown widget (0x%x)\n", wid, partnum); 138 break; 139 } 140} 141 142static int __init ip30_xtalk_init(void) 143{ 144 int i; 145 146 /* 147 * Walk widget IDs backwards so that BaseIO is probed first. This 148 * ensures that the BaseIO IOC3 is always detected as eth0. 149 */ 150 for (i = IP30_WIDGET_PCI_BASE; i > IP30_WIDGET_HEART; i--) 151 xtalk_init_widget(i, IP30_WIDGET_HEART); 152 153 return 0; 154} 155 156arch_initcall(ip30_xtalk_init);