Esempio n. 1
0
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
}
Esempio n. 2
0
/**
 * 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));
}
Esempio n. 3
0
/**
 * 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;
}
Esempio n. 4
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;
}
Esempio n. 5
0
/**
 * 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);
}
Esempio n. 6
0
/**
 * 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;

}
Esempio n. 7
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 */
	}