|
|
1.1 root 1: /* $Id: stp220x.c,v 1.5 2010/06/05 18:59:29 fredette Exp $ */
2:
3: /* ic/stp220x.c - emulation of the uniprocessor system controller
4: (STP2200) and the dual-processor system controller (STP2202): */
5:
6: /*
7: * Copyright (c) 2009 Matt Fredette
8: * All rights reserved.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by Matt Fredette.
21: * 4. The name of the author may not be used to endorse or promote products
22: * derived from this software without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
28: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34: * POSSIBILITY OF SUCH DAMAGE.
35: */
36:
37: #include <tme/common.h>
38: _TME_RCSID("$Id: stp220x.c,v 1.5 2010/06/05 18:59:29 fredette Exp $");
39:
40: /* includes: */
41: #include "stp22xx-impl.h"
42:
43: /* macros: */
44:
45: /* MIDs: */
46: #define TME_STP220X_MID_CPU(n) (n)
47: #define TME_STP220X_MID_IO (31)
48:
49: /* UPA ports: */
50: #define TME_STP220X_UPA_PORT_CPU(n) (n)
51: #define TME_STP220X_UPA_PORT_IO (2)
52: #define TME_STP220X_UPA_PORT_FFB (3)
53: #define TME_STP220X_UPA_PORT_COUNT_MAX (4)
54:
55: /* the size of a UPA port: */
56: #define TME_STP220X_UPA_PORT_SIZE (((tme_uint64_t) 1) << 33)
57:
58: /* the number of SIMM groups: */
59: #define TME_STP220X_SIMM_GROUP_COUNT (4)
60:
61: /* registers: */
62: #define TME_STP220X_SC_CONTROL (0x00)
63: #define TME_STP220X_SC_ID (0x04)
64: #define TME_STP220X_SC_PERF(n) (0x08 + (4 * (n)))
65: #define TME_STP220X_SC_PERFSHADOW (0x10)
66: #define TME_STP220X_SC_PERF_CTRL (0x20)
67: #define TME_STP220X_SC_DEBUG_PIN_CTRL (0x30)
68: #define TME_STP220X_SC_UPA_CONFIG(port) (0x40 + (8 * (port)))
69: #define TME_STP220X_SC_UPA_STATUS(port) (0x44 + (8 * (port)))
70: #define TME_STP2200_SC_MC_CONTROL0 (0x60)
71: #define TME_STP2200_SC_MC_CONTROL1 (0x64)
72: #define TME_STP2202_SC_CC_DIAG (0x70)
73: #define TME_STP2202_SC_CC_SNPVEC (0x74)
74: #define TME_STP2202_SC_CC_FAULT (0x78)
75: #define TME_STP2202_SC_CC_PROC_INDEX (0x7c)
76: #define TME_STP2202_SC_MEMCTRL(n) (0x80 + (4 * (n)))
77:
78: /* this converts an SC UPA port config or status register address into
79: a UPA port: */
80: #define TME_STP220X_SC_ADDRESS_UPA_PORT(address) \
81: (((address) \
82: - TME_STP220X_SC_UPA_CONFIG(0)) \
83: / (TME_STP220X_SC_UPA_CONFIG(1) \
84: - TME_STP220X_SC_UPA_CONFIG(0)))
85:
86: /* the control register: */
87: #define TME_STP220X_SC_CONTROL_POR (((tme_uint32_t) 1) << 31)
88: #define TME_STP220X_SC_CONTROL_SOFT_POR TME_BIT(30)
89: #define TME_STP220X_SC_CONTROL_SOFT_XIR TME_BIT(29)
90: #define TME_STP220X_SC_CONTROL_B_POR TME_BIT(28)
91: #define TME_STP220X_SC_CONTROL_B_XIR TME_BIT(27)
92: #define TME_STP220X_SC_CONTROL_WAKEUP TME_BIT(26)
93: #define TME_STP220X_SC_CONTROL_FATAL TME_BIT(25)
94: #define TME_STP220X_SC_CONTROL_IAP TME_BIT(23)
95: #define TME_STP220X_SC_CONTROL_EN_WKUP_POR TME_BIT(22)
96: #define TME_STP220X_SC_CONTROL_MBZ \
97: (TME_BIT(24) \
98: | ((2 << 21) - (1 << 0)))
99:
100: /* a UPA port configuration register: */
101: #define TME_STP220X_UPA_CONFIG_MD (((tme_uint32_t) 1) << 31)
102: #define TME_STP220X_UPA_CONFIG_S_SLEEP TME_BIT(30)
103: #define TME_STP220X_UPA_CONFIG_SPRQS ((2 << 27) - (1 << 24))
104: #define TME_STP220X_UPA_CONFIG_SPDQS ((2 << 23) - (1 << 18))
105: #define TME_STP220X_UPA_CONFIG_SPIQS ((2 << 17) - (1 << 16))
106: #define TME_STP220X_UPA_CONFIG_SQUEN TME_BIT(15)
107: #define TME_STP220X_UPA_CONFIG_ONEREAD TME_BIT(14)
108: #define TME_STP220X_UPA_CONFIG_MBZ \
109: (((2 << 29) - (1 << 28)) \
110: | ((2 << 13) - (1 << 0)))
111:
112: /* a UPA port status register: */
113: #define TME_STP220X_UPA_STATUS_FATAL (((tme_uint32_t) 1) << 31)
114: #define TME_STP220X_UPA_STATUS_IADDR TME_BIT(30)
115: #define TME_STP220X_UPA_STATUS_IPORT TME_BIT(29)
116: #define TME_STP220X_UPA_STATUS_IPRTY TME_BIT(28)
117: #define TME_STP220X_UPA_STATUS_MC0OF TME_BIT(27)
118: #define TME_STP220X_UPA_STATUS_MC1OF TME_BIT(26)
119: #define TME_STP220X_UPA_STATUS_MC0Q ((2 << 25) - (1 << 23))
120: #define TME_STP220X_UPA_STATUS_MC1Q ((2 << 22) - (1 << 20))
121: #define TME_STP220X_UPA_STATUS_MC1Q_0 TME_BIT(19)
122:
123: /* this gives the log2 of the SIMM group size: */
124: #define TME_STP220X_SIMM_GROUP_SIZE_LOG2(stp220x) (TME_STP220X_IS_2200(stp220x) ? 28 : 29)
125:
126: /* connections: */
127: #define TME_STP220X_CONN_UPA_PORT(n) (n)
128: #define TME_STP220X_CONN_SIMM_GROUP(n) TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_COUNT_MAX + (n))
129: #define TME_STP220X_CONN_EBUS TME_STP220X_CONN_SIMM_GROUP(TME_STP220X_SIMM_GROUP_COUNT)
130: #define TME_STP220X_CONN_COUNT (TME_STP220X_CONN_EBUS + 1)
131: #define TME_STP220X_CONN_NULL (TME_STP220X_CONN_COUNT)
132:
133: /* reset states: */
134: #define TME_STP220X_RESET_STATE_NEGATING (TME_STP220X_UPA_PORT_COUNT_MAX)
135: #define TME_STP220X_RESET_STATE_ASSERTING (TME_STP220X_UPA_PORT_COUNT_MAX * 2)
136:
137: /* predicates: */
138: #define TME_STP220X_IS_2200(stp220x) ((stp220x)->tme_stp220x_is_2200)
139:
140: /* types: */
141:
142: /* the device: */
143: struct tme_stp220x {
144:
145: /* the common structure, and space for the connections: */
146: struct tme_stp22xx tme_stp220x;
147: #define tme_stp220x_master_conn_index_pending tme_stp220x.tme_stp22xx_master_conn_index_pending
148: #define tme_stp220x_master_conn_index tme_stp220x.tme_stp22xx_master_conn_index
149: #define tme_stp220x_master_completion tme_stp220x.tme_stp22xx_master_completion
150: union tme_stp22xx_conn __tme_stp220x_conns[TME_STP220X_CONN_COUNT];
151:
152: /* the last address in each connection: */
153: tme_bus_addr64_t tme_stp220x_conn_address_last[TME_STP220X_CONN_COUNT];
154:
155: /* this is nonzero if this is an STP2200: */
156: int tme_stp220x_is_2200;
157:
158: /* the reset state: */
159: unsigned int tme_stp220x_reset_state;
160:
161: /* the reset bus signal: */
162: tme_uint32_t tme_stp220x_reset_signal;
163:
164: /* the mask of connection indices requesting the bus: */
165: tme_uint32_t tme_stp220x_brs;
166:
167: /* the ebus EB_ADDR and EB_DATA registers: */
168: unsigned int tme_stp220x_eb_addr;
169: tme_uint8_t tme_stp220x_eb_data[sizeof(tme_uint32_t)];
170:
171: /* the registers: */
172: tme_uint32_t tme_stp220x_sc_control;
173: tme_uint32_t tme_stp220x_sc_perf[2];
174: tme_uint32_t tme_stp220x_sc_perfshadow;
175: tme_uint32_t tme_stp220x_sc_perf_ctrl;
176: tme_uint32_t tme_stp220x_sc_upa_config[TME_STP220X_UPA_PORT_COUNT_MAX];
177: tme_uint32_t tme_stp220x_sc_upa_status[TME_STP220X_UPA_PORT_COUNT_MAX];
178: tme_uint32_t tme_stp2202_sc_cc_diag;
179: tme_uint32_t tme_stp2202_sc_cc_fault;
180: tme_uint32_t tme_stp2202_sc_cc_proc_index;
181: tme_uint32_t tme_stp220x_sc_memctrl[0xe];
182: #define tme_stp2200_sc_mc_control tme_stp220x_sc_memctrl
183: #define tme_stp2202_sc_memctrl tme_stp220x_sc_memctrl
184: };
185:
186: /* globals: */
187:
188: /* the ebus subregion, decoded by the PAL block of the RIC chip
189: (STP2210), for the PLL chip (either an mc12429 or an mc12439): */
190: static const struct tme_bus_subregion _tme_stp2210_mc124x9_subregion = {
191:
192: /* the first and last addresses, starting from zero, of this
193: subregion: */
194: 0x4000,
195: 0x4003,
196:
197: /* there are no other subregions for this bus connection: */
198: (const struct tme_bus_subregion *) NULL
199: };
200:
201: /* this converts a connection index into a MID: */
202: static unsigned int
203: _tme_stp220x_conn_index_mid(const struct tme_stp220x *stp220x,
204: unsigned int conn_index)
205: {
206: switch (conn_index) {
207: default: assert (FALSE);
208: case TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_CPU(0)):
209: return (TME_STP220X_MID_CPU(0));
210: case TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_CPU(1)):
211: assert (!TME_STP220X_IS_2200(stp220x));
212: return (TME_STP220X_MID_CPU(1));
213: case TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_IO):
214: return (TME_STP220X_MID_IO);
215: }
216: }
217:
218: /* this converts a MID into a connection index: */
219: static unsigned int
220: _tme_stp220x_lookup_mid(const struct tme_stp220x *stp220x,
221: tme_uint32_t mid)
222: {
223: switch (mid) {
224: case TME_STP220X_MID_CPU(0):
225: return (TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_CPU(0)));
226: case TME_STP220X_MID_CPU(1):
227: return (TME_STP220X_IS_2200(stp220x)
228: ? TME_STP220X_CONN_NULL
229: : TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_CPU(1)));
230: case TME_STP220X_MID_IO:
231: return (TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_IO));
232: default:
233: return (TME_STP220X_CONN_NULL);
234: }
235: }
236:
237: /* this converts an address into a connection index and a
238: connection-relative address: */
239: static unsigned int
240: _tme_stp220x_lookup_address(const struct tme_stp220x *stp220x,
241: tme_bus_addr64_t *_address,
242: tme_bus_addr64_t *_region_size_m1)
243: {
244: tme_uint32_t address_32_64;
245: tme_uint32_t address_0_31;
246: unsigned int group_size_log2;
247: unsigned int group;
248: tme_uint32_t group_size_m1;
249: unsigned int conn_index;
250: tme_uint32_t upn;
251:
252: /* get bits 32..64 of the address: */
253: address_32_64 = (*_address >> 32);
254:
255: /* if this address is in memory: */
256: if (address_32_64 < 0x100) {
257:
258: /* get bits 0..31 of the address: */
259: address_0_31 = *_address;
260:
261: /* get the SIMM group number: */
262: group_size_log2 = TME_STP220X_SIMM_GROUP_SIZE_LOG2(stp220x);
263: group = (address_0_31 >> group_size_log2) % TME_STP220X_SIMM_GROUP_COUNT;
264:
265: /* get the connection index for this SIMM group: */
266: conn_index = TME_STP220X_CONN_SIMM_GROUP(group);
267:
268: /* get the size, minus one, of the SIMM group: */
269: group_size_m1 = stp220x->tme_stp220x_conn_address_last[conn_index];
270:
271: /* return the truncated address within the SIMM group, the size of
272: the SIMM group, and the connection index: */
273: *_address = (address_0_31 & group_size_m1);
274: *_region_size_m1 = group_size_m1;
275: return (conn_index);
276: }
277:
278: /* make the region size the UPA port size: */
279: *_region_size_m1 = (TME_STP220X_UPA_PORT_SIZE - 1);
280:
281: /* if this address is in a UPA port: */
282: if (__tme_predict_true(address_32_64 >= 0x1c0)) {
283:
284: /* make the address within the UPA port: */
285: *_address %= TME_STP220X_UPA_PORT_SIZE;
286:
287: /* get the UPN: */
288: upn = (address_32_64 - 0x1c0) >> 1;
289:
290: /* UPN 30 is the FFB: */
291: if (upn == 30) {
292: return (TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_FFB));
293: }
294:
295: /* all other UPNs are either valid MIDs or are reserved: */
296: return (_tme_stp220x_lookup_mid(stp220x, upn));
297: }
298:
299: /* this address is in a reserved region: */
300: return (TME_STP220X_CONN_NULL);
301: }
302:
303: /* this busies an agent generic bus connection: */
304: #define _tme_stp220x_agent_busy_bus(stp220x, agent_conn_index) \
305: tme_stp22xx_busy_bus(&(stp220x)->tme_stp220x, agent_conn_index)
306:
307: /* this unbusies an agent generic bus connection: */
308: #define _tme_stp220x_agent_unbusy_bus(stp220x, agent_conn_bus) \
309: tme_stp22xx_unbusy_bus(&(stp220x)->tme_stp220x, agent_conn_bus)
310:
311: /* this busies a slave generic bus connection: */
312: #define _tme_stp220x_slave_busy_bus(stp220x, slave_conn_index) \
313: tme_stp22xx_slave_busy_bus(&(stp220x)->tme_stp220x, slave_conn_index)
314:
315: /* this unbusies a slave connection: */
316: #define _tme_stp220x_slave_unbusy(stp220x) \
317: tme_stp22xx_slave_unbusy(&(stp220x)->tme_stp220x)
318:
319: /* this busies a slave UPA connection: */
320: static struct tme_upa_bus_connection *
321: _tme_stp220x_slave_busy_upa(struct tme_stp220x *stp220x,
322: unsigned int slave_conn_index)
323: {
324: struct tme_upa_bus_connection *slave_conn_upa;
325: struct tme_bus_connection *slave_conn_bus;
326:
327: /* if the connection index is valid: */
328: slave_conn_upa = NULL;
329: if (__tme_predict_true(slave_conn_index != TME_STP220X_CONN_NULL)) {
330:
331: /* if there is a UPA slave at this connection index: */
332: slave_conn_upa = stp220x->tme_stp220x.tme_stp22xx_conns[slave_conn_index].tme_stp22xx_conn_upa;
333: if (__tme_predict_true(slave_conn_upa != NULL
334: && slave_conn_upa->tme_upa_bus_connection.tme_bus_connection.tme_connection_type == TME_CONNECTION_BUS_UPA)) {
335:
336: /* busy the connection to the UPA slave: */
337: slave_conn_bus = _tme_stp220x_slave_busy_bus(stp220x, slave_conn_index);
338: assert (slave_conn_bus == &slave_conn_upa->tme_upa_bus_connection);
339: return ((struct tme_upa_bus_connection *) slave_conn_bus);
340: }
341: }
342:
343: return (NULL);
344: }
345:
346: /* this enters an stp220x: */
347: #define _tme_stp220x_enter_bus(agent_conn_bus) \
348: ((struct tme_stp220x *) tme_stp22xx_enter((struct tme_stp22xx *) (agent_conn_bus)->tme_bus_connection.tme_connection_element->tme_element_private))
349:
350: /* these enter an stp220x as the bus master: */
351: #define _tme_stp220x_enter_master_bus(agent_conn_bus) \
352: ((struct tme_stp220x *) tme_stp22xx_enter_master(agent_conn_bus))
353: #define _tme_stp220x_enter_master_upa(agent_conn_upa) \
354: _tme_stp220x_enter_master_bus(&(agent_conn_upa)->tme_upa_bus_connection)
355:
356: /* this leaves an stp220x: */
357: #define _tme_stp220x_leave(stp220x) \
358: tme_stp22xx_leave(&(stp220x)->tme_stp220x)
359:
360: /* this validates an agent's completion: */
361: /* NB: agent_completion may be NULL: */
362: #define _tme_stp220x_completion_validate(stp220x, completion) \
363: tme_stp22xx_completion_validate(&(stp220x)->tme_stp220x, completion)
364:
365: /* this allocates a completion: */
366: #define _tme_stp220x_completion_alloc(stp220x, handler, arg) \
367: tme_stp22xx_completion_alloc(&(stp220x)->tme_stp220x, handler, arg)
368:
369: /* this completes a bus operation between master and slave: */
370: #define _tme_stp220x_complete_master tme_stp22xx_complete_master
371:
372: /* this completes a reset assertion or negation: */
373: static void
374: _tme_stp220x_complete_reset(struct tme_stp22xx *stp22xx,
375: struct tme_completion *completion,
376: void *arg)
377: {
378: struct tme_stp220x *stp220x;
379:
380: /* recover our data structure: */
381: stp220x = (struct tme_stp220x *) stp22xx;
382:
383: /* update the reset state: */
384: stp220x->tme_stp220x_reset_state--;
385:
386: /* unused: */
387: completion = 0;
388: arg = 0;
389: }
390:
391: /* this completes a bus grant: */
392: #define _tme_stp220x_complete_bg tme_stp22xx_complete_bg
393:
394: /* this calls out a bus signal to an agent: */
395: #define _tme_stp220x_callout_signal(stp220x, conn_index, signal, completion_handler) \
396: tme_stp22xx_callout_signal(&(stp220x)->tme_stp220x, conn_index, signal, completion_handler)
397:
398: /* the run function: */
399: static void
400: _tme_stp220x_run(struct tme_stp22xx *stp22xx)
401: {
402: struct tme_stp220x *stp220x;
403: unsigned int reset_state;
404: unsigned int agent_conn_index;
405: unsigned int master_conn_index;
406: tme_uint32_t brs;
407:
408: /* recover our data structure: */
409: stp220x = (struct tme_stp220x *) stp22xx;
410:
411: /* loop forever: */
412: for (;;) {
413:
414: /* if we need to assert reset to another agent: */
415: reset_state = stp220x->tme_stp220x_reset_state;
416: if (reset_state > TME_STP220X_RESET_STATE_NEGATING) {
417:
418: /* assert reset to the next agent: */
419: agent_conn_index = reset_state - (TME_STP220X_RESET_STATE_NEGATING + 1);
420: _tme_stp220x_callout_signal(stp220x,
421: agent_conn_index,
422: (stp220x->tme_stp220x_reset_signal
423: | TME_BUS_SIGNAL_EDGE
424: | TME_BUS_SIGNAL_LEVEL_ASSERTED),
425: _tme_stp220x_complete_reset);
426: continue;
427: }
428:
429: /* if there is a current master: */
430: master_conn_index = stp220x->tme_stp220x_master_conn_index;
431: if (master_conn_index != TME_STP220X_CONN_NULL) {
432:
433: /* if the current master is still requesting the bus: */
434: if (stp220x->tme_stp220x_brs & (1 << master_conn_index)) {
435:
436: /* stop now. we can't do anything else until the current
437: master releases the bus: */
438: break;
439: }
440:
441: /* there is no current master: */
442: stp220x->tme_stp220x_master_conn_index = TME_STP220X_CONN_NULL;
443:
444: /* negate bus grant to the former master: */
445: _tme_stp220x_callout_signal(stp220x,
446: master_conn_index,
447: (TME_BUS_SIGNAL_BG
448: | TME_BUS_SIGNAL_EDGE
449: | TME_BUS_SIGNAL_LEVEL_NEGATED),
450: tme_stp22xx_complete_nop);
451: continue;
452: }
453:
454: /* if we need to negate reset to another agent: */
455: reset_state = stp220x->tme_stp220x_reset_state;
456: if (reset_state) {
457:
458: /* negate reset to the next agent: */
459: agent_conn_index = reset_state - 1;
460: _tme_stp220x_callout_signal(stp220x,
461: agent_conn_index,
462: (stp220x->tme_stp220x_reset_signal
463: | TME_BUS_SIGNAL_EDGE
464: | TME_BUS_SIGNAL_LEVEL_NEGATED),
465: _tme_stp220x_complete_reset);
466: continue;
467: }
468:
469: /* if one or more agents are requesting the bus: */
470: brs = stp220x->tme_stp220x_brs;
471: if (brs != 0) {
472:
473: /* get the connection index for the next master: */
474: /* XXX FIXME - should we do something fair here? */
475: for (master_conn_index = 0;
476: (brs & 1) == 0;
477: brs >>= 1, master_conn_index++);
478:
479: /* set the pending master: */
480: stp220x->tme_stp220x_master_conn_index_pending = master_conn_index;
481:
482: /* assert bus grant to the current master: */
483: _tme_stp220x_callout_signal(stp220x,
484: master_conn_index,
485: (TME_BUS_SIGNAL_BG
486: | TME_BUS_SIGNAL_EDGE
487: | TME_BUS_SIGNAL_LEVEL_ASSERTED),
488: _tme_stp220x_complete_bg);
489: continue;
490: }
491:
492: /* no other running is needed: */
493: break;
494: }
495: }
496:
497: /* this does a reset: */
498: static void
499: _tme_stp220x_reset(struct tme_stp220x *stp220x,
500: tme_uint32_t resets)
501: {
502: tme_uint32_t sc_control;
503: tme_uint32_t reset;
504:
505: /* get the current status registers, so that the chosen reset may
506: reset them: */
507: sc_control = stp220x->tme_stp220x_sc_control;
508:
509: /* "If multiple resets occur simultaneously, the following order
510: will be chosen for the reporting:" */
511:
512: if (resets & TME_STP220X_SC_CONTROL_POR) {
513: sc_control = 0;
514: reset = TME_STP220X_SC_CONTROL_POR;
515: }
516: else if (resets & TME_STP220X_SC_CONTROL_FATAL) {
517: reset = TME_STP220X_SC_CONTROL_FATAL;
518: }
519: else if (resets & TME_STP220X_SC_CONTROL_B_POR) {
520: sc_control = 0;
521: reset = TME_STP220X_SC_CONTROL_B_POR;
522: }
523: else if (resets & TME_STP220X_SC_CONTROL_WAKEUP) {
524: reset = TME_STP220X_SC_CONTROL_WAKEUP;
525: }
526: else if (resets & TME_STP220X_SC_CONTROL_SOFT_POR) {
527: sc_control = 0;
528: reset = TME_STP220X_SC_CONTROL_SOFT_POR;
529: }
530: else if (resets & TME_STP220X_SC_CONTROL_B_XIR) {
531: reset = TME_STP220X_SC_CONTROL_B_XIR;
532: }
533: else {
534: assert (resets == TME_STP220X_SC_CONTROL_SOFT_XIR);
535: reset = TME_STP220X_SC_CONTROL_SOFT_XIR;
536: }
537:
538: /* update the status registers: */
539: stp220x->tme_stp220x_sc_control = sc_control | reset;
540:
541: /* if this is a type of power or fatal reset: */
542: if (reset
543: & (TME_STP220X_SC_CONTROL_FATAL
544: | TME_STP220X_SC_CONTROL_POR
545: | TME_STP220X_SC_CONTROL_B_POR
546: | TME_STP220X_SC_CONTROL_SOFT_POR)) {
547:
548: /* start asserting SYS_RESET_L: */
549: stp220x->tme_stp220x_reset_state = TME_STP220X_RESET_STATE_ASSERTING;
550: stp220x->tme_stp220x_reset_signal = TME_BUS_SIGNAL_RESET;
551: }
552:
553: /* otherwise, if this is a wakeup: */
554: else if (reset == TME_STP220X_SC_CONTROL_WAKEUP) {
555:
556: /* XXX WRITEME: */
557: abort();
558: }
559:
560: /* otherwise, this must be an XIR: */
561: else {
562: assert (reset == TME_STP220X_SC_CONTROL_B_XIR
563: || reset == TME_STP220X_SC_CONTROL_SOFT_XIR);
564:
565: /* start asserting UPA_XIR_L: */
566: /* NB: we reuse TME_BUS_SIGNAL_HALT for this: */
567: stp220x->tme_stp220x_reset_state = TME_STP220X_RESET_STATE_ASSERTING;
568: stp220x->tme_stp220x_reset_signal = TME_BUS_SIGNAL_HALT;
569: }
570: }
571:
572: /* this handles a bus signal: */
573: static void
574: _tme_stp220x_signal(struct tme_bus_connection *agent_conn_bus,
575: unsigned int signal,
576: struct tme_completion *agent_completion)
577: {
578: struct tme_stp220x *stp220x;
579: tme_uint32_t level;
580: tme_uint32_t agent_conn_index_mask;
581:
582: /* enter: */
583: stp220x = _tme_stp220x_enter_bus(agent_conn_bus);
584:
585: /* get the level. this must be an edge: */
586: assert (signal & TME_BUS_SIGNAL_EDGE);
587: level = signal - TME_BUS_SIGNAL_EDGE;
588: signal = TME_BUS_SIGNAL_WHICH(signal);
589: level ^= signal;
590:
591: /* get the agent's connection index mask: */
592: agent_conn_index_mask = (1 << agent_conn_bus->tme_bus_connection.tme_connection_id);
593:
594: /* dispatch on the signal: */
595: switch (signal) {
596:
597: /* the bus request signal: */
598: case TME_BUS_SIGNAL_BR:
599:
600: /* mark this caller's bus request line as either asserted or
601: negated: */
602: assert (level == TME_BUS_SIGNAL_LEVEL_NEGATED
603: || level == TME_BUS_SIGNAL_LEVEL_ASSERTED);
604: stp220x->tme_stp220x_brs
605: = ((stp220x->tme_stp220x_brs
606: | agent_conn_index_mask)
607: & (level == TME_BUS_SIGNAL_LEVEL_ASSERTED
608: ? ~0
609: : ~agent_conn_index_mask));
610: break;
611:
612: default:
613: assert (FALSE);
614: break;
615: }
616:
617: /* leave: */
618: _tme_stp220x_completion_validate(stp220x, agent_completion);
619: _tme_stp220x_leave(stp220x);
620: }
621:
622: /* this handles a bus cycle: */
623: static void
624: _tme_stp220x_cycle(struct tme_bus_connection *master_conn_bus,
625: struct tme_bus_cycle *master_cycle,
626: tme_uint32_t *_master_fast_cycle_types,
627: struct tme_completion *master_completion)
628: {
629: struct tme_stp220x *stp220x;
630: tme_bus_addr64_t slave_address;
631: unsigned int slave_conn_index;
632: tme_bus_addr64_t region_size_m1;
633:
634: /* enter: */
635: stp220x = _tme_stp220x_enter_master_bus(master_conn_bus);
636:
637: /* start this cycle: */
638: assert (stp220x->tme_stp220x_master_completion == NULL);
639: stp220x->tme_stp220x_master_completion = &master_completion;
640:
641: /* convert the master's address into a slave connection index and
642: address: */
643: slave_address = master_cycle->tme_bus_cycle_address;
644: slave_conn_index = _tme_stp220x_lookup_address(stp220x, &slave_address, ®ion_size_m1);
645: master_cycle->tme_bus_cycle_address = slave_address;
646:
647: /* run the slave bus cycle: */
648: tme_stp22xx_slave_cycle(master_conn_bus,
649: slave_conn_index,
650: master_cycle,
651: _master_fast_cycle_types,
652: &master_completion);
653:
654: /* leave: */
655: _tme_stp220x_leave(stp220x);
656: }
657:
658: /* this delivers an interrupt: */
659: static void
660: _tme_stp220x_interrupt(struct tme_upa_bus_connection *master_conn_upa,
661: tme_uint32_t slave_mid,
662: const tme_uint64_t *data,
663: struct tme_completion *master_completion)
664: {
665: struct tme_stp220x *stp220x;
666: unsigned int slave_conn_index;
667: struct tme_upa_bus_connection *slave_conn_upa;
668: struct tme_completion *completion;
669: struct tme_upa_bus_connection *slave_conn_upa_other;
670:
671: /* enter: */
672: stp220x = _tme_stp220x_enter_master_upa(master_conn_upa);
673:
674: /* convert the MID into a connection index: */
675: slave_conn_index = _tme_stp220x_lookup_mid(stp220x, slave_mid);
676:
677: /* busy the connection to the slave: */
678: slave_conn_upa = _tme_stp220x_slave_busy_upa(stp220x, slave_conn_index);
679:
680: /* if this slave does not exist: */
681: if (__tme_predict_false(slave_conn_upa == NULL)) {
682:
683: /* complete with an error: */
684: master_completion->tme_completion_error = ENOENT;
685: _tme_stp220x_completion_validate(stp220x, master_completion);
686: }
687:
688: /* otherwise, if this master is trying to interrupt itself: */
689: else if (__tme_predict_false(slave_conn_upa == master_conn_upa)) {
690:
691: /* unbusy the connection to the slave: */
692: _tme_stp220x_slave_unbusy(stp220x);
693:
694: /* complete with an error: */
695: master_completion->tme_completion_error = EIO;
696: _tme_stp220x_completion_validate(stp220x, master_completion);
697: }
698:
699: /* otherwise, we can deliver this interrupt: */
700: else {
701:
702: /* start this cycle: */
703: assert (stp220x->tme_stp220x_master_completion == NULL);
704: stp220x->tme_stp220x_master_completion = &master_completion;
705:
706: /* when we complete, we will will complete for the master: */
707: completion = _tme_stp220x_completion_alloc(stp220x,
708: _tme_stp220x_complete_master,
709: &master_completion);
710:
711: /* leave: */
712: _tme_stp220x_leave(stp220x);
713:
714: /* deliver this interrupt: */
715: slave_conn_upa_other = (struct tme_upa_bus_connection *) slave_conn_upa->tme_upa_bus_connection.tme_bus_connection.tme_connection_other;
716: (*slave_conn_upa_other->tme_upa_bus_interrupt)
717: (slave_conn_upa_other,
718: master_conn_upa->tme_upa_bus_connection_mid,
719: data,
720: completion);
721:
722: /* reenter: */
723: stp220x = _tme_stp220x_enter_bus(&master_conn_upa->tme_upa_bus_connection);
724: }
725:
726: /* leave: */
727: _tme_stp220x_leave(stp220x);
728: }
729:
730: /* this fills a TLB entry: */
731: static void
732: _tme_stp220x_tlb_fill(struct tme_bus_connection *agent_conn_bus,
733: struct tme_bus_tlb *tlb,
734: tme_bus_addr_t agent_address_wider,
735: unsigned int cycle_type)
736: {
737: struct tme_stp220x *stp220x;
738: tme_bus_addr64_t slave_address;
739: unsigned int slave_conn_index;
740: tme_bus_addr64_t region_size_m1;
741: tme_bus_addr64_t agent_address;
742: struct tme_bus_tlb tlb_mapping;
743:
744: /* enter: */
745: stp220x = _tme_stp220x_enter_bus(agent_conn_bus);
746:
747: /* convert the agent's address into a slave connection index and
748: address: */
749: slave_address = agent_address_wider;
750: slave_conn_index = _tme_stp220x_lookup_address(stp220x, &slave_address, ®ion_size_m1);
751:
752: /* fill the TLB entry: */
753: tme_stp22xx_tlb_fill(agent_conn_bus,
754: tlb,
755: slave_conn_index,
756: slave_address,
757: cycle_type);
758:
759: /* leave: */
760: _tme_stp220x_leave(stp220x);
761:
762: /* map the filled TLB entry: */
763: agent_address = ~region_size_m1;
764: agent_address &= agent_address_wider;
765: tlb_mapping.tme_bus_tlb_addr_first = agent_address;
766: agent_address |= region_size_m1;
767: tlb_mapping.tme_bus_tlb_addr_last = agent_address;
768: #if TME_STP22XX_BUS_TRANSITION
769: tlb_mapping.tme_bus_tlb_cycles_ok = (TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE);
770: #endif /* TME_STP22XX_BUS_TRANSITION */
771: tme_bus_tlb_map(tlb, slave_address, &tlb_mapping, agent_address_wider);
772: }
773:
774: /* this handles an ebus cycle: */
775: static void
776: _tme_stp220x_ebus_cycle(struct tme_bus_connection *ebus_conn_bus,
777: struct tme_bus_cycle *cycle,
778: tme_uint32_t *_master_fast_cycle_types,
779: struct tme_completion *completion)
780: {
781: struct tme_stp220x *stp220x;
782: unsigned int upa_port;
783: tme_bus_addr32_t address;
784: tme_uint8_t value8;
785: tme_uint32_t value32;
786:
787: /* enter: */
788: stp220x = _tme_stp220x_enter_bus(ebus_conn_bus);
789:
790: /* get the address: */
791: address = cycle->tme_bus_cycle_address;
792:
793: /* get any UPA port number: */
794: upa_port = TME_STP220X_SC_ADDRESS_UPA_PORT(stp220x->tme_stp220x_eb_addr);
795:
796: /* if this is a write: */
797: if (cycle->tme_bus_cycle_type == TME_BUS_CYCLE_WRITE) {
798:
799: /* get value being written: */
800: tme_bus_cycle_xfer_memory(cycle,
801: &value8 - address,
802: address);
803:
804: /* if this is a write to EB_ADDR: */
805: if (address < sizeof(tme_uint32_t)) {
806:
807: /* update EB_ADDR: */
808: stp220x->tme_stp220x_eb_addr = value8;
809: }
810:
811: /* otherwise, if this is a write to EB_DATA: */
812: else if (address < (2 * sizeof(tme_uint32_t))) {
813:
814: /* update EB_DATA: */
815: stp220x->tme_stp220x_eb_data[address % sizeof(tme_uint32_t)] = value8;
816:
817: /* if this was a write to EB_DATA bits 0..7: */
818: if (address == ((sizeof(tme_uint32_t) * 2) - 1)) {
819:
820: /* get the EB_DATA value: */
821: value32 = stp220x->tme_stp220x_eb_data[0];
822: value32 = (value32 << 8) + stp220x->tme_stp220x_eb_data[1];
823: value32 = (value32 << 8) + stp220x->tme_stp220x_eb_data[2];
824: value32 = (value32 << 8) + stp220x->tme_stp220x_eb_data[3];
825:
826: /* dispatch on EB_ADDR: */
827: switch (stp220x->tme_stp220x_eb_addr) {
828: default:
829: /* case TME_STP220X_SC_DEBUG_PIN_CTRL: */
830: /* case TME_STP2202_SC_CC_SNPVEC: */
831: abort();
832: break;
833: case TME_STP220X_SC_CONTROL:
834:
835: /* clear any R/W1C bits: */
836: stp220x->tme_stp220x_sc_control
837: = (stp220x->tme_stp220x_sc_control
838: & ~(value32
839: & (TME_STP220X_SC_CONTROL_POR
840: | TME_STP220X_SC_CONTROL_B_POR
841: | TME_STP220X_SC_CONTROL_B_XIR
842: | TME_STP220X_SC_CONTROL_WAKEUP
843: | TME_STP220X_SC_CONTROL_FATAL)));
844:
845: /* we don't support these bits: */
846: if (value32
847: & (TME_STP220X_SC_CONTROL_IAP
848: | TME_STP220X_SC_CONTROL_EN_WKUP_POR)) {
849: abort();
850: }
851:
852: /* update the R/W bits: */
853: value32
854: = ((stp220x->tme_stp220x_sc_control
855: ^ value32)
856: & (TME_STP220X_SC_CONTROL_SOFT_POR
857: | TME_STP220X_SC_CONTROL_SOFT_XIR
858: ));
859: stp220x->tme_stp220x_sc_control ^= value32;
860:
861: /* handle any soft resets: */
862: value32 &= stp220x->tme_stp220x_sc_control;
863: value32
864: &= (TME_STP220X_SC_CONTROL_SOFT_POR
865: | TME_STP220X_SC_CONTROL_SOFT_XIR);
866: if (value32 != 0) {
867: _tme_stp220x_reset(stp220x, value32);
868: }
869: break;
870: case TME_STP220X_SC_ID:
871: case TME_STP220X_SC_PERF(0):
872: case TME_STP220X_SC_PERF(1):
873: case TME_STP220X_SC_PERFSHADOW:
874: break;
875: case TME_STP220X_SC_PERF_CTRL:
876: if (value32 & (1 << 15)) {
877: stp220x->tme_stp220x_sc_perf[1] = 0;
878: }
879: if (value32 & (1 << 7)) {
880: stp220x->tme_stp220x_sc_perf[0] = 0;
881: }
882: stp220x->tme_stp220x_sc_perf_ctrl = value32;
883: break;
884: case TME_STP220X_SC_UPA_CONFIG(TME_STP220X_UPA_PORT_CPU(0)):
885: case TME_STP220X_SC_UPA_CONFIG(TME_STP220X_UPA_PORT_CPU(1)):
886: case TME_STP220X_SC_UPA_CONFIG(TME_STP220X_UPA_PORT_IO):
887: case TME_STP220X_SC_UPA_CONFIG(TME_STP220X_UPA_PORT_FFB):
888: if (upa_port == TME_STP220X_UPA_PORT_CPU(0)
889: || upa_port == TME_STP220X_UPA_PORT_CPU(1)) {
890: value32 &= ~TME_STP220X_UPA_CONFIG_SPDQS;
891: }
892: else {
893: value32
894: &= ~(TME_STP220X_UPA_CONFIG_S_SLEEP
895: | TME_STP220X_UPA_CONFIG_SPIQS);
896: }
897: if (upa_port == TME_STP220X_UPA_PORT_FFB) {
898: value32
899: |= (TME_STP220X_UPA_CONFIG_MD
900: | TME_STP220X_UPA_CONFIG_ONEREAD);
901: }
902: if ((value32 & TME_STP220X_UPA_CONFIG_SQUEN) == 0) {
903: value32
904: = ((value32
905: & ~(TME_STP220X_UPA_CONFIG_SPRQS
906: | TME_STP220X_UPA_CONFIG_SPIQS))
907: | (stp220x->tme_stp220x_sc_upa_config[upa_port]
908: & (TME_STP220X_UPA_CONFIG_SPRQS
909: | TME_STP220X_UPA_CONFIG_SPIQS)));
910: }
911: value32
912: &= ~(TME_STP220X_UPA_CONFIG_SQUEN
913: | TME_STP220X_UPA_CONFIG_MBZ);
914: stp220x->tme_stp220x_sc_upa_config[upa_port] = value32;
915: break;
916: case TME_STP220X_SC_UPA_STATUS(TME_STP220X_UPA_PORT_CPU(0)):
917: case TME_STP220X_SC_UPA_STATUS(TME_STP220X_UPA_PORT_CPU(1)):
918: case TME_STP220X_SC_UPA_STATUS(TME_STP220X_UPA_PORT_IO):
919: case TME_STP220X_SC_UPA_STATUS(TME_STP220X_UPA_PORT_FFB):
920: stp220x->tme_stp220x_sc_upa_status[upa_port]
921: &= ~(value32
922: & (TME_STP220X_UPA_STATUS_FATAL
923: | TME_STP220X_UPA_STATUS_IADDR
924: | TME_STP220X_UPA_STATUS_IPORT
925: | TME_STP220X_UPA_STATUS_IPRTY
926: | TME_STP220X_UPA_STATUS_MC0OF
927: | TME_STP220X_UPA_STATUS_MC1OF));
928: break;
929: case TME_STP2200_SC_MC_CONTROL0:
930: stp220x->tme_stp2200_sc_mc_control[0]
931: = (value32
932: & ~((((tme_uint32_t) 2) << 30) - (1 << 16)));
933: break;
934: case TME_STP2200_SC_MC_CONTROL1:
935: stp220x->tme_stp2200_sc_mc_control[1]
936: = (value32
937: & ~((((tme_uint32_t) 2) << 31) - (1 << 13)));
938: break;
939: case TME_STP2202_SC_MEMCTRL(0x0):
940: case TME_STP2202_SC_MEMCTRL(0x1):
941: case TME_STP2202_SC_MEMCTRL(0x2):
942: case TME_STP2202_SC_MEMCTRL(0x3):
943: case TME_STP2202_SC_MEMCTRL(0x4):
944: case TME_STP2202_SC_MEMCTRL(0x5):
945: case TME_STP2202_SC_MEMCTRL(0x6):
946: case TME_STP2202_SC_MEMCTRL(0x7):
947: case TME_STP2202_SC_MEMCTRL(0x8):
948: case TME_STP2202_SC_MEMCTRL(0x9):
949: case TME_STP2202_SC_MEMCTRL(0xa):
950: case TME_STP2202_SC_MEMCTRL(0xb):
951: case TME_STP2202_SC_MEMCTRL(0xc):
952: case TME_STP2202_SC_MEMCTRL(0xd):
953: stp220x->tme_stp2202_sc_memctrl
954: [(stp220x->tme_stp220x_eb_addr
955: - TME_STP2202_SC_MEMCTRL(0x0))
956: / (TME_STP2202_SC_MEMCTRL(0x1)
957: - TME_STP2202_SC_MEMCTRL(0x0))]
958: = value32;
959: break;
960: case TME_STP2202_SC_CC_DIAG:
961: stp220x->tme_stp2202_sc_cc_diag
962: = (value32
963: & ~((2 << 14) - (1 << 0)));
964: break;
965: case TME_STP2202_SC_CC_FAULT:
966: stp220x->tme_stp2202_sc_cc_fault
967: = ((stp220x->tme_stp2202_sc_cc_fault
968: | ((2 << 27) - (1 << 13))) /* FLTIndex */
969: & (value32
970: ^ ((1 << 31) /* PERR0 */
971: | (1 << 30) /* CERR0 */
972: | (1 << 29) /* PERR1 */
973: | (1 << 28)))); /* CERR1 */
974: case TME_STP2202_SC_CC_PROC_INDEX:
975: stp220x->tme_stp2202_sc_cc_proc_index = value32;
976: break;
977: }
978: }
979: }
980:
981: /* otherwise, this must be a write to the PLL chip: */
982: else {
983: assert (address >= _tme_stp2210_mc124x9_subregion.tme_bus_subregion_address_first
984: && address <= _tme_stp2210_mc124x9_subregion.tme_bus_subregion_address_last);
985:
986: /* we can ignore all writes to the PLL chip, except for a write
987: to the PLL serial load and reset address, which is the first
988: address: */
989: if (address
990: == (tme_bus_addr32_t) _tme_stp2210_mc124x9_subregion.tme_bus_subregion_address_first) {
991:
992: /* when the PLL serial load and reset address is written, the
993: STP2210 asserts B_POR to the STP220x: */
994: _tme_stp220x_reset(stp220x, TME_STP220X_SC_CONTROL_B_POR);
995: }
996: }
997: }
998:
999: /* otherwise, this must be a read: */
1000: else {
1001: assert (cycle->tme_bus_cycle_type == TME_BUS_CYCLE_READ);
1002:
1003: /* if this is a read of EB_ADDR: */
1004: if (address < sizeof(tme_uint32_t)) {
1005:
1006: /* return EB_ADDR: */
1007: value8 = stp220x->tme_stp220x_eb_addr;
1008: }
1009:
1010: /* otherwise, if this is a read of EB_DATA: */
1011: else if (address < (2 * sizeof(tme_uint32_t))) {
1012:
1013: /* if this is a read of EB_DATA bits 24..31: */
1014: if (address == sizeof(tme_uint32_t)) {
1015:
1016: /* dispatch on EB_ADDR: */
1017: switch (stp220x->tme_stp220x_eb_addr) {
1018: default:
1019: /* case TME_STP220X_SC_DEBUG_PIN_CTRL: */
1020: /* case TME_STP2202_SC_CC_SNPVEC: */
1021: abort();
1022: case TME_STP220X_SC_CONTROL:
1023: value32 = stp220x->tme_stp220x_sc_control;
1024: break;
1025: case TME_STP220X_SC_ID:
1026: value32
1027: = (((TME_STP220X_IS_2200(stp220x)
1028: ? 0x3340
1029: : 0xacf1) << 16)
1030: + ((TME_STP220X_IS_2200(stp220x)
1031: ? 3
1032: : 4) << 12)
1033: + (1 << 4)
1034: + (1 << 0));
1035: break;
1036: case TME_STP220X_SC_PERF(0):
1037: value32 = stp220x->tme_stp220x_sc_perf[0];
1038: stp220x->tme_stp220x_sc_perfshadow = stp220x->tme_stp220x_sc_perf[1];
1039: break;
1040: case TME_STP220X_SC_PERF(1):
1041: value32 = stp220x->tme_stp220x_sc_perf[1];
1042: stp220x->tme_stp220x_sc_perfshadow = stp220x->tme_stp220x_sc_perf[0];
1043: break;
1044: case TME_STP220X_SC_PERFSHADOW:
1045: value32 = stp220x->tme_stp220x_sc_perfshadow;
1046: break;
1047: case TME_STP220X_SC_PERF_CTRL:
1048: value32 = stp220x->tme_stp220x_sc_perf_ctrl;
1049: break;
1050: case TME_STP220X_SC_UPA_CONFIG(TME_STP220X_UPA_PORT_CPU(0)):
1051: case TME_STP220X_SC_UPA_CONFIG(TME_STP220X_UPA_PORT_CPU(1)):
1052: case TME_STP220X_SC_UPA_CONFIG(TME_STP220X_UPA_PORT_IO):
1053: case TME_STP220X_SC_UPA_CONFIG(TME_STP220X_UPA_PORT_FFB):
1054: value32 = stp220x->tme_stp220x_sc_upa_config[upa_port];
1055: break;
1056: case TME_STP220X_SC_UPA_STATUS(TME_STP220X_UPA_PORT_CPU(0)):
1057: case TME_STP220X_SC_UPA_STATUS(TME_STP220X_UPA_PORT_CPU(1)):
1058: case TME_STP220X_SC_UPA_STATUS(TME_STP220X_UPA_PORT_IO):
1059: case TME_STP220X_SC_UPA_STATUS(TME_STP220X_UPA_PORT_FFB):
1060: value32 = stp220x->tme_stp220x_sc_upa_status[upa_port];
1061: break;
1062: case TME_STP2200_SC_MC_CONTROL0:
1063: value32 = stp220x->tme_stp2200_sc_mc_control[0];
1064: break;
1065: case TME_STP2200_SC_MC_CONTROL1:
1066: value32 = stp220x->tme_stp2200_sc_mc_control[1];
1067: break;
1068: case TME_STP2202_SC_CC_DIAG:
1069: value32 = stp220x->tme_stp2202_sc_cc_diag;
1070: break;
1071: case TME_STP2202_SC_CC_FAULT:
1072: value32 = stp220x->tme_stp2202_sc_cc_fault;
1073: break;
1074: case TME_STP2202_SC_CC_PROC_INDEX:
1075: value32 = stp220x->tme_stp2202_sc_cc_proc_index;
1076: break;
1077: case TME_STP2202_SC_MEMCTRL(0x0):
1078: case TME_STP2202_SC_MEMCTRL(0x1):
1079: case TME_STP2202_SC_MEMCTRL(0x2):
1080: case TME_STP2202_SC_MEMCTRL(0x3):
1081: case TME_STP2202_SC_MEMCTRL(0x4):
1082: case TME_STP2202_SC_MEMCTRL(0x5):
1083: case TME_STP2202_SC_MEMCTRL(0x6):
1084: case TME_STP2202_SC_MEMCTRL(0x7):
1085: case TME_STP2202_SC_MEMCTRL(0x8):
1086: case TME_STP2202_SC_MEMCTRL(0x9):
1087: case TME_STP2202_SC_MEMCTRL(0xa):
1088: case TME_STP2202_SC_MEMCTRL(0xb):
1089: case TME_STP2202_SC_MEMCTRL(0xc):
1090: case TME_STP2202_SC_MEMCTRL(0xd):
1091: value32
1092: = (stp220x->tme_stp2202_sc_memctrl
1093: [(stp220x->tme_stp220x_eb_addr
1094: - TME_STP2202_SC_MEMCTRL(0x0))
1095: / (TME_STP2202_SC_MEMCTRL(0x1)
1096: - TME_STP2202_SC_MEMCTRL(0x0))]);
1097: break;
1098: }
1099:
1100: /* update the EB_DATA value: */
1101: stp220x->tme_stp220x_eb_data[3] = value32;
1102: value32 >>= 8;
1103: stp220x->tme_stp220x_eb_data[2] = value32;
1104: value32 >>= 8;
1105: stp220x->tme_stp220x_eb_data[1] = value32;
1106: value32 >>= 8;
1107: stp220x->tme_stp220x_eb_data[0] = value32;
1108: }
1109:
1110: /* return the EB_DATA byte: */
1111: value8 = stp220x->tme_stp220x_eb_data[address % sizeof(tme_uint32_t)];
1112: }
1113:
1114: /* return the value: */
1115: tme_bus_cycle_xfer_memory(cycle,
1116: &value8 - address,
1117: address);
1118: }
1119:
1120: /* leave: */
1121: completion->tme_completion_error = TME_OK;
1122: _tme_stp220x_completion_validate(stp220x, completion);
1123: _tme_stp220x_leave(stp220x);
1124:
1125: /* ebus cycles can never be fast: */
1126: *_master_fast_cycle_types = 0;
1127: }
1128:
1129: /* this fills a TLB entry for the ebus connection: */
1130: static void
1131: _tme_stp220x_ebus_tlb_fill(struct tme_bus_connection *ebus_conn_bus,
1132: struct tme_bus_tlb *tlb,
1133: tme_bus_addr_t address_wider,
1134: unsigned int cycle_type)
1135: {
1136:
1137: /* initialize the TLB entry: */
1138: tme_bus_tlb_initialize(tlb);
1139:
1140: /* this TLB entry covers only this address: */
1141: /* XXX FIXME - this is because we're lazy and don't want to write
1142: the bus cycle handler to size cycles down to a byte: */
1143: tlb->tme_bus_tlb_addr_first = address_wider;
1144: tlb->tme_bus_tlb_addr_last = address_wider;
1145: }
1146:
1147: #if TME_STP22XX_BUS_TRANSITION
1148:
1149: /* this is the bus signal transition glue: */
1150: static int
1151: _tme_stp220x_signal_transition(struct tme_bus_connection *agent_conn_bus,
1152: unsigned int signal)
1153: {
1154: struct tme_completion completion_buffer;
1155: tme_completion_init(&completion_buffer);
1156: _tme_stp220x_signal(agent_conn_bus,
1157: signal,
1158: &completion_buffer);
1159: return (TME_OK);
1160: }
1161: #define _tme_stp220x_signal _tme_stp220x_signal_transition
1162:
1163: /* this is the bus cycle transition glue: */
1164: static int
1165: _tme_stp220x_cycle_transition(void *_master_conn_bus,
1166: struct tme_bus_cycle *master_cycle)
1167: {
1168: struct tme_completion completion_buffer;
1169: tme_uint32_t master_fast_cycle_types;
1170: tme_completion_init(&completion_buffer);
1171: _tme_stp220x_cycle((struct tme_bus_connection *) _master_conn_bus,
1172: master_cycle,
1173: &master_fast_cycle_types,
1174: &completion_buffer);
1175: return (completion_buffer.tme_completion_error);
1176: }
1177:
1178: /* this is the bus TLB fill transition glue: */
1179: static int
1180: _tme_stp220x_tlb_fill_transition(struct tme_bus_connection *agent_conn_bus,
1181: struct tme_bus_tlb *tlb,
1182: tme_bus_addr_t agent_address_wider,
1183: unsigned int cycle_type)
1184: {
1185: _tme_stp220x_tlb_fill(agent_conn_bus,
1186: tlb,
1187: agent_address_wider,
1188: cycle_type);
1189:
1190: /* we always handle any slow cycles: */
1191: tlb->tme_bus_tlb_cycles_ok |= cycle_type;
1192: tlb->tme_bus_tlb_addr_offset = 0;
1193: tlb->tme_bus_tlb_addr_shift = 0;
1194: tlb->tme_bus_tlb_cycle = _tme_stp220x_cycle_transition;
1195: tlb->tme_bus_tlb_cycle_private = agent_conn_bus;
1196: assert (tlb->tme_bus_tlb_fault_handler_count == 0);
1197:
1198: return (TME_OK);
1199: }
1200: #define _tme_stp220x_tlb_fill _tme_stp220x_tlb_fill_transition
1201:
1202: /* this is the ebus cycle transition glue: */
1203: static int
1204: _tme_stp220x_ebus_cycle_transition(void *_ebus_conn_bus,
1205: struct tme_bus_cycle *cycle)
1206: {
1207: struct tme_completion completion_buffer;
1208: tme_uint32_t master_fast_cycle_types;
1209: tme_completion_init(&completion_buffer);
1210: _tme_stp220x_ebus_cycle((struct tme_bus_connection *) _ebus_conn_bus,
1211: cycle,
1212: &master_fast_cycle_types,
1213: &completion_buffer);
1214: return (completion_buffer.tme_completion_error);
1215: }
1216:
1217: /* this is the ebus TLB fill transition glue: */
1218: static int
1219: _tme_stp220x_ebus_tlb_fill_transition(struct tme_bus_connection *ebus_conn_bus,
1220: struct tme_bus_tlb *tlb,
1221: tme_bus_addr_t address_wider,
1222: unsigned int cycle_type)
1223: {
1224: _tme_stp220x_ebus_tlb_fill(ebus_conn_bus,
1225: tlb,
1226: address_wider,
1227: cycle_type);
1228:
1229: /* allow reading and writing: */
1230: tlb->tme_bus_tlb_cycles_ok = TME_BUS_CYCLE_READ | TME_BUS_CYCLE_WRITE;
1231:
1232: /* our bus cycle handler: */
1233: tlb->tme_bus_tlb_cycle_private = ebus_conn_bus;
1234: tlb->tme_bus_tlb_cycle = _tme_stp220x_ebus_cycle_transition;
1235:
1236: return (TME_OK);
1237: }
1238: #define _tme_stp220x_ebus_tlb_fill _tme_stp220x_ebus_tlb_fill_transition
1239:
1240: #endif /* TME_STP22XX_BUS_TRANSITION */
1241:
1242: /* our command function: */
1243: static int
1244: _tme_stp220x_command(struct tme_element *element,
1245: const char * const * args,
1246: char **_output)
1247: {
1248: struct tme_bus_connection dummy_conn_bus;
1249: struct tme_stp220x *stp220x;
1250: int do_reset;
1251:
1252: /* enter: */
1253: dummy_conn_bus.tme_bus_connection.tme_connection_element = element;
1254: stp220x = _tme_stp220x_enter_bus(&dummy_conn_bus);
1255:
1256: /* assume no reset: */
1257: do_reset = FALSE;
1258:
1259: /* the "power" command: */
1260: if (TME_ARG_IS(args[1], "power")
1261: && args[2] == NULL) {
1262: _tme_stp220x_reset(stp220x, TME_STP220X_SC_CONTROL_POR);
1263: }
1264:
1265: /* the "reset" command: */
1266: else if (TME_ARG_IS(args[1], "reset")
1267: && args[2] == NULL) {
1268: _tme_stp220x_reset(stp220x, TME_STP220X_SC_CONTROL_B_XIR);
1269: }
1270:
1271: /* any other command: */
1272: else {
1273: if (args[1] != NULL) {
1274: tme_output_append_error(_output,
1275: "%s '%s', ",
1276: _("unknown command"),
1277: args[1]);
1278: }
1279: tme_output_append_error(_output,
1280: _("available %s commands: %s %s"),
1281: args[0],
1282: "power",
1283: "reset");
1284: return (EINVAL);
1285: }
1286:
1287: /* leave: */
1288: _tme_stp220x_leave(stp220x);
1289: return (TME_OK);
1290: }
1291:
1292: /* the connection scorer: */
1293: static int
1294: _tme_stp220x_connection_score(struct tme_connection *conn,
1295: unsigned int *_score)
1296: {
1297: struct tme_bus_connection *conn_bus;
1298: struct tme_stp220x *stp220x;
1299: struct tme_upa_bus_connection *conn_upa_other;
1300: struct tme_bus_connection *conn_bus_other;
1301: unsigned int score;
1302:
1303: /* recover the bus connection: */
1304: conn_bus = (struct tme_bus_connection *) conn;
1305:
1306: /* enter: */
1307: stp220x = _tme_stp220x_enter_bus(conn_bus);
1308:
1309: /* assume that this connection is useless: */
1310: score = 0;
1311:
1312: /* dispatch on the connection type: */
1313: conn_upa_other = (struct tme_upa_bus_connection *) conn->tme_connection_other;
1314: conn_bus_other = (struct tme_bus_connection *) conn->tme_connection_other;
1315: switch (conn->tme_connection_type) {
1316:
1317: /* this must be a UPA agent, and not another controller: */
1318: case TME_CONNECTION_BUS_UPA:
1319: if (conn_upa_other->tme_upa_bus_connection.tme_bus_tlb_set_add == NULL
1320: && conn_upa_other->tme_upa_bus_interrupt != NULL) {
1321: score = 10;
1322: }
1323: break;
1324:
1325: /* the ebus connection must be to a bus, not an agent. FFB and
1326: memory connections must be to agents, not buses: */
1327: case TME_CONNECTION_BUS_GENERIC:
1328: if ((conn_bus_other->tme_bus_tlb_set_add != NULL)
1329: == (conn->tme_connection_id == TME_STP220X_CONN_EBUS)) {
1330: score = 1;
1331: }
1332: break;
1333:
1334: default: abort();
1335: }
1336:
1337: /* leave: */
1338: _tme_stp220x_leave(stp220x);
1339: *_score = score;
1340: return (TME_OK);
1341: }
1342:
1343: /* this makes a new connection: */
1344: static int
1345: _tme_stp220x_connection_make(struct tme_connection *conn, unsigned int state)
1346: {
1347: struct tme_upa_bus_connection *conn_upa;
1348: struct tme_bus_connection *conn_bus;
1349: struct tme_stp220x *stp220x;
1350: unsigned int conn_index;
1351: const struct tme_bus_connection *conn_bus_other;
1352: tme_bus_addr64_t slave_address_last;
1353:
1354: /* ignore a half-connection: */
1355: if (state == TME_CONNECTION_HALF) {
1356: return (TME_OK);
1357: }
1358:
1359: /* recover the bus connection: */
1360: conn_upa = (struct tme_upa_bus_connection *) conn;
1361: conn_bus = (struct tme_bus_connection *) conn;
1362:
1363: /* enter: */
1364: stp220x = _tme_stp220x_enter_bus(conn_bus);
1365:
1366: /* dispatch on the connection index: */
1367: conn_index = conn->tme_connection_id;
1368: switch (conn_index) {
1369: default: assert (FALSE);
1370: case TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_CPU(0)):
1371: case TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_CPU(1)):
1372: case TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_IO):
1373: stp220x->tme_stp220x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_upa = conn_upa;
1374: break;
1375: case TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_FFB):
1376: case TME_STP220X_CONN_SIMM_GROUP(0):
1377: case TME_STP220X_CONN_SIMM_GROUP(1):
1378: case TME_STP220X_CONN_SIMM_GROUP(2):
1379: case TME_STP220X_CONN_SIMM_GROUP(3):
1380: #if TME_STP220X_SIMM_GROUP_COUNT != 4
1381: #error "TME_STP220X_SIMM_GROUP_COUNT changed"
1382: #endif
1383: conn_bus_other = (struct tme_bus_connection *) conn_bus->tme_bus_connection.tme_connection_other;
1384: slave_address_last = conn_bus_other->tme_bus_subregions.tme_bus_subregion_address_last;
1385: stp220x->tme_stp220x_conn_address_last[conn_index] = slave_address_last;
1386: assert (conn_bus_other->tme_bus_subregions.tme_bus_subregion_address_first == 0);
1387: assert (slave_address_last > 0
1388: && (((slave_address_last + 1) & slave_address_last) == 0)
1389: && (conn_index == TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_FFB)
1390: || slave_address_last < (((tme_uint32_t) 1) << TME_STP220X_SIMM_GROUP_SIZE_LOG2(stp220x))));
1391: assert (conn_bus_other->tme_bus_subregions.tme_bus_subregion_next == NULL);
1392: case TME_STP220X_CONN_EBUS:
1393: stp220x->tme_stp220x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus = conn_bus;
1394: break;
1395: }
1396:
1397: /* leave: */
1398: _tme_stp220x_leave(stp220x);
1399: return (TME_OK);
1400: }
1401:
1402: /* this breaks a connection: */
1403: static int
1404: _tme_stp220x_connection_break(struct tme_connection *conn, unsigned int state)
1405: {
1406: abort();
1407: }
1408:
1409: /* this makes new connection sides: */
1410: static int
1411: _tme_stp220x_connections_new(struct tme_element *element,
1412: const char * const *args,
1413: struct tme_connection **_conns,
1414: char **_output)
1415: {
1416: int rc;
1417: struct tme_stp220x *stp220x;
1418: struct tme_upa_bus_connection *conn_upa;
1419: struct tme_bus_connection *conn_bus;
1420: struct tme_connection *conn;
1421: tme_bus_addr_t address;
1422: unsigned int conn_index;
1423: tme_bus_addr64_t region_size_m1;
1424:
1425: /* assume that we will succeed: */
1426: rc = TME_OK;
1427:
1428: /* recover our data structure: */
1429: stp220x = (struct tme_stp220x *) element->tme_element_private;
1430:
1431: /* lock the mutex: */
1432: tme_mutex_lock(&stp220x->tme_stp220x.tme_stp22xx_mutex);
1433:
1434: /* if we have no arguments, this is the ebus connection: */
1435: if (args[1] == NULL) {
1436:
1437: /* if an ebus connection has already been made: */
1438: if (stp220x->tme_stp220x.tme_stp22xx_conns[TME_STP220X_CONN_EBUS].tme_stp22xx_conn_bus != NULL) {
1439: rc = EEXIST;
1440: }
1441:
1442: /* otherwise, the ebus connection hasn't already been made: */
1443: else {
1444:
1445: /* create our side of a generic bus connection: */
1446: conn_bus = tme_new0(struct tme_bus_connection, 1);
1447: conn_bus->tme_bus_connection.tme_connection_type = TME_CONNECTION_BUS_GENERIC;
1448:
1449: /* fill in the generic bus connection: */
1450: conn_bus->tme_bus_subregions.tme_bus_subregion_address_first = 0;
1451: conn_bus->tme_bus_subregions.tme_bus_subregion_address_last = (sizeof(tme_uint32_t) * 2) - 1;
1452: conn_bus->tme_bus_subregions.tme_bus_subregion_next = &_tme_stp2210_mc124x9_subregion;
1453: conn_bus->tme_bus_signals_add = NULL;
1454: conn_bus->tme_bus_signal = NULL;
1455: conn_bus->tme_bus_intack = NULL;
1456: conn_bus->tme_bus_tlb_set_add = NULL;
1457: conn_bus->tme_bus_tlb_fill = _tme_stp220x_ebus_tlb_fill;
1458:
1459: /* fill in the generic connection: */
1460: conn = &conn_bus->tme_bus_connection;
1461: conn->tme_connection_id = TME_STP220X_CONN_EBUS;
1462: conn->tme_connection_score = _tme_stp220x_connection_score;
1463: conn->tme_connection_make = _tme_stp220x_connection_make;
1464: conn->tme_connection_break = _tme_stp220x_connection_break;
1465:
1466: /* add in this connection side possibility: */
1467: conn->tme_connection_next = *_conns;
1468: *_conns = conn;
1469: }
1470: }
1471:
1472: /* otherwise, if this is a UPA bus connection: */
1473: else if (TME_ARG_IS(args[1], "addr")
1474: && ((address
1475: = tme_bus_addr_parse(args[2], 0 - (tme_uint64_t) 1))
1476: != (0 - (tme_uint64_t) 1))
1477: && args[3] == NULL) {
1478:
1479: /* convert the address into a connection index and address: */
1480: conn_index = _tme_stp220x_lookup_address(stp220x, &address, ®ion_size_m1);
1481:
1482: /* if this connection is reserved: */
1483: if (conn_index == TME_STP220X_CONN_NULL) {
1484: rc = EINVAL;
1485: }
1486:
1487: /* otherwise, if this connection is already made: */
1488: else if (stp220x->tme_stp220x.tme_stp22xx_conns[conn_index].tme_stp22xx_conn_bus != NULL) {
1489: rc = EEXIST;
1490: }
1491:
1492: /* otherwise, this connection hasn't been made yet: */
1493: else {
1494:
1495: /* if this is a CPU or IO connection: */
1496: if (conn_index == TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_IO)
1497: || conn_index == TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_CPU(0))
1498: || conn_index == TME_STP220X_CONN_UPA_PORT(TME_STP220X_UPA_PORT_CPU(1))) {
1499:
1500: /* create our side of a UPA connection: */
1501: conn_upa = tme_new0(struct tme_upa_bus_connection, 1);
1502: conn_upa->tme_upa_bus_interrupt = _tme_stp220x_interrupt;
1503: conn_upa->tme_upa_bus_connection_mid = _tme_stp220x_conn_index_mid(stp220x, conn_index);
1504: conn_bus = &conn_upa->tme_upa_bus_connection;
1505: conn_bus->tme_bus_connection.tme_connection_type = TME_CONNECTION_BUS_UPA;
1506: }
1507:
1508: /* otherwise, this is an FFB or memory connection: */
1509: else {
1510:
1511: /* create our side of a generic bus connection: */
1512: conn_bus = tme_new0(struct tme_bus_connection, 1);
1513: conn_bus->tme_bus_connection.tme_connection_type = TME_CONNECTION_BUS_GENERIC;
1514: }
1515:
1516: /* fill in the generic bus connection: */
1517: conn_bus->tme_bus_signals_add = NULL;
1518: conn_bus->tme_bus_signal = _tme_stp220x_signal;
1519: conn_bus->tme_bus_intack = NULL;
1520: conn_bus->tme_bus_tlb_set_add = tme_stp22xx_tlb_set_add;
1521: conn_bus->tme_bus_tlb_fill = _tme_stp220x_tlb_fill;
1522:
1523: /* fill in the generic connection: */
1524: conn = &conn_bus->tme_bus_connection;
1525: conn->tme_connection_id = conn_index;
1526: conn->tme_connection_score = _tme_stp220x_connection_score;
1527: conn->tme_connection_make = _tme_stp220x_connection_make;
1528: conn->tme_connection_break = _tme_stp220x_connection_break;
1529:
1530: /* add in this connection side possibility: */
1531: conn->tme_connection_next = *_conns;
1532: *_conns = conn;
1533: }
1534: }
1535:
1536: /* otherwise, the arguments are unknown: */
1537: else {
1538: tme_output_append_error(_output,
1539: "%s %s [ addr %s ]",
1540: _("usage:"),
1541: args[0],
1542: _("BUS-ADDRESS"));
1543: rc = EINVAL;
1544: }
1545:
1546: /* unlock the mutex: */
1547: tme_mutex_unlock(&stp220x->tme_stp220x.tme_stp22xx_mutex);
1548:
1549: return (rc);
1550: }
1551:
1552: /* this creates a new stp220x element: */
1553: static int
1554: _tme_stp220x_new(struct tme_element *element,
1555: const char * const *args,
1556: const void *extra,
1557: char **_output,
1558: unsigned int is_2200)
1559: {
1560: struct tme_stp220x *stp220x;
1561: int arg_i;
1562: int usage;
1563:
1564: /* check our arguments: */
1565: usage = 0;
1566: arg_i = 1;
1567: for (;;) {
1568:
1569: if (0) {
1570: }
1571:
1572: /* if we ran out of arguments: */
1573: else if (args[arg_i] == NULL) {
1574:
1575: break;
1576: }
1577:
1578: /* otherwise this is a bad argument: */
1579: else {
1580: tme_output_append_error(_output,
1581: _("%s unexpected, "),
1582: args[arg_i]);
1583: usage = TRUE;
1584: break;
1585: }
1586: }
1587:
1588: if (usage) {
1589: tme_output_append_error(_output,
1590: "%s %s",
1591: _("usage:"),
1592: args[0]);
1593: return (EINVAL);
1594: }
1595:
1596: /* start the stp220x structure: */
1597: stp220x = tme_new0(struct tme_stp220x, 1);
1598: stp220x->tme_stp220x.tme_stp22xx_element = element;
1599: stp220x->tme_stp220x.tme_stp22xx_run = _tme_stp220x_run;
1600: tme_stp22xx_init(&stp220x->tme_stp220x,
1601: sizeof(struct tme_stp220x),
1602: TME_STP220X_CONN_NULL);
1603:
1604: /* set the type: */
1605: stp220x->tme_stp220x_is_2200 = is_2200;
1606: if (TME_STP220X_IS_2200(stp220x) != is_2200) {
1607: tme_free(stp220x);
1608: return (ENXIO);
1609: }
1610:
1611: /* initialize the last address in each connection to all-bits-one: */
1612: memset (stp220x->tme_stp220x_conn_address_last,
1613: 0xff,
1614: sizeof(stp220x->tme_stp220x_conn_address_last));
1615:
1616: /* fill the element: */
1617: element->tme_element_private = stp220x;
1618: element->tme_element_connections_new = _tme_stp220x_connections_new;
1619: element->tme_element_command = _tme_stp220x_command;
1620:
1621: return (TME_OK);
1622: }
1623:
1624: /* this creates a new stp2200 element: */
1625: TME_ELEMENT_X_NEW_DECL(tme_ic_,stp22xx,stp2200) {
1626: return (_tme_stp220x_new(element, args, extra, _output, TRUE));
1627: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.