1
2
3
4
5
6
7
8
9#include <linux/bitops.h>
10#include <linux/string.h>
11#include <linux/mmzone.h>
12#include <asm/sn/addrs.h>
13#include <asm/sn/arch.h>
14#include <asm/sn/hub.h>
15
16
17static int force_fire_and_forget = 1;
18
19
20
21
22
23
24
25
26
27
28unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget,
29 unsigned long xtalk_addr, size_t size)
30{
31 nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
32 unsigned i;
33
34
35 if ((xtalk_addr % SWIN_SIZE) + size <= SWIN_SIZE)
36 return NODE_SWIN_BASE(nasid, widget) + (xtalk_addr % SWIN_SIZE);
37
38 if ((xtalk_addr % BWIN_SIZE) + size > BWIN_SIZE) {
39 printk(KERN_WARNING "PIO mapping at hub %d widget %d addr 0x%lx"
40 " too big (%ld)\n",
41 nasid, widget, xtalk_addr, size);
42 return 0;
43 }
44
45 xtalk_addr &= ~(BWIN_SIZE-1);
46 for (i = 0; i < HUB_NUM_BIG_WINDOW; i++) {
47 if (test_and_set_bit(i, hub_data(cnode)->h_bigwin_used))
48 continue;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 IIO_ITTE_PUT(nasid, i, HUB_PIO_MAP_TO_MEM, widget, xtalk_addr);
66 (void) HUB_L(IIO_ITTE_GET(nasid, i));
67
68 return NODE_BWIN_BASE(nasid, widget) + (xtalk_addr % BWIN_SIZE);
69 }
70
71 printk(KERN_WARNING "unable to establish PIO mapping for at"
72 " hub %d widget %d addr 0x%lx\n",
73 nasid, widget, xtalk_addr);
74 return 0;
75}
76
77
78
79
80
81
82
83
84static void hub_setup_prb(nasid_t nasid, int prbnum, int credits)
85{
86 iprb_t prb;
87 int prb_offset;
88
89
90
91
92 prb_offset = IIO_IOPRB(prbnum);
93 prb.iprb_regval = REMOTE_HUB_L(nasid, prb_offset);
94
95
96
97
98 prb.iprb_ovflow = 1;
99 prb.iprb_bnakctr = 0;
100 prb.iprb_anakctr = 0;
101
102
103
104
105 prb.iprb_ff = force_fire_and_forget ? 1 : 0;
106
107
108
109
110 prb.iprb_xtalkctr = credits;
111
112
113
114
115 REMOTE_HUB_S(nasid, prb_offset, prb.iprb_regval);
116}
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136static void hub_set_piomode(nasid_t nasid)
137{
138 hubreg_t ii_iowa;
139 hubii_wcr_t ii_wcr;
140 unsigned i;
141
142 ii_iowa = REMOTE_HUB_L(nasid, IIO_OUTWIDGET_ACCESS);
143 REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, 0);
144
145 ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid, IIO_WCR);
146
147 if (ii_wcr.iwcr_dir_con) {
148
149
150
151 hub_setup_prb(nasid, 0, 3);
152 } else {
153
154
155
156 hub_setup_prb(nasid, 0, 1);
157 }
158
159
160
161
162
163 for (i = HUB_WIDGET_ID_MIN; i <= HUB_WIDGET_ID_MAX; i++)
164 hub_setup_prb(nasid, i, 3);
165
166 REMOTE_HUB_S(nasid, IIO_OUTWIDGET_ACCESS, ii_iowa);
167}
168
169
170
171
172
173
174void hub_pio_init(cnodeid_t cnode)
175{
176 nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
177 unsigned i;
178
179
180 bitmap_zero(hub_data(cnode)->h_bigwin_used, HUB_NUM_BIG_WINDOW);
181 for (i = 0; i < HUB_NUM_BIG_WINDOW; i++)
182 IIO_ITTE_DISABLE(nasid, i);
183
184 hub_set_piomode(nasid);
185}
186