1 // SPDX-License-Identifier: GPL-2.0
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>
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>
15 #include <asm/xtalk/xwidget.h>
16 #include <asm/pci/bridge.h>
18 #define IP30_SWIN_BASE(widget) \
19 (0x0000000010000000 | (((unsigned long)(widget)) << 24))
21 #define IP30_RAW_SWIN_BASE(widget) (IO_BASE + IP30_SWIN_BASE(widget))
23 #define IP30_SWIN_SIZE (1 << 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 */
29 #define XTALK_NODEV 0xffffffff
31 #define XBOW_REG_LINK_STAT_0 0x114
32 #define XBOW_REG_LINK_BLK_SIZE 0x40
33 #define XBOW_REG_LINK_ALIVE 0x80000000
35 #define HEART_INTR_ADDR 0x00000080
37 #define xtalk_read __raw_readl
39 static void bridge_platform_create(int widget
, int masterwid
)
41 struct xtalk_bridge_platform_data
*bd
;
42 struct sgi_w1_platform_data
*wd
;
43 struct platform_device
*pdev
;
44 struct resource w1_res
;
46 wd
= kzalloc(sizeof(*wd
), GFP_KERNEL
);
50 snprintf(wd
->dev_id
, sizeof(wd
->dev_id
), "bridge-%012lx",
51 IP30_SWIN_BASE(widget
));
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
;
59 pdev
= platform_device_alloc("sgi_w1", PLATFORM_DEVID_AUTO
);
64 platform_device_add_resources(pdev
, &w1_res
, 1);
65 platform_device_add_data(pdev
, wd
, sizeof(*wd
));
66 platform_device_add(pdev
);
68 bd
= kzalloc(sizeof(*bd
), GFP_KERNEL
);
71 pdev
= platform_device_alloc("xtalk-bridge", PLATFORM_DEVID_AUTO
);
77 bd
->bridge_addr
= IP30_RAW_SWIN_BASE(widget
);
78 bd
->intr_addr
= HEART_INTR_ADDR
;
80 bd
->masterwid
= masterwid
;
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
);
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
);
94 platform_device_add_data(pdev
, bd
, sizeof(*bd
));
95 platform_device_add(pdev
);
96 pr_info("xtalk:%x bridge widget\n", widget
);
100 pr_warn("xtalk:%x bridge create out of memory\n", widget
);
103 static unsigned int __init
xbow_widget_active(s8 wid
)
105 unsigned int link_stat
;
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
*
112 return (link_stat
& XBOW_REG_LINK_ALIVE
) ? 1 : 0;
115 static void __init
xtalk_init_widget(s8 wid
, s8 masterwid
)
117 xwidget_part_num_t partnum
;
118 widgetreg_t widget_id
;
120 if (!xbow_widget_active(wid
))
123 widget_id
= xtalk_read((void *)(IP30_RAW_SWIN_BASE(wid
) + WIDGET_ID
));
125 partnum
= XWIDGET_PART_NUM(widget_id
);
128 case BRIDGE_WIDGET_PART_NUM
:
129 case XBRIDGE_WIDGET_PART_NUM
:
130 bridge_platform_create(wid
, masterwid
);
133 pr_info("xtalk:%x unknown widget (0x%x)\n", wid
, partnum
);
138 static int __init
ip30_xtalk_init(void)
143 * Walk widget IDs backwards so that BaseIO is probed first. This
144 * ensures that the BaseIO IOC3 is always detected as eth0.
146 for (i
= IP30_WIDGET_PCI_BASE
; i
> IP30_WIDGET_HEART
; i
--)
147 xtalk_init_widget(i
, IP30_WIDGET_HEART
);
152 arch_initcall(ip30_xtalk_init
);