Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | /* * Copyright (c) 2019 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include <device.h> #include <init.h> #include <soc.h> #include <kernel.h> #include <arch/cpu.h> #include <arch/arm/aarch32/cortex_m/cmsis.h> /* * Make sure PCR sleep enables are clear except for crypto * which do not have internal clock gating. */ static int soc_pcr_init(void) { PCR_REGS->SLP_EN0 = 0; PCR_REGS->SLP_EN1 = 0; PCR_REGS->SLP_EN2 = 0; PCR_REGS->SLP_EN4 = 0; PCR_REGS->SLP_EN3 = MCHP_PCR3_CRYPTO_MASK; return 0; } /* * Select 32KHz clock source used for PLL reference. * Options are: * Internal 32KHz silicon oscillator. * External parallel resonant crystal between XTAL1 and XTAL2 pins. * External single ended crystal connected to XTAL2 pin. * External 32KHz square wave from Host chipset/board on 32KHZ_IN pin. * NOTES: * PLL can take up to 3 ms to lock. Before lock the PLL output * will be ramping up from ~20MHz. * 32KHZ_IN pin must be configured for 32KHZ_IN function. * Crystals vary and may take longer time to stabilize this will * affect PLL lock time. * Crystal do not like to be power cycled. If using a crystal * the board should supply a battery backed (VBAT) power rail. * The VBAT clock control register selecting 32KHz source is * connected to the VBAT power rail. If using a battery one can * check the VBAT Power Fail and Reset Status register for a VBAT POR. */ static void clk32_change(u8_t new_clk32) { new_clk32 &= MCHP_VBATR_CLKEN_MASK; if ((VBATR_REGS->CLK32_EN & MCHP_VBATR_CLKEN_MASK) == (u32_t)new_clk32) { return; } if (new_clk32 == MCHP_VBATR_USE_SIL_OSC) { VBATR_REGS->CLK32_EN = new_clk32; } else { /* 1. switch to internal oscillator */ VBATR_REGS->CLK32_EN = MCHP_VBATR_USE_SIL_OSC; /* 2. delay for PLL */ while ((PCR_REGS->OSC_ID & MCHP_PCR_OSC_ID_PLL_LOCK) == 0) ; /* 3. switch to desired source */ VBATR_REGS->CLK32_EN = new_clk32; } } static int soc_clk32_init(void) { u8_t new_clk32; #ifdef CONFIG_SOC_MEC1501_EXT_32K #ifdef CONFIG_SOC_MEC1501_EXT_32K_CRYSTAL #ifdef CONFIG_SOC_MEC1501_EXT_32K_PARALLEL_CRYSTAL new_clk32 = MCHP_VBATR_USE_PAR_CRYSTAL; #else new_clk32 = MCHP_VBATR_USE_SE_CRYSTAL; #endif #else /* Use 32KHZ_PIN as 32KHz source */ new_clk32 = MCHP_VBATR_USE_32KIN_PIN; #endif #else /* Use internal 32KHz +/-2% silicon oscillator * if required performed OTP value override */ if (MCHP_REVISION_ID() == MCHP_GCFG_REV_B0) { VBATR_REGS->CKK32_TRIM = 0x06; } new_clk32 = MCHP_VBATR_USE_SIL_OSC; #endif clk32_change(new_clk32); return 0; } /* * Initialize MEC1501 EC Interrupt Aggregator (ECIA) and external NVIC * inputs. */ static int soc_ecia_init(void) { GIRQ_Type *pg; u32_t n; mchp_pcr_periph_slp_ctrl(PCR_ECIA, MCHP_PCR_SLEEP_DIS); ECS_REGS->INTR_CTRL |= MCHP_ECS_ICTRL_DIRECT_EN; /* gate off all aggregated outputs */ ECIA_REGS->BLK_EN_CLR = 0xFFFFFFFFul; /* gate on GIRQ's that are aggregated only */ ECIA_REGS->BLK_EN_SET = MCHP_ECIA_AGGR_BITMAP; /* Clear all GIRQn source enables and source status */ pg = &ECIA_REGS->GIRQ08; for (n = MCHP_FIRST_GIRQ; n <= MCHP_LAST_GIRQ; n++) { pg->EN_CLR = 0xFFFFFFFFul; pg->SRC = 0xFFFFFFFFul; pg++; } /* Clear all external NVIC enables and pending status */ for (n = 0u; n < MCHP_NUM_NVIC_REGS; n++) { NVIC->ICER[n] = 0xFFFFFFFFul; NVIC->ICPR[n] = 0xFFFFFFFFul; } return 0; } static int soc_init(struct device *dev) { u32_t isave; ARG_UNUSED(dev); isave = __get_PRIMASK(); __disable_irq(); soc_pcr_init(); soc_clk32_init(); /* * On HW reset PCR Processor Clock Divider = 4 for 48/4 = 12 MHz. * Set clock divider = 1 for maximum speed. * NOTE1: This clock divider affects all Cortex-M4 core clocks. * If you change it you must repogram SYSTICK to maintain the * same absolute time interval. */ PCR_REGS->PROC_CLK_CTRL = CONFIG_SOC_MEC1501_PROC_CLK_DIV; soc_ecia_init(); if (!isave) { __enable_irq(); } return 0; } SYS_INIT(soc_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); |