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(pdev);
67
68	bd = kzalloc(sizeof(*bd), GFP_KERNEL);
69	if (!bd)
70		goto no_mem;
71	pdev = platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO);
72	if (!pdev) {
73		kfree(bd);
74		goto no_mem;
75	}
76
77	bd->bridge_addr	= IP30_RAW_SWIN_BASE(widget);
78	bd->intr_addr	= HEART_INTR_ADDR;
79	bd->nasid	= 0;
80	bd->masterwid	= masterwid;
81
82	bd->mem.name	= "Bridge PCI MEM";
83	bd->mem.start	= IP30_SWIN_BASE(widget) + BRIDGE_DEVIO0;
84	bd->mem.end	= IP30_SWIN_BASE(widget) + IP30_SWIN_SIZE - 1;
85	bd->mem.flags	= IORESOURCE_MEM;
86	bd->mem_offset	= IP30_SWIN_BASE(widget);
87
88	bd->io.name	= "Bridge PCI IO";
89	bd->io.start	= IP30_SWIN_BASE(widget) + BRIDGE_DEVIO0;
90	bd->io.end	= IP30_SWIN_BASE(widget) + IP30_SWIN_SIZE - 1;
91	bd->io.flags	= IORESOURCE_IO;
92	bd->io_offset	= IP30_SWIN_BASE(widget);
93
94	platform_device_add_data(pdev, bd, sizeof(*bd));
95	platform_device_add(pdev);
96	pr_info("xtalk:%x bridge widget\n", widget);
97	return;
98
99no_mem:
100	pr_warn("xtalk:%x bridge create out of memory\n", widget);
101}
102
103static unsigned int __init xbow_widget_active(s8 wid)
104{
105	unsigned int link_stat;
106
107	link_stat = xtalk_read((void *)(IP30_RAW_SWIN_BASE(IP30_WIDGET_XBOW) +
108					XBOW_REG_LINK_STAT_0 +
109					XBOW_REG_LINK_BLK_SIZE *
110					(wid - 8)));
111
112	return (link_stat & XBOW_REG_LINK_ALIVE) ? 1 : 0;
113}
114
115static void __init xtalk_init_widget(s8 wid, s8 masterwid)
116{
117	xwidget_part_num_t partnum;
118	widgetreg_t widget_id;
119
120	if (!xbow_widget_active(wid))
121		return;
122
123	widget_id = xtalk_read((void *)(IP30_RAW_SWIN_BASE(wid) + WIDGET_ID));
124
125	partnum = XWIDGET_PART_NUM(widget_id);
126
127	switch (partnum) {
128	case BRIDGE_WIDGET_PART_NUM:
129	case XBRIDGE_WIDGET_PART_NUM:
130		bridge_platform_create(wid, masterwid);
131		break;
132	default:
133		pr_info("xtalk:%x unknown widget (0x%x)\n", wid, partnum);
134		break;
135	}
136}
137
138static int __init ip30_xtalk_init(void)
139{
140	int i;
141
142	/*
143	 * Walk widget IDs backwards so that BaseIO is probed first.  This
144	 * ensures that the BaseIO IOC3 is always detected as eth0.
145	 */
146	for (i = IP30_WIDGET_PCI_BASE; i > IP30_WIDGET_HEART; i--)
147		xtalk_init_widget(i, IP30_WIDGET_HEART);
148
149	return 0;
150}
151
152arch_initcall(ip30_xtalk_init);
153