mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
4a9cb807c6
The CPU has multiple issues and several parts of the platform code does not even compile cleanly for this CPU in the current state. This removes support for parts MK60DN256ZVLL10, MK60DN512ZVLL10 (note the Z) CPUs with this part number were used in Mulle v0.60 which only has been used in some in-house projects at Eistec and LTU.
265 lines
7.1 KiB
C
265 lines
7.1 KiB
C
/*
|
|
* Copyright (C) 2014-2015 Eistec AB
|
|
*
|
|
* This file is subject to the terms and conditions of the GNU Lesser General
|
|
* Public License v2.1. See the file LICENSE in the top level directory for more
|
|
* details.
|
|
*/
|
|
|
|
/**
|
|
* @ingroup board_mulle
|
|
* @{
|
|
*
|
|
* @file
|
|
* @brief Board specific implementations for the Mulle board
|
|
*
|
|
* @author Joakim Nohlgård <joakim.nohlgard@eistec.se>
|
|
*
|
|
* @}
|
|
*/
|
|
|
|
#include <stddef.h> /* for NULL */
|
|
#include <stdio.h>
|
|
#include "board.h"
|
|
#include "cpu.h"
|
|
#include "mcg.h"
|
|
#include "periph/gpio.h"
|
|
#include "periph/rtt.h"
|
|
#include "periph/spi.h"
|
|
#include "nvram-spi.h"
|
|
#include "nvram.h"
|
|
#include "xtimer.h"
|
|
#include "vfs.h"
|
|
#include "fs/devfs.h"
|
|
#include "mtd_spi_nor.h"
|
|
|
|
static nvram_t mulle_nvram_dev;
|
|
nvram_t *mulle_nvram = &mulle_nvram_dev;
|
|
static nvram_spi_params_t nvram_spi_params = {
|
|
.spi = MULLE_NVRAM_SPI_DEV,
|
|
.clk = MULLE_NVRAM_SPI_CLK,
|
|
.cs = MULLE_NVRAM_SPI_CS,
|
|
.address_count = MULLE_NVRAM_SPI_ADDRESS_COUNT,
|
|
};
|
|
|
|
static devfs_t mulle_nvram_devfs = {
|
|
.path = "/fram0",
|
|
.f_op = &nvram_vfs_ops,
|
|
.private_data = &mulle_nvram_dev,
|
|
};
|
|
|
|
static mtd_spi_nor_t mulle_nor_dev = {
|
|
.base = {
|
|
.driver = &mtd_spi_nor_driver,
|
|
.page_size = 256,
|
|
.pages_per_sector = 256,
|
|
.sector_count = 32,
|
|
},
|
|
.opcode = &mtd_spi_nor_opcode_default,
|
|
.spi = MULLE_NOR_SPI_DEV,
|
|
.cs = MULLE_NOR_SPI_CS,
|
|
.addr_width = 3,
|
|
.mode = SPI_MODE_3,
|
|
.clk = SPI_CLK_10MHZ,
|
|
};
|
|
|
|
mtd_dev_t *mtd0 = (mtd_dev_t *)&mulle_nor_dev;
|
|
|
|
static devfs_t mulle_nor_devfs = {
|
|
.path = "/mtd0",
|
|
.f_op = &mtd_vfs_ops,
|
|
.private_data = &mulle_nor_dev,
|
|
};
|
|
|
|
/** @brief Initialize the GPIO pins controlling the power switches. */
|
|
static inline void power_pins_init(void);
|
|
|
|
/**
|
|
* @brief Set clock prescalers to safe values
|
|
*
|
|
* This should be done before switching to FLL/PLL as clock source to ensure
|
|
* that all clocks remain within the specified limits.
|
|
*/
|
|
static inline void set_safe_clock_dividers(void);
|
|
|
|
/** @brief Set the FLL source clock to RTC32k */
|
|
static inline void set_fll_source(void);
|
|
|
|
static void increase_boot_count(void);
|
|
static int mulle_nvram_init(void);
|
|
|
|
int mulle_nor_init(void);
|
|
|
|
void board_init(void)
|
|
{
|
|
int status;
|
|
|
|
/* initialize the boards LEDs */
|
|
gpio_init(LED0_PIN, GPIO_OUT);
|
|
gpio_init(LED1_PIN, GPIO_OUT);
|
|
gpio_init(LED2_PIN, GPIO_OUT);
|
|
|
|
/* Initialize power control pins */
|
|
power_pins_init();
|
|
|
|
/* Turn on Vperiph for peripherals */
|
|
/*
|
|
* By turning on Vperiph first, and before waiting for the clocks to
|
|
* stabilize, we will have used enough time to have let the FRAM start up
|
|
* properly when we want to access it later without having to add any extra
|
|
* delays.
|
|
*/
|
|
gpio_set(MULLE_POWER_VPERIPH);
|
|
|
|
/* Turn on AVDD for reading voltages */
|
|
gpio_set(MULLE_POWER_AVDD);
|
|
|
|
/* Initialize RTC oscillator as early as possible since we are using it as a
|
|
* base clock for the FLL.
|
|
* It takes a while to stabilize the oscillator, therefore we do this as
|
|
* soon as possible during boot in order to let it stabilize while other
|
|
* stuff is initializing. */
|
|
/* If the clock is not stable then the UART will have the wrong baud rate
|
|
* for debug prints as well */
|
|
rtt_init();
|
|
|
|
/* Set up clocks */
|
|
set_safe_clock_dividers();
|
|
|
|
set_fll_source();
|
|
|
|
kinetis_mcg_set_mode(KINETIS_MCG_FEE);
|
|
|
|
/* At this point we need to wait for 1 ms until the clock is stable.
|
|
* Since the clock is not yet stable we can only guess how long we must
|
|
* wait. I have tried to make this as short as possible but still being able
|
|
* to read the initialization messages written on the UART.
|
|
* (If the clock is not stable all UART output is garbled until it has
|
|
* stabilized) */
|
|
for (int i = 0; i < 100000; ++i) {
|
|
__asm__ volatile("nop\n");
|
|
}
|
|
|
|
/* initialize the CPU */
|
|
cpu_init();
|
|
|
|
/* NVRAM requires xtimer for timing */
|
|
xtimer_init();
|
|
|
|
/* Initialize NVRAM */
|
|
status = mulle_nvram_init();
|
|
if (status == 0) {
|
|
/* Increment boot counter */
|
|
increase_boot_count();
|
|
}
|
|
|
|
/* Initialize NOR flash */
|
|
mulle_nor_init();
|
|
}
|
|
|
|
static inline void power_pins_init(void)
|
|
{
|
|
gpio_init(MULLE_POWER_AVDD, GPIO_OUT);
|
|
gpio_init(MULLE_POWER_VPERIPH, GPIO_OUT);
|
|
gpio_init(MULLE_POWER_VSEC, GPIO_OUT);
|
|
gpio_clear(MULLE_POWER_AVDD);
|
|
gpio_clear(MULLE_POWER_VPERIPH);
|
|
gpio_clear(MULLE_POWER_VSEC);
|
|
}
|
|
|
|
static inline void set_safe_clock_dividers(void)
|
|
{
|
|
/*
|
|
* We want to achieve the following clocks:
|
|
* Core/system: <100MHz
|
|
* Bus: <50MHz
|
|
* FlexBus: <50MHz
|
|
* Flash: <25MHz
|
|
*
|
|
* using dividers 1-2-2-4 will obey the above limits when using a 96MHz FLL source.
|
|
*/
|
|
SIM->CLKDIV1 = (
|
|
SIM_CLKDIV1_OUTDIV1(CONFIG_CLOCK_K60_SYS_DIV) | /* Core/System clock divider */
|
|
SIM_CLKDIV1_OUTDIV2(CONFIG_CLOCK_K60_BUS_DIV) | /* Bus clock divider */
|
|
SIM_CLKDIV1_OUTDIV3(CONFIG_CLOCK_K60_FB_DIV) | /* FlexBus divider, not used in Mulle */
|
|
SIM_CLKDIV1_OUTDIV4(CONFIG_CLOCK_K60_FLASH_DIV)); /* Flash clock divider */
|
|
|
|
}
|
|
|
|
static inline void set_fll_source(void)
|
|
{
|
|
/* Select FLL as source (as opposed to PLL) */
|
|
SIM->SOPT2 &= ~(SIM_SOPT2_PLLFLLSEL_MASK);
|
|
/* Use external 32kHz RTC clock as source for OSC32K */
|
|
SIM->SOPT1 = (SIM->SOPT1 & ~(SIM_SOPT1_OSC32KSEL_MASK)) | SIM_SOPT1_OSC32KSEL(2);
|
|
|
|
/* Select RTC 32kHz clock as reference clock for the FLL */
|
|
MCG->C7 = (MCG_C7_OSCSEL_MASK);
|
|
}
|
|
|
|
static int mulle_nvram_init(void)
|
|
{
|
|
union {
|
|
uint32_t u32;
|
|
uint8_t u8[sizeof(uint32_t)];
|
|
} rec;
|
|
rec.u32 = 0;
|
|
|
|
if (nvram_spi_init(mulle_nvram, &nvram_spi_params, MULLE_NVRAM_CAPACITY) != 0) {
|
|
return -2;
|
|
}
|
|
|
|
if (mulle_nvram->read(mulle_nvram, &rec.u8[0], MULLE_NVRAM_MAGIC, sizeof(rec.u32)) != sizeof(rec.u32)) {
|
|
return -3;
|
|
}
|
|
|
|
if (rec.u32 != MULLE_NVRAM_MAGIC_EXPECTED) {
|
|
int i;
|
|
union {
|
|
uint64_t u64;
|
|
uint8_t u8[sizeof(uint64_t)];
|
|
} zero;
|
|
zero.u64 = 0;
|
|
for (i = 0; i < MULLE_NVRAM_CAPACITY; i += sizeof(zero)) {
|
|
if (mulle_nvram->write(mulle_nvram, &zero.u8[0], i, sizeof(zero.u64)) != sizeof(zero.u64)) {
|
|
return -4;
|
|
}
|
|
}
|
|
rec.u32 = MULLE_NVRAM_MAGIC_EXPECTED;
|
|
if (mulle_nvram->write(mulle_nvram, &rec.u8[0], MULLE_NVRAM_MAGIC, sizeof(rec.u32)) != sizeof(rec.u32)) {
|
|
return -5;
|
|
}
|
|
}
|
|
|
|
/* Register DevFS node */
|
|
devfs_register(&mulle_nvram_devfs);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void increase_boot_count(void)
|
|
{
|
|
union {
|
|
uint32_t u32;
|
|
uint8_t u8[sizeof(uint32_t)];
|
|
} rec;
|
|
rec.u32 = 0;
|
|
if (mulle_nvram->read(mulle_nvram, &rec.u8[0], MULLE_NVRAM_BOOT_COUNT, sizeof(rec.u32)) != sizeof(rec.u32)) {
|
|
return;
|
|
}
|
|
++rec.u32;
|
|
mulle_nvram->write(mulle_nvram, &rec.u8[0], MULLE_NVRAM_BOOT_COUNT, sizeof(rec.u32));
|
|
}
|
|
|
|
int mulle_nor_init(void)
|
|
{
|
|
int res = mtd_init(mtd0);
|
|
|
|
if (res >= 0) {
|
|
/* Register DevFS node */
|
|
devfs_register(&mulle_nor_devfs);
|
|
}
|
|
|
|
return res;
|
|
}
|