|
|
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.