void octeon_set_baud(uint32_t uart, uint32_t baud) { uint16_t divisor; uint8_t uart_index = GET_UART_INDEX(uart); uint8_t node = GET_UART_NODE(uart); cvmx_uart_lcr_t lcrval; divisor = compute_divisor(octeon_get_ioclk_hz(), baud); lcrval.u64 = cvmx_read_csr_node(node, CVMX_MIO_UARTX_LCR(uart_index)); cvmx_wait((2 * divisor * 16) + 10000); lcrval.s.dlab = 1; /* temporary to program the divisor */ cvmx_write_csr_node(node, CVMX_MIO_UARTX_LCR(uart_index), lcrval.u64); cvmx_write_csr_node(node, CVMX_MIO_UARTX_DLL(uart_index), divisor & 0xff); cvmx_write_csr_node(node, CVMX_MIO_UARTX_DLH(uart_index), (divisor >> 8) & 0xff); /* divisor is programmed now, set this back to normal */ lcrval.s.dlab = 0; cvmx_write_csr_node(node, CVMX_MIO_UARTX_LCR(uart_index), lcrval.u64); #ifndef CONFIG_OCTEON_SIM_SPEED /* spec says need to wait after you program the divisor */ cvmx_wait((2 * divisor * 16) + 10000); /* Wait a little longer..... */ mdelay(5); #endif }
/** * Get a single byte from serial port. * * @param uart_index Uart to read from (0 or 1) * @return The byte read */ static inline uint8_t uart_read_byte(int uart) { cvmx_uart_lsr_t lsrval; uint8_t uart_index = GET_UART_INDEX(uart); uint8_t node = GET_UART_NODE(uart); /* Spin until data is available */ do { lsrval.u64 = cvmx_read_csr_node(node, CVMX_MIO_UARTX_LSR(uart_index)); WATCHDOG_RESET(); octeon_board_poll(); } while (!lsrval.s.dr); /* Read and return the data */ return cvmx_read_csr_node(node, CVMX_MIO_UARTX_RBR(uart_index)); }
/** * Get clock rate based on the clock type. * * @param node - CPU node number * @param clock - Enumeration of the clock type. * @return - return the clock rate. */ uint64_t cvmx_clock_get_rate_node(int node, cvmx_clock_t clock) { const uint64_t REF_CLOCK = 50000000; #ifdef CVMX_BUILD_FOR_UBOOT uint64_t rate_eclk = 0; uint64_t rate_sclk = 0; uint64_t rate_dclk = 0; #endif if (cvmx_unlikely(!rate_eclk)) { /* Note: The order of these checks is important. ** octeon_has_feature(OCTEON_FEATURE_PCIE) is true for both 6XXX ** and 52XX/56XX, so OCTEON_FEATURE_NPEI _must_ be checked first */ if (octeon_has_feature(OCTEON_FEATURE_NPEI)) { cvmx_npei_dbg_data_t npei_dbg_data; npei_dbg_data.u64 = cvmx_read_csr(CVMX_PEXP_NPEI_DBG_DATA); rate_eclk = REF_CLOCK * npei_dbg_data.s.c_mul; rate_sclk = rate_eclk; } else if (OCTEON_IS_OCTEON3()) { cvmx_rst_boot_t rst_boot; rst_boot.u64 = cvmx_read_csr_node(node, CVMX_RST_BOOT); rate_eclk = REF_CLOCK * rst_boot.s.c_mul; rate_sclk = REF_CLOCK * rst_boot.s.pnr_mul; } else if (octeon_has_feature(OCTEON_FEATURE_PCIE)) { cvmx_mio_rst_boot_t mio_rst_boot; mio_rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT); rate_eclk = REF_CLOCK * mio_rst_boot.s.c_mul; rate_sclk = REF_CLOCK * mio_rst_boot.s.pnr_mul; } else { cvmx_dbg_data_t dbg_data; dbg_data.u64 = cvmx_read_csr(CVMX_DBG_DATA); rate_eclk = REF_CLOCK * dbg_data.s.c_mul; rate_sclk = rate_eclk; } } switch (clock) { case CVMX_CLOCK_SCLK: case CVMX_CLOCK_TIM: case CVMX_CLOCK_IPD: return rate_sclk; case CVMX_CLOCK_RCLK: case CVMX_CLOCK_CORE: return rate_eclk; case CVMX_CLOCK_DDR: #if !defined(CVMX_BUILD_FOR_LINUX_HOST) && !defined(CVMX_BUILD_FOR_TOOLCHAIN) if (cvmx_unlikely(!rate_dclk)) rate_dclk = cvmx_sysinfo_get()->dram_data_rate_hz; #endif return rate_dclk; } cvmx_dprintf("cvmx_clock_get_rate: Unknown clock type\n"); return 0; }
static int octeon_serial_tstc(void) { cvmx_uart_lsr_t lsrval; uint8_t uart_index = GET_UART_INDEX(gd->arch.console_uart); uint8_t node = GET_UART_NODE(gd->arch.console_uart); octeon_board_poll(); WATCHDOG_RESET(); lsrval.u64 = cvmx_read_csr_node(node, CVMX_MIO_UARTX_LSR(uart_index)); return lsrval.s.dr; }
/** * Put a single byte to uart port. * * @param uart_index Uart to write to (0 or 1) * @param ch Byte to write */ static inline void uart_write_byte(int uart, uint8_t ch) { cvmx_uart_lsr_t lsrval; uint8_t uart_index = GET_UART_INDEX(uart); uint8_t node = GET_UART_NODE(uart); /* Spin until there is room */ do { lsrval.u64 = cvmx_read_csr_node(node, CVMX_MIO_UARTX_LSR(uart_index)); } while (lsrval.s.thre == 0); WATCHDOG_RESET(); /* Write the byte */ cvmx_write_csr_node(node, CVMX_MIO_UARTX_THR(uart_index), ch); }
/** * Function that does the real work of setting up the Octeon uart. * Takes all parameters as arguments, so it does not require gd * structure to be set up. * * @param uart_index Index of uart to configure * @param cpu_clock_hertz * CPU clock frequency in Hz * @param baudrate Baudrate to configure * * @return 0 on success * !0 on error */ int octeon_uart_setup2(int uart, int cpu_clock_hertz, int baudrate) { uint16_t divisor; cvmx_uart_fcr_t fcrval; cvmx_uart_mcr_t mcrval; cvmx_uart_lcr_t lcrval; uint8_t uart_index = GET_UART_INDEX(uart); uint8_t node = GET_UART_NODE(uart); #if !CONFIG_OCTEON_SIM_SPEED uint64_t read_cycle; #endif fcrval.u64 = 0; fcrval.s.en = 1; /* enable the FIFO's */ fcrval.s.rxfr = 1; /* reset the RX fifo */ fcrval.s.txfr = 1; /* reset the TX fifo */ divisor = compute_divisor(cpu_clock_hertz, baudrate); cvmx_write_csr_node(node, CVMX_MIO_UARTX_FCR(uart_index), fcrval.u64); mcrval.u64 = 0; #if CONFIG_OCTEON_SIM_SETUP if (uart_index == 1) mcrval.s.afce = 1; /* enable auto flow control for * simulator. Needed for gdb * regression callfuncs.exp. */ else mcrval.s.afce = 0; /* disable auto flow control so board * can power on without serial port * connected */ #else mcrval.s.afce = 0; /* disable auto flow control so board can power * on without serial port connected */ #endif mcrval.s.rts = 1; /* looks like this must be set for auto flow * control to work */ cvmx_read_csr_node(node, CVMX_MIO_UARTX_LSR(uart_index)); lcrval.u64 = 0; lcrval.s.cls = CVMX_UART_BITS8; lcrval.s.stop = 0; /* stop bit included? */ lcrval.s.pen = 0; /* no parity? */ lcrval.s.eps = 1; /* even parity? */ lcrval.s.dlab = 1; /* temporary to program the divisor */ cvmx_write_csr_node(node, CVMX_MIO_UARTX_LCR(uart_index), lcrval.u64); cvmx_write_csr_node(node, CVMX_MIO_UARTX_DLL(uart_index), divisor & 0xff); cvmx_write_csr_node(node, CVMX_MIO_UARTX_DLH(uart_index), (divisor >> 8) & 0xff); /* divisor is programmed now, set this back to normal */ lcrval.s.dlab = 0; cvmx_write_csr_node(node, CVMX_MIO_UARTX_LCR(uart_index), lcrval.u64); #if !CONFIG_OCTEON_SIM_SPEED /* spec says need to wait after you program the divisor */ read_cycle = octeon_get_cycles() + (2 * divisor * 16) + 10000; while (octeon_get_cycles() < read_cycle) { /* Spin */ } #endif /* Don't enable flow control until after baud rate is configured. - we * don't want to allow characters in until after the baud rate is * fully configured */ cvmx_write_csr_node(node, CVMX_MIO_UARTX_MCR(uart_index), mcrval.u64); return 0; }
void init_octeon_pcie(void) { int first_busno; int i; int rc = 0; int node = cvmx_get_node_num(); struct pci_controller *hose; int pcie_port; first_busno = OCTEON_FIRST_PCIE_BUSNO; memset(&hose_pcie[0], 0, sizeof(hose_pcie[0]) * num_pcie_ports); debug("Starting PCIE on node %d\n", node); for (i = 0; i < num_pcie_ports; i++) { pcie_port = ((node << 4) | i); rc = cvmx_pcie_rc_initialize(pcie_port); if (rc != 0) continue; mdelay(1000); /* Should delay 1 second according to standard */ hose = &hose_pcie[i]; hose->priv_data = (void *)&oct_pcie_data[i]; oct_pcie_data[i].pcie_port = pcie_port;; hose->config_table = pci_board_config_table; hose->first_busno = first_busno; hose->last_busno = 0xff; /* PCI I/O space (Sub-DID == 2) */ pci_set_region(hose->regions + 0, octeon_pcie_region_info[i].io_base, octeon_pcie_region_info[i].io_base, octeon_pcie_region_info[i].io_size, PCI_REGION_IO); /* PCI memory space (Sub-DID == 3) */ pci_set_region(hose->regions + 1, octeon_pcie_region_info[i].mem_base, octeon_pcie_region_info[i].mem_base, octeon_pcie_region_info[i].mem_size, PCI_REGION_MEM); hose->region_count = 2; pci_set_ops(hose, octeon_pcie_read_config_byte, octeon_pcie_read_config_word, octeon_pcie_read_config_dword, octeon_pcie_write_config_byte, octeon_pcie_write_config_word, octeon_pcie_write_config_dword); pci_register_hose(hose); hose->last_busno = pci_hose_scan(hose); debug("PCIe: port=%d, first_bus=%d, last_bus=%d,\n\t" "mem_base=0x%x, mem_size=0x%x, io_base=0x%x, io_size=0x%x\n", octeon_get_pcie_port(hose), hose->first_busno, hose->last_busno, octeon_pcie_region_info[i].mem_base, octeon_pcie_region_info[i].mem_size, octeon_pcie_region_info[i].io_base, octeon_pcie_region_info[i].io_size); first_busno = hose->last_busno + 1; #if CONFIG_OCTEON_PCI_ENABLE_32BIT_MAPPING if (OCTEON_IS_OCTEON2() || OCTEON_IS_OCTEON3()) { cvmx_pemx_bar_ctl_t bar_ctl; cvmx_pemx_bar1_indexx_t pemx_bar1_indexx; uint64_t bar_base; int j; /* Setup BAR1 to map bus address 0x0 to the base of * u-boot's TLB mapping. This allows us to have u-boot * located anywhere in memory (including above 32 bit * addressable space) and still have 32 bit PCI devices * have access to memory that is statically allocated * or malloced by u-boot, both of which are TLB mapped. */ cvmx_write_csr_node(node, CVMX_PEMX_P2N_BAR1_START(i), 0); /* Disable bar0/bar2, as we are not using them here */ cvmx_write_csr_node(node, CVMX_PEMX_P2N_BAR0_START(i), -1); cvmx_write_csr_node(node, CVMX_PEMX_P2N_BAR2_START(i), -1); /* Select 64 MByte mapping size for bar 1 on * all ports */ bar_ctl.u64 = cvmx_read_csr_node(node, CVMX_PEMX_BAR_CTL(i)); bar_ctl.s.bar1_siz = 1; /* 64MB */ bar_ctl.s.bar2_enb = 0; cvmx_write_csr_node(node, CVMX_PEMX_BAR_CTL(i), bar_ctl.u64); /* Configure the regions in bar 1 to map to the * DRAM used by u-boot. */ /* Round down to 4MByte boundary to meet BAR mapping * requirements */ bar_base = gd->bd->bi_uboot_ram_addr & ~0x3fffffull; debug("pcie: port %d, setting BAR base to 0x%llx\n", i, bar_base); pemx_bar1_indexx.u64 = 0; pemx_bar1_indexx.s.addr_v = 1; pemx_bar1_indexx.s.end_swp = 1; pemx_bar1_indexx.s.ca = 1; for (j = 0; j < 16; j++) { pemx_bar1_indexx.s.addr_idx = (bar_base + 4 * 1024 * 1024 * j) >> 22; cvmx_write64_uint64(CVMX_PEMX_BAR1_INDEXX(j, i), pemx_bar1_indexx.u64); } } #endif /* CONFIG_OCTEON_PCI_ENABLE_32BIT_MAPPING */ }