diff options
author | 2025-03-08 22:04:20 +0800 | |
---|---|---|
committer | 2025-03-08 22:04:20 +0800 | |
commit | a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch) | |
tree | 84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /arch/mips/sgi-ip30/ip30-xtalk.c | |
download | ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip |
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'arch/mips/sgi-ip30/ip30-xtalk.c')
-rw-r--r-- | arch/mips/sgi-ip30/ip30-xtalk.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/arch/mips/sgi-ip30/ip30-xtalk.c b/arch/mips/sgi-ip30/ip30-xtalk.c new file mode 100644 index 000000000..8a2894645 --- /dev/null +++ b/arch/mips/sgi-ip30/ip30-xtalk.c | |||
@@ -0,0 +1,152 @@ | |||
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 | |||
39 | static 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 | |||
99 | no_mem: | ||
100 | pr_warn("xtalk:%x bridge create out of memory\n", widget); | ||
101 | } | ||
102 | |||
103 | static 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 | |||
115 | static 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 | |||
138 | static 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 | |||
152 | arch_initcall(ip30_xtalk_init); | ||