pac55xx: adding memctl for flash/sram access, and clock/pll configuration functions.
Merge-conflict: took _prior_ verision of CCS_MUXSELR_MASK_PIN as bracketing of (pin) seemed more correct!
This commit is contained in:
committed by
Karl Palsson
parent
245761f894
commit
253a091936
@@ -4,6 +4,7 @@
|
||||
* @defgroup system_defines Clock Config and System Defines
|
||||
* @ingroup PAC55xx_defines
|
||||
* @author Brian Viele <vielster@allocor.tech>
|
||||
* @author Kevin Stefanik <kevin@allocor.tech>
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
* @date 1 Dec 2019
|
||||
*
|
||||
@@ -26,18 +27,95 @@
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef INCLUDE_LIBOPENCM3_PAC55XX_CCS_H_
|
||||
#define INCLUDE_LIBOPENCM3_PAC55XX_CCS_H_
|
||||
#ifndef LIBOPENCM3_PAC55XX_CCS_H_
|
||||
#define LIBOPENCM3_PAC55XX_CCS_H_
|
||||
|
||||
#include <libopencm3/cm3/common.h>
|
||||
#include <libopencm3/cm3/memorymap.h>
|
||||
#include <libopencm3/pac55xx/memorymap.h>
|
||||
#include <libopencm3/pac55xx/memctl.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/** Clock Control Registers
|
||||
* @defgroup clock_config_regs Clock Config Registers.
|
||||
* @{*/
|
||||
/** @defgroup ccs_frequencies CCS Frequencies
|
||||
@{*/
|
||||
/** Ring Oscillator Frequency */
|
||||
#define CCS_ROSC_FREQ (16000000U)
|
||||
/** Internally generated and trimmed 4MHz clock */
|
||||
#define CCS_CLKREF_FREQ ( 4000000U)
|
||||
/** Maximum external clock frequency */
|
||||
#define CCS_EXTCLK_MAX_FREQ (20000000U)
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup ccs_ctl_reg Clock Control Register
|
||||
@{*/
|
||||
#define CCSCTL MMIO32(SCC_BASE)
|
||||
#define CCS_CTL_FRCLKMUXSEL_MASK (0x03)
|
||||
#define CCS_CTL_FRCLKMUXSEL(sel) ((sel) & CCS_CTL_FRCLKMUXSEL_MASK)
|
||||
#define CCS_CTL_FRCLKMUXSEL_ROSC (0)
|
||||
#define CCS_CTL_FRCLKMUXSEL_CLKREF (1)
|
||||
#define CCS_CTL_FRCLKMUXSEL_EXTCLK (3)
|
||||
#define CCS_CTL_ROSCEN BIT2
|
||||
#define CCS_CTL_SCLKMUXSEL BIT4
|
||||
#define CCS_CTL_SCLKMUXSEL_FRCLK (0)
|
||||
#define CCS_CTL_SCLKMUXSEL_PLLCLK (1)
|
||||
#define CCS_CTL_CLKFAILEN BIT5
|
||||
#define CCS_CTL_CLKFAILMUXSEL BIT6
|
||||
#define CCS_CTL_CLKFAILIF BIT7
|
||||
#define CCS_CTL_LDOEN BIT8
|
||||
#define CCS_CTL_SWRESET BIT11
|
||||
#define CCS_CTL_PCLKEN BIT12
|
||||
#define CCS_CTL_ACLKEN BIT13
|
||||
#define CCS_CTL_ADCCLKEN BIT14
|
||||
#define CCS_CTL_STCLKSLPEN BIT15
|
||||
#define CCS_CTL_PCLKDIV_MASK (0x07)
|
||||
#define CCS_CTL_PCLKDIV_SHIFT (16)
|
||||
/* Supported PCLK divisors: 1-8 */
|
||||
#define CCS_CTL_PCLKDIV(div) (((div-1) & CCS_CTL_PCLKDIV_MASK) << CCS_CTL_PCLKDIV_SHIFT)
|
||||
#define CCS_CTL_ACLKDIV_MASK (0x07)
|
||||
#define CCS_CTL_ACLKDIV_SHIFT (20)
|
||||
/* Supported ACLK divisors: 1-8 */
|
||||
#define CCS_CTL_ACLKDIV(div) (((div-1) & CCS_CTL_ACLKDIV_MASK) << CCS_CTL_ACLKDIV_SHIFT)
|
||||
#define CCS_CTL_HCLKDIV_MASK (0x07)
|
||||
#define CCS_CTL_HCLKDIV_SHIFT (24)
|
||||
/* Supported HCLK divisors: 1-8 */
|
||||
#define CCS_CTL_HCLKDIV(div) (((div-1) & CCS_CTL_HCLKDIV_MASK) << CCS_CTL_HCLKDIV_SHIFT)
|
||||
#define CCS_CTL_USAMODE BIT28
|
||||
#define CCS_CTL_USBMODE BIT29
|
||||
#define CCS_CTL_USCMODE BIT30
|
||||
#define CCS_CTL_USDMODE BIT31
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup ccs_pllctl_reg CCS PLL Control Register
|
||||
@{*/
|
||||
#define CCSPLLCTL MMIO32(SCC_BASE + 0x04)
|
||||
/** PLL Enable */
|
||||
#define CCS_PLLCTL_PLLEN BIT0
|
||||
/** PLL Bypass */
|
||||
#define CCS_PLLCTL_PLLBP BIT1
|
||||
#define CCS_PLLCTL_PLLOUTDIV_MASK (0x03)
|
||||
#define CCS_PLLCTL_PLLOUTDIV_SHIFT (2)
|
||||
/** PLL Output Divisor */
|
||||
#define CCS_PLLCTL_PLLOUTDIV(div) (((div) & CCS_PLLCTL_PLLOUTDIV_MASK) << CCS_PLLCTL_PLLOUTDIV_SHIFT)
|
||||
#define CCS_PLLCTL_PLLOUTDIV1 (0)
|
||||
#define CCS_PLLCTL_PLLOUTDIV2 (1)
|
||||
#define CCS_PLLCTL_PLLOUTDIV4 (2)
|
||||
#define CCS_PLLCTL_PLLOUTDIV8 (3)
|
||||
#define CCS_PLLCTL_PLLINDIV_MASK (0x0F)
|
||||
#define CCS_PLLCTL_PLLINDIV_SHIFT (4)
|
||||
/** PLL Input Divisor */
|
||||
#define CCS_PLLCTL_PLLINDIV(div) (((div) & CCS_PLLCTL_PLLINDIV_MASK) << CCS_PLLCTL_PLLINDIV_SHIFT)
|
||||
#define CCS_PLLCTL_PLLFBDIV_MASK (0x3FFF)
|
||||
#define CCS_PLLCTL_PLLFBDIV_SHIFT (8)
|
||||
/** PLL Feedback Divisor */
|
||||
#define CCS_PLLCTL_PLLFBDIV(div) (((div) & CCS_PLLCTL_PLLFBDIV_MASK) << CCS_PLLCTL_PLLFBDIV_SHIFT)
|
||||
/** PLL Lock */
|
||||
#define CCS_PLLCTL_PLLLOCK BIT24
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup ccs_rosctrim Ring Oscillator Trim Control Register
|
||||
@{*/
|
||||
#define CCSROSCTRIM_MASK (0x7F)
|
||||
#define CCSROSCTRIM MMIO32(SCC_BASE + 0x08)
|
||||
/**@}*/
|
||||
|
||||
@@ -136,6 +214,162 @@ typedef enum {
|
||||
CCS_DSR_DS_25MA = 0x07,
|
||||
} ccs_drive_strength_t;
|
||||
/**@}*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
#endif /* INCLUDE_LIBOPENCM3_PAC55XX_CCS_H_ */
|
||||
BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* @defgroup ccs_api Clock Control System API
|
||||
* @ingroup peripheral_apis
|
||||
* @brief <b>PAC5xx CCS Driver</b>
|
||||
* @author @htmlonly © @endhtmlonly 2020 Kevin Stefanik <kevin@allocor.tech>
|
||||
* @date March 7, 2020
|
||||
*
|
||||
* This library supports the CCS module in the PAC55xx SoC from Qorvo.
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**
|
||||
* Select the source for FRCLK.
|
||||
* @param[in] sel one of:
|
||||
* - /ref CCS_CTL_FRCLKMUXSEL_ROSC - 16MHz ring oscillator
|
||||
* - /ref CCS_CTL_FRCLKMUXSEL_CLKREF - trimmed 4MHz clock
|
||||
* - /ref CCS_CTL_FRCLKMUXSEL_EXTCLK
|
||||
*/
|
||||
void ccs_frclkmux_select(uint32_t sel);
|
||||
/** Enable the 16MHz Ring oscillator */
|
||||
void ccs_rosc_enable(void);
|
||||
/** Disable the 16MHz Ring oscillator */
|
||||
void ccs_rosc_disable(void);
|
||||
/** Select FRCLK for SCLK */
|
||||
void ccs_sclkmux_select_frclk(void);
|
||||
/** Select PLLCLK for SCLK */
|
||||
void ccs_sclkmux_select_pllclk(void);
|
||||
/** Enable Clock Fail Detection */
|
||||
void ccs_clkfail_enable(void);
|
||||
/** Disable Clock Fail Detection */
|
||||
void ccs_clkfail_disable(void);
|
||||
/** Select FRCLK for Clock Fail Detection */
|
||||
void ccs_clkfailmux_select_frclk(void);
|
||||
/** Select PLLCLK for Clock Fail Detection */
|
||||
void ccs_clkfailmux_select_pllclk(void);
|
||||
/** Enable the LDO */
|
||||
void ccs_ldo_enable(void);
|
||||
/** Disable the LDO */
|
||||
void ccs_ldo_disable(void);
|
||||
/** Enable the Peripheral Clock */
|
||||
void ccs_pclk_enable(void);
|
||||
/** Disable the Peripheral Clock */
|
||||
void ccs_pclk_disable(void);
|
||||
/** Enable the Auxiliary Clock */
|
||||
void ccs_aclk_enable(void);
|
||||
/** Disable the Auxiliary Clock */
|
||||
void ccs_aclk_disable(void);
|
||||
/** Enable the ADC Clock */
|
||||
void ccs_adcclk_enable(void);
|
||||
/** Disable the ADC Clock */
|
||||
void ccs_adcclk_disable(void);
|
||||
/** Enable SysTick clock gating in deep sleep mode */
|
||||
void ccs_stclk_sleep_enable(void);
|
||||
/** Disable SysTick clock gating in deep sleep mode */
|
||||
void ccs_stclk_sleep_disable(void);
|
||||
/**
|
||||
* Set the divisor for the Peripheral Clock.
|
||||
* @param[in] div PCLK Divisor: 1-8.
|
||||
*/
|
||||
void ccs_set_pclkdiv(uint32_t div);
|
||||
/**
|
||||
* Set the divisor for the Auxiliary Clock.
|
||||
* @param[in] div ACLK Divisor: 1-8.
|
||||
*/
|
||||
void ccs_set_aclkdiv(uint32_t div);
|
||||
/**
|
||||
* Set the divisor for the AHB Clock.
|
||||
* @param[in] div HCLK Divisor: 1-8.
|
||||
*/
|
||||
void ccs_set_hclkdiv(uint32_t div);
|
||||
/** Enable the PLL */
|
||||
void ccs_pll_enable(void);
|
||||
/** Disable the PLL */
|
||||
void ccs_pll_disable(void);
|
||||
/** Check if the PLL is locked.
|
||||
* @return true if locked.
|
||||
*/
|
||||
bool ccs_pll_locked(void);
|
||||
/** Enable the PLL bypass */
|
||||
void ccs_pll_bypass_enable(void);
|
||||
/** Disable the PLL bypass */
|
||||
void ccs_pll_bypass_disable(void);
|
||||
/**
|
||||
* Set the output divisor.
|
||||
* @param[in] div Output divisor, one of:
|
||||
* - /ref CCS_PLLCTL_PLLOUTDIV1
|
||||
* - /ref CCS_PLLCTL_PLLOUTDIV2
|
||||
* - /ref CCS_PLLCTL_PLLOUTDIV4
|
||||
* - /ref CCS_PLLCTL_PLLOUTDIV8
|
||||
*/
|
||||
void ccs_pll_set_outdiv(uint32_t div);
|
||||
/**
|
||||
* Set the PLL input divisor.
|
||||
* @param[in] div Input divisor, 1-15.
|
||||
*/
|
||||
void ccs_pll_set_indiv(uint32_t div);
|
||||
/**
|
||||
* Set the PLL feedback divisor.
|
||||
* @param[in] div Feedback divisor, 4-16383.
|
||||
*/
|
||||
void ccs_pll_set_fbdiv(uint32_t div);
|
||||
/**
|
||||
* Configure the CCS PLL, enable it, and wait for lock.
|
||||
* @param[in] indiv Input divisor, 1-15.
|
||||
* @param[in] fbdiv Feedback divisor, 4-16383.
|
||||
* @param[in] outdiv Output divisor, one of:
|
||||
* - /ref CCS_PLLCTL_PLLOUTDIV1
|
||||
* - /ref CCS_PLLCTL_PLLOUTDIV2
|
||||
* - /ref CCS_PLLCTL_PLLOUTDIV4
|
||||
* - /ref CCS_PLLCTL_PLLOUTDIV8
|
||||
*/
|
||||
void css_pll_config_enable(uint32_t indiv, uint32_t fbdiv, uint32_t outdiv);
|
||||
/**
|
||||
* Get the clock rate (in Hz) of the specified peripheral. This will pull the
|
||||
* proper sources out of the clock tree and calculate the clock for the
|
||||
* peripheral for return to the user, based on current settings.
|
||||
* @param[in] periph Peripheral base address to get the clock rate for.
|
||||
* @param[in] select Peripheral-controlled clock select value. Set to 0 when not applicable.
|
||||
* @return Clock rate in Hz for the specified peripheral. 0 if undefined or error.
|
||||
*/
|
||||
uint32_t ccs_get_peripheral_clk_freq(uint32_t periph, uint32_t select);
|
||||
/** Restores CCSCTL and CCSPLLCTL registers to default/safe values */
|
||||
void ccs_reset_clocks(void);
|
||||
|
||||
/** CCS Clock Configuration structure. */
|
||||
struct ccs_clk_config {
|
||||
uint32_t frclk_source; /**< FRCLK source input selection */
|
||||
uint32_t extclk_frequency; /**< EXTCLK frequency, 0 if none. */
|
||||
uint32_t sclk_source; /**< SCLK source selection */
|
||||
uint32_t pll_indiv; /**< PLL Input Divider 1-15 */
|
||||
uint32_t pll_fbdiv; /**< PLL Feedback Divider 4-16383 */
|
||||
uint32_t pll_outdiv; /**< PLL Output Divider */
|
||||
uint32_t hclkdiv; /**< Divisor from SCLK to HCLK */
|
||||
uint32_t aclkdiv; /**< Divisor from SCLK to ACLK */
|
||||
uint32_t pclkdiv; /**< Divisor from HCLK to PCLK */
|
||||
uint32_t mem_wstate; /**< Number of Flash Read wait states */
|
||||
uint32_t mem_mclkdiv; /**< Divisor from HCLK to MCLK */
|
||||
bool mem_mclksel; /**< false: ROSCLK, true: HCLK/MCLK */
|
||||
bool mem_enable_cache; /**< false: disable cache, true: enable cache */
|
||||
};
|
||||
/**
|
||||
* Setup the PAC55xx clocks with the given struct.
|
||||
* @param[in] config CCS Clock configuration struct /ref ccs_clk_config
|
||||
*/
|
||||
void ccs_configure_clocks(const struct ccs_clk_config *config);
|
||||
|
||||
/**@}*/
|
||||
|
||||
END_DECLS
|
||||
|
||||
#endif /* LIBOPENCM3_PAC55XX_CCS_H_ */
|
||||
|
||||
163
include/libopencm3/pac55xx/memctl.h
Normal file
163
include/libopencm3/pac55xx/memctl.h
Normal file
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* @brief Memory Controller definitions for the Qorvo PAC55xx series of microcontrollers
|
||||
*
|
||||
* @addtogroup PAC55xx_memctl Memory Controller Defines
|
||||
* @ingroup PAC55xx_defines
|
||||
* @author Kevin Stefanik <kevin@allocor.tech>
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
* @date 17 Mar 2020
|
||||
*
|
||||
* Definitions in this file come from the PAC55XX Family User Guide Rev 1.23
|
||||
* by Active-Semi dated November 19, 2019.
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2020 Kevin Stefanik <kevin@allocor.tech>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef LIBOPENCM3_PAC55XX_MEMCTL_H_
|
||||
#define LIBOPENCM3_PAC55XX_MEMCTL_H_
|
||||
|
||||
#include <libopencm3/cm3/common.h>
|
||||
#include <libopencm3/pac55xx/memorymap.h>
|
||||
/**@{*/
|
||||
|
||||
/** @defgroup memctl_reg Memory Controller Configuration Register
|
||||
@{*/
|
||||
/** Memory Controller Configuration Register */
|
||||
#define MEMCTL_MEMCTLR MMIO32(MEMCTL_BASE)
|
||||
#define MEMCTL_MEMCTLR_WSTATE_MASK (0xF)
|
||||
#define MEMCTL_MEMCTLR_WSTATE(ws) ((ws) & MEMCTL_MEMCTLR_WSTATE_MASK)
|
||||
#define MEMCTL_MEMCTLR_MCLKDIV_MASK (0xF)
|
||||
#define MEMCTL_MEMCTLR_MCLKDIV_SHIFT 4
|
||||
/* Supported MCLK divisors: 1-16 */
|
||||
#define MEMCTL_MEMCTLR_MCLKDIV(div) (((div-1) & MEMCTL_MEMCTLR_MCLKDIV_MASK) << MEMCTL_MEMCTLR_MCLKDIV_SHIFT)
|
||||
#define MEMCTL_MEMCTLR_WRITEWORDCNT_MASK (0x3)
|
||||
#define MEMCTL_MEMCTLR_WRITEWORDCNT_SHIFT 8
|
||||
#define MEMCTL_MEMCTLR_WRITEWORDCNT(cnt) (((cnt) & MEMCTL_MEMCTLR_WRITEWORDCNT_MASK) << MEMCTL_MEMCTLR_WRITEWORDCNT_SHIFT)
|
||||
#define MEMCTL_MEMCTLR_SEIE BIT16
|
||||
#define MEMCTL_MEMCTLR_DEIE BIT17
|
||||
#define MEMCTL_MEMCTLR_INVADDRIE BIT18
|
||||
#define MEMCTL_MEMCTLR_STBY BIT19
|
||||
#define MEMCTL_MEMCTLR_ECCDIS BIT20
|
||||
#define MEMCTL_MEMCTLR_CACHEDIS BIT21
|
||||
#define MEMCTL_MEMCTLR_MCLKSEL BIT22
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup memstatus_reg Memory Controller Status Register
|
||||
@{*/
|
||||
/** Memory Controller Status Register */
|
||||
#define MEMCTL_MEMSTATUS MMIO32(MEMCTL_BASE + 0x0004)
|
||||
#define MEMCTL_MEMSTATUS_WBUSY BIT0
|
||||
#define MEMCTL_MEMSTATUS_EBUSY BIT1
|
||||
#define MEMCTL_MEMSTATUS_WRITEWORDCNT_MASK (0x3)
|
||||
#define MEMCTL_MEMSTATUS_WRITEWORDCNT_SHIFT 8
|
||||
#define MEMCTL_MEMSTATUS_WRITEWORDCNT ((MEMCTL_MEMSTATUS >> MEMCTL_MEMSTATUS_WRITEWORDCNT_SHIFT) & MEMCTL_MEMSTATUS_WRITEWORDCNT_MASK)
|
||||
#define MEMCTL_MEMSTATUS_WRITEWORDCNT_4BYTES (0)
|
||||
#define MEMCTL_MEMSTATUS_WRITEWORDCNT_8BYTES (1)
|
||||
#define MEMCTL_MEMSTATUS_WRITEWORDCNT_12BYTES (2)
|
||||
#define MEMCTL_MEMSTATUS_WRITEWORDCNT_16BYTES (3)
|
||||
#define MEMCTL_MEMSTATUS_SE BIT16
|
||||
#define MEMCTL_MEMSTATUS_DE BIT17
|
||||
#define MEMCTL_MEMSTATUS_INVADDR BIT18
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup flashlock_vals Flash Lock/Write Enable Register values
|
||||
@{*/
|
||||
/** Flash Lock Access Register */
|
||||
#define MEMCTL_FLASHLOCK MMIO32(MEMCTL_BASE + 0x0008)
|
||||
#define MEMCTL_FLASHLOCK_CLEAR (0)
|
||||
#define MEMCTL_FLASHLOCK_ALLOW_FLASH_WRITE (0x43DF140A)
|
||||
#define MEMCTL_FLASHLOCK_ALLOW_MEMCTL_WRITE (0xD513B490)
|
||||
#define MEMCTL_FLASHLOCK_ALLOW_INFO2_SWDFUSE (0x79B4F762)
|
||||
/**@}*/
|
||||
|
||||
/** Flash Page Address Register */
|
||||
#define MEMCTL_FLASHPAGE MMIO32(MEMCTL_BASE + 0x000C)
|
||||
/** SWD Unlock Register */
|
||||
#define MEMCTL_SWDUNLOCK MMIO32(MEMCTL_BASE + 0x0010)
|
||||
|
||||
/** @defgroup flasherase_vals Flash Erase Enable Register values
|
||||
@{*/
|
||||
/** Flash Erase Enable Register */
|
||||
#define MEMCTL_FLASHERASE MMIO32(MEMCTL_BASE + 0x0020)
|
||||
#define MEMCTL_FLASHERASE_PAGE_ERASE (0x8C799CA7)
|
||||
#define MEMCTL_FLASHERASE_MASS_PAGE_ERASE (0x09EE76C9)
|
||||
#define MEMCTL_FLASHERASE_INFO3_ERASE (0x1266FF45)
|
||||
/**@}*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* @defgroup memctl_api Memory Controller API
|
||||
* @ingroup peripheral_apis
|
||||
* @brief <b>PAC5xx MEMCTL Driver</b>
|
||||
* @author @htmlonly © @endhtmlonly 2020 Kevin Stefanik <kevin@allocor.tech>
|
||||
* @date March 7, 2020
|
||||
*
|
||||
* This library supports the MEMCTL module in the PAC55xx SoC from Qorvo.
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/*@{*/
|
||||
|
||||
/** Set the number of wait states for Flash reads.
|
||||
* @param[in] wstate Wait states: 0-15
|
||||
*/
|
||||
void memctl_flash_set_wstate(uint32_t wstate);
|
||||
/** Set the MCLK divisor.
|
||||
* @param[in] div HCLK to MCLK divisor: 1-16
|
||||
*/
|
||||
void memctl_flash_set_mclkdiv(uint32_t div);
|
||||
/** Set WRITEWORDCOUNT to 0 to reset the Flash write data buffer */
|
||||
void memctl_flash_reset_write_buffer(void);
|
||||
/** Enable Flash Standby Mode */
|
||||
void memctl_flash_standby_mode_enable(void);
|
||||
/** Disable Flash Standby Mode */
|
||||
void memctl_flash_standby_mode_disable(void);
|
||||
/** Enable Flash cache */
|
||||
void memctl_flash_cache_enable(void);
|
||||
/** Disable Flash cache */
|
||||
void memctl_flash_cache_disable(void);
|
||||
/** Select ROSCCLK as input to Flash Memory Controller */
|
||||
void memctl_flash_select_roscclk(void);
|
||||
/** Select MCLK as input to Flash Memory Controller */
|
||||
void memctl_flash_select_mclk(void);
|
||||
/** Enable SRAM ECC */
|
||||
void memctl_sram_ecc_enable(void);
|
||||
/** Disable SRAM ECC */
|
||||
void memctl_sram_ecc_disable(void);
|
||||
/** Enable SRAM ECC Single Bit Detection Interrupt */
|
||||
void memctl_sram_ecc_single_bit_interrupt_enable(void);
|
||||
/** Disable SRAM ECC Single Bit Detection Interrupt */
|
||||
void memctl_sram_ecc_single_bit_interrupt_disable(void);
|
||||
/** Enable SRAM ECC Dual Bit Detection Interrupt */
|
||||
void memctl_sram_ecc_dual_bit_interrupt_enable(void);
|
||||
/** Disable SRAM ECC Dual Bit Detection Interrupt */
|
||||
void memctl_sram_ecc_dual_bit_interrupt_disable(void);
|
||||
/** Enable Invalid Memory Access Interrupt */
|
||||
void memctl_invaddr_interrupt_enable(void);
|
||||
/** Disable Invalid Memory Access Interrupt */
|
||||
void memctl_invaddr_interrupt_disable(void);
|
||||
|
||||
/**@}*/
|
||||
|
||||
END_DECLS
|
||||
|
||||
#endif /* LIBOPENCM3_PAC55XX_MEMCTL_H_ */
|
||||
@@ -36,7 +36,9 @@ TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += can.o
|
||||
OBJS += ccs.o
|
||||
OBJS += gpio.o
|
||||
OBJS += memctl.o
|
||||
|
||||
VPATH += ../cm3
|
||||
|
||||
|
||||
261
lib/pac55xx/ccs.c
Normal file
261
lib/pac55xx/ccs.c
Normal file
@@ -0,0 +1,261 @@
|
||||
/**
|
||||
* @brief <b>PAC55xxxx CCS Driver</b>
|
||||
* @author @htmlonly © @endhtmlonly 2020 Kevin Stefanik <kevin@allocor.tech>
|
||||
* @date March 7, 2020
|
||||
*
|
||||
* This library supports the CCS module in the PAC55xx SoC from Qorvo.
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <libopencm3/pac55xx/ccs.h>
|
||||
#include <libopencm3/pac55xx/memorymap.h>
|
||||
#include <libopencm3/pac55xx/memctl.h>
|
||||
#include <libopencm3/cm3/assert.h>
|
||||
|
||||
static volatile uint32_t ccs_extclk_frequency = 0;
|
||||
static volatile uint32_t ccs_frclk_frequency = CCS_ROSC_FREQ;
|
||||
static volatile uint32_t ccs_sclk_frequency = CCS_ROSC_FREQ;
|
||||
static volatile uint32_t ccs_pll_clk_frequency = 0;
|
||||
static volatile uint32_t ccs_hclk_frequency = CCS_ROSC_FREQ;
|
||||
static volatile uint32_t ccs_aclk_frequency = CCS_ROSC_FREQ;
|
||||
static volatile uint32_t ccs_pclk_frequency = CCS_ROSC_FREQ;
|
||||
|
||||
void ccs_frclkmux_select(uint32_t sel) {
|
||||
CCSCTL = (CCSCTL & ~CCS_CTL_FRCLKMUXSEL(CCS_CTL_FRCLKMUXSEL_MASK)) | CCS_CTL_FRCLKMUXSEL(sel);
|
||||
}
|
||||
void ccs_rosc_enable(void) {
|
||||
CCSCTL |= CCS_CTL_ROSCEN;
|
||||
}
|
||||
void ccs_rosc_disable(void) {
|
||||
CCSCTL &= ~CCS_CTL_ROSCEN;
|
||||
}
|
||||
void ccs_sclkmux_select_frclk(void) {
|
||||
CCSCTL &= ~CCS_CTL_SCLKMUXSEL;
|
||||
}
|
||||
void ccs_sclkmux_select_pllclk(void) {
|
||||
CCSCTL |= CCS_CTL_SCLKMUXSEL;
|
||||
}
|
||||
void ccs_clkfail_enable(void) {
|
||||
CCSCTL |= CCS_CTL_CLKFAILEN;
|
||||
}
|
||||
void ccs_clkfail_disable(void) {
|
||||
CCSCTL &= ~CCS_CTL_CLKFAILEN;
|
||||
}
|
||||
void ccs_clkfailmux_select_frclk(void) {
|
||||
CCSCTL &= ~CCS_CTL_CLKFAILMUXSEL;
|
||||
}
|
||||
void ccs_clkfailmux_select_pllclk(void) {
|
||||
CCSCTL |= CCS_CTL_CLKFAILMUXSEL;
|
||||
}
|
||||
void ccs_ldo_enable(void) {
|
||||
CCSCTL |= CCS_CTL_LDOEN;
|
||||
}
|
||||
void ccs_ldo_disable(void) {
|
||||
CCSCTL &= ~CCS_CTL_LDOEN;
|
||||
}
|
||||
void ccs_pclk_enable(void) {
|
||||
CCSCTL |= CCS_CTL_PCLKEN;
|
||||
}
|
||||
void ccs_pclk_disable(void) {
|
||||
CCSCTL &= ~CCS_CTL_PCLKEN;
|
||||
}
|
||||
void ccs_aclk_enable(void) {
|
||||
CCSCTL |= CCS_CTL_ACLKEN;
|
||||
}
|
||||
void ccs_aclk_disable(void) {
|
||||
CCSCTL &= ~CCS_CTL_ACLKEN;
|
||||
}
|
||||
void ccs_adcclk_enable(void) {
|
||||
CCSCTL |= CCS_CTL_ADCCLKEN;
|
||||
}
|
||||
void ccs_adcclk_disable(void) {
|
||||
CCSCTL &= ~CCS_CTL_ADCCLKEN;
|
||||
}
|
||||
void ccs_stclk_sleep_enable(void) {
|
||||
CCSCTL |= CCS_CTL_STCLKSLPEN;
|
||||
}
|
||||
void ccs_stclk_sleep_disable(void) {
|
||||
CCSCTL &= ~CCS_CTL_STCLKSLPEN;
|
||||
}
|
||||
void ccs_set_pclkdiv(uint32_t div) {
|
||||
CCSCTL = (CCSCTL & ~CCS_CTL_PCLKDIV(8)) | CCS_CTL_PCLKDIV(div);
|
||||
}
|
||||
void ccs_set_aclkdiv(uint32_t div) {
|
||||
CCSCTL = (CCSCTL & ~CCS_CTL_ACLKDIV(8)) | CCS_CTL_ACLKDIV(div);
|
||||
}
|
||||
void ccs_set_hclkdiv(uint32_t div) {
|
||||
CCSCTL = (CCSCTL & ~CCS_CTL_HCLKDIV(8)) | CCS_CTL_HCLKDIV(div);
|
||||
}
|
||||
void ccs_pll_enable(void) {
|
||||
CCSPLLCTL |= CCS_PLLCTL_PLLEN;
|
||||
}
|
||||
void ccs_pll_disable(void) {
|
||||
CCSPLLCTL &= ~CCS_PLLCTL_PLLEN;
|
||||
}
|
||||
bool ccs_pll_locked(void) {
|
||||
return (CCSPLLCTL & CCS_PLLCTL_PLLLOCK) == CCS_PLLCTL_PLLLOCK;
|
||||
}
|
||||
void ccs_pll_bypass_enable(void) {
|
||||
CCSPLLCTL |= CCS_PLLCTL_PLLBP;
|
||||
}
|
||||
void ccs_pll_bypass_disable(void) {
|
||||
CCSPLLCTL &= ~CCS_PLLCTL_PLLBP;
|
||||
}
|
||||
void ccs_pll_set_outdiv(uint32_t div) {
|
||||
CCSPLLCTL = (CCSPLLCTL & ~CCS_PLLCTL_PLLOUTDIV(CCS_PLLCTL_PLLOUTDIV_MASK)) | CCS_PLLCTL_PLLOUTDIV(div);
|
||||
}
|
||||
void ccs_pll_set_indiv(uint32_t div) {
|
||||
if (div <= 15 && div >= 1) {
|
||||
CCSPLLCTL = (CCSPLLCTL & ~CCS_PLLCTL_PLLINDIV(CCS_PLLCTL_PLLINDIV_MASK)) | CCS_PLLCTL_PLLINDIV(div);
|
||||
} else {
|
||||
cm3_assert_not_reached();
|
||||
}
|
||||
}
|
||||
void ccs_pll_set_fbdiv(uint32_t div) {
|
||||
if (div <= 16383 && div >= 4) {
|
||||
CCSPLLCTL = (CCSPLLCTL & ~CCS_PLLCTL_PLLFBDIV(CCS_PLLCTL_PLLFBDIV_MASK)) | CCS_PLLCTL_PLLFBDIV(div);
|
||||
} else {
|
||||
cm3_assert_not_reached();
|
||||
}
|
||||
}
|
||||
void css_pll_config_enable(uint32_t indiv, uint32_t fbdiv, uint32_t outdiv) {
|
||||
ccs_pll_disable();
|
||||
ccs_pll_set_fbdiv(fbdiv);
|
||||
ccs_pll_set_outdiv(outdiv);
|
||||
ccs_pll_set_indiv(indiv);
|
||||
ccs_pll_enable();
|
||||
while (!ccs_pll_locked()) ; /* Wait for PLL lock ~500us */
|
||||
}
|
||||
uint32_t ccs_get_peripheral_clk_freq(uint32_t periph, uint32_t select) {
|
||||
switch (periph) {
|
||||
case ADC_BASE:
|
||||
return ccs_sclk_frequency;
|
||||
case I2C_BASE: /* fall through */
|
||||
case USARTA_BASE: /* fall through */
|
||||
case USARTB_BASE: /* fall through */
|
||||
case USARTC_BASE: /* fall through */
|
||||
case USARTD_BASE: /* fall through */
|
||||
case CAN_BASE: /* fall through */
|
||||
case GPTIMERA_BASE: /* fall through */
|
||||
case GPTIMERB_BASE:
|
||||
return ccs_pclk_frequency;
|
||||
case TIMERA_BASE: /* fall through */
|
||||
case TIMERB_BASE: /* fall through */
|
||||
case TIMERC_BASE: /* fall through */
|
||||
case TIMERD_BASE:
|
||||
return (select == 0) ? ccs_pclk_frequency : ccs_aclk_frequency;
|
||||
case MEMCTL_BASE:
|
||||
return (select == 0) ? CCS_ROSC_FREQ : ccs_hclk_frequency;
|
||||
case WWDT_BASE:
|
||||
return (select == 0) ? ccs_frclk_frequency : CCS_ROSC_FREQ;
|
||||
case RTC_BASE:
|
||||
return ccs_frclk_frequency;
|
||||
case CRC_BASE: /* fall through */
|
||||
case SYS_TICK_BASE:
|
||||
return ccs_hclk_frequency;
|
||||
default:
|
||||
cm3_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
void ccs_reset_clocks(void) {
|
||||
CCSCTL = CCS_CTL_LDOEN | CCS_CTL_ROSCEN |
|
||||
CCS_CTL_PCLKEN | CCS_CTL_ACLKEN |
|
||||
CCS_CTL_ADCCLKEN | CCS_CTL_STCLKSLPEN;
|
||||
CCSPLLCTL = 0;
|
||||
}
|
||||
|
||||
void ccs_configure_clocks(const struct ccs_clk_config *config) {
|
||||
MEMCTL_FLASHLOCK = MEMCTL_FLASHLOCK_ALLOW_MEMCTL_WRITE;
|
||||
|
||||
ccs_reset_clocks(); /* set safe defaults */
|
||||
ccs_frclkmux_select(CCS_CTL_FRCLKMUXSEL_ROSC);
|
||||
ccs_sclkmux_select_frclk();
|
||||
memctl_flash_select_roscclk();
|
||||
|
||||
if (config->mem_enable_cache) {
|
||||
memctl_flash_cache_enable();
|
||||
} else {
|
||||
memctl_flash_cache_disable();
|
||||
}
|
||||
|
||||
ccs_frclkmux_select(CCS_CTL_FRCLKMUXSEL_CLKREF); /* switch frclk to 4MHz CLKREF */
|
||||
|
||||
switch (config->frclk_source) {
|
||||
case CCS_CTL_FRCLKMUXSEL_ROSC:
|
||||
ccs_frclkmux_select(CCS_CTL_FRCLKMUXSEL_ROSC);
|
||||
ccs_frclk_frequency = CCS_ROSC_FREQ;
|
||||
break;
|
||||
case CCS_CTL_FRCLKMUXSEL_CLKREF:
|
||||
ccs_frclkmux_select(CCS_CTL_FRCLKMUXSEL_CLKREF);
|
||||
ccs_frclk_frequency = CCS_CLKREF_FREQ;
|
||||
break;
|
||||
case CCS_CTL_FRCLKMUXSEL_EXTCLK:
|
||||
if (config->extclk_frequency > CCS_EXTCLK_MAX_FREQ
|
||||
|| config->extclk_frequency == 0) {
|
||||
cm3_assert_not_reached();
|
||||
}
|
||||
ccs_frclkmux_select(CCS_CTL_FRCLKMUXSEL_EXTCLK);
|
||||
ccs_frclk_frequency = ccs_extclk_frequency = config->extclk_frequency;
|
||||
break;
|
||||
default:
|
||||
cm3_assert_not_reached();
|
||||
}
|
||||
|
||||
if (config->sclk_source == CCS_CTL_SCLKMUXSEL_FRCLK) {
|
||||
ccs_set_hclkdiv(config->hclkdiv);
|
||||
ccs_set_aclkdiv(config->aclkdiv);
|
||||
memctl_flash_set_wstate(config->mem_wstate);
|
||||
ccs_sclkmux_select_frclk();
|
||||
memctl_flash_set_mclkdiv(config->mem_mclkdiv);
|
||||
if (config->mem_mclksel == false) {
|
||||
memctl_flash_select_roscclk();
|
||||
} else {
|
||||
memctl_flash_select_mclk();
|
||||
}
|
||||
ccs_sclk_frequency = ccs_frclk_frequency;
|
||||
} else if (config->sclk_source == CCS_CTL_SCLKMUXSEL_PLLCLK) {
|
||||
css_pll_config_enable(config->pll_indiv, config->pll_fbdiv, config->pll_outdiv);
|
||||
ccs_set_hclkdiv(config->hclkdiv);
|
||||
ccs_set_aclkdiv(config->aclkdiv);
|
||||
memctl_flash_set_wstate(config->mem_wstate);
|
||||
ccs_sclkmux_select_pllclk();
|
||||
memctl_flash_set_mclkdiv(config->mem_mclkdiv);
|
||||
if (config->mem_mclksel == false) {
|
||||
memctl_flash_select_roscclk();
|
||||
} else {
|
||||
memctl_flash_select_mclk();
|
||||
}
|
||||
ccs_pll_clk_frequency = ((ccs_frclk_frequency * config->pll_fbdiv) / config->pll_indiv) >> config->pll_outdiv;
|
||||
ccs_sclk_frequency = ccs_pll_clk_frequency;
|
||||
} else {
|
||||
cm3_assert_not_reached();
|
||||
}
|
||||
ccs_set_pclkdiv(config->pclkdiv);
|
||||
ccs_pclk_enable();
|
||||
ccs_aclk_enable();
|
||||
ccs_adcclk_enable();
|
||||
ccs_stclk_sleep_disable();
|
||||
|
||||
ccs_hclk_frequency = ccs_sclk_frequency / config->hclkdiv;
|
||||
ccs_aclk_frequency = ccs_sclk_frequency / config->aclkdiv;
|
||||
ccs_pclk_frequency = ccs_hclk_frequency / config->pclkdiv;
|
||||
|
||||
MEMCTL_FLASHLOCK = MEMCTL_FLASHLOCK_CLEAR;
|
||||
}
|
||||
78
lib/pac55xx/memctl.c
Normal file
78
lib/pac55xx/memctl.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @brief <b>PAC55xxxx Memory Controller Driver</b>
|
||||
* @author @htmlonly © @endhtmlonly 2020 Kevin Stefanik <kevin@allocor.tech>
|
||||
* @date April 1, 2020
|
||||
*
|
||||
* This library supports the Memory Controller in the PAC55xx SoC from Qorvo.
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <libopencm3/pac55xx/memctl.h>
|
||||
|
||||
void memctl_flash_set_wstate(uint32_t wstate) {
|
||||
MEMCTL_MEMCTLR = (MEMCTL_MEMCTLR & ~MEMCTL_MEMCTLR_WSTATE(MEMCTL_MEMCTLR_WSTATE_MASK)) | MEMCTL_MEMCTLR_WSTATE(wstate);
|
||||
}
|
||||
void memctl_flash_set_mclkdiv(uint32_t div) {
|
||||
MEMCTL_MEMCTLR = (MEMCTL_MEMCTLR & ~MEMCTL_MEMCTLR_MCLKDIV(16)) | MEMCTL_MEMCTLR_MCLKDIV(div);
|
||||
}
|
||||
void memctl_flash_reset_write_buffer(void) {
|
||||
MEMCTL_MEMCTLR = (MEMCTL_MEMCTLR & ~MEMCTL_MEMCTLR_WRITEWORDCNT(MEMCTL_MEMCTLR_WRITEWORDCNT_MASK));
|
||||
}
|
||||
void memctl_flash_standby_mode_enable(void) {
|
||||
MEMCTL_MEMCTLR |= MEMCTL_MEMCTLR_STBY;
|
||||
}
|
||||
void memctl_flash_standby_mode_disable(void) {
|
||||
MEMCTL_MEMCTLR &= ~MEMCTL_MEMCTLR_STBY;
|
||||
}
|
||||
void memctl_flash_cache_enable(void) {
|
||||
MEMCTL_MEMCTLR &= ~MEMCTL_MEMCTLR_CACHEDIS;
|
||||
}
|
||||
void memctl_flash_cache_disable(void) {
|
||||
MEMCTL_MEMCTLR |= MEMCTL_MEMCTLR_CACHEDIS;
|
||||
}
|
||||
void memctl_flash_select_roscclk(void) {
|
||||
MEMCTL_MEMCTLR &= ~MEMCTL_MEMCTLR_MCLKSEL;
|
||||
}
|
||||
void memctl_flash_select_mclk(void) {
|
||||
MEMCTL_MEMCTLR |= MEMCTL_MEMCTLR_MCLKSEL;
|
||||
}
|
||||
void memctl_sram_ecc_enable(void) {
|
||||
MEMCTL_MEMCTLR &= ~MEMCTL_MEMCTLR_ECCDIS;
|
||||
}
|
||||
void memctl_sram_ecc_disable(void) {
|
||||
MEMCTL_MEMCTLR |= MEMCTL_MEMCTLR_ECCDIS;
|
||||
}
|
||||
void memctl_sram_ecc_single_bit_interrupt_enable(void) {
|
||||
MEMCTL_MEMCTLR |= MEMCTL_MEMCTLR_SEIE;
|
||||
}
|
||||
void memctl_sram_ecc_single_bit_interrupt_disable(void) {
|
||||
MEMCTL_MEMCTLR &= ~MEMCTL_MEMCTLR_SEIE;
|
||||
}
|
||||
void memctl_sram_ecc_dual_bit_interrupt_enable(void) {
|
||||
MEMCTL_MEMCTLR |= MEMCTL_MEMCTLR_DEIE;
|
||||
}
|
||||
void memctl_sram_ecc_dual_bit_interrupt_disable(void) {
|
||||
MEMCTL_MEMCTLR &= ~MEMCTL_MEMCTLR_DEIE;
|
||||
}
|
||||
void memctl_invaddr_interrupt_enable(void) {
|
||||
MEMCTL_MEMCTLR |= MEMCTL_MEMCTLR_INVADDRIE;
|
||||
}
|
||||
void memctl_invaddr_interrupt_disable(void) {
|
||||
MEMCTL_MEMCTLR &= ~MEMCTL_MEMCTLR_INVADDRIE;
|
||||
}
|
||||
Reference in New Issue
Block a user