| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| #include <assert.h> |
| #include <stdint.h> |
| |
| #include <os/mynewt.h> |
| |
| #include <hal/hal_bsp.h> |
| #include <bsp/bsp.h> |
| |
| static inline int PLL_ODIV(int n) |
| { |
| if (n == 2) { |
| return 1; |
| } else if (n == 4) { |
| return 2; |
| } else if (n == 8) { |
| return 3; |
| } else if (n == 16) { |
| return 4; |
| } else { |
| return 5; |
| } |
| } |
| |
| uint32_t SystemCoreClock; |
| |
| void |
| SystemClock_Config(void) |
| { |
| /* unlock system for clock configuration */ |
| SYSKEY = 0x00000000; |
| SYSKEY = 0xAA996655; |
| SYSKEY = 0x556699AA; |
| |
| #if (MYNEWT_VAL(SYSTEM_CLOCK_FPLLIDIV)) |
| fpllidiv = MYNEWT_VAL(SYSTEM_CLOCK_FPLLIDIV); |
| #endif |
| |
| #if MYNEWT_VAL_CHOICE(SYSTEM_CLOCK_SRC, POSC) ||\ |
| MYNEWT_VAL_CHOICE(SYSTEM_CLOCK_SRC, POSC_PLL) |
| #if MYNEWT_VAL(SYSTEM_CLOCK_OSC_FREQ) |
| OSCCON = (OSCCON & ~_OSCCON_NOSC_MASK) | (2 << _OSCCON_NOSC_POSITION) | _OSCCON_OSWEN_MASK; |
| SystemCoreClock = MYNEWT_VAL(SYSTEM_CLOCK_OSC_FREQ); |
| #else |
| #error When POSC is selected OSC_FREQ must also be specified |
| #endif |
| #endif |
| |
| #if MYNEWT_VAL_CHOICE(SYSTEM_CLOCK_SRC, FRC_DIV) |
| OSCCON = (OSCCON & ~(_OSCCON_NOSC_MASK | _OSCCON_FRCDIV_MASK)) | _OSCCON_OSWEN_MASK | |
| ((MYNEWT_VAL(SYSTEM_CLOCK_FRC_DIV) - 1) << _OSCCON_FRCDIV_POSITION); |
| SystemCoreClock = 8000000 / MYNEWT_VAL(SYSTEM_CLOCK_FRC_DIV); |
| #elif MYNEWT_VAL_CHOICE(SYSTEM_CLOCK_SRC, POSC) |
| OSCCON = (OSCCON & ~_OSCCON_NOSC_MASK) | (2 << _OSCCON_NOSC_POSITION) | _OSCCON_OSWEN_MASK; |
| SystemCoreClock = MYNEWT_VAL(SYSTEM_CLOCK_OSC_FREQ); |
| #elif MYNEWT_VAL(SYSTEM_CLOCK_SRC) == MYNEWT_VAL_CHOICE(SYSTEM_CLOCK_SRC, FRC_PLL) |
| /* Running on PLL now, switch to FRC */ |
| if ((OSCCON & _OSCCON_COSC_MASK) == (1 << _OSCCON_COSC_POSITION)) { |
| OSCCON = (OSCCON & ~(_OSCCON_CLKLOCK_MASK | _OSCCON_NOSC_MASK | _OSCCON_FRCDIV_MASK)) | _OSCCON_OSWEN_MASK; |
| while (OSCCON & _OSCCON_COSC_MASK) ; |
| } |
| SPLLCON = (PLL_ODIV(MYNEWT_VAL(SYSTEM_CLOCK_PLLODIV))) << _SPLLCON_PLLODIV_POSITION | |
| (MYNEWT_VAL(SYSTEM_CLOCK_PLLMULT) - 1) << _SPLLCON_PLLMULT_POSITION | |
| (MYNEWT_VAL(SYSTEM_CLOCK_PLLIDIV) - 1) << _SPLLCON_PLLIDIV_POSITION | |
| _SPLLCON_PLLICLK_MASK | |
| (MYNEWT_VAL(SYSTEM_CLOCK_PLLRANGE)) << _SPLLCON_PLLRANGE_POSITION; |
| OSCCON = (OSCCON & ~_OSCCON_NOSC_MASK) | (1 << _OSCCON_NOSC_POSITION) | _OSCCON_OSWEN_MASK; |
| SystemCoreClock = 8000000 / MYNEWT_VAL(SYSTEM_CLOCK_PLLIDIV) * |
| MYNEWT_VAL(SYSTEM_CLOCK_PLLMULT) / MYNEWT_VAL(SYSTEM_CLOCK_PLLODIV); |
| |
| #elif MYNEWT_VAL(SYSTEM_CLOCK_SRC) == MYNEWT_VAL_CHOICE(SYSTEM_CLOCK_SRC, POSC_PLL) |
| /* Running on PLL now, switch to FRC */ |
| if ((OSCCON & _OSCCON_COSC_MASK) == (1 << _OSCCON_COSC_POSITION)) { |
| OSCCON = (OSCCON & ~(_OSCCON_CLKLOCK_MASK | _OSCCON_NOSC_MASK | _OSCCON_FRCDIV_MASK)) | _OSCCON_OSWEN_MASK; |
| while (OSCCON & _OSCCON_COSC_MASK) ; |
| } |
| SPLLCON = (PLL_ODIV(MYNEWT_VAL(SYSTEM_CLOCK_PLLODIV))) << _SPLLCON_PLLODIV_POSITION | |
| (MYNEWT_VAL(SYSTEM_CLOCK_PLLMULT) - 1) << _SPLLCON_PLLMULT_POSITION | |
| (MYNEWT_VAL(SYSTEM_CLOCK_PLLIDIV) - 1) << _SPLLCON_PLLIDIV_POSITION | |
| (MYNEWT_VAL(SYSTEM_CLOCK_PLLRANGE)) << _SPLLCON_PLLRANGE_POSITION; |
| OSCCON = (OSCCON & ~_OSCCON_NOSC_MASK) | (1 << _OSCCON_NOSC_POSITION) | _OSCCON_OSWEN_MASK; |
| SystemCoreClock = MYNEWT_VAL(SYSTEM_CLOCK_OSC_FREQ) / MYNEWT_VAL(SYSTEM_CLOCK_PLLIDIV) * |
| MYNEWT_VAL(SYSTEM_CLOCK_PLLMULT) / MYNEWT_VAL(SYSTEM_CLOCK_PLLODIV); |
| #endif |
| /* Lock system since done with clock configuration */ |
| SYSKEY = 0x33333333; |
| } |
| |
| void |
| SystemInit(void) |
| { |
| /* Configure System Clock */ |
| SystemClock_Config(); |
| } |