1 /* kinetis_hw.c
2  *
3  * Copyright (C) 2006-2021 wolfSSL Inc.
4  *
5  * This file is part of wolfSSL.
6  *
7  * wolfSSL is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * wolfSSL is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20  */
21 
22 
23 #include "hw.h"
24 #include "user_settings.h"
25 
26 #if defined(FREESCALE) && defined(K_SERIES)
27 
28 /**********************************************
29  * NOTE: Customize for actual hardware
30  **********************************************/
31 
32 // CPU include for Rowley CrossWorks packages
33 // $(TargetsDir) location:
34 // On Mac OS/X: Users/USERNAME/Library/Rowley Associates Limited/CrossWorks for ARM/packages/targets/
35 // On Windows: C:/Users/USERNAME/Application Data/Local/Rowley Associates Limited/CrossWorks for ARM/packages/targets/
36 // On Linux: home/USERNAME/.rowley_associates_limited/CrossWorks for ARM/v4/packages/targets/
37 
38 // Located in $(TargetsDir)/Kinetis/CMSIS/
39 #ifdef FREESCALE_KSDK_BM
40     #include "fsl_common.h"
41     #include "fsl_debug_console.h"
42     #include "fsl_rtc.h"
43     #include "fsl_trng.h"
44     #include "fsl_lpuart.h"
45     #include "fsl_port.h"
46     #include "clock_config.h"
47 #else
48     #include <MK64F12.h> // Located in $(TargetsDir)/Kinetis/CMSIS/
49 #endif
50 
51 
52 // System clock
53 #ifdef FREESCALE_KSDK_BM
54     #define SYS_CLK_HZ      SystemCoreClock
55 #else
56     #define SYS_CLK_HZ      96000000ul                  /* Core system clock in Hz */
57     #define SYS_CLK_DRS     MCG_C4_DRST_DRS(0x03)       /* DRS 0=24MHz, 1=48MHz, 2=72MHz, 3=96MHz */
58     #define SYS_CLK_DMX     MCG_C4_DMX32_MASK           /* 0=Disable DMX32 (lower actual speed), MCG_C4_DMX32_MASK=Enable DMX32 */
59     #define SYS_CLK_DIV     1                           /* System clock divisor */
60     #define BUS_CLK_DIV     2                           /* Bus clock divisor */
61     #define BUS_CLK_KHZ     (SYS_CLK_HZ/BUS_CLK_DIV)    /* Helper to calculate bus speed for UART */
62     #define FLASH_CLK_DIV   4                           /* Flash clock divisor */
63 #endif
64 
65 // UART TX Port, Pin, Mux and Baud
66 #ifdef FREESCALE_KSDK_BM
67     #define UART_PORT       LPUART4                     /* UART Port */
68     #define UART_TX_PORT    PORTC                       /* UART TX Port */
69     #define UART_TX_PIN     15U                         /* UART TX Pin */
70     #define UART_TX_MUX     kPORT_MuxAlt3               /* Kinetis UART pin mux */
71 #elif defined (WOLFSSL_FRDM_K64)
72     #define UART_PORT       UART0                       /* UART Port */
73     #define UART_TX_PORT    PORTB                       /* UART TX Port */
74     #define UART_TX_PIN     17U                         /* UART TX Pin */
75     #define UART_TX_MUX     0x3                         /* Kinetis UART pin mux */
76 #else
77     #define UART_PORT       UART4                       /* UART Port */
78     #define UART_TX_PORT    PORTE                       /* UART TX Port */
79     #define UART_TX_PIN     24U                         /* UART TX Pin */
80     #define UART_TX_MUX     0x3                         /* Kinetis UART pin mux */
81 #endif
82 #define UART_BAUD_RATE      115200                      /* UART Baud Rate */
83 
84 #ifdef WOLFSSL_FRDM_K64
85     #define UART_BAUD       UART_BAUD_RATE*8
86 #else
87     #define UART_BAUD       UART_BAUD_RATE
88 #endif
89 
90 /* Note: You will also need to update the UART clock gate in hw_uart_init (SIM_SCGC1_UART5_MASK) */
91 /* Note: TWR-K60 is UART3, PTC17 */
92 /* Note: FRDM-K64 is UART4, PTE24 or UART0 PTB17 for OpenOCD  (SIM_SCGC4_UART0_MASK)*/
93 /* Note: TWR-K64 is UART5, PTE8 */
94 /* Note: FRDM-K82F is LPUART4 PTC15 Alt3 (OpenOCD UART) */
95 
96 /***********************************************/
97 
98 // Private functions
99 static uint32_t mDelayCyclesPerUs = 0;
100 #define NOP_FOR_LOOP_INSTRUCTION_COUNT  6
delay_nop(uint32_t count)101 static void delay_nop(uint32_t count)
102 {
103    int i;
104    for(i=0; i<count; i++) {
105       __asm volatile("nop");
106    }
107 }
108 
hw_mcg_init(void)109 static void hw_mcg_init(void)
110 {
111 #ifdef FREESCALE_KSDK_BM
112     BOARD_BootClockHSRUN();
113 #else
114     /* Adjust clock dividers (core/system=div/1, bus=div/2, flex bus=div/2, flash=div/4) */
115     SIM->CLKDIV1 = SIM_CLKDIV1_OUTDIV1(SYS_CLK_DIV-1) | SIM_CLKDIV1_OUTDIV2(BUS_CLK_DIV-1) |
116         SIM_CLKDIV1_OUTDIV3(BUS_CLK_DIV-1) | SIM_CLKDIV1_OUTDIV4(FLASH_CLK_DIV-1);
117 
118     /* Configure FEI internal clock speed */
119     MCG->C4 = (SYS_CLK_DMX | SYS_CLK_DRS);
120     while((MCG->C4 & (MCG_C4_DRST_DRS_MASK | MCG_C4_DMX32_MASK)) != (SYS_CLK_DMX | SYS_CLK_DRS));
121 #endif
122 }
123 
hw_gpio_init(void)124 static void hw_gpio_init(void)
125 {
126 #ifdef FREESCALE_KSDK_BM
127     CLOCK_EnableClock(kCLOCK_PortA);
128     CLOCK_EnableClock(kCLOCK_PortB);
129     CLOCK_EnableClock(kCLOCK_PortC);
130     CLOCK_EnableClock(kCLOCK_PortD);
131     CLOCK_EnableClock(kCLOCK_PortE);
132 #else
133     /* Enable clocks to all GPIO ports */
134     SIM->SCGC5 |= (SIM_SCGC5_PORTA_MASK | SIM_SCGC5_PORTB_MASK
135 #ifdef SIM_SCGC5_PORTC_MASK
136         | SIM_SCGC5_PORTC_MASK
137 #endif
138 #ifdef SIM_SCGC5_PORTD_MASK
139         | SIM_SCGC5_PORTD_MASK
140 #endif
141 #ifdef SIM_SCGC5_PORTE_MASK
142         | SIM_SCGC5_PORTE_MASK
143 #endif
144    );
145 
146 #if 0 /* Debug clock */
147     /* ClockOut on PTC3 */
148     PORTC->PCR[3] = PORT_PCR_MUX(0x05); /* Alt 5 */
149     SIM_SOPT2 |= SIM_SOPT2_CLKOUTSEL(0); /* FlexBus CLKOUT */
150 #endif
151 
152 #endif
153 }
154 
hw_uart_init(void)155 static void hw_uart_init(void)
156 {
157 #ifdef FREESCALE_KSDK_BM
158     PORT_SetPinMux(UART_TX_PORT, UART_TX_PIN, UART_TX_MUX);
159     CLOCK_SetLpuartClock(1); /* MCGPLLCLK */
160     DbgConsole_Init((uint32_t)UART_PORT, UART_BAUD, DEBUG_CONSOLE_DEVICE_TYPE_LPUART, SYS_CLK_HZ);
161 #else
162     register uint16_t sbr, brfa;
163     uint8_t temp;
164 
165     #ifdef WOLFSSL_FRDM_K64
166         /* Enable UART core clock ONLY for FRDM-K64F */
167         SIM->SCGC4 |= SIM_SCGC4_UART0_MASK;
168     #else
169         /* Enable UART core clock */
170         /* Note: Remember to update me if UART_PORT changes */
171         SIM->SCGC1 |= SIM_SCGC1_UART4_MASK;
172     #endif
173     /* Configure UART TX pin */
174     UART_TX_PORT->PCR[UART_TX_PIN] = PORT_PCR_MUX(UART_TX_MUX);
175 
176     /* Disable transmitter and receiver while we change settings. */
177     UART_PORT->C2 &= ~(UART_C2_TE_MASK | UART_C2_RE_MASK );
178 
179     /* Configure the UART for 8-bit mode, no parity */
180     UART_PORT->C1 = 0;
181 
182     /* Calculate baud settings */
183     sbr = (uint16_t)((BUS_CLK_KHZ * 1000)/(UART_BAUD * 16));
184     temp = UART_PORT->BDH & ~(UART_BDH_SBR(0x1F));
185     UART_PORT->BDH = temp | UART_BDH_SBR(((sbr & 0x1F00) >> 8));
186     UART_PORT->BDL = (uint8_t)(sbr & UART_BDL_SBR_MASK);
187 
188     /* Determine if a fractional divider is needed to get closer to the baud rate */
189     brfa = (((BUS_CLK_KHZ * 32000)/(UART_BAUD * 16)) - (sbr * 32));
190     temp = UART_PORT->C4 & ~(UART_C4_BRFA(0x1F));
191     UART_PORT->C4 = temp | UART_C4_BRFA(brfa);
192 
193     /* Enable receiver and transmitter */
194 	UART_PORT->C2 |= (UART_C2_TE_MASK | UART_C2_RE_MASK);
195 #endif
196 }
197 
hw_rtc_init(void)198 static void hw_rtc_init(void)
199 {
200     /* Init nop delay */
201     mDelayCyclesPerUs = (SYS_CLK_HZ / 1000000 / NOP_FOR_LOOP_INSTRUCTION_COUNT);
202 
203     /* Enable RTC clock and oscillator */
204     SIM->SCGC6 |= SIM_SCGC6_RTC_MASK;
205 
206     if (RTC->SR & RTC_SR_TIF_MASK) {
207         /* Resets the RTC registers except for the SWR bit */
208         RTC->CR |= RTC_CR_SWR_MASK;
209         RTC->CR &= ~RTC_CR_SWR_MASK;
210 
211         /* Set TSR register to 0x1 to avoid the TIF bit being set in the SR register */
212         RTC->TSR = 1;
213     }
214 
215     /* Disable RTC Interrupts */
216     RTC->IER = 0;
217 
218     /* Enable OSC */
219     if ((RTC->CR & RTC_CR_OSCE_MASK) == 0) {
220         /* Turn on */
221         RTC->CR |= RTC_CR_OSCE_MASK;
222 
223         /* Wait RTC startup delay 1000 us */
224         delay_us(1000);
225     }
226 
227     /* Enable counter */
228     RTC->SR |= RTC_SR_TCE_MASK;
229 }
230 
hw_rand_init(void)231 static void hw_rand_init(void)
232 {
233 #ifdef FREESCALE_KSDK_BM
234     trng_config_t trngConfig;
235     TRNG_GetDefaultConfig(&trngConfig);
236     /* Set sample mode of the TRNG ring oscillator to Von Neumann, for better random data.*/
237     trngConfig.sampleMode = kTRNG_SampleModeVonNeumann;
238     /* Initialize TRNG */
239     TRNG_Init(TRNG0, &trngConfig);
240 #else
241     /* Enable RNG clocks */
242     SIM->SCGC6 |= SIM_SCGC6_RNGA_MASK;
243     SIM->SCGC3 |= SIM_SCGC3_RNGA_MASK;
244 
245     /* Wake up RNG to normal mode (take out of sleep) */
246     RNG->CR &= ~RNG_CR_SLP_MASK;
247 
248     /* Enable High Assurance mode (Enables notification of security violations via SR[SECV]) */
249     RNG->CR |= RNG_CR_HA_MASK;
250 
251     /* Enable RNG generation to RANDOUT FIFO */
252     RNG->CR |= RNG_CR_GO_MASK;
253 #endif
254 }
255 
256 
257 /* Public Functions */
hw_init(void)258 void hw_init(void)
259 {
260     hw_mcg_init();
261     hw_gpio_init();
262     hw_uart_init();
263     hw_rtc_init();
264     hw_rand_init();
265 }
266 
hw_get_time_sec(void)267 uint32_t hw_get_time_sec(void)
268 {
269     /* Return RTC seconds */
270     return RTC->TSR;
271 }
272 
hw_get_time_msec(void)273 uint32_t hw_get_time_msec(void)
274 {
275     /* RTC TPR precision register increments every 32.768 kHz clock cycle */
276     /* Convert with rounding crystal count (32768 or (1 << 15)) to milliseconds */
277     return ( ((uint32_t)RTC->TPR * 1000) + ((1 << 15) / 2) ) / (1 << 15);
278 }
279 
hw_uart_printchar(int c)280 void hw_uart_printchar(int c)
281 {
282 #ifdef FREESCALE_KSDK_BM
283     LPUART_WriteBlocking(UART_PORT, (const uint8_t*)&c, 1); /* Send the character */
284 #else
285     while(!(UART_PORT->S1 & UART_S1_TDRE_MASK)); /* Wait until space is available in the FIFO */
286     UART_PORT->D = (uint8_t)c; /* Send the character */
287 #endif
288 }
289 
hw_rand(void)290 uint32_t hw_rand(void)
291 {
292     uint32_t rng;
293 #ifdef FREESCALE_KSDK_BM
294     TRNG_GetRandomData(TRNG0, &rng, sizeof(rng));
295 #else
296     while((RNG->SR & RNG_SR_OREG_LVL(0xF)) == 0) {}; /* Wait until FIFO has a value available */
297     rng = RNG->OR; /* Return next value in FIFO output register */
298 #endif
299     return rng;
300 }
301 
delay_us(uint32_t microseconds)302 void delay_us(uint32_t microseconds)
303 {
304    delay_nop(mDelayCyclesPerUs * microseconds);
305 }
306 
307 
308 // Watchdog
hw_watchdog_disable(void)309 void hw_watchdog_disable(void)
310 {
311     WDOG->UNLOCK = 0xC520;
312     WDOG->UNLOCK = 0xD928;
313     WDOG->STCTRLH = WDOG_STCTRLH_ALLOWUPDATE_MASK;
314 }
315 
316 // Flash configuration
317 #define FSEC_UNSECURE             2
318 #define FSEC_SECURE               0
319 #define FSEC_FSLACC_DENIED        2
320 #define FSEC_FSLACC_GRANTED       3
321 #define FSEC_KEY_ENABLED          2
322 #define FSEC_KEY_DISABLED         3
323 #define FSEC_MASS_ERASE_DISABLE   2
324 #define FSEC_MASS_ERASE_ENABLE    3
325 
326 struct flash_conf {
327    uint8_t backdoor_key[8];   /* Backdoor Comparison Key */
328    uint8_t fprot[4];          /* Program flash protection bytes */
329    uint8_t fsec;              /* Flash security byte */
330    uint8_t fopt;              /* Flash nonvolatile option byte */
331    uint8_t feprot;            /* FlexNVM: EEPROM protection byte */
332    uint8_t fdprot;            /* FlexNVM: Data flash protection byte */
333 };
334 const struct flash_conf flash_conf __attribute__ ((section (".flashconf"),used)) =
335 {
336    .backdoor_key = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
337    .fprot = { 0xFF, 0xFF, 0xFF, 0xFF },
338    .fsec = NV_FSEC_SEC(FSEC_UNSECURE) | NV_FSEC_FSLACC(FSEC_FSLACC_GRANTED) |
339            NV_FSEC_MEEN(FSEC_MASS_ERASE_ENABLE) | NV_FSEC_KEYEN(FSEC_KEY_DISABLED),
340    .fopt = 0xFF,
341    .feprot = 0xFF,
342    .fdprot = 0xFF
343 };
344 
345 #endif /* FREESCALE && K_SERIES */
346