static void connect_pinmux(uint32_t signal, uint32_t dio, uint16_t flags) { if (FIELD_IS_FUNC(signal)) { /* Connect peripheral function to DIO */ if (flags & DIO_OUTPUT) { /* drive DIO from peripheral */ DIO_SEL_REG(dio) = PERIPH_FUNC(signal); } if (flags & DIO_INPUT) { /* drive peripheral from DIO */ PERIPH_SEL_REG(signal) = DIO_FUNC(dio); /* enable digital input */ REG_WRITE_MLV(DIO_CTL_REG(dio), DIO_CTL_IE_MASK, DIO_CTL_IE_LSB, 1); } } else { /* Connect GPIO to DIO */ const struct gpio_info *g = gpio_list + FIELD_GET_GPIO(signal); int bitnum = GPIO_MASK_TO_NUM(g->mask); if ((g->flags & GPIO_OUTPUT) || (flags & DIO_OUTPUT)) { /* drive DIO output from GPIO */ DIO_SEL_REG(dio) = GET_GPIO_FUNC(g->port, bitnum); } if ((g->flags & GPIO_INPUT) || (flags & DIO_INPUT)) { /* drive GPIO input from DIO */ GET_GPIO_SEL_REG(g->port, bitnum) = DIO_FUNC(dio); /* enable digital input */ REG_WRITE_MLV(DIO_CTL_REG(dio), DIO_CTL_IE_MASK, DIO_CTL_IE_LSB, 1); } } }
void uart_tx_stop(void) { /* Disable the TX interrupt */ REG_WRITE_MLV(GR_UART_ICTRL(0), GC_UART_ICTRL_TX_MASK, GC_UART_ICTRL_TX_LSB, 0); /* Re-allow deep sleep */ enable_sleep(SLEEP_MASK_UART); }
static void update_prescaler(void) { /* * We want the timer to tick every microsecond, but we can only divide * PCLK by 1, 16, or 256. We're targeting 30MHz, so we'll just let it * run at 1:1. */ REG_WRITE_MLV(GR_TIMEHS_CONTROL(0, 1), GC_TIMEHS_TIMER1CONTROL_PRE_MASK, GC_TIMEHS_TIMER1CONTROL_PRE_LSB, 0); REG_WRITE_MLV(GR_TIMEHS_CONTROL(0, 2), GC_TIMEHS_TIMER1CONTROL_PRE_MASK, GC_TIMEHS_TIMER1CONTROL_PRE_LSB, 0); /* * We're not yet doing anything to detect the current frequency, we're * just hard-coding it. We're also assuming the clock rate is an * integer multiple of MHz. */ clock_mul_factor = 30; /* NOTE: prototype board */ clock_div_factor = 0xffffffff / clock_mul_factor; }
void gpio_pre_init(void) { const struct gpio_info *g = gpio_list; const struct gpio_alt_func *af = gpio_alt_funcs; int i; /* Enable clocks */ REG_WRITE_MLV(GR_PMU_PERICLKSET0, GC_PMU_PERICLKSET0_DGPIO0_CLK_MASK, GC_PMU_PERICLKSET0_DGPIO0_CLK_LSB, 1); REG_WRITE_MLV(GR_PMU_PERICLKSET0, GC_PMU_PERICLKSET0_DGPIO1_CLK_MASK, GC_PMU_PERICLKSET0_DGPIO1_CLK_LSB, 1); /* Set up the pinmux */ for (i = 0; i < gpio_alt_funcs_count; i++, af++) connect_pinmux(af->port, af->mask, af->flags); /* Set up ARM core GPIOs */ for (i = 0; i < GPIO_COUNT; i++, g++) if (g->mask && !(g->flags & GPIO_DEFAULT)) gpio_set_flags_by_mask(g->port, g->mask, g->flags); }
void uart_tx_start(void) { /* If interrupt is already enabled, nothing to do */ if (GR_UART_ICTRL(0) & GC_UART_ICTRL_TX_MASK) return; /* Do not allow deep sleep while transmit in progress */ disable_sleep(SLEEP_MASK_UART); /* * Re-enable the transmit interrupt, then forcibly trigger the * interrupt. This works around a hardware problem with the * UART where the FIFO only triggers the interrupt when its * threshold is _crossed_, not just met. */ /* TODO(crosbug.com/p/33819): Do we need this hack here? Find out. */ REG_WRITE_MLV(GR_UART_ICTRL(0), GC_UART_ICTRL_TX_MASK, GC_UART_ICTRL_TX_LSB, 1); task_trigger_irq(GC_IRQNUM_UART0_TXINT); }
static void switch_osc_to_rc_trim(void) { unsigned trimmed; unsigned saved_trim, fuse_trim, default_trim; unsigned trim_code; /* check which clock we are running on */ unsigned osc_sel = GR_PMU_OSC_SELECT_STAT; if (osc_sel == GC_PMU_OSC_SELECT_RC_TRIM) { /* already using the rc_trim so nothing to do here */ /* make sure the hold signal is set for future power downs */ GR_PMU_OSC_HOLD_SET = 0x1; return; } /* Turn on DXO clock so we can write in the trim code in */ clock_on_xo0(); /* disable the RC_TRIM Clock */ REG_WRITE_MLV(GR_PMU_OSC_CTRL, GC_PMU_OSC_CTRL_RC_TRIM_READYB_MASK, GC_PMU_OSC_CTRL_RC_TRIM_READYB_LSB, 1); /* power up the clock if not already powered up */ GR_PMU_CLRDIS = 1 << GC_PMU_SETDIS_RC_TRIM_LSB; /* Try to find the trim code */ saved_trim = GR_XO_OSC_RC_STATUS; fuse_trim = GR_PMU_FUSE_RD_RC_OSC_26MHZ; default_trim = GR_XO_OSC_RC; /* Check for the trim code in the always-on domain before looking at * the fuse */ if (saved_trim & GC_XO_OSC_RC_STATUS_EN_MASK) { trim_code = (saved_trim & GC_XO_OSC_RC_STATUS_TRIM_MASK) >> GC_XO_OSC_RC_STATUS_TRIM_LSB; trimmed = 1; } else if (fuse_trim & GC_PMU_FUSE_RD_RC_OSC_26MHZ_EN_MASK) {