unsigned int unipro_cport_count(void) { /* * Reduce the run-time CPort count to what's available on the * GPBridges, unless we can determine that we're running on an * APBridge. */ return ((tsb_get_product_id() == tsb_pid_apbridge) ? APBRIDGE_CPORT_MAX : GPBRIDGE_CPORT_MAX); }
static void sdb_fixups(void) { /** * DETECT_IN is not working on both GPBridges on the SDB. The workaround * is to pull up GPIO24. * * Documentation related to this fix (items 33 and 44) * https://docs.google.com/spreadsheets/d/1BBVHjFZu6GEUDCua8WlXHl9TmGYdpUwQXF82NXWEI-o/edit#gid=779323147 * * This change will have no impact on BDB2{A,B} since the GPIO24 is * only connected to a test point. */ if (tsb_get_product_id() == tsb_pid_gpbridge) { modifyreg32(TSB_IO_PULL_UPDOWN_ENABLE0, TSB_IO_PULL_UPDOWN_GPIO(24), 0); modifyreg32(TSB_IO_PULL_UPDOWN0, 0, TSB_IO_PULL_UPDOWN_GPIO(24)); } /** * When attached to the 96Boards Expansion Header on the SDB, Helium is * held in reset unless HELIUM_EXT_NRST_BTN_GPIO is pulled high or * driven high on APBridgeA. * * Rob Herring indicates that this behavior is the opposite of the * 96Boards specification, which would suggest active low. * * We'll pull the pin high, as that's less aggressive and avoids * the need to enable the GPIO subsystem at this point in the boot * sequence. * * This change should have no impact on BDB2{A,B} since on APBridgeA, * HELIUM_EXT_NRST_BTN_GPIO is only connected to a test point. */ #ifdef CONFIG_APBRIDGEA if (tsb_get_product_id() == tsb_pid_apbridge) { modifyreg32(TSB_IO_PULL_UPDOWN_ENABLE0, TSB_IO_PULL_UPDOWN_GPIO(HELIUM_EXT_NRST_BTN_GPIO), 0); modifyreg32(TSB_IO_PULL_UPDOWN0, 0, TSB_IO_PULL_UPDOWN_GPIO(HELIUM_EXT_NRST_BTN_GPIO)); } #endif }
static void configure_transfer_mode(int mode) { /* * Set transfer mode 2 */ switch (mode) { case 2: unipro_write(AHM_MODE_CTRL_0, TRANSFER_MODE_2_CTRL_0); if (tsb_get_product_id() == tsb_pid_apbridge) { unipro_write(AHM_MODE_CTRL_1, TRANSFER_MODE_2_CTRL_1); unipro_write(AHM_MODE_CTRL_2, TRANSFER_MODE_2_CTRL_2); } break; default: lldbg("Unsupported transfer mode: %u\n", mode); break; } }
unsigned int unipro_cport_count(void) { uint32_t num_cports; int retval; if (tsb_get_rev_id() == tsb_rev_es2) { /* T_NUMCPORTS is incorrect on es2 */ /* * Reduce the run-time CPort count to what's available on the * GPBridges, unless we can determine that we're running on an * APBridge. */ return ((tsb_get_product_id() == tsb_pid_apbridge) ? ES2_APBRIDGE_CPORT_MAX : ES2_GPBRIDGE_CPORT_MAX); } retval = unipro_attr_local_read(T_NUMCPORTS, &num_cports, 0); if (retval) { lowsyslog("unipro: cannot determine number of cports\n"); return 0; } return num_cports; }
/** * @brief Initialize the UniPro core */ void unipro_init(void) { unsigned int i; int retval; struct cport *cport; /* * Compute and cache the number of CPorts that this bridge has, for use * by the functions in this source file. The value does not change. */ if (cport_count == 0) cport_count = unipro_cport_count(); cporttable = zalloc(sizeof(struct cport) * cport_count); if (!cporttable) { return; } retval = unipro_tx_init(); if (retval) { free(cporttable); cporttable = NULL; return; } for (i = 0; i < cport_count; i++) { cport = &cporttable[i]; cport->tx_buf = CPORT_TX_BUF(i); cport->cportid = i; cport->connected = 0; list_init(&cport->tx_fifo); } unipro_write(LUP_INT_EN, 0x1); /* * Set transfer mode 2 on all cports * Receiver choses address for received message * Header is delivered transparently to receiver (and used to carry the first eight * L4 payload bytes) */ DEBUGASSERT(TRANSFER_MODE == 2); configure_transfer_mode(TRANSFER_MODE); /* * Initialize cports. */ unipro_write(UNIPRO_INT_EN, 0x0); for (i = 0; i < cport_count; i++) { unipro_init_cport(i); } unipro_write(UNIPRO_INT_EN, 0x1); /* * Disable FCT transmission. See ENG-376. */ unipro_write(CPB_RX_E2EFC_EN_0, 0x0); if (tsb_get_product_id() == tsb_pid_apbridge) { unipro_write(CPB_RX_E2EFC_EN_1, 0x0); } irq_attach(TSB_IRQ_UNIPRO, irq_unipro); up_enable_irq(TSB_IRQ_UNIPRO); #ifdef UNIPRO_DEBUG unipro_info(); #endif lldbg("UniPro enabled\n"); }
/** * @brief UniPro debug dump */ static void dump_regs(void) { uint32_t val; unsigned int i; #define DBG_ATTR(attr) do { \ (void)unipro_attr_local_read(attr, &val, 0); \ lldbg(" [%s]: 0x%x\n", #attr, val); \ } while (0); #define DBG_CPORT_ATTR(attr, cportid) do { \ unipro_attr_local_read(attr, &val, cportid); \ lldbg(" [%s]: 0x%x\n", #attr, val); \ } while (0); #define REG_DBG(reg) do { \ val = unipro_read(reg); \ lldbg(" [%s]: 0x%x\n", #reg, val); \ } while (0) lldbg("DME Attributes\n"); lldbg("========================================\n"); DBG_ATTR(PA_ACTIVETXDATALANES); DBG_ATTR(PA_ACTIVERXDATALANES); DBG_ATTR(PA_TXGEAR); DBG_ATTR(PA_TXTERMINATION); DBG_ATTR(PA_HSSERIES); DBG_ATTR(PA_PWRMODE); DBG_ATTR(PA_ACTIVERXDATALANES); DBG_ATTR(PA_RXGEAR); DBG_ATTR(PA_RXTERMINATION); DBG_ATTR(PA_PWRMODEUSERDATA0); DBG_ATTR(N_DEVICEID); DBG_ATTR(N_DEVICEID_VALID); DBG_ATTR(DME_DDBL1_REVISION); DBG_ATTR(DME_DDBL1_LEVEL); DBG_ATTR(DME_DDBL1_DEVICECLASS); DBG_ATTR(DME_DDBL1_MANUFACTURERID); DBG_ATTR(DME_DDBL1_PRODUCTID); DBG_ATTR(DME_DDBL1_LENGTH); DBG_ATTR(TSB_DME_DDBL2_A); DBG_ATTR(TSB_DME_DDBL2_B); DBG_ATTR(TSB_MAILBOX); DBG_ATTR(TSB_MAXSEGMENTCONFIG); DBG_ATTR(TSB_DME_POWERMODEIND); lldbg("Unipro Interrupt Info:\n"); lldbg("========================================\n"); REG_DBG(UNIPRO_INT_EN); REG_DBG(AHM_RX_EOM_INT_EN_0); REG_DBG(AHM_RX_EOM_INT_EN_1); REG_DBG(UNIPRO_INT_BEF); REG_DBG(AHS_TIMEOUT_INT_BEF_0); REG_DBG(AHS_TIMEOUT_INT_BEF_1); REG_DBG(AHM_HRESP_ERR_INT_BEF_0); REG_DBG(AHM_HRESP_ERR_INT_BEF_1); REG_DBG(CPB_RX_E2EFC_RSLT_ERR_INT_BEF_0); REG_DBG(CPB_RX_E2EFC_RSLT_ERR_INT_BEF_1); REG_DBG(CPB_TX_RSLTCODE_ERR_INT_BEF_0); REG_DBG(CPB_TX_RSLTCODE_ERR_INT_BEF_1); REG_DBG(CPB_RX_MSGST_ERR_INT_BEF_0); REG_DBG(CPB_RX_MSGST_ERR_INT_BEF_1); REG_DBG(LUP_INT_BEF); REG_DBG(A2D_ATTRACS_INT_BEF); REG_DBG(AHM_RX_EOM_INT_BEF_0); REG_DBG(AHM_RX_EOM_INT_BEF_1); REG_DBG(AHM_RX_EOM_INT_BEF_2); REG_DBG(AHM_RX_EOT_INT_BEF_0); REG_DBG(AHM_RX_EOT_INT_BEF_1); lldbg("Unipro Registers:\n"); lldbg("========================================\n"); REG_DBG(AHM_MODE_CTRL_0); if (tsb_get_product_id() == tsb_pid_apbridge) { REG_DBG(AHM_MODE_CTRL_1); REG_DBG(AHM_MODE_CTRL_2); } REG_DBG(AHM_ADDRESS_00); REG_DBG(REG_RX_PAUSE_SIZE_00); REG_DBG(CPB_RX_TRANSFERRED_DATA_SIZE_00); REG_DBG(CPB_TX_BUFFER_SPACE_00); REG_DBG(CPB_TX_RESULTCODE_0); REG_DBG(AHS_HRESP_MODE_0); REG_DBG(AHS_TIMEOUT_00); REG_DBG(CPB_TX_E2EFC_EN_0); REG_DBG(CPB_TX_E2EFC_EN_1); REG_DBG(CPB_RX_E2EFC_EN_0); REG_DBG(CPB_RX_E2EFC_EN_1); REG_DBG(CPORT_STATUS_0); REG_DBG(CPORT_STATUS_1); REG_DBG(CPORT_STATUS_2); lldbg("Connected CPorts:\n"); lldbg("========================================\n"); for (i = 0; i < cport_count; i++) { struct cport *cport = cport_handle(i); if (!cport) { continue; } val = cport_get_status(cport); if (val == CPORT_STATUS_CONNECTED) { lldbg("CPORT %u:\n", i); DBG_CPORT_ATTR(T_PEERDEVICEID, i); DBG_CPORT_ATTR(T_PEERCPORTID, i); DBG_CPORT_ATTR(T_TRAFFICCLASS, i); DBG_CPORT_ATTR(T_CPORTFLAGS, i); DBG_CPORT_ATTR(T_LOCALBUFFERSPACE, i); DBG_CPORT_ATTR(T_PEERBUFFERSPACE, i); DBG_CPORT_ATTR(T_CREDITSTOSEND, i); DBG_CPORT_ATTR(T_RXTOKENVALUE, i); DBG_CPORT_ATTR(T_TXTOKENVALUE, i); DBG_CPORT_ATTR(T_CONNECTIONSTATE, i); } } lldbg("NVIC:\n"); lldbg("========================================\n"); tsb_dumpnvic(); }