From bdb5addd5ba1239754c5012bf988f1c1853fb53d Mon Sep 17 00:00:00 2001 From: Travis Geiselbrecht Date: Thu, 29 May 2014 15:32:32 -0700 Subject: [PATCH] [platform][zynq] initial implementation of some clock routines -Mostly introspection at this point -Move target specific jam table to early platform init --- platform/zynq/clocks.c | 277 ++++++++++++++++++++++++++ platform/zynq/include/platform/zynq.h | 229 +++++++++++++++++++++ platform/zynq/platform.c | 10 +- platform/zynq/uart.c | 81 +++----- target/zybo/rules.mk | 2 +- target/zybo/target.c | 3 - 6 files changed, 544 insertions(+), 58 deletions(-) diff --git a/platform/zynq/clocks.c b/platform/zynq/clocks.c index bf4a72c9..2bb2b458 100644 --- a/platform/zynq/clocks.c +++ b/platform/zynq/clocks.c @@ -21,10 +21,287 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include +#include #include +#include +#include +#include #include #include #include #include #include +#define LOCAL_TRACE 0 + +static uint32_t get_arm_pll_freq(void) +{ + LTRACEF("ARM_PLL_CTRL 0x%x\n", SLCR_REG(ARM_PLL_CTRL)); + + // XXX test that the pll is actually enabled + + uint32_t fdiv = BITS_SHIFT(SLCR_REG(ARM_PLL_CTRL), 18, 12); + + return EXTERNAL_CLOCK_FREQ * fdiv; +} + +static uint32_t get_ddr_pll_freq(void) +{ + LTRACEF("DDR_PLL_CTRL 0x%x\n", SLCR_REG(DDR_PLL_CTRL)); + + // XXX test that the pll is actually enabled + + uint32_t fdiv = BITS_SHIFT(SLCR_REG(DDR_PLL_CTRL), 18, 12); + + return EXTERNAL_CLOCK_FREQ * fdiv; +} + +static uint32_t get_io_pll_freq(void) +{ + LTRACEF("IO_PLL_CTRL 0x%x\n", SLCR_REG(IO_PLL_CTRL)); + + // XXX test that the pll is actually enabled + + uint32_t fdiv = BITS_SHIFT(SLCR_REG(IO_PLL_CTRL), 18, 12); + + return EXTERNAL_CLOCK_FREQ * fdiv; +} + +static uint32_t get_cpu_input_freq(void) +{ + LTRACEF("ARM_CLK_CTRL 0x%x\n", SLCR_REG(ARM_CLK_CTRL)); + + uint32_t divisor = BITS_SHIFT(SLCR_REG(ARM_CLK_CTRL), 13, 8); + uint32_t srcsel = BITS_SHIFT(SLCR_REG(ARM_CLK_CTRL), 5, 4); + + uint32_t srcclk; + switch (srcsel) { + default: case 0: case 1: // arm pll + srcclk = get_arm_pll_freq(); + break; + case 2: // ddr pll + srcclk = get_ddr_pll_freq(); + break; + case 3: // io pll + srcclk = get_io_pll_freq(); + break; + } + + // cpu 6x4x + return srcclk / divisor; +} + +static uint32_t get_cpu_6x4x_freq(void) +{ + // cpu 6x4x is the post divided frequency in the cpu clock block + return get_cpu_input_freq(); +} + +static uint32_t get_cpu_3x2x_freq(void) +{ + // cpu 3x2x is always half the speed of 6x4x + return get_cpu_input_freq() / 2; +} + +static uint32_t get_cpu_2x_freq(void) +{ + // cpu 2x is either /3 or /2 the speed of 6x4x + return get_cpu_input_freq() / ((SLCR_REG(CLK_621_TRUE) & 1) ? 3 : 2); +} + +static uint32_t get_cpu_1x_freq(void) +{ + // cpu 1x is either /6 or /4 the speed of 6x4x + return get_cpu_input_freq() / ((SLCR_REG(CLK_621_TRUE) & 1) ? 6 : 4); +} + +uint32_t zynq_get_arm_freq(void) +{ + return get_cpu_6x4x_freq(); +} + +uint32_t zynq_get_arm_timer_freq(void) +{ + return get_cpu_3x2x_freq(); +} + +struct periph_clock { + addr_t clk_ctrl_reg; + uint enable_bit_pos; +}; + +static addr_t periph_clk_ctrl_reg(enum zynq_periph periph) +{ + DEBUG_ASSERT(periph < _PERIPH_MAX); + + switch (periph) { + case PERIPH_USB0: return SLCR_BASE + USB0_CLK_CTRL; + case PERIPH_USB1: return SLCR_BASE + USB1_CLK_CTRL; + case PERIPH_GEM0: return SLCR_BASE + GEM0_CLK_CTRL; + case PERIPH_GEM1: return SLCR_BASE + GEM1_CLK_CTRL; + case PERIPH_SMC: return SLCR_BASE + SMC_CLK_CTRL; + case PERIPH_LQSPI: return SLCR_BASE + LQSPI_CLK_CTRL; + case PERIPH_SDIO0: return SLCR_BASE + SDIO_CLK_CTRL; + case PERIPH_SDIO1: return SLCR_BASE + SDIO_CLK_CTRL; + case PERIPH_UART0: return SLCR_BASE + UART_CLK_CTRL; + case PERIPH_UART1: return SLCR_BASE + UART_CLK_CTRL; + case PERIPH_SPI0: return SLCR_BASE + SPI_CLK_CTRL; + case PERIPH_SPI1: return SLCR_BASE + SPI_CLK_CTRL; + case PERIPH_CAN0: return SLCR_BASE + CAN_CLK_CTRL; + case PERIPH_CAN1: return SLCR_BASE + CAN_CLK_CTRL; + case PERIPH_DBG: return SLCR_BASE + DBG_CLK_CTRL; + case PERIPH_PCAP: return SLCR_BASE + PCAP_CLK_CTRL; + case PERIPH_FPGA0: return SLCR_BASE + FPGA0_CLK_CTRL; + case PERIPH_FPGA1: return SLCR_BASE + FPGA1_CLK_CTRL; + case PERIPH_FPGA2: return SLCR_BASE + FPGA2_CLK_CTRL; + case PERIPH_FPGA3: return SLCR_BASE + FPGA3_CLK_CTRL; + default: return 0; + } +} + +static uint periph_clk_ctrl_enable_bitpos(enum zynq_periph periph) +{ + switch (periph) { + case PERIPH_SDIO1: + case PERIPH_UART1: + case PERIPH_SPI1: + case PERIPH_CAN1: + return 1; + default: + // most peripherals have the enable bit in bit0 + return 0; + } +} + +static const char *periph_to_name(enum zynq_periph periph) +{ + switch (periph) { + case PERIPH_USB0: return "USB0"; + case PERIPH_USB1: return "USB1"; + case PERIPH_GEM0: return "GEM0"; + case PERIPH_GEM1: return "GEM1"; + case PERIPH_SMC: return "SMC"; + case PERIPH_LQSPI: return "LQSPI"; + case PERIPH_SDIO0: return "SDIO0"; + case PERIPH_SDIO1: return "SDIO1"; + case PERIPH_UART0: return "UART0"; + case PERIPH_UART1: return "UART1"; + case PERIPH_SPI0: return "SPI0"; + case PERIPH_SPI1: return "SPI1"; + case PERIPH_CAN0: return "CAN0"; + case PERIPH_CAN1: return "CAN1"; + case PERIPH_DBG: return "DBG"; + case PERIPH_PCAP: return "PCAP"; + case PERIPH_FPGA0: return "FPGA0"; + case PERIPH_FPGA1: return "FPGA1"; + case PERIPH_FPGA2: return "FPGA2"; + case PERIPH_FPGA3: return "FPGA3"; + default: return "unknown"; + } +} + +status_t zynq_set_clock(enum zynq_periph periph, bool enable, enum zynq_clock_source source, uint32_t divisor) +{ + DEBUG_ASSERT(periph < _PERIPH_MAX); + DEBUG_ASSERT(divisor > 0 && divisor <= 0x3f); + DEBUG_ASSERT(source < 4); + + // get the clock control register base + addr_t clk_reg = periph_clk_ctrl_reg(periph); + DEBUG_ASSERT(clk_reg != 0); + + uint enable_bitpos = periph_clk_ctrl_enable_bitpos(periph); + + // if we're enabling + if (enable) { + switch (periph) { + case PERIPH_USB0: + case PERIPH_USB1: + case PERIPH_GEM0: + case PERIPH_GEM1: + PANIC_UNIMPLEMENTED; + default: + ; + } + + uint32_t ctrl = *REG32(clk_reg); + + // set the divisor, source, and enable + // XXX handle split divisors + ctrl = (ctrl & ~(0x3f << 8)) | (divisor << 8); + ctrl = (ctrl & ~(0x3 << 4)) | (source << 4); + ctrl |= (1 << enable_bitpos); + + *REG32(clk_reg) = ctrl; + } else { + // disabling + uint32_t ctrl = *REG32(clk_reg); + + ctrl &= ~(1 << enable_bitpos); + + *REG32(clk_reg) = ctrl; + } + + return NO_ERROR; +} + +uint32_t zynq_get_clock(enum zynq_periph periph) +{ + DEBUG_ASSERT(periph < _PERIPH_MAX); + + // get the clock control register base + addr_t clk_reg = periph_clk_ctrl_reg(periph); + DEBUG_ASSERT(clk_reg != 0); + + uint enable_bitpos = periph_clk_ctrl_enable_bitpos(periph); + + // see if it's enabled + if ((*REG32(clk_reg) & (1 << enable_bitpos)) == 0) { + // not enabled + return 0; + } + + // get the source clock + uint32_t srcclk; + switch (BITS_SHIFT(*REG32(clk_reg), 5, 4)) { + case 0: case 1: + srcclk = get_io_pll_freq(); + break; + case 2: + srcclk = get_arm_pll_freq(); + break; + case 3: + srcclk = get_ddr_pll_freq(); + break; + } + + // get the divisor out of the register + uint32_t divisor = BITS_SHIFT(*REG32(clk_reg), 13, 8); + if (divisor == 0) + return 0; + + uint32_t clk = srcclk / divisor; + + return clk; +} + +void zynq_dump_clocks(void) +{ + printf("zynq clocks:\n"); + printf("\tarm pll %d\n", get_arm_pll_freq()); + printf("\tddr pll %d\n", get_ddr_pll_freq()); + printf("\tio pll %d\n", get_io_pll_freq()); + + printf("\tarm clock %d\n", zynq_get_arm_freq()); + printf("\tarm timer clock %d\n", zynq_get_arm_timer_freq()); + printf("\tcpu6x4x clock %d\n", get_cpu_6x4x_freq()); + printf("\tcpu3x2x clock %d\n", get_cpu_3x2x_freq()); + printf("\tcpu2x clock %d\n", get_cpu_2x_freq()); + printf("\tcpu1x clock %d\n", get_cpu_1x_freq()); + + printf("peripheral clocks:\n"); + for (uint i = 0; i < _PERIPH_MAX; i++) { + printf("\tperiph %d (%s) clock %u\n", i, periph_to_name(i), zynq_get_clock(i)); + } +} + diff --git a/platform/zynq/include/platform/zynq.h b/platform/zynq/include/platform/zynq.h index f0887825..79229ef7 100644 --- a/platform/zynq/include/platform/zynq.h +++ b/platform/zynq/include/platform/zynq.h @@ -23,6 +23,7 @@ #pragma once #include +#include /* memory addresses */ #define SDRAM_BASE (0) @@ -77,3 +78,231 @@ #define MAX_INT 96 +/* UART registers */ +#define UART_CR (0x00) +#define UART_MR (0x04) +#define UART_IER (0x08) +#define UART_IDR (0x0c) +#define UART_IMR (0x10) +#define UART_ISR (0x14) +#define UART_BAUDGEN (0x18) +#define UART_RXTOUT (0x1c) +#define UART_RXWM (0x20) +#define UART_MODEMCR (0x24) +#define UART_MODEMSR (0x28) +#define UART_SR (0x2c) +#define UART_FIFO (0x30) +#define UART_BAUD_DIV (0x34) +#define UART_FLOW_DELAY (0x38) +#define UART_TX_FIFO_TRIGGER (0x44) + +#define NUM_UARTS 2 + +/* SLCR registers */ +#define SLCR_REG(reg) (*REG32(SLCR_BASE + (reg))) + +#define SCL 0x00000000 +#define SLCR_LOCK 0x00000004 +#define SLCR_UNLOCK 0x00000008 +#define SLCR_LOCKSTA 0x0000000c +#define ARM_PLL_CTRL 0x00000100 +#define DDR_PLL_CTRL 0x00000104 +#define IO_PLL_CTRL 0x00000108 +#define PLL_STATUS 0x0000010c +#define ARM_PLL_CFG 0x00000110 +#define DDR_PLL_CFG 0x00000114 +#define IO_PLL_CFG 0x00000118 +#define ARM_CLK_CTRL 0x00000120 +#define DDR_CLK_CTRL 0x00000124 +#define IO_CLK_CTRL 0x00000128 +#define APER_CLK_CTRL 0x0000012c +#define USB0_CLK_CTRL 0x00000130 +#define USB1_CLK_CTRL 0x00000134 +#define GEM0_RCLK_CTRL 0x00000138 +#define GEM1_RCLK_CTRL 0x0000013c +#define GEM0_CLK_CTRL 0x00000140 +#define GEM1_CLK_CTRL 0x00000144 +#define SMC_CLK_CTRL 0x00000148 +#define LQSPI_CLK_CTRL 0x0000014c +#define SDIO_CLK_CTRL 0x00000150 +#define UART_CLK_CTRL 0x00000154 +#define SPI_CLK_CTRL 0x00000158 +#define CAN_CLK_CTRL 0x0000015C +#define CAN_MIOCLK_CTRL 0x00000160 +#define DBG_CLK_CTRL 0x00000164 +#define PCAP_CLK_CTRL 0x00000168 +#define TOPSW_CLK_CTRL 0x0000016C +#define FPGA0_CLK_CTRL 0x00000170 +#define FPGA0_THR_CTRL 0x00000174 +#define FPGA0_THR_CNT 0x00000178 +#define FPGA0_THR_STA 0x0000017C +#define FPGA1_CLK_CTRL 0x00000180 +#define FPGA1_THR_CTRL 0x00000184 +#define FPGA1_THR_CNT 0x00000188 +#define FPGA1_THR_STA 0x0000018C +#define FPGA2_CLK_CTRL 0x00000190 +#define FPGA2_THR_CTRL 0x00000194 +#define FPGA2_THR_CNT 0x00000198 +#define FPGA2_THR_STA 0x0000019C +#define FPGA3_CLK_CTRL 0x000001A0 +#define FPGA3_THR_CTRL 0x000001A4 +#define FPGA3_THR_CNT 0x000001A8 +#define FPGA3_THR_STA 0x000001AC +#define CLK_621_TRUE 0x000001C4 +#define PSS_RST_CTRL 0x00000200 +#define DDR_RST_CTRL 0x00000204 +#define TOPSW_RST_CTRL 0x00000208 +#define DMAC_RST_CTRL 0x0000020C +#define USB_RST_CTRL 0x00000210 +#define GEM_RST_CTRL 0x00000214 +#define SDIO_RST_CTRL 0x00000218 +#define SPI_RST_CTRL 0x0000021C +#define CAN_RST_CTRL 0x00000220 +#define I2C_RST_CTRL 0x00000224 +#define UART_RST_CTRL 0x00000228 +#define GPIO_RST_CTRL 0x0000022C +#define LQSPI_RST_CTRL 0x00000230 +#define SMC_RST_CTRL 0x00000234 +#define OCM_RST_CTRL 0x00000238 +#define FPGA_RST_CTRL 0x00000240 +#define A9_CPU_RST_CTRL 0x00000244 +#define RS_AWDT_CTRL 0x0000024C +#define REBOOT_STATUS 0x00000258 +#define BOOT_MODE 0x0000025C +#define APU_CTRL 0x00000300 +#define WDT_CLK_SEL 0x00000304 +#define TZ_DMA_NS 0x00000440 +#define TZ_DMA_IRQ_NS 0x00000444 +#define TZ_DMA_PERIPH_NS 0x00000448 +#define PSS_IDCODE 0x00000530 +#define DDR_URGENT 0x00000600 +#define DDR_CAL_START 0x0000060C +#define DDR_REF_START 0x00000614 +#define DDR_CMD_STA 0x00000618 +#define DDR_URGENT_SEL 0x0000061C +#define DDR_DFI_STATUS 0x00000620 +#define MIO_PIN_00 0x00000700 +#define MIO_PIN_01 0x00000704 +#define MIO_PIN_02 0x00000708 +#define MIO_PIN_03 0x0000070C +#define MIO_PIN_04 0x00000710 +#define MIO_PIN_05 0x00000714 +#define MIO_PIN_06 0x00000718 +#define MIO_PIN_07 0x0000071C +#define MIO_PIN_08 0x00000720 +#define MIO_PIN_09 0x00000724 +#define MIO_PIN_10 0x00000728 +#define MIO_PIN_11 0x0000072C +#define MIO_PIN_12 0x00000730 +#define MIO_PIN_13 0x00000734 +#define MIO_PIN_14 0x00000738 +#define MIO_PIN_15 0x0000073C +#define MIO_PIN_16 0x00000740 +#define MIO_PIN_17 0x00000744 +#define MIO_PIN_18 0x00000748 +#define MIO_PIN_19 0x0000074C +#define MIO_PIN_20 0x00000750 +#define MIO_PIN_21 0x00000754 +#define MIO_PIN_22 0x00000758 +#define MIO_PIN_23 0x0000075C +#define MIO_PIN_24 0x00000760 +#define MIO_PIN_25 0x00000764 +#define MIO_PIN_26 0x00000768 +#define MIO_PIN_27 0x0000076C +#define MIO_PIN_28 0x00000770 +#define MIO_PIN_29 0x00000774 +#define MIO_PIN_30 0x00000778 +#define MIO_PIN_31 0x0000077C +#define MIO_PIN_32 0x00000780 +#define MIO_PIN_33 0x00000784 +#define MIO_PIN_34 0x00000788 +#define MIO_PIN_35 0x0000078C +#define MIO_PIN_36 0x00000790 +#define MIO_PIN_37 0x00000794 +#define MIO_PIN_38 0x00000798 +#define MIO_PIN_39 0x0000079C +#define MIO_PIN_40 0x000007A0 +#define MIO_PIN_41 0x000007A4 +#define MIO_PIN_42 0x000007A8 +#define MIO_PIN_43 0x000007AC +#define MIO_PIN_44 0x000007B0 +#define MIO_PIN_45 0x000007B4 +#define MIO_PIN_46 0x000007B8 +#define MIO_PIN_47 0x000007BC +#define MIO_PIN_48 0x000007C0 +#define MIO_PIN_49 0x000007C4 +#define MIO_PIN_50 0x000007C8 +#define MIO_PIN_51 0x000007CC +#define MIO_PIN_52 0x000007D0 +#define MIO_PIN_53 0x000007D4 +#define MIO_LOOPBACK 0x00000804 +#define MIO_MST_TRI0 0x0000080C +#define MIO_MST_TRI1 0x00000810 +#define SD0_WP_CD_SEL 0x00000830 +#define SD1_WP_CD_SEL 0x00000834 +#define LVL_SHFTR_EN 0x00000900 +#define OCM_CFG 0x00000910 +#define Reserved 0x00000A1C +#define GPIOB_CTRL 0x00000B00 +#define GPIOB_CFG_CMOS18 0x00000B04 +#define GPIOB_CFG_CMOS25 0x00000B08 +#define GPIOB_CFG_CMOS33 0x00000B0C +#define GPIOB_CFG_HSTL 0x00000B14 +#define GPIOB_DRVR_BIAS_C 0x00000B18 +#define DDRIOB_ADDR0 0x00000B40 +#define DDRIOB_ADDR1 0x00000B44 +#define DDRIOB_DATA0 0x00000B48 +#define DDRIOB_DATA1 0x00000B4C +#define DDRIOB_DIFF0 0x00000B50 +#define DDRIOB_DIFF1 0x00000B54 +#define DDRIOB_CLOCK 0x00000B58 +#define DDRIOB_DRIVE_SLEW_ADDR 0x00000B5C +#define DDRIOB_DRIVE_SLEW_DATA 0x00000B60 +#define DDRIOB_DRIVE_SLEW_DIFF 0x00000B64 +#define DDRIOB_DRIVE_SLEW_CLOCK 0x00000B68 +#define DDRIOB_DDR_CTRL 0x00000B6C +#define DDRIOB_DCI_CTRL 0x00000B70 +#define DDRIOB_DCI_STATU 0x00000B74 + +static inline void zynq_slcr_unlock(void) { SLCR_REG(SLCR_UNLOCK) = 0xdf0d; } +static inline void zynq_slcr_lock(void) { SLCR_REG(SLCR_LOCK) = 0x767b; } + +/* zynq specific functions */ +uint32_t zynq_get_arm_freq(void); +uint32_t zynq_get_arm_timer_freq(void); +void zynq_dump_clocks(void); + +enum zynq_clock_source { + PLL_CPU, + PLL_DDR, + PLL_IO, +}; + +enum zynq_periph { + PERIPH_USB0, + PERIPH_USB1, + PERIPH_GEM0, + PERIPH_GEM1, + PERIPH_SMC, + PERIPH_LQSPI, + PERIPH_SDIO0, + PERIPH_SDIO1, + PERIPH_UART0, + PERIPH_UART1, + PERIPH_SPI0, + PERIPH_SPI1, + PERIPH_CAN0, + PERIPH_CAN1, + PERIPH_DBG, + PERIPH_PCAP, + PERIPH_FPGA0, + PERIPH_FPGA1, + PERIPH_FPGA2, + PERIPH_FPGA3, + + _PERIPH_MAX, +}; + +status_t zynq_set_clock(enum zynq_periph, bool enable, enum zynq_clock_source, uint32_t divisor); +uint32_t zynq_get_clock(enum zynq_periph); + diff --git a/platform/zynq/platform.c b/platform/zynq/platform.c index 7aa2c84e..aefdf37b 100644 --- a/platform/zynq/platform.c +++ b/platform/zynq/platform.c @@ -22,6 +22,7 @@ */ #include #include +#include #include #include #include @@ -30,6 +31,9 @@ #include #include "platform_p.h" +// target must specify this as the initial jam table to set up the soc +extern int ps7_init(void); + void platform_init_mmu_mappings(void) { #define MB (1024*1024) @@ -42,17 +46,21 @@ void platform_init_mmu_mappings(void) void platform_early_init(void) { + ps7_init(); + uart_init_early(); /* initialize the interrupt controller */ arm_gic_init(); /* initialize the timer block */ - arm_cortex_a9_timer_init(CPUPRIV_BASE, TIMER_CLOCK_FREQ); + arm_cortex_a9_timer_init(CPUPRIV_BASE, zynq_get_arm_timer_freq()); } void platform_init(void) { uart_init(); + + zynq_dump_clocks(); } diff --git a/platform/zynq/uart.c b/platform/zynq/uart.c index 1c9e6637..06a2a186 100644 --- a/platform/zynq/uart.c +++ b/platform/zynq/uart.c @@ -29,32 +29,13 @@ #include #include -#define UART_CR (0x00) -#define UART_MR (0x04) -#define UART_IER (0x08) -#define UART_IDR (0x0c) -#define UART_IMR (0x10) -#define UART_ISR (0x14) -#define UART_BAUDGEN (0x18) -#define UART_RXTOUT (0x1c) -#define UART_RXWM (0x20) -#define UART_MODEMCR (0x24) -#define UART_MODEMSR (0x28) -#define UART_SR (0x2c) -#define UART_FIFO (0x30) -#define UART_BAUD_DIV (0x34) -#define UART_FLOW_DELAY (0x38) -#define UART_TX_FIFO_TRIGGER (0x44) - -#define UARTREG(base, reg) (*REG32((base) + (reg))) - #define RXBUF_SIZE 16 -static cbuf_t uart0_rx_buf; -static cbuf_t uart1_rx_buf; +static cbuf_t uart_rx_buf[NUM_UARTS]; static inline uintptr_t uart_to_ptr(unsigned int n) { return (n == 0) ? UART0_BASE : UART1_BASE; } -static inline cbuf_t *uart_to_rxbuf(unsigned int n) { return (n == 0) ? &uart0_rx_buf : &uart1_rx_buf; } + +#define UART_REG(base, reg) (*REG32((base) + (reg))) static enum handler_return uart_irq(void *arg) { @@ -63,16 +44,15 @@ static enum handler_return uart_irq(void *arg) uintptr_t base = uart_to_ptr(port); /* read interrupt status and mask */ - uint32_t isr = UARTREG(base, UART_ISR); - isr &= UARTREG(base, UART_IMR); + uint32_t isr = UART_REG(base, UART_ISR); + isr &= UART_REG(base, UART_IMR); if (isr & (1<<0)) { // rxtrig - UARTREG(base, UART_ISR) = (1<< 0); - cbuf_t *rxbuf = uart_to_rxbuf(port); + UART_REG(base, UART_ISR) = (1<< 0); - while ((UARTREG(base, UART_SR) & (1<<1)) == 0) { - char c = UARTREG(base, UART_FIFO); - cbuf_write_char(rxbuf, c, false); + while ((UART_REG(base, UART_SR) & (1<<1)) == 0) { + char c = UART_REG(base, UART_FIFO); + cbuf_write_char(&uart_rx_buf[port], c, false); resched = true; } @@ -83,35 +63,32 @@ static enum handler_return uart_irq(void *arg) void uart_init(void) { - cbuf_initialize(&uart0_rx_buf, RXBUF_SIZE); - cbuf_initialize(&uart1_rx_buf, RXBUF_SIZE); + for (uint i = 0; i < NUM_UARTS; i++) { + cbuf_initialize(&uart_rx_buf[i], RXBUF_SIZE); - register_int_handler(UART0_INT, &uart_irq, (void *)0); - register_int_handler(UART1_INT, &uart_irq, (void *)1); + register_int_handler(UART0_INT + i, &uart_irq, (void *)0); - // clear all irqs - UARTREG(uart_to_ptr(0), UART_IDR) = 0xffffffff; - UARTREG(uart_to_ptr(1), UART_IDR) = 0xffffffff; + // clear all irqs + UART_REG(uart_to_ptr(i), UART_IDR) = 0xffffffff; - UARTREG(uart_to_ptr(0), UART_CR) |= (1<<2); // rxen - UARTREG(uart_to_ptr(1), UART_CR) |= (1<<2); // rxen + // set rx fifo trigger to 1 + UART_REG(uart_to_ptr(i), UART_RXWM) = 1; - // set rx fifo trigger to 1 - UARTREG(uart_to_ptr(0), UART_RXWM) = 1; - UARTREG(uart_to_ptr(1), UART_RXWM) = 1; + // enable the receiver + UART_REG(uart_to_ptr(i), UART_CR) |= (1<<2); // rxen - // enable rx interrupt - UARTREG(uart_to_ptr(0), UART_IER) = (1<<0); // rxtrig - UARTREG(uart_to_ptr(1), UART_IER) = (1<<0); // rxtrig + // enable rx interrupt + UART_REG(uart_to_ptr(i), UART_IER) = (1<<0); // rxtrig - unmask_interrupt(UART0_INT); - unmask_interrupt(UART1_INT); + unmask_interrupt(UART0_INT + i); + } } void uart_init_early(void) { - UARTREG(uart_to_ptr(0), UART_CR) = (1<<4); // txen - UARTREG(uart_to_ptr(1), UART_CR) = (1<<4); // txen + for (uint i = 0; i < NUM_UARTS; i++) { + UART_REG(uart_to_ptr(i), UART_CR) = (1<<4); // txen + } } int uart_putc(int port, char c) @@ -119,19 +96,17 @@ int uart_putc(int port, char c) uintptr_t base = uart_to_ptr(port); /* spin while fifo is full */ - while (UARTREG(base, UART_SR) & (1<<4)) + while (UART_REG(base, UART_SR) & (1<<4)) ; - UARTREG(base, UART_FIFO) = c; + UART_REG(base, UART_FIFO) = c; return 1; } int uart_getc(int port, bool wait) { - cbuf_t *rxbuf = uart_to_rxbuf(port); - char c; - if (cbuf_read_char(rxbuf, &c, wait) == 1) + if (cbuf_read_char(&uart_rx_buf[port], &c, wait) == 1) return c; return -1; diff --git a/target/zybo/rules.mk b/target/zybo/rules.mk index f058b56c..95a9f82d 100644 --- a/target/zybo/rules.mk +++ b/target/zybo/rules.mk @@ -11,7 +11,7 @@ GLOBAL_INCLUDES += \ $(LOCAL_DIR)/include GLOBAL_DEFINES += \ - TIMER_CLOCK_FREQ=325000000 \ + EXTERNAL_CLOCK_FREQ=50000000 \ WITH_STATIC_HEAP=1 \ HEAP_START=0x00100000 \ HEAP_LEN=0x1ff00000 diff --git a/target/zybo/target.c b/target/zybo/target.c index 78050f6b..cf190a4e 100644 --- a/target/zybo/target.c +++ b/target/zybo/target.c @@ -20,15 +20,12 @@ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -extern int ps7_init(void); void target_early_init(void) { - ps7_init(); } void target_init(void) { } -